Insanely huge initial commit

This commit is contained in:
2026-02-21 16:40:15 -08:00
parent 208d626100
commit f74c547a13
33825 changed files with 5213498 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
using System.IO;
using System.Runtime.InteropServices;
using System;
using UnityEngine;
using System.Text;
#if UNITY_2020_2_OR_NEWER
using UnityEditor.AssetImporters;
#elif UNITY_2019_4_OR_NEWER
using UnityEditor.Experimental.AssetImporters;
#endif
namespace Lofelt.NiceVibrations
{
[ScriptedImporter(version: 3, ext: "haptic", AllowCaching = true)]
/// <summary>
/// Provides an importer for the HapticClip component.
/// </summary>
///
/// The importer takes a <c>.haptic</c> file and converts it into a HapticClip.
public class HapticImporter : ScriptedImporter
{
#if !NICE_VIBRATIONS_DISABLE_GAMEPAD_SUPPORT
[DllImport("nice_vibrations_editor_plugin")]
private static extern IntPtr nv_plugin_convert_haptic_to_gamepad_rumble([In] byte[] bytes, long size);
[DllImport("nice_vibrations_editor_plugin")]
private static extern void nv_plugin_destroy(IntPtr gamepadRumble);
[DllImport("nice_vibrations_editor_plugin")]
private static extern UIntPtr nv_plugin_get_length(IntPtr gamepadRumble);
[DllImport("nice_vibrations_editor_plugin")]
private static extern void nv_plugin_get_durations(IntPtr gamepadRumble, [Out] int[] durations);
[DllImport("nice_vibrations_editor_plugin")]
private static extern void nv_plugin_get_low_frequency_motor_speeds(IntPtr gamepadRumble, [Out] float[] lowFrequencies);
[DllImport("nice_vibrations_editor_plugin")]
private static extern void nv_plugin_get_high_frequency_motor_speeds(IntPtr gamepadRumble, [Out] float[] highFrequencies);
// We can not use "[return: MarshalAs(UnmanagedType.LPUTF8Str)]" here, and have to use
// IntPtr for the return type instead. Otherwise the C# runtime tries to free the returned
// string, which is invalid as the native plugin keeps ownership of the string.
// We use PtrToStringUTF8() to manually convert the IntPtr to a string instead.
[DllImport("nice_vibrations_editor_plugin")]
private static extern IntPtr nv_plugin_get_last_error();
[DllImport("nice_vibrations_editor_plugin")]
private static extern UIntPtr nv_plugin_get_last_error_length();
// Alternative to Marshal.PtrToStringUTF8() which was introduced in .NET 5 and isn't yet
// supported by Unity
private string PtrToStringUTF8(IntPtr ptr, int length)
{
byte[] bytes = new byte[length];
Marshal.Copy(ptr, bytes, 0, length);
return Encoding.UTF8.GetString(bytes, 0, length);
}
#endif
public override void OnImportAsset(AssetImportContext ctx)
{
// Load .haptic clip from file
var fileName = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);
var jsonBytes = File.ReadAllBytes(ctx.assetPath);
var hapticClip = HapticClip.CreateInstance<HapticClip>();
hapticClip.json = jsonBytes;
#if !NICE_VIBRATIONS_DISABLE_GAMEPAD_SUPPORT
// Convert JSON to a GamepadRumble struct. The conversion algorithm is inside the native
// library nice_vibrations_editor_plugin. That plugin is only used in the Unity editor, and
// not at runtime.
GamepadRumble rumble = default;
IntPtr nativeRumble = nv_plugin_convert_haptic_to_gamepad_rumble(jsonBytes, jsonBytes.Length);
if (nativeRumble != IntPtr.Zero)
{
try
{
uint length = (uint)nv_plugin_get_length(nativeRumble);
rumble.durationsMs = new int[length];
rumble.lowFrequencyMotorSpeeds = new float[length];
rumble.highFrequencyMotorSpeeds = new float[length];
nv_plugin_get_durations(nativeRumble, rumble.durationsMs);
nv_plugin_get_low_frequency_motor_speeds(nativeRumble, rumble.lowFrequencyMotorSpeeds);
nv_plugin_get_high_frequency_motor_speeds(nativeRumble, rumble.highFrequencyMotorSpeeds);
int totalDurationMs = 0;
foreach (int duration in rumble.durationsMs)
{
totalDurationMs += duration;
}
rumble.totalDurationMs = totalDurationMs;
}
finally
{
nv_plugin_destroy(nativeRumble);
}
}
else
{
var lastErrorPtr = nv_plugin_get_last_error();
var lastErrorLength = (int)nv_plugin_get_last_error_length();
var lastError = PtrToStringUTF8(lastErrorPtr, lastErrorLength);
Debug.LogWarning($"Failed to convert haptic clip {ctx.assetPath} to gamepad rumble: {lastError}");
}
hapticClip.gamepadRumble = rumble;
#endif
// Use hapticClip as the imported asset
ctx.AddObjectToAsset("com.lofelt.HapticClip", hapticClip);
ctx.SetMainObject(hapticClip);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dc84fb4fa9e67485a972c887d976d004
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,155 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
namespace Lofelt.NiceVibrations
{
[CustomEditor(typeof(HapticSource))]
[CanEditMultipleObjects]
/// <summary>
/// Provides an inspector for the HapticSource component
/// </summary>
///
/// The inspector lets you link a HapticSource to a HapticClip.
public class HapticSourceInspector : Editor
{
string hapticsDirectory;
SerializedProperty hapticClip;
SerializedProperty priority;
SerializedProperty level;
SerializedProperty frequencyShift;
SerializedProperty loop;
SerializedProperty fallbackPreset;
public static GUIContent hapticClipLabel = EditorGUIUtility.TrTextContent("Haptic Clip", "The HapticClip asset played by the HapticSource.");
public static GUIContent fallbackPresetLabel = EditorGUIUtility.TrTextContent("Haptic Preset fallback", "Set the haptic preset to play in case the device doesn't support playback of haptic clips");
public static GUIContent loopLabel = EditorGUIUtility.TrTextContent("Loop", "Set the haptic source to loop playback of the haptic clip");
void OnEnable()
{
hapticClip = serializedObject.FindProperty("clip");
priority = serializedObject.FindProperty("priority");
level = serializedObject.FindProperty("_level");
frequencyShift = serializedObject.FindProperty("_frequencyShift");
fallbackPreset = serializedObject.FindProperty("_fallbackPreset");
loop = serializedObject.FindProperty("_loop");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(hapticClip, hapticClipLabel);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(fallbackPreset, fallbackPresetLabel);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(loop, loopLabel);
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
CreatePrioritySlider();
CreateLevelSlider();
CreateFrequencyShiftSlider();
serializedObject.ApplyModifiedProperties();
}
/// Helper function to create a priority slider for haptic source with High and Max text labels.
void CreatePrioritySlider()
{
Rect position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.IntSlider(position, priority, 0, 256);
// Move to next line
position.y += EditorGUIUtility.singleLineHeight;
// Subtract the label
position.x += EditorGUIUtility.labelWidth;
position.width -= EditorGUIUtility.labelWidth;
// Subtract the text field width thats drawn with slider
position.width -= EditorGUIUtility.fieldWidth;
GUIStyle style = GUI.skin.label;
TextAnchor defaultAlignment = GUI.skin.label.alignment;
style.alignment = TextAnchor.UpperLeft; EditorGUI.LabelField(position, "High", style);
style.alignment = TextAnchor.UpperRight; EditorGUI.LabelField(position, "Low", style);
GUI.skin.label.alignment = defaultAlignment;
// Allow space for the High/Low labels
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
/// Helper function to create a level slider for haptic
/// source with labels.
void CreateLevelSlider()
{
Rect position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.Slider(position, level, 0.0f, 5.0f);
// Move to next line
position.y += EditorGUIUtility.singleLineHeight;
// Subtract the label
position.x += EditorGUIUtility.labelWidth;
position.width -= EditorGUIUtility.labelWidth;
// Subtract the text field width thats drawn with slider
position.width -= EditorGUIUtility.fieldWidth;
GUIStyle style = GUI.skin.label;
TextAnchor defaultAlignment = GUI.skin.label.alignment;
style.alignment = TextAnchor.UpperLeft; EditorGUI.LabelField(position, "0.0", style);
style.alignment = TextAnchor.UpperRight; EditorGUI.LabelField(position, "5.0", style);
GUI.skin.label.alignment = defaultAlignment;
// Allow space for the labels
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
/// Helper function to create a frequency shift slider for haptic
/// source with labels.
void CreateFrequencyShiftSlider()
{
Rect position = EditorGUILayout.GetControlRect(true, EditorGUIUtility.singleLineHeight);
EditorGUI.Slider(position, frequencyShift, -1.0f, 1.0f);
// Move to next line
position.y += EditorGUIUtility.singleLineHeight;
// Subtract the label
position.x += EditorGUIUtility.labelWidth;
position.width -= EditorGUIUtility.labelWidth;
// Subtract the text field width thats drawn with slider
position.width -= EditorGUIUtility.fieldWidth;
GUIStyle style = GUI.skin.label;
TextAnchor defaultAlignment = GUI.skin.label.alignment;
style.alignment = TextAnchor.UpperLeft; EditorGUI.LabelField(position, "-1.0", style);
style.alignment = TextAnchor.UpperRight; EditorGUI.LabelField(position, "1.0", style);
GUI.skin.label.alignment = defaultAlignment;
// Allow space for the labels
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90a030b5ab0574cd9880e136f5e0261c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
{
"name": "Lofelt.NiceVibrations.Editor",
"references": [
"GUID:57a0b9bc628ab4740af4b6f1f0b2e134"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 67bc5fafbf62b48858241ce814d3d489
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: