Replace UltimateXR with HurricaneVR

This commit is contained in:
2024-08-08 17:01:07 +02:00
parent e8658374d6
commit fb21dbbb73
5932 changed files with 358362 additions and 2174150 deletions

8
Assets/HurricaneVR.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed18a0babc8b032438b8b4758d1d90f4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 281637870489c904da4051738c7900e6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8ff21fe5616684e4383d0aa958bf111f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 975def741748acc49afc0f7490930658
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d1bb57c7847e5343b5f70d65b53da5b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: e57bd9c082580bf4f8a951b1ec95dc1e
guid: 5d8c74653f3e7d74aa56a7d95be90f1e
folderAsset: yes
DefaultImporter:
externalObjects: {}

View File

@@ -0,0 +1,55 @@
using HurricaneVR.Framework.Core.ScriptableObjects;
using HurricaneVR.Framework.Core.Utils;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
public class CustomContexts
{
[MenuItem("Assets/HVR/Convert to Strength", false, 1)]
private static void StrengthConvert(MenuCommand command)
{
foreach (var o in Selection.objects)
{
var path = AssetDatabase.GetAssetPath(o);
var js = AssetDatabase.LoadAssetAtPath<HVRJointSettings>(path);
if (!js)
continue;
var fileName = path.Replace(".asset", "");
fileName += "_Strength.asset";
var s = AssetDatabase.LoadAssetAtPath<PDStrength>(fileName);
if (!s)
{
s = ScriptableObject.CreateInstance<PDStrength>();
}
s.Mode = js.ApplyMode;
s.Spring = js.XDrive.Spring;
s.Damper = js.XDrive.Damper;
s.MaxForce = js.XDrive.MaxForce;
s.TorqueSpring = js.SlerpDrive.Spring;
s.TorqueDamper = js.SlerpDrive.Damper;
s.MaxTorque = js.SlerpDrive.MaxForce;
AssetUtils.CreateOrReplaceAsset(s, fileName);
}
}
[MenuItem("Assets/HVR/Convert to Strength", true, 1)]
private static bool StrengthConvertValidation()
{
foreach (var o in Selection.objects)
{
var path = AssetDatabase.GetAssetPath(o);
var js = AssetDatabase.LoadAssetAtPath<HVRJointSettings>(path);
if (!js)
return false;
}
return Selection.objects.Length > 0;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e2d14f6a173045b08af8717e276df756
timeCreated: 1666239275

View File

@@ -0,0 +1,35 @@
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace HurricaneVR.Editor
{
//this file merely exists because unity packages appear to add only and this trash is no good at all
//[CustomEditor(typeof(Object), true, isFallback = true)]
//public class DefaultEditor : UnityEditor.Editor
//{
// public override VisualElement CreateInspectorGUI()
// {
// var container = new VisualElement();
// var iterator = serializedObject.GetIterator();
// if (iterator.NextVisible(true))
// {
// do
// {
// var propertyField = new PropertyField(iterator.Copy()) { name = "PropertyField:" + iterator.propertyPath };
// if (iterator.propertyPath == "m_Script" && serializedObject.targetObject != null)
// propertyField.SetEnabled(value: false);
// container.Add(propertyField);
// }
// while (iterator.NextVisible(false));
// }
// return container;
// }
//}
}

View File

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

View File

@@ -0,0 +1,97 @@
using System;
using System.Collections;
using System.Collections.Generic;
using HurricaneVR.Framework.Core.Utils;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomPropertyDrawer(typeof(DrawIfAttribute))]
public class DrawIfPropertyDrawer : PropertyDrawer
{
#region Fields
// Reference to the attribute on the property.
DrawIfAttribute drawIf;
// Field that is being compared.
SerializedProperty comparedField;
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!ShowMe(property) && drawIf.disablingType == DrawIfAttribute.DisablingType.DontDraw)
return 0f;
// The height of the property should be defaulted to the default height.
return base.GetPropertyHeight(property, label);
}
/// <summary>
/// Errors default to showing the property.
/// </summary>
private bool ShowMe(SerializedProperty property)
{
drawIf = attribute as DrawIfAttribute;
// Replace propertyname to the value from the parameter
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawIf.comparedPropertyName) : drawIf.comparedPropertyName;
comparedField = property.serializedObject.FindProperty(path);
if (comparedField == null)
{
Debug.LogError("Cannot find property with name: " + path);
return true;
}
// get the value & compare based on types
switch (comparedField.type)
{ // Possible extend cases to support your own type
case "bool":
return comparedField.boolValue.Equals(drawIf.comparedValue);
case "Enum":
return comparedField.enumValueIndex.Equals((int)drawIf.comparedValue);
default:
Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
return true;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// If the condition is met, simply draw the field.
if (ShowMe(property))
{
EditorGUI.PropertyField(position, property, label);
} //...check if the disabling type is read only. If it is, draw it disabled
else if (drawIf.disablingType == DrawIfAttribute.DisablingType.ReadOnly)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label);
GUI.enabled = true;
}
}
}
public enum DisablingType
{
ReadOnly = 2,
DontDraw = 3
}
public enum ComparisonType
{
Equals = 1,
NotEqual = 2,
GreaterThan = 3,
SmallerThan = 4,
SmallerOrEqual = 5,
GreaterOrEqual = 6
}
}

View File

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

View File

@@ -0,0 +1,49 @@
using HurricaneVR.Framework.Core.Utils;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomPropertyDrawer(typeof(EmbeddedAttribute), true)]
public class EmbeddedAssetDrawer : PropertyDrawer
{
private EmbeddeAssetEditor _editor;
public EmbeddeAssetEditor Editor
{
get
{
if (_editor == null)
_editor = new EmbeddeAssetEditor();
return _editor;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var a = attribute as EmbeddedAttribute;
Editor.DrawEditorCombo(position, fieldInfo.FieldType, label, property, $"Save {property.displayName}.", $"{property.displayName.Replace(" ", "_")}", "asset", string.Empty);
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!property.isExpanded || property.objectReferenceValue == null)
{
return EditorGUIUtility.singleLineHeight;
}
float height = base.GetPropertyHeight(property, label) + EditorGUIUtility.singleLineHeight;
var so = new SerializedObject(property.objectReferenceValue);
var prop = so.GetIterator();
prop.NextVisible(true);
while (prop.NextVisible(true))
{
if (prop.name == "m_Script")
continue;
height += EditorGUIUtility.singleLineHeight;
}
return height * 1.2f;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d3003c99effe439d9d06c4e9334443ba
timeCreated: 1666146629

View File

@@ -0,0 +1,181 @@
using System;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEditor.VersionControl;
using UnityEngine;
using UnityEngine.UIElements;
namespace HurricaneVR.Editor
{
/// <summary>
/// Helper for drawing embedded asset editors
/// </summary>
public class EmbeddeAssetEditor
{
/// <summary>
/// Free the resources in OnDisable()
/// </summary>
public void OnDisable()
{
DestroyEditor();
}
private readonly GUIContent m_CreateButtonGUIContent = new GUIContent("Create Asset", "Create new asset.");
UnityEditor.Editor m_Editor = null;
const int kIndentOffset = 3;
private Type _type;
public void DrawEditorCombo(Rect position, Type type, GUIContent label, SerializedProperty property, string title, string defaultName, string extension, string message)
{
_type = type;
DrawEditorCombo(position, property, title, defaultName, extension, message, false);
}
/// <summary>
/// Call this from OnInspectorGUI. Will draw the asset reference field, and
/// the embedded editor, or a Create Asset button, if no asset is set.
/// </summary>
private void DrawEditorCombo(Rect position, SerializedProperty property,
string title, string defaultName, string extension, string message,
bool indent)
{
UpdateEditor(property);
if (!m_Editor)
{
AssetFieldWithCreateButton(position, property, title, defaultName, extension, message);
return;
}
var rect = position;
var propRect = rect;
propRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(propRect, property);
if (EditorGUI.EndChangeCheck())
{
property.serializedObject.ApplyModifiedProperties();
UpdateEditor(property);
}
if (m_Editor)
{
Rect foldoutRect = new Rect(rect.x - kIndentOffset, rect.y, rect.width + kIndentOffset, EditorGUIUtility.singleLineHeight);
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, GUIContent.none, true);
bool canEditAsset = AssetDatabase.IsOpenForEdit(m_Editor.target, StatusQueryOptions.UseCachedIfPossible);
GUI.enabled = canEditAsset;
if (property.isExpanded)
{
position.y += EditorGUIUtility.singleLineHeight;
var box = position;
box.height *= .9f;
EditorGUI.HelpBox(box, "CTRL+S to persist asset changes.", MessageType.None);
position.y += EditorGUIUtility.singleLineHeight;
EditorGUI.BeginChangeCheck();
var so = new SerializedObject(property.objectReferenceValue);
var prop = so.GetIterator();
while (prop.NextVisible(true))
{
if (prop.name == "m_Script")
continue;
position.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(position, prop);
position.y += EditorGUIUtility.singleLineHeight;
}
if (EditorGUI.EndChangeCheck())
{
so.ApplyModifiedProperties();
}
}
GUI.enabled = true;
if (m_Editor.target != null)
{
if (!canEditAsset && GUILayout.Button("Check out"))
{
Task task = Provider.Checkout(AssetDatabase.GetAssetPath(m_Editor.target), CheckoutMode.Asset);
task.Wait();
}
}
}
}
void AssetFieldWithCreateButton(Rect position, SerializedProperty property,
string title, string defaultName, string extension, string message)
{
EditorGUI.BeginChangeCheck();
float hSpace = 5;
float buttonWidth = GUI.skin.button.CalcSize(m_CreateButtonGUIContent).x;
var r = position;
r.width -= buttonWidth + hSpace;
EditorGUI.PropertyField(r, property);
r.x += r.width + hSpace;
r.width = buttonWidth;
if (GUI.Button(r, m_CreateButtonGUIContent))
{
string newAssetPath = EditorUtility.SaveFilePanelInProject(
title, defaultName, extension, message);
if (!string.IsNullOrEmpty(newAssetPath))
{
var asset = CreateAt(_type, newAssetPath);
property.objectReferenceValue = asset;
property.serializedObject.ApplyModifiedProperties();
}
}
if (EditorGUI.EndChangeCheck())
{
property.serializedObject.ApplyModifiedProperties();
UpdateEditor(property);
}
}
void DestroyEditor()
{
if (m_Editor != null)
{
UnityEngine.Object.DestroyImmediate(m_Editor);
m_Editor = null;
}
}
void UpdateEditor(SerializedProperty property)
{
property.serializedObject.ApplyModifiedProperties();
var target = property.objectReferenceValue;
if (m_Editor && m_Editor.target != target)
{
DestroyEditor();
}
if (target != null)
{
if (!m_Editor)
{
m_Editor = UnityEditor.Editor.CreateEditor(target);
}
}
}
public static ScriptableObject CreateAt(Type assetType, string assetPath)
{
ScriptableObject asset = ScriptableObject.CreateInstance(assetType);
if (!asset)
{
Debug.LogError("Failed to create instance of " + assetType.Name + " at " + assetPath);
return null;
}
AssetDatabase.CreateAsset(asset, assetPath);
return asset;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 63f79aabdd614d20a214af69939cd772
timeCreated: 1666142031

View File

@@ -0,0 +1,47 @@
#if UNITY_EDITOR
using System;
using System.Reflection;
using HurricaneVR.Framework.Core.Utils;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomPropertyDrawer(typeof(EnumFlagAttribute))]
public class EnumFlagDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EnumFlagAttribute flagSettings = (EnumFlagAttribute)attribute;
Enum targetEnum = GetBaseProperty<Enum>(property);
string propName = flagSettings.enumName;
if (string.IsNullOrEmpty(propName))
propName = property.name;
EditorGUI.BeginProperty(position, label, property);
Enum enumNew = EditorGUI.EnumFlagsField(position, propName, targetEnum);
property.intValue = (int)Convert.ChangeType(enumNew, targetEnum.GetType());
EditorGUI.EndProperty();
}
static T GetBaseProperty<T>(SerializedProperty prop)
{
// Separate the steps it takes to get to this property
string[] separatedPaths = prop.propertyPath.Split('.');
// Go down to the root of this serialized property
System.Object reflectionTarget = prop.serializedObject.targetObject as object;
// Walk down the path to get the target object
foreach (var path in separatedPaths)
{
FieldInfo fieldInfo = reflectionTarget.GetType().GetField(path);
reflectionTarget = fieldInfo.GetValue(reflectionTarget);
}
return (T)reflectionTarget;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 65081c63cc3a470592efc2d38872c555
timeCreated: 1599786045

View File

@@ -0,0 +1,78 @@
using HurricaneVR.Framework.Components;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRButton))]
public class HVRButtonEditor : UnityEditor.Editor
{
private SerializedProperty SP_StartPosition;
private SerializedProperty SP_Threshold;
private SerializedProperty SP_UpThreshold;
public HVRButton Button { get; private set; }
protected void OnEnable()
{
SP_StartPosition = serializedObject.FindProperty("StartPosition");
SP_Threshold = serializedObject.FindProperty("Threshold");
SP_UpThreshold = serializedObject.FindProperty("UpThreshold");
Button = target as HVRButton;
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
if (SP_UpThreshold.floatValue > SP_Threshold.floatValue)
{
EditorGUILayout.HelpBox("Up Threshold should not be greater than Threshold.", MessageType.Error);
}
var position = Button.transform.localPosition;
position.Scale(Button.Axis);
var startPosition = SP_StartPosition.vector3Value;
startPosition.Scale(Button.Axis);
var valid = true;
if (position.x > startPosition.x || position.y > startPosition.y || position.z > startPosition.z)
{
valid = false;
EditorGUILayout.HelpBox("Button position cannot be greater than the start position.", MessageType.Error);
}
if (GUILayout.Button("Save Initial Position"))
{
SP_StartPosition.vector3Value = Button.transform.localPosition;
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("Save Threshold"))
{
if (valid)
{
var delta = SP_StartPosition.vector3Value - Button.transform.localPosition;
delta.Scale(Button.Axis);
SP_Threshold.floatValue = delta.magnitude;
serializedObject.ApplyModifiedProperties();
}
}
if (GUILayout.Button("Save Up Threshold"))
{
if (valid)
{
var delta = SP_StartPosition.vector3Value - Button.transform.localPosition;
delta.Scale(Button.Axis);
SP_UpThreshold.floatValue = delta.magnitude;
serializedObject.ApplyModifiedProperties();
}
}
if (GUILayout.Button("Return To Start Position"))
{
Button.transform.localPosition = SP_StartPosition.vector3Value;
}
}
}
}

View File

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

View File

@@ -0,0 +1,70 @@
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Weapons;
using HurricaneVR.Framework.Weapons.Guns;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRCockingHandle))]
public class HVRCockingHandleEditor : UnityEditor.Editor
{
private SerializedProperty ForwardPosition;
private SerializedProperty BackwardPosition;
private SerializedProperty EjectPosition;
private SerializedProperty ChamberRoundPosition;
public HVRCockingHandle component;
protected void OnEnable()
{
ForwardPosition = serializedObject.FindProperty("ForwardPosition");
BackwardPosition = serializedObject.FindProperty("BackwardPosition");
EjectPosition = serializedObject.FindProperty("EjectPosition");
ChamberRoundPosition = serializedObject.FindProperty("ChamberRoundPosition");
component = target as HVRCockingHandle;
}
public override void OnInspectorGUI()
{
//EditorGUILayout.HelpBox("1. Choose the local axis the drawer will move on.\r\n" +
// "2. Save the start position of the drawer.\r\n" +
// "3. Save the end position of the drawer.\r\n"
// //"4. Save the down and reset positions.\r\n" +
// //"5. Return the transform to start by pressing the return button.\r\n" +
// //"6. If the Connected Body is left blank, the button will be jointed to the world and cannot be moved."
// , MessageType.Info);
DrawButtons("Forward", ForwardPosition);
DrawButtons("Backward", BackwardPosition);
DrawButtons("Eject", EjectPosition);
DrawButtons("ChamberRound", ChamberRoundPosition);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
private void DrawButtons(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.vector3Value = component.transform.localPosition;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localPosition = property.vector3Value;
}
GUILayout.EndHorizontal();
}
}
}

View File

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

View File

@@ -0,0 +1,42 @@
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRComments))]
public class HVRCommentsInspector : UnityEditor.Editor
{
private HVRComments Comments { get { return target as HVRComments; } }
private readonly GUIStyle style = new GUIStyle(EditorStyles.helpBox);
// Colors
private static Color DarkSkinFontColor = new Color(.8f, .8f, .8f, 1f);//new Color(0.5f, 0.7f, 0.3f, 1f);
private static Color NormalFontColor = new Color(0.2f, 0.3f, 0.1f, 1f);
public override void OnInspectorGUI()
{
if (serializedObject == null)
return;
style.wordWrap = true;
style.fontSize = 15;
style.normal.textColor = EditorGUIUtility.isProSkin ? DarkSkinFontColor : NormalFontColor;
serializedObject.Update();
EditorGUILayout.Space();
var updatedText = EditorGUILayout.TextArea(Comments.text, style);
if (updatedText != Comments.text)
{
Undo.RecordObject(Comments, "Edit Comments");
Comments.text = updatedText;
serializedObject.ApplyModifiedProperties();
}
EditorGUILayout.Space();
}
}
}

View File

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

View File

@@ -0,0 +1,63 @@
using System;
using HurricaneVR.Framework.Core.ScriptableObjects;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
public static class HVREditorExtensions
{
public static void Toggle(string label, ref bool value)
{
value = EditorGUILayout.Toggle(label, value);
}
public static void IntField(string label, ref int value)
{
value = EditorGUILayout.IntField(label, value);
}
public static void FloatField(string label, ref float value)
{
value = EditorGUILayout.FloatField(label, value);
}
public static void EnumField<T>(string label, ref T value) where T : Enum
{
value = (T)EditorGUILayout.EnumPopup(label, value);
}
public static void ObjectField(string label, ref GameObject value, bool allowSceneObjects = true)
{
value = EditorGUILayout.ObjectField(label, value, typeof(GameObject), allowSceneObjects) as GameObject;
}
public static void ObjectField<T>(string label, ref T value, bool allowSceneObjects = true) where T : UnityEngine.Object
{
value = EditorGUILayout.ObjectField(label, value, typeof(T), allowSceneObjects) as T;
}
public static void JointField(string label, ref HVRJointSettings value)
{
value = EditorGUILayout.ObjectField(label, value, typeof(HVRJointSettings), false) as HVRJointSettings;
}
public static void StrengthField(string label, ref PDStrength value)
{
value = EditorGUILayout.ObjectField(label, value, typeof(PDStrength), false) as PDStrength;
}
public static void Header(string label)
{
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
}
public static void FloatRange(string label, ref float value, float min = 0f, float max = 1f)
{
var position = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight);
position = EditorGUI.PrefixLabel(position, new GUIContent(label));
value = EditorGUI.Slider(position, value, min, max);
}
}
}

View File

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

View File

@@ -0,0 +1,35 @@
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
public class HVREditorManager
{
private const string HurricaneVRUploader = "HurricaneVRUploader";
public const string Version = "2.9.2";
[InitializeOnLoadMethod]
private static void Hook()
{
EditorApplication.delayCall += CheckUpdate;
}
private static void CheckUpdate()
{
if (Application.productName != HurricaneVRUploader)
{
var kickit = HVRSettings.Instance;
if (HVREditorPreferences.UpdateDisplayedVersion != Version)
{
HVREditorPreferences.UpdateDisplayedVersion = Version;
HVRSetupWindow.ShowWindow();
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,50 @@
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
public class HVREditorPreferences : ScriptableObject
{
private static HVREditorPreferences instance;
[SerializeField]
private string _updatedDisplayedVersion;
public static HVREditorPreferences Instance
{
get
{
if (instance == null)
{
instance = Resources.Load<HVREditorPreferences>("HVREditorPreferences");
if (instance == null)
{
instance = CreateInstance<HVREditorPreferences>();
Save();
}
}
return instance;
}
}
public static string UpdateDisplayedVersion
{
get { return Instance._updatedDisplayedVersion; }
set
{
if (Instance._updatedDisplayedVersion == value) return;
Instance._updatedDisplayedVersion = value;
Save();
}
}
public static void Save()
{
//Debug.Log($"saved");
EditorUtility.SetDirty(instance);
HVRSettings.Instance.AddAssetToResource(instance, "HVREditorPreferences");
}
}
}

View File

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

View File

@@ -0,0 +1,58 @@
using HurricaneVR.Framework.Weapons;
using HurricaneVR.Framework.Weapons.Guns;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRGunBolt))]
public class HVRGunBoltEditor : UnityEditor.Editor
{
private SerializedProperty ForwardPosition;
private SerializedProperty BackwardPosition;
public HVRGunBolt component;
protected void OnEnable()
{
ForwardPosition = serializedObject.FindProperty("ForwardPosition");
BackwardPosition = serializedObject.FindProperty("BackwardPosition");
component = target as HVRGunBolt;
}
public override void OnInspectorGUI()
{
EditorGUILayout.HelpBox("1. Save the forward position of the bolt.\r\n" +
"2. Save the backward position of the bolt.\r\n", MessageType.Info);
DrawButtons("Forward", ForwardPosition);
DrawButtons("Backward", BackwardPosition);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
private void DrawButtons(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.vector3Value = component.transform.localPosition;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localPosition = property.vector3Value;
}
GUILayout.EndHorizontal();
}
}
}

View File

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

View File

@@ -0,0 +1,852 @@
using System.Collections.Generic;
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Bags;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core.HandPoser;
using HurricaneVR.Framework.Core.ScriptableObjects;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using HurricaneVR.Framework.Weapons;
using HurricaneVR.Framework.Weapons.Guns;
using HurricaneVR.Framework.Weapons.Guns.PartFinders;
using UnityEditor;
using UnityEngine;
using HVRPistol = HurricaneVR.Framework.Weapons.Guns.HVRPistol;
using Object = UnityEngine.Object;
namespace HurricaneVR.Editor
{
public class HVRGunCreator : EditorWindow
{
private const string RecoilSMG = "RecoilSettings/HVR_Recoil_SMG";
private const string RecoilAR = "RecoilSettings/HVR_Recoil_AR";
private const string RecoilPistol = "RecoilSettings/HVR_Recoil_Pistol";
private const string RecoilPump = "RecoilSettings/HVR_Recoil_PumpShotgun";
//private const string TwoHandPistol = "HandSettings/HVR_Pistol_TwoHand";
//private const string TwoHandLarge = "HandSettings/HVR_LargeWeapon_TwoHanded";
private const string TwoHandLargeStabilizer = "HandSettings/HVR_Stabilizer_TwoHanded_Strength";
private const string TwoHandPistolStabilizer = "HandSettings/HVR_Pistol_Stabilizer_TwoHanded_Strength";
//private const string OneHandPistol = "HandSettings/HVR_Pistol_OneHand";
//private const string OneHandDefault = "HandSettings/HVR_DefaultHandSettings";
private static HVRGunCreator _window;
private GameObject _gunPrefab;
private GameObject _casingPrefab;
private GameObject _ejectedBulletPrefab;
private GameObject _bulletPrefab;
private HVRGunType _gunType;
private LayerMask _hitLayerMask = ~0;
private HVRTriggerCollider _socketCollider = HVRTriggerCollider.Box;
private HVRTriggerCollider _stabilizerCollider = HVRTriggerCollider.Box;
private HVRTriggerCollider _cockingHandleCollider = HVRTriggerCollider.Capsule;
private float _ammoTimeout = 2f;
private float _gunMass = 1.5f;
private float _bulletSpeed = 80f;
private int _rpm = 900;
private GunFireType _firingType;
private HVRHandPose _gripPose;
private HVRHandPose _stabilizerPose;
private HVRHandPose _cockingHandlePose;
//mags
private bool _animateMagazine;
private bool _animateMagazineEject;
private bool _magazineHeld = true;
private bool _magazineHoverSwap = true;
//private SocketHoldType _magazineHoldType = SocketHoldType.RemoveRigidbody;
private bool _addMagGrab = true;
private float _magGrabDelay = .1f;
private bool _stabilizerGrabsGrip;
private bool _stabilizerRequiresGripGrabbed = true;
private bool _stabilizerDropsOnGripReleased = true;
private float _cycleTime = .05f;
private PDStrength _gripOneHand;
private PDStrength _gripTwoHand;
private PDStrength _stabilizerTwoHand;
private bool _ejectedBulletPooled = true;
private HVRRecoilSettings _recoilSettings;
private Vector2 _scrollPosition;
public AudioClip DryFireSFX;
public AudioClip FiredSFX;
public AudioClip CockedBackSFX;
public AudioClip CockedForwardSFX;
[MenuItem("Tools/HurricaneVR/Gun Creator")]
public static void ShowWindow()
{
_window = GetWindow<HVRGunCreator>(false);
_window.titleContent = new GUIContent("Gun Creator");
}
//#if CLOUDWALKER
//[Shortcut("Refresh Window", KeyCode.F9)]
public static void Refresh()
{
if (_window)
{
_window.Close();
}
ShowWindow();
}
//#endif
private void OnGUI()
{
_scrollPosition = GUILayout.BeginScrollView(_scrollPosition);
HVREditorExtensions.Header("Prefabs");
_gunPrefab = EditorGUILayout.ObjectField("Gun Prefab", _gunPrefab, typeof(GameObject), false) as GameObject;
_casingPrefab = EditorGUILayout.ObjectField("Casing Prefab", _casingPrefab, typeof(GameObject), false) as GameObject;
_ejectedBulletPrefab = EditorGUILayout.ObjectField("Ejected Bullet Prefab", _ejectedBulletPrefab, typeof(GameObject), false) as GameObject;
HVREditorExtensions.Toggle("Pooled Ejected Bullet", ref _ejectedBulletPooled);
_bulletPrefab = EditorGUILayout.ObjectField("Bullet Prefab", _bulletPrefab, typeof(GameObject), false) as GameObject;
GUILayout.Space(20f);
HVREditorExtensions.Header("Animation");
HVREditorExtensions.FloatField("Cycling Time", ref _cycleTime);
GUILayout.Space(20f);
HVREditorExtensions.Header("Gun Settings");
HVREditorExtensions.IntField("Rounds Per Minute", ref _rpm);
HVREditorExtensions.FloatField("Bullet Speed", ref _bulletSpeed);
_firingType = (GunFireType)EditorGUILayout.EnumPopup("Firing Mode", _firingType);
var currentType = _gunType;
_gunType = (HVRGunType)EditorGUILayout.EnumPopup("Type", _gunType);
_hitLayerMask = LayerMaskDrawer.LayerMaskField("Hit Layer Mask", _hitLayerMask);
_gunMass = EditorGUILayout.FloatField("Gun Mass", _gunMass);
_cockingHandleCollider = (HVRTriggerCollider)EditorGUILayout.EnumPopup("Cocking Handle Trigger", _cockingHandleCollider);
HVREditorExtensions.ObjectField("Recoil Settings", ref _recoilSettings, false);
GUILayout.Space(20f);
if (_gunType == HVRGunType.PumpShotgun)
{
HVREditorExtensions.Header("Pump Grabbable");
_stabilizerCollider = (HVRTriggerCollider)EditorGUILayout.EnumPopup("Pump Trigger", _stabilizerCollider);
HVREditorExtensions.Toggle("Grabs Grip On Release", ref _stabilizerGrabsGrip);
}
else
{
HVREditorExtensions.Header("Stabilizer Grabbable");
_stabilizerCollider = (HVRTriggerCollider)EditorGUILayout.EnumPopup("Stabilizer Trigger", _stabilizerCollider);
HVREditorExtensions.Toggle("Grabs Grip On Release", ref _stabilizerGrabsGrip);
HVREditorExtensions.Toggle("Requires Grip Grabbed", ref _stabilizerRequiresGripGrabbed);
HVREditorExtensions.Toggle("Drops On Grip Released", ref _stabilizerDropsOnGripReleased);
}
GUILayout.Space(10f);
HVREditorExtensions.Header("Ammo Socket Settings");
if (_gunType != HVRGunType.PumpShotgun)
{
HVREditorExtensions.Toggle("Releases On Hover", ref _magazineHoverSwap);
HVREditorExtensions.FloatField("Socket Grab Timeout", ref _ammoTimeout);
HVREditorExtensions.Toggle("Magazine Must Be Held", ref _magazineHeld);
HVREditorExtensions.Toggle("Animate Magazine", ref _animateMagazine);
HVREditorExtensions.Toggle("Animate Magazine Eject", ref _animateMagazineEject);
//HVREditorExtensions.EnumField("Hold Type", ref _magazineHoldType);
HVREditorExtensions.Toggle("Add Magazine Grab", ref _addMagGrab);
HVREditorExtensions.FloatField("Mag Grab Delay", ref _magGrabDelay);
}
_socketCollider = (HVRTriggerCollider)EditorGUILayout.EnumPopup("Ammo Socket Collider", _socketCollider);
GUILayout.Space(20f);
HVREditorExtensions.Header("Grabbable Hand Strength Settings");
//if (GUILayout.Button("Populate Defaults"))
//{
// PopulateDefaultHandSettings();
//}
HVREditorExtensions.StrengthField("Grip One Handed", ref _gripOneHand);
HVREditorExtensions.StrengthField("Grip Two Handed", ref _gripTwoHand);
HVREditorExtensions.StrengthField("Stabilizer Two Handed", ref _stabilizerTwoHand);
GUILayout.Space(20f);
HVREditorExtensions.Header("SFX");
HVREditorExtensions.ObjectField("Dry Fire", ref DryFireSFX, false);
HVREditorExtensions.ObjectField("Cocked Back", ref CockedBackSFX, false);
HVREditorExtensions.ObjectField("Cocked Forward", ref CockedForwardSFX, false);
HVREditorExtensions.ObjectField("Fired", ref FiredSFX, false);
GUILayout.Space(20f);
HVREditorExtensions.Header("Poses (If You have Already)");
_gripPose = EditorGUILayout.ObjectField("Gun Pose", _gripPose, typeof(HVRHandPose), false) as HVRHandPose;
if (_gunType == HVRGunType.PumpShotgun)
{
_stabilizerPose = EditorGUILayout.ObjectField("Pump Pose", _stabilizerPose, typeof(HVRHandPose), false) as HVRHandPose;
}
else
{
_stabilizerPose = EditorGUILayout.ObjectField("Stabilizer Pose", _stabilizerPose, typeof(HVRHandPose), false) as HVRHandPose;
_cockingHandlePose = EditorGUILayout.ObjectField("Cocking Handle Pose", _cockingHandlePose, typeof(HVRHandPose), false) as HVRHandPose;
}
GUI.enabled = _gunPrefab;
if (GUILayout.Button("Create"))
{
GameObject root = null;
switch (_gunType)
{
case HVRGunType.Pistol:
root = CreatePistol();
break;
case HVRGunType.AssaultRifle:
case HVRGunType.SMG:
root = CreateAutomatic();
break;
case HVRGunType.PumpShotgun:
root = CreatePumpShotgun();
break;
}
root.SetExpandedRecursive(true);
}
GUI.enabled = true;
if (currentType != _gunType)
{
OnGunTypeChanged();
}
//if (!_gripPose)
//{
// _gripPose = LoadAsset<HVRHandPose>("pistol_grip");
//}
//if (!_stabilizerPose)
//{
// _stabilizerPose = LoadAsset<HVRHandPose>("pistol_offhand");
//}
//if (!_cockingHandlePose)
//{
// _cockingHandlePose = LoadAsset<HVRHandPose>("pistol_slide");
//}
//SetDefault(ref _bulletPrefab, "HVR_bullet_trail");
//SetDefault(ref _casingPrefab, "HVR_bullet_casing");
//SetDefault(ref _ejectedBulletPrefab, "HVR_smg_bullet");
//SetDefault(ref _gunPrefab, "HVR_smg");
PopulateDefaultStabilizerSettings(true);
if (_recoilSettings == null)
{
SetDefaultRecoil();
}
GUILayout.EndScrollView();
}
private void OnGunTypeChanged()
{
SetDefaultRecoil();
//PopulateDefaultHandSettings();
PopulateDefaultStabilizerSettings(false);
}
private void SetDefaultRecoil()
{
string recoil;
switch (_gunType)
{
case HVRGunType.Pistol:
recoil = RecoilPistol;
break;
case HVRGunType.AssaultRifle:
recoil = RecoilAR;
break;
case HVRGunType.SMG:
recoil = RecoilSMG;
break;
case HVRGunType.PumpShotgun:
recoil = RecoilPump;
break;
default:
return;
}
TryLoadAsset(ref _recoilSettings, recoil);
}
private void PopulateDefaultStabilizerSettings(bool onlyIfNull)
{
var foregrip = TwoHandLargeStabilizer;
switch (_gunType)
{
case HVRGunType.Pistol:
foregrip = TwoHandPistolStabilizer;
break;
case HVRGunType.SMG:
foregrip = TwoHandLargeStabilizer;
break;
case HVRGunType.PumpShotgun:
case HVRGunType.AssaultRifle:
foregrip = TwoHandLargeStabilizer;
break;
}
if (onlyIfNull)
{
SetDefault(ref _stabilizerTwoHand, foregrip);
}
else
{
TryLoadAsset(ref _stabilizerTwoHand, foregrip);
}
}
//private void PopulateDefaultHandSettings()
//{
// var grip = OneHandDefault;
// var gripTwoHand = TwoHandLarge;
// switch (_gunType)
// {
// case HVRGunType.Pistol:
// grip = OneHandPistol;
// gripTwoHand = TwoHandPistol;
// break;
// case HVRGunType.SMG:
// gripTwoHand = TwoHandLarge;
// break;
// case HVRGunType.PumpShotgun:
// case HVRGunType.AssaultRifle:
// gripTwoHand = TwoHandLarge;
// break;
// }
// TryLoadAsset(ref _gripOneHand, grip);
// TryLoadAsset(ref _gripTwoHand, gripTwoHand);
//}
private void SetDefault<T>(ref T value, string assetName) where T : Object
{
if (!value && !string.IsNullOrWhiteSpace(assetName))
{
value = Resources.Load<T>(assetName);
}
}
private void TryLoadAsset<T>(ref T value, string assetName) where T : Object
{
if (!string.IsNullOrWhiteSpace(assetName))
{
value = Resources.Load<T>(assetName);
}
}
private GameObject CreateGun<T>(out HVRGrabbable gunGrabbable, out GameObject model, out HVRGunBase gun) where T : HVRGunBase
{
var root = new GameObject(_gunPrefab.name);
Undo.RegisterCreatedObjectUndo(root, _gunPrefab.name);
gunGrabbable = AddGrabbable(root, out var poser, out var gp);
gunGrabbable.OneHandStrength = _gripOneHand;
gunGrabbable.TwoHandStrength = _gripTwoHand;
poser.PrimaryPose.Pose = _gripPose;
gunGrabbable.HoldType = HVRHoldType.Swap;
gunGrabbable.RequireOverlapClearance = true;
gunGrabbable.OverlapTimeout = 2f;
gunGrabbable.LinkedGrabbables = new List<HVRGrabbable>();
//after grabpoints
model = Instantiate(_gunPrefab, Vector3.zero, Quaternion.identity, root.transform) as GameObject;
model.name = model.name.Replace("(Clone)", "");
gun = root.AddComponent<T>();
SetupCommonObjects(gun, model, gunGrabbable);
return root;
}
private GameObject CreatePistol()
{
var root = CreateGun<HVRPistol>(out var gunGrabbable, out var model, out var gun);
return root;
}
private GameObject CreateAutomatic()
{
var root = CreateGun<HVRAutomaticGun>(out var gunGrabbable, out var model, out var gun);
return root;
}
private GameObject CreatePumpShotgun()
{
var root = CreateGun<HVRShotgun>(out var gunGrabbable, out var model, out var gun);
var mag = root.AddComponent<HVRShotgunMagazine>();
gun.ChambersAfterFiring = false;
mag.MaxCount = 5;
mag.StartingCount = 3;
mag.DestroyIfEmpty = false;
gun.AnimateGun = false;
gun.EjectCasingAfterFiring = false;
gun.BoltPushedBackAfterEmpty = false;
var socket = root.GetComponentInChildren<HVRShotgunAmmoSocket>();
if (socket)
{
socket.ShotgunMagazine = mag;
}
return root;
}
private static T LoadAsset<T>(string name) where T : Object
{
var fuzzyMatchesUnityBadSearch = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
foreach (var fuzzyMatch in fuzzyMatchesUnityBadSearch)
{
var path = AssetDatabase.GUIDToAssetPath(fuzzyMatch);
if (path.ToLower().Contains(name.ToLower()))
{
var asset = AssetDatabase.LoadAssetAtPath<T>(path);
return asset;
}
}
return null;
}
private HVRGrabbable SetupStabilizer(HVRGunBase hvrGunBase, Transform parent, HVRGrabbable gunGrabbable)
{
var offhand = new GameObject("StabilizerGrabbable");
offhand.transform.parent = parent;
offhand.transform.ResetLocalProps();
var grabbable = AddGrabbable(offhand, out var poser, out var gp);
poser.PrimaryPose.Pose = _stabilizerPose;
//grabbable.TrackingType = HVRGrabTracking.None;
grabbable.HoldType = HVRHoldType.OneHand;
grabbable.DisableHandCollision = true;
grabbable.ForceGrabbable = false;
grabbable.TwoHandStrength = _stabilizerTwoHand;
grabbable.ExtraIgnoreCollisionParents = new List<Transform>() { gunGrabbable.Rigidbody.transform };
if (_stabilizerRequiresGripGrabbed)
{
var require = offhand.AddComponent<HVRRequireOtherGrabbable>();
require.Grabbable = gunGrabbable;
require.DropIfReleased = _stabilizerDropsOnGripReleased;
require.GrabRequiredIfReleased = _stabilizerGrabsGrip;
}
hvrGunBase.StabilizerGrabbable = grabbable;
var gunRB = hvrGunBase.GetRigidbody();
grabbable.Rigidbody = gunRB;
grabbable.MasterGrabbable = gunGrabbable;
gunGrabbable.LinkedGrabbables.Add(grabbable);
AddTriggerCollider(_stabilizerCollider, offhand);
var handStrength = offhand.AddComponent<HVRTwoHandStrength>();
handStrength.Others = new HVRGrabbable[1];
handStrength.Others[0] = gunGrabbable;
return grabbable;
}
private void SetupCommonObjects(HVRGunBase gun, GameObject model, HVRGrabbable gunGrabbable)
{
var rb = gun.gameObject.AddComponent<Rigidbody>();
rb.mass = _gunMass;
gunGrabbable.Rigidbody = rb;
FindObject<HVRChamberedCasingFinder>(model, ref gun.ChamberedCasing);
FindObject<HVRChamberedRoundFinder>(model, ref gun.ChamberedRound);
var bolt = FindBolt(model);
gun.TriggerAnimator = FindTriggerAnimator(model);
gun.RecoilComponent = gun.gameObject.AddComponent<HVRRecoil>();
gun.RecoilComponent.Settings = _recoilSettings;
gun.GunSounds = gun.gameObject.AddComponent<HVRGunSounds>();
gun.GunSounds.Fired = FiredSFX;
gun.GunSounds.OutOfAmmo = DryFireSFX;
gun.GunSounds.SlideBack = CockedBackSFX;
gun.GunSounds.SlideForward = CockedForwardSFX;
gun.Bolt = bolt;
var adjustTransforms = AddAdjustTransform(gun.gameObject);
if (_gunType != HVRGunType.PumpShotgun)
{
SetupStabilizer(gun, adjustTransforms.transform, gunGrabbable);
}
var emitters = new GameObject("Emitters (Right Vector)");
emitters.transform.parent = adjustTransforms.transform;
emitters.transform.ResetLocalProps();
SetupCockingHandle(gunGrabbable, model, gun, bolt, adjustTransforms);
AddRecoilTransforms(adjustTransforms, gun.RecoilComponent);
AddCasingEmitter(emitters, _casingPrefab, gun);
AddBulletEmitter(emitters, _ejectedBulletPrefab, gun);
AddBulletOrigin(adjustTransforms, gun);
AddAmmoSocket(gunGrabbable, adjustTransforms, gun, model);
gun.BulletPrefab = _bulletPrefab;
gun.FireType = _firingType;
gun.HitLayerMask = _hitLayerMask;
gun.BulletSpeed = _bulletSpeed;
gun.CyclingTime = _cycleTime;
gun.Cooldown = 1f / (_rpm / 60f);
Selection.activeGameObject = adjustTransforms;
}
private void AddRecoilTransforms(GameObject adjustTransforms, HVRRecoil gunRecoilComponent)
{
var up = new GameObject("UpRecoil (Up Vector)");
up.transform.parent = adjustTransforms.transform;
var back = new GameObject("BackwardRecoil (Forward Vector)");
back.transform.parent = adjustTransforms.transform;
up.transform.ResetLocalProps();
back.transform.ResetLocalProps();
back.transform.localRotation = Quaternion.Euler(180f, 0f, 0f);
gunRecoilComponent.UpRecoil = up.transform;
gunRecoilComponent.BackRecoil = back.transform;
}
private HVRGunBolt FindBolt(GameObject model)
{
var component = model.GetComponentInChildren<HVRGunBolt>();
if (!component)
{
Debug.Log($"HVRGunBolt not located.");
return null;
}
return component;
}
private void FindObject<T>(GameObject model, ref GameObject field) where T : MonoBehaviour
{
var component = model.GetComponentInChildren<T>(true);
if (!component)
{
Debug.Log($"{typeof(T).Name} not found.");
return;
}
field = component.gameObject;
}
private HVRTriggerAnimator FindTriggerAnimator(GameObject model)
{
var triggerAnimator = model.GetComponentInChildren<HVRTriggerAnimator>();
if (!triggerAnimator)
{
Debug.Log($"HVRTriggerAnimator not located.");
return null;
}
return triggerAnimator;
}
private void SetupCockingHandle(HVRGrabbable gripGrabbable, GameObject model, HVRGunBase gun, HVRGunBolt hvrGunBolt, GameObject adjustTransforms)
{
var cockingHandle = model.GetComponentInChildren<HVRCockingHandle>();
if (!cockingHandle)
{
Debug.Log($"HVRCockingHandle not located.");
return;
}
cockingHandle.Bolt = hvrGunBolt;
gun.CockingHandle = cockingHandle;
var handleGO = cockingHandle.gameObject;
AddGrabPoints(handleGO, out var poser, out var grabPoint);
if (_gunType == HVRGunType.PumpShotgun)
{
var stabilizer = SetupStabilizer(gun, adjustTransforms.transform, gripGrabbable);
stabilizer.gameObject.name = "PumpGrabbable";
var go = stabilizer.gameObject;
var gp = stabilizer.GetComponentInChildren<HVRPosableGrabPoint>();
var poser2 = stabilizer.GetComponentInChildren<HVRHandPoser>();
Destroy(grabPoint.GetComponent<HVRHandPoser>());
Destroy(grabPoint.GetComponent<HVRPosableGrabPoint>());
gp.VisualGrabPoint = grabPoint.transform;
poser2.PrimaryPose.Pose = _stabilizerPose;
cockingHandle.Grabbable = stabilizer;
}
else
{
var grabbableObject = handleGO;
poser.PrimaryPose.Pose = _cockingHandlePose;
var handleGrabbable = grabbableObject.AddComponent<HVRGrabbable>();
handleGrabbable.TrackingType = HVRGrabTracking.None;
handleGrabbable.HoldType = HVRHoldType.OneHand;
handleGrabbable.PoseImmediately = true;
handleGrabbable.DisableHandCollision = true;
handleGrabbable.Stationary = true;
handleGrabbable.ForceGrabbable = false;
AddTriggerCollider(_cockingHandleCollider, handleGO);
var require = grabbableObject.AddComponent<HVRRequireOtherGrabbable>();
require.Grabbable = gripGrabbable;
require.DropIfReleased = true;
require.GrabRequiredIfReleased = true;
}
}
internal GameObject AddAmmoSocket(HVRGrabbable gunGrabbable, GameObject parent, HVRGunBase gun, GameObject model)
{
var go = new GameObject("AmmoSocket");
go.transform.parent = gun.gameObject.transform;
go.transform.ResetLocalProps();
var bagGo = new GameObject("AmmoSocketTrigger");
bagGo.transform.parent = parent.transform;
bagGo.transform.ResetLocalProps();
var bag = bagGo.AddComponent<HVRTriggerGrabbableBag>();
AddTriggerCollider(_socketCollider, bagGo);
HVRSocket socket;
if (_gunType == HVRGunType.PumpShotgun)
{
socket = go.AddComponent<HVRShotgunAmmoSocket>();
socket.GrabsFromHand = true;
socket.GrabbableMustBeHeld = true;
socket.CanRemoveGrabbable = false;
socket.HoldType = SocketHoldType.Kinematic;
}
else
{
var magazine = model.GetComponentInChildren<HVRMagazineFinder>();
var magSocket = go.AddComponent<HVRMagazineSocket>();
magSocket.Animate = _animateMagazine;
magSocket.AnimateEject = _animateMagazineEject;
var magGO = new GameObject("AnimationDirection (Forward Axis)");
magGO.transform.parent = magSocket.gameObject.transform;
magGO.transform.ResetLocalProps();
magSocket.MagazineAxis = magGO.transform;
socket = magSocket;
socket.GrabsFromHand = true;
socket.GrabbableMustBeHeld = _magazineHeld;
socket.ScaleGrabbable = false;
socket.CanRemoveGrabbable = false;
socket.GrabTimeout = _ammoTimeout;
socket.HoldType = SocketHoldType.Kinematic;
if (_magazineHoverSwap)
{
var magRelease = new GameObject("MagazineHoverEject");
magRelease.transform.parent = parent.transform;
var autoDrop = magRelease.AddComponent<HVRAutoDropMagazine>();
autoDrop.MagazineSocket = socket;
var collider = magRelease.AddComponent<BoxCollider>();
collider.size = new Vector3(.07f, .08f, .07f);
collider.isTrigger = true;
}
if (_addMagGrab)
{
var magGrab = new GameObject("MagazineGrabbable");
var g = magGrab.AddComponent<HVRGrabbable>();
g.ForceGrabbable = false;
g.PhysicsPoserFallback = false;
var grabMag = magGrab.AddComponent<HVRGrabMagazine>();
grabMag.GrabDelay = _magGrabDelay;
grabMag.MagSocket = socket;
var collider = magGrab.AddComponent<BoxCollider>();
collider.size = new Vector3(.05f, .08f, .07f);
collider.isTrigger = true;
magGrab.transform.parent = parent.transform;
magGrab.transform.ResetLocalProps();
var require = magGrab.AddComponent<HVRRequireOtherGrabbable>();
require.Grabbable = gunGrabbable;
require.DropIfReleased = false;
require.GrabRequiredIfReleased = false;
}
if (magazine)
{
go.transform.localPosition = magazine.transform.localPosition;
go.transform.localRotation = magazine.transform.localRotation;
}
gun.AmmoSocket = socket;
}
socket.GrabBags = new List<HVRGrabbableBag>() { bag };
return go;
}
private static void AddTriggerCollider(HVRTriggerCollider colliderType, GameObject go)
{
Collider collider = null;
switch (colliderType)
{
case HVRTriggerCollider.Box:
var box = go.AddComponent<BoxCollider>();
box.size = new Vector3(.08f, .08f, .08f);
collider = box;
break;
case HVRTriggerCollider.Sphere:
var sphere = go.AddComponent<SphereCollider>();
sphere.radius = .06f;
collider = sphere;
break;
case HVRTriggerCollider.Capsule:
var capsule = go.AddComponent<CapsuleCollider>();
capsule.height = .1f;
capsule.radius = .02f;
capsule.direction = 2;
collider = capsule;
break;
}
if (collider != null)
{
collider.isTrigger = true;
}
}
internal static GameObject AddAdjustTransform(GameObject parent)
{
var go = new GameObject("Position These Objects");
go.transform.parent = parent.transform;
go.transform.ResetLocalProps();
return go;
}
internal static void AddBulletOrigin(GameObject parent, HVRGunBase hvrGunBase)
{
var go = new GameObject("BulletOrigin (Forward Vector)");
go.transform.parent = parent.transform;
go.transform.ResetLocalProps();
hvrGunBase.BulletOrigin = go.transform;
}
internal void AddBulletEmitter(GameObject parent, GameObject prefab, HVRGunBase gun)
{
var go = new GameObject("BulletEmitter (Right Vector)");
HVRGunEmitterBase emitter;
if (_ejectedBulletPooled)
{
emitter = go.AddComponent<HVRPooledEmitter>();
}
else
{
emitter = go.AddComponent<HVRBulletEmitter>();
}
emitter.Prefab = prefab;
go.transform.parent = parent.transform;
go.transform.ResetLocalProps();
gun.BulletEmitter = emitter;
}
internal static void AddCasingEmitter(GameObject parent, GameObject prefab, HVRGunBase gun)
{
var go = new GameObject("CasingEmitter (Right Vector)");
var emitter = go.AddComponent<HVRPooledEmitter>();
emitter.Prefab = prefab;
go.transform.parent = parent.transform;
go.transform.ResetLocalProps();
gun.CasingEmitter = emitter;
}
internal static HVRGrabbable AddGrabbable(GameObject obj, out HVRHandPoser poser, out HVRPosableGrabPoint grabPoint)
{
var grabbable = obj.AddComponent<HVRGrabbable>();
AddGrabPoints(obj, out poser, out grabPoint);
obj.SetExpandedRecursive(true);
return grabbable;
}
internal static GameObject AddGrabPoint(GameObject obj, out HVRHandPoser poser, out HVRPosableGrabPoint grabPoint)
{
var go = new GameObject("GrabPoint");
go.transform.parent = obj.transform;
go.transform.ResetLocalProps();
poser = go.AddComponent<HVRHandPoser>();
poser.PrimaryPose = new HVRHandPoseBlend();
grabPoint = go.AddComponent<HVRPosableGrabPoint>();
grabPoint.HandPoser = poser;
return go;
}
internal static GameObject AddGrabPoints(GameObject obj, out HVRHandPoser poser, out HVRPosableGrabPoint grabPoint)
{
var points = new GameObject("GrabPoints");
points.AddComponent<HVRGrabPoints>();
points.transform.parent = obj.transform;
points.transform.ResetLocalProps();
obj.SetExpandedRecursive(true);
AddGrabPoint(points, out poser, out grabPoint);
return points;
}
}
public enum HVRTriggerCollider
{
Box, Sphere, Capsule, AddMyself
}
public enum HVRGunType
{
Pistol, AssaultRifle, SMG, PumpShotgun
}
}

View File

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

View File

@@ -0,0 +1,55 @@
using HurricaneVR.Framework.Weapons;
using HurricaneVR.Framework.Weapons.Guns;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRGunPart), true)]
public class HVRGunPartEditor : UnityEditor.Editor
{
private SerializedProperty ForwardPosition;
private SerializedProperty BackwardPosition;
public HVRGunPart component;
protected void OnEnable()
{
ForwardPosition = serializedObject.FindProperty("ForwardPosition");
BackwardPosition = serializedObject.FindProperty("BackwardPosition");
component = target as HVRGunPart;
}
public override void OnInspectorGUI()
{
DrawButtons("Forward", ForwardPosition);
DrawButtons("Backward", BackwardPosition);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
private void DrawButtons(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.vector3Value = component.transform.localPosition;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localPosition = property.vector3Value;
}
GUILayout.EndHorizontal();
}
}
}

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,885 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using HurricaneVR.Editor;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core.HandPoser;
using HurricaneVR.Framework.Core.Player;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace HurricaneVR
{
public class HVRHandSetup : EditorWindow
{
public Transform Left;
public Transform Right;
public Transform RigRoot;
public Transform LeftFingerParent;
public Transform RightFingerParent;
public List<FingerSetting> settings = new List<FingerSetting>();
[MenuItem("Tools/HurricaneVR/Custom Hand Model Helper")]
public static void ShowWindow()
{
var wnd = GetWindow<HVRHandSetup>();
wnd.titleContent = new GUIContent("Hand Setup");
}
private void OnEnable()
{
_mirrorText = Mirroring ? "Stop Mirroring" : "Start Mirroring";
SceneView.duringSceneGui += OnSceneGui;
settings.Add(new FingerSetting() { BoneCount = 3, Finger = Finger.Index, Index = 0 });
settings.Add(new FingerSetting() { BoneCount = 3, Finger = Finger.Middle, Index = 1 });
settings.Add(new FingerSetting() { BoneCount = 3, Finger = Finger.Pinky, Index = 2 });
settings.Add(new FingerSetting() { BoneCount = 3, Finger = Finger.Ring, Index = 3 });
settings.Add(new FingerSetting() { BoneCount = 3, Finger = Finger.Thumb, Index = 4 });
}
private void OnDisable()
{
UnsubSceneGui();
}
private bool _mirroring => Mirroring;
private string _mirrorText = "Mirror";
private GUIStyle helpBoxStyle;
public bool HandsSetup;
public bool MirrorDetected;
public bool RigSetup;
public bool PosesAssigned;
public bool ColliderSetup;
public bool Mirroring;
public HVRPosableHand RightHand;
public HVRPosableHand LeftHand;
public HVRPhysicsPoser LeftPhysics;
public HVRPhysicsPoser RightPhysics;
public HVRHandPoser LeftPoser;
public HVRHandPoser RightPoser;
public HVRHandPose OpenPose;
public HVRHandPose ClosedPose;
public HVRHandPose RelaxedPose;
private Vector2 scroll;
public void OnGUI()
{
scroll = EditorGUILayout.BeginScrollView(scroll);
try
{
if (helpBoxStyle == null)
{
helpBoxStyle = GUI.skin.GetStyle("HelpBox");
helpBoxStyle = new GUIStyle(helpBoxStyle);
helpBoxStyle.fontSize = 13;
}
var currLeft = Left;
var currRight = Right;
EditorGUILayout.TextArea("1. Create an empty game object and place the hand model's as children of the new object. Make the palms face each other with the finger's facing along the forward (blue) vector of the parent empty.\r\n\r\n" +
"2. Assign the roots of each hand model.\r\n\r\n" +
"3. Assign the root of the XR Rig the hand's will be used with.", helpBoxStyle);
EditorGUILayout.Space();
HVREditorExtensions.ObjectField("Left Hand Model", ref Left);
HVREditorExtensions.ObjectField("Right Hand Model", ref Right);
HVREditorExtensions.ObjectField("XR Rig Root", ref RigRoot);
if ((!Left || (currLeft && currLeft != Left)) ||
(!Right || (currRight && currRight != Right)))
{
RightHand = LeftHand = null;
LeftPoser = RightPoser = null;
LeftPhysics = RightPhysics = null;
HandsSetup = MirrorDetected = RigSetup = PosesAssigned = false;
}
if (!Left || !Right)
return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Progress Tracking", EditorStyles.boldLabel);
HVREditorExtensions.Toggle("Hand Setup", ref HandsSetup);
HVREditorExtensions.Toggle("Mirror Detected", ref MirrorDetected);
HVREditorExtensions.Toggle("Rig Setup", ref RigSetup);
HVREditorExtensions.Toggle("Poses Assigned", ref PosesAssigned);
//HVREditorExtensions.Toggle("Collider Setup", ref ColliderSetup);
Mirror();
if (!LeftHand && Left) LeftHand = Left.transform.GetComponentsInChildren<HVRPosableHand>().FirstOrDefault(e => e.IsLeft);
if (!RightHand && Right) RightHand = Right.transform.GetComponentsInChildren<HVRPosableHand>().FirstOrDefault(e => !e.IsLeft);
if (!HandsSetup) HandSetup();
if (!MirrorDetected) DetectMirror();
if (!RigSetup) SetupRig();
if (!PosesAssigned) PoseValidation();
FinalSetup();
}
finally
{
EditorGUILayout.EndScrollView();
}
}
private void PoseValidation()
{
if (!LeftHand || !RightHand || !RigSetup || !RigRoot) return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Pose Setup", EditorStyles.boldLabel);
if (!LeftPhysics) LeftHand.TryGetComponent(out LeftPhysics);
if (!RightPhysics) RightHand.TryGetComponent(out RightPhysics);
if (!LeftPoser) LeftHand.TryGetComponent(out LeftPoser);
if (!RightPoser) RightHand.TryGetComponent(out RightPoser);
var error = new StringBuilder();
if (!LeftPhysics) error.AppendLine("Left HVRPhysicsPoser missing.");
else
{
if (LeftPhysics.OpenPose == null) error.AppendLine("Left HVRPhysicsPoser missing OpenPose.");
if (LeftPhysics.ClosedPose == null) error.AppendLine("Left HVRPhysicsPoser missing ClosedPose.");
}
if (!RightPhysics) error.AppendLine("Right HVRPhysicsPoser missing.");
else
{
if (RightPhysics.OpenPose == null) error.AppendLine("Right HVRPhysicsPoser missing OpenPose.");
if (RightPhysics.ClosedPose == null) error.AppendLine("Right HVRPhysicsPoser missing ClosedPose.");
}
if (!LeftPoser) error.AppendLine("Left HVRHandPoser missing.");
else
{
if (LeftPoser.PrimaryPose.Pose == null) error.AppendLine("Left HVRHandPoser Primary Pose not assigned.");
}
if (!RightPoser) error.AppendLine("Right HVRHandPoser missing.");
else if (RightPoser.PrimaryPose.Pose == null) error.AppendLine("Right HVRHandPoser Primary Pose not assigned.");
EditorGUILayout.TextArea("1. Pressing Auto Setup will auto create prefabs of your hands in the root Assets Folder and automate Step 2 for you. Either do this by manually or let the automation do it for you.\r\n\r\n" +
"2. Locate HVRSettings in your project folder:\r\n" +
" - Assign the newly created hand prefabs to the 'Left Hand' and 'Right Hand' fields.\r\n" +
" - Toggle off 'Inverse Kinematics' if it's enabled.\r\n" +
" - Clear out the 'Open Hand Pose' field.\r\n\r\n" +
"3. Press Create Hand Poser and begin creating the required poses.\r\n" +
" - RelaxedPose: for when your hands are not holding something.\r\n" +
" - ClosedPose: for the physics poser, and for the resting pose to blend into using finger curl information.\r\n" +
" - OpenPose: a flat 'Open Hand Pose' pose for the physics poser.\r\n\r\n" +
"4. Assign the poses below and press 'Setup Poses'", helpBoxStyle);
RelaxedPose = EditorGUILayout.ObjectField("Relaxed Pose:", RelaxedPose, typeof(HVRHandPose), true) as HVRHandPose;
OpenPose = EditorGUILayout.ObjectField("Open Pose:", OpenPose, typeof(HVRHandPose), true) as HVRHandPose;
ClosedPose = EditorGUILayout.ObjectField("Closed Pose:", ClosedPose, typeof(HVRHandPose), true) as HVRHandPose;
if (GUILayout.Button("Auto Setup Prefab / HVRSettings"))
{
Left.localPosition = Vector3.zero;
Right.localPosition = Vector3.zero;
var leftPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(Left.gameObject, $"Assets/{Left.name}.prefab", InteractionMode.UserAction);
var rightPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(Right.gameObject, $"Assets/{Right.name}.prefab", InteractionMode.UserAction);
var so = new SerializedObject(HVRSettings.Instance);
var left = so.FindProperty("LeftHand");
var right = so.FindProperty("RightHand");
so.FindProperty("OpenHandPose").objectReferenceValue = null;
so.FindProperty("InverseKinematics").boolValue = false;
left.objectReferenceValue = leftPrefab;
right.objectReferenceValue = rightPrefab;
so.ApplyModifiedProperties();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
if (GUILayout.Button("Create Hand Poser"))
{
var poser = GameObject.Find("PoserSetup");
if (!poser) poser = new GameObject("PoserSetup");
var p = poser.UndoEnsureComponent<HVRHandPoser>();
poser.transform.position += Vector3.up * 1.7f;
Selection.activeGameObject = poser;
}
if (GUILayout.Button("Setup Poses"))
{
SetupPhysicsPoserPoses(LeftPhysics);
SetupPhysicsPoserPoses(RightPhysics);
SetupHandPoser(LeftPoser);
SetupHandPoser(RightPoser);
var leftHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Left);
var rightHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Right);
SetupFallback(leftHand);
SetupFallback(rightHand);
PosesAssigned = true;
EditorApplication.delayCall += () =>
{
var leftPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(LeftPhysics.gameObject);
var rightPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(RightPhysics.gameObject);
Debug.Log($"Applying pose overrides to {leftPath} and {rightPath}.");
PrefabUtility.ApplyObjectOverride(LeftPhysics, leftPath, InteractionMode.AutomatedAction);
PrefabUtility.ApplyObjectOverride(RightPhysics, rightPath, InteractionMode.AutomatedAction);
PrefabUtility.ApplyObjectOverride(LeftPoser, leftPath, InteractionMode.AutomatedAction);
PrefabUtility.ApplyObjectOverride(RightPoser, rightPath, InteractionMode.AutomatedAction);
//if (leftHand.FallbackPoser)
//{
// var so = new SerializedObject(leftHand.FallbackPoser);
// var blend = so.FindProperty("PrimaryPose");
// var pose = blend.FindPropertyRelative("Pose");
// PrefabUtility.ApplyPropertyOverride(pose, leftPath, InteractionMode.AutomatedAction);
//}
//if (rightHand.FallbackPoser)
//{
// var so = new SerializedObject(rightHand.FallbackPoser);
// var blend = so.FindProperty("PrimaryPose");
// var pose = blend.FindPropertyRelative("Pose");
// PrefabUtility.ApplyPropertyOverride(pose, rightPath, InteractionMode.AutomatedAction);
//}
};
}
if (error.Length > 0)
{
EditorGUILayout.HelpBox(error.ToString(), MessageType.Error);
}
}
private void SetupFallback(HVRHandGrabber hand)
{
if (hand && hand.FallbackPoser)
{
var so = new SerializedObject(hand.FallbackPoser);
var blend = so.FindProperty("PrimaryPose");
var pose = blend.FindPropertyRelative("Pose");
pose.objectReferenceValue = ClosedPose;
so.ApplyModifiedProperties();
EditorUtility.SetDirty(hand);
}
}
private void SetupHandPoser(HVRHandPoser poser)
{
var so = new SerializedObject(poser);
var blend = so.FindProperty("PrimaryPose");
var pose = blend.FindPropertyRelative("Pose");
pose.objectReferenceValue = RelaxedPose;
so.ApplyModifiedProperties();
var SP_Blends = so.FindProperty("Blends");
var i = SP_Blends.arraySize;
if (i == 0) SP_Blends.InsertArrayElementAtIndex(i);
i = 0;
var test = SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("Pose");
test.objectReferenceValue = ClosedPose;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("AnimationParameter").stringValue = HVRHandPoseBlend.DefaultParameter;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("Weight").floatValue = 1f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("Speed").floatValue = 16f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("Mask").enumValueIndex = (int)HVRHandPoseMask.None;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("Type").enumValueIndex = (int)BlendType.Immediate;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("ThumbType").enumValueIndex = (int)HVRFingerType.Close;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("IndexType").enumValueIndex = (int)HVRFingerType.Close;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("MiddleType").enumValueIndex = (int)HVRFingerType.Close;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("RingType").enumValueIndex = (int)HVRFingerType.Close;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("PinkyType").enumValueIndex = (int)HVRFingerType.Close;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("ThumbStart").floatValue = 0f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("IndexStart").floatValue = 0f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("MiddleStart").floatValue = 0f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("RingStart").floatValue = 0f;
SP_Blends.GetArrayElementAtIndex(i).FindPropertyRelative("PinkyStart").floatValue = 0f;
so.ApplyModifiedProperties();
}
private void SetupPhysicsPoserPoses(HVRPhysicsPoser pp)
{
var so = new SerializedObject(pp);
var open = so.FindProperty("OpenPose");
var closed = so.FindProperty("ClosedPose");
open.objectReferenceValue = OpenPose;
closed.objectReferenceValue = ClosedPose;
so.ApplyModifiedProperties();
}
private void FinalSetup()
{
if (!LeftHand || !RightHand || !RigRoot || !RigSetup || !PosesAssigned) return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Final Setup", EditorStyles.boldLabel);
EditorGUILayout.TextArea("Orient the new hands to match the existing hand model or orient in play mode and copy and paste the transform component out into editor mode." +
"\r\n\r\nLocate 'JointAnchor' on each physics hand and move it to the center of the palm" +
"\r\n\r\nAt this point you should add colliders to your hands, if you want per bone capsules, you can use the helper buttons on the HVRPosableHand component inspectors. " +
"\r\n\r\nIf you're ok with a primitive box shape, you can press 'Add Collider Controller' which will add a component to the root that will dynamically manage the hand collider. " +
"\r\n\r\nA Box collider will be added to the hand rigidbody relative to the hand model, make sure you're happy with the hand orientation first.\r\n" +
"\r\nYou can always adjust the box collider shape and rotation manually after it's created.\r\n" +
"\r\nAssign an animation curve on the collider controller, which will be used in conjunction with finger curl information to shrink the box to fit a fist pose. The default exponential curve provided by unity seems to work fine.\r\n",
helpBoxStyle);
if (GUILayout.Button("Add Collider Controller"))
{
var cc = RigRoot.EnsureComponent<HVRHandColliderController>();
cc.LeftPosableHand = LeftHand;
cc.RightPosableHand = RightHand;
var leftHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Left);
var rightHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Right);
if (leftHand)
cc.LeftParent = Add(leftHand.transform, "Colliders");
if (rightHand)
cc.RightParent = Add(rightHand.transform, "Colliders");
cc.AddHandBoxesF();
ColliderSetup = true;
}
}
private void SetupRig()
{
if (!LeftHand || !RightHand || !HandsSetup || !RigRoot) return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Rig Setup", EditorStyles.boldLabel);
EditorGUILayout.TextArea("Press 'Setup Rig References', this will update required component references for you.\r\n"
, helpBoxStyle);
if (GUILayout.Button("Setup Rig References"))
{
SetupRigRefs();
RigSetup = true;
}
}
private GameObject _clone;
private void Mirror()
{
if (!LeftHand || !RightHand || !HandsSetup || !MirrorDetected || RigSetup) return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mirror Testing", EditorStyles.boldLabel);
if (LeftHand.transform.parent != RightHand.transform.parent)
{
EditorGUILayout.HelpBox("To test mirroring, both hands must be the child of the same empty game object.", MessageType.Warning);
return;
}
if (GUILayout.Button(_mirrorText))
{
if (!Mirroring)
{
var clone = Object.Instantiate(LeftHand.transform.parent);
clone.transform.parent = null;
clone.transform.position += Vector3.right * .5f;
_leftMirrorHand = clone.GetComponentsInChildren<HVRPosableHand>().FirstOrDefault(e => e.IsLeft);
_rightMirrorHand = clone.GetComponentsInChildren<HVRPosableHand>().FirstOrDefault(e => !e.IsLeft);
_clone = clone.gameObject;
Selection.activeGameObject = _rightMirrorHand.gameObject;
_rightMirrorHand.gameObject.SetExpandedRecursive(true);
}
else
{
if (_clone)
{
DestroyImmediate(_clone);
_leftMirrorHand = null;
_rightMirrorHand = null;
}
}
Mirroring = !Mirroring;
_mirrorText = Mirroring ? "Stop Mirroring" : "Start Mirroring";
}
}
private void UnsubSceneGui()
{
SceneView.duringSceneGui -= OnSceneGui;
}
private bool _badMirror;
private string _badMirrorText;
private void DetectMirror()
{
if (!LeftHand || !RightHand || !HandsSetup) return;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Mirror Detect", EditorStyles.boldLabel);
EditorGUILayout.TextArea("Orient the hands into a mirrored pose with the fingers facing along the " +
"forward (blue) axis of the parent object and the palms facing each other.\r\n\r\n" +
"The thumb bones may need to be bent a bit to align it's forward vector with the parent's forward vector if the detection fails.\r\n\r\n" +
"Once Done Press Detect Mirror", helpBoxStyle);
if (GUILayout.Button("Detect Mirror"))
{
DetectBoneAxes(LeftHand, RightHand, LeftHand.transform.parent.forward, LeftHand.transform.parent.up);
DetectBoneAxes(RightHand, LeftHand, LeftHand.transform.parent.forward, LeftHand.transform.parent.up);
_badMirrorText = "";
_badMirror = false;
ValidateMirrorSettings(LeftHand);
ValidateMirrorSettings(RightHand);
EditorUtility.SetDirty(LeftHand);
EditorUtility.SetDirty(RightHand);
MirrorDetected = !_badMirror;
}
if (_badMirror)
{
EditorGUILayout.TextArea($"Unable to detect all forward and up axes of the bones.\r\n\r\n" +
$"Bend the offending fingers so that each bone's forward and up axes align more closely with the parent object's forward and up axes.\r\n\r\n" +
$"{_badMirrorText}", helpBoxStyle);
}
}
public void DetectBoneAxes(HVRPosableHand hand, HVRPosableHand otherHand, Vector3 forward, Vector3 up)
{
var so = new SerializedObject(hand);
var fingers = so.FindProperty("_fingers");
for (var i = 0; i < fingers.arraySize; i++)
{
var spFinger = fingers.GetArrayElementAtIndex(i);
var spBones = spFinger.FindPropertyRelative("Bones");
for (var j = 0; j < spBones.arraySize; j++)
{
var spBone = spBones.GetArrayElementAtIndex(j);
var bone = hand.Fingers[i].Bones[j];
var targetBone = otherHand.Fingers[i].Bones[j];
// Get local orthogonal axes of the right hand pointing forward and up
var axis1 = HVRPosableHand.GetSignedAxisVectorToDirection(bone.Transform.rotation, forward);
var axis2 = HVRPosableHand.GetSignedAxisVectorToDirection(bone.Transform.rotation, up);
var targetAxis1 = HVRPosableHand.GetSignedAxisVectorToDirection(targetBone.Transform.rotation, forward);
var targetAxis2 = HVRPosableHand.GetSignedAxisVectorToDirection(targetBone.Transform.rotation, up);
spBone.FindPropertyRelative(nameof(HVRPosableBone.Forward)).vector3Value = axis1;
spBone.FindPropertyRelative(nameof(HVRPosableBone.Up)).vector3Value = axis2;
spBone.FindPropertyRelative(nameof(HVRPosableBone.OtherForward)).vector3Value = targetAxis1;
spBone.FindPropertyRelative(nameof(HVRPosableBone.OtherUp)).vector3Value = targetAxis2;
}
}
so.ApplyModifiedProperties();
}
private void ValidateMirrorSettings(HVRPosableHand hand)
{
for (var i = 0; i < hand.Fingers.Length; i++)
{
var finger = hand.Fingers[i];
for (var j = 0; j < finger.Bones.Count; j++)
{
var bone = finger.Bones[j];
if (!Mathf.Approximately(0f, Vector3.Dot(bone.Forward, bone.Up)))
{
_badMirror = true;
_badMirrorText += $"{bone.Transform.name.PadRight(25)}: Forward ({bone.Forward.LogFormatF0()}) Up: ({bone.Up.LogFormatF0()}).\r\n";
}
if (!Mathf.Approximately(0f, Vector3.Dot(bone.OtherForward, bone.OtherUp)))
{
_badMirror = true;
_badMirrorText += $"{bone.Transform.name.PadRight(25)}: OtherForward ({bone.OtherForward.LogFormatF0()}) OtherUp: ({bone.OtherUp.LogFormatF0()}).\r\n";
}
}
}
}
private void HandSetup()
{
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("Hand Setup", EditorStyles.boldLabel);
EditorGUILayout.TextArea(
"1. The 'Parent' field is the transform that is the common parent of each finger's first bone." +
"\r\n\r\n2. Match the order of the finger list with the order on the hand model." +
" The default order matches most hand rigs. If your hand has less than 5 fingers, set those slots to 'None'\r\n" +
"\r\n3. Update the bone count for each finger.\r\n" +
"\r\n4. Some hand rigs may have an uneven hierarchy, update the Root Offset field with the # of bones between the parent and first bone.\r\n" +
"\r\n5. Press Setup and verify each HVRPosableHand fingers have the proper Root, Tip, and Bone counts assigned. Move the tip transforms to the center of the finger pad.\r\n" +
"\r\n6. Move the 'Palm' transforms that were added to the hands to the center of the palm (barely touching the surface) with the forward (blue) axis facing out of the palm.", helpBoxStyle);
//int i = 0;
//bool up = false;
//bool down = false;
HVREditorExtensions.ObjectField("Left Finger Parent", ref LeftFingerParent);
HVREditorExtensions.ObjectField("Right Finger Parent", ref RightFingerParent);
foreach (var s in settings)
{
EditorGUILayout.BeginHorizontal();
HVREditorExtensions.EnumField("Finger", ref s.Finger);
HVREditorExtensions.IntField("Bones", ref s.BoneCount);
HVREditorExtensions.IntField("Root Offset", ref s.BoneOffset);
//if (GUILayout.Button("^"))
//{
// i = s.Index;
// up = true;
//}
//if (GUILayout.Button("V"))
//{
// i = s.Index;
// down = true;
//}
EditorGUILayout.EndHorizontal();
}
//if (up && i > 0)
//{
// var temp = settings[i];
// settings.RemoveAt(i);
// settings.Insert(i - 1, temp);
//}
//if (down && i < settings.Count - 1)
//{
// var temp = settings[i];
// settings.RemoveAt(i);
// settings.Insert(i + 1, temp);
//}
//for (var k = 0; k < settings.Count; k++)
//{
// settings[k].Index = k;
//}
if (GUILayout.Button("Setup"))
{
var left = SetupHand(true, Left, LeftFingerParent);
var right = SetupHand(false, Right, RightFingerParent);
left.SetupFingerArray();
right.SetupFingerArray();
EditorUtility.SetDirty(left);
EditorUtility.SetDirty(right);
HandsSetup = true;
}
}
private HVRPosableHand _leftMirrorHand, _rightMirrorHand;
private void OnSceneGui(SceneView obj)
{
if (_mirroring && _leftMirrorHand && _rightMirrorHand)
{
_rightMirrorHand.Mirror(_leftMirrorHand, MirrorAxis.X);
}
}
private void SetupRigRefs()
{
var leftHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Left);
var rightHand = RigRoot.GetComponentsInChildren<HVRHandGrabber>().FirstOrDefault(e => e.HandSide == HVRHandSide.Right);
Left.parent = leftHand.transform;
Left.transform.localPosition = Vector3.zero;
Right.parent = rightHand.transform;
Right.transform.localPosition = Vector3.zero;
SetupHandGrabber(leftHand, Left);
SetupHandGrabber(rightHand, Right);
}
private void SetupHandGrabber(HVRHandGrabber hand, Transform handRoot)
{
var so = new SerializedObject(hand);
var hover = so.FindProperty("HoverPoser");
hover.objectReferenceValue = null;
var grabPoser = so.FindProperty("GrabPoser");
grabPoser.objectReferenceValue = null;
so.FindProperty("HandAnimator").objectReferenceValue = handRoot.gameObject.GetComponent<HVRHandAnimator>();
so.FindProperty("PhysicsPoser").objectReferenceValue = handRoot.gameObject.GetComponent<HVRPhysicsPoser>();
so.FindProperty("InverseKinematics").boolValue = false;
so.FindProperty("HandModel").objectReferenceValue = handRoot;
so.ApplyModifiedProperties();
var fg = hand.gameObject.GetComponentInChildren<HVRForceGrabber>();
if (fg)
{
so = new SerializedObject(fg);
hover = so.FindProperty("HoverPoser");
hover.objectReferenceValue = null;
grabPoser = so.FindProperty("GrabPoser");
grabPoser.objectReferenceValue = null;
EditorUtility.SetDirty(fg);
so.ApplyModifiedProperties();
}
if (hand.FallbackPoser)
{
so = new SerializedObject(hand.FallbackPoser);
var blend = so.FindProperty("PrimaryPose");
var pose = blend.FindPropertyRelative("Pose");
pose.objectReferenceValue = null;
so.ApplyModifiedProperties();
}
EditorUtility.SetDirty(hand);
}
HVRPosableHand SetupHand(bool left, Transform t, Transform fingerParent)
{
var go = t.gameObject;
var hand = go.UndoEnsureComponent<HVRPosableHand>();
var animator = go.UndoEnsureComponent<HVRHandAnimator>();
var physicsPoser = go.UndoEnsureComponent<HVRPhysicsPoser>();
var poser = go.UndoEnsureComponent<HVRHandPoser>();
var hm = go.UndoEnsureComponent<HVRHandMirrorer>();
var palm = t.Find("Palm");
if (!palm)
{
var p = new GameObject("Palm");
p.transform.parent = t;
p.transform.ResetLocalProps();
palm = p.transform;
}
hand.IsLeft = left;
hand.HandMirrorer = hm;
animator.DefaultPoseHand = false;
animator.PhysicsPoser = physicsPoser;
animator.Hand = hand;
animator.DefaultPoser = poser;
physicsPoser.Hand = hand;
physicsPoser.Palm = palm;
int i = 0;
foreach (var s in settings)
{
HVRPosableFinger finger;
switch (s.Finger)
{
case Finger.Thumb:
finger = hand.Thumb = new HVRPosableFinger();
break;
case Finger.Index:
finger = hand.Index = new HVRPosableFinger();
break;
case Finger.Middle:
finger = hand.Middle = new HVRPosableFinger();
break;
case Finger.Ring:
finger = hand.Ring = new HVRPosableFinger();
break;
case Finger.Pinky:
finger = hand.Pinky = new HVRPosableFinger();
break;
default:
i++;
continue;
}
var node = fingerParent.GetChild(i);
for (var k = 0; k < s.BoneOffset; k++)
node = node.GetChild(0);
for (var j = 0; j < s.BoneCount; j++)
{
var bone = new HVRPosableBone();
bone.Transform = node;
finger.Bones.Add(bone);
if (j < s.BoneCount - 1) node = node.GetChild(0);
}
if (finger.Bones.Count > 0)
{
var last = finger.Bones.Last();
var tipName = s.Finger.ToString() + " Tip";
var existing = last.Transform.Find(tipName);
if (!existing)
{
var tip = new GameObject(tipName);
tip.transform.parent = last.Transform;
tip.transform.ResetLocalProps();
finger.Tip = tip.transform;
Undo.RegisterCreatedObjectUndo(tip, $"Add {tipName} to {last.Transform.name}");
}
else
{
finger.Tip = existing;
}
finger.Root = finger.Bones[0].Transform;
}
i++;
}
if (hand.Index != null)
{
hand.IndexRoot = hand.Index.Bones.FirstOrDefault()?.Transform;
hand.IndexTip = hand.Index?.Tip;
}
if (hand.Thumb != null)
{
hand.ThumbRoot = hand.Thumb.Bones.FirstOrDefault()?.Transform;
hand.ThumbTip = hand.Thumb?.Tip;
}
if (hand.Middle != null)
{
hand.MiddleRoot = hand.Middle.Bones.FirstOrDefault()?.Transform;
hand.MiddleTip = hand.Middle?.Tip;
}
if (hand.Ring != null)
{
hand.RingRoot = hand.Ring.Bones.FirstOrDefault()?.Transform;
hand.RingTip = hand.Ring?.Tip;
}
if (hand.Pinky != null)
{
hand.PinkyRoot = hand.Pinky.Bones.FirstOrDefault()?.Transform;
hand.PinkyTip = hand.Pinky?.Tip;
}
EditorUtility.SetDirty(hand);
EditorUtility.SetDirty(animator);
EditorUtility.SetDirty(physicsPoser);
EditorUtility.SetDirty(poser);
return hand;
}
private Transform Add(Transform parent, string name)
{
var existing = parent.Find(name);
if (!existing)
{
var tip = new GameObject(name);
tip.transform.parent = parent;
tip.transform.ResetLocalProps();
existing = tip.transform;
Undo.RegisterCreatedObjectUndo(tip, $"Add {name} to {parent.name}");
Debug.Log($"{tip.name} added to {parent.name}");
}
return existing;
}
}
public class FingerSetting
{
public Finger Finger;
public int BoneCount = 3;
public int BoneOffset = 0;
public int Index;
}
public enum Finger
{
None, Thumb, Index, Middle, Ring, Pinky
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4f0472cefbaa9584b954464702dc8c64
timeCreated: 1636698677

View File

@@ -0,0 +1,513 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.HandPoser;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using GameObject = UnityEngine.GameObject;
namespace HurricaneVR.Editor
{
public class HVRManagementWindow : EditorWindow
{
private ObjectField grabbableObjectField;
private ObjectField posableObjectField;
private ObjectField grabPointsObjectField;
private UnityEditor.Editor _poserEditor;
private VisualElement _poserRoot;
private TextField _recordedPrefixTextBox;
private VisualElement _root;
private ScrollView _scrollView;
[MenuItem("Tools/HurricaneVR/Posing")]
public static void ShowExample()
{
HVRManagementWindow wnd = GetWindow<HVRManagementWindow>();
wnd.titleContent = new GUIContent("HVR Posing");
}
public const string GrabbleName = "VRPoser_Grabbable";
public GameObject SelectedGrabPoints
{
get
{
var obj = grabPointsObjectField.value as GameObject;
return obj;
}
}
public GameObject SelectedPoser
{
get
{
return posableObjectField.value as GameObject;
}
}
public GameObject SelectedGrabbable
{
get
{
return grabbableObjectField.value as GameObject;
}
}
private void OnDestroy()
{
}
public void OnEnable()
{
_root = rootVisualElement;
var visualTree = UnityEngine.Resources.Load<VisualTreeAsset>("HVRManagementWindow");
_root.Add(visualTree.CloneTree());
_scrollView = _root.Q<ScrollView>("ScrollView");
SetupObjectFields(_root);
SetupFocusButtons(_root);
SetupAddPoser(_root);
SetupPoseSelected(_root);
var list = _root.Q<VisualElement>("RecordedPoses");
list.styleSheets.Add(Resources.Load<StyleSheet>("HVRManagementWindow"));
_recordedPrefixTextBox = _root.Q<TextField>("RecordedPrefixTextBox");
SetupButtons(_root);
}
public ListView PosesListView { get; set; }
private List<HVRHandPose> Poses { get; set; }
private void SetupPosesListView(List<HVRHandPose> poses)
{
var posesParent = GameObject.Find("RecordedPosesCloneHolder");
if (!posesParent)
{
posesParent = new GameObject("RecordedPosesCloneHolder");
}
foreach (Transform child in posesParent.transform)
{
DestroyImmediate(child.gameObject);
}
Poses = poses;
var listview = _root.Q<ScrollView>("RecordedPoses");
listview.Clear();
foreach (var pose in poses)
{
var row = new VisualElement();
row.AddToClassList("poserow");
var field = new ObjectField("Pose:");
field.objectType = typeof(HVRHandPose);
field.value = pose;
row.Add(field);
field.AddToClassList("poserow-field");
var clone = Instantiate(HVRSettings.Instance.GetPoserHand(pose.SnappedLeft ? HVRHandSide.Left : HVRHandSide.Right), posesParent.transform, true);
var posableHand = clone.GetComponent<HVRPosableHand>();
if (posableHand != null)
{
posableHand.Pose(pose);
}
var attach = new Button(() =>
{
if (!SelectedGrabPoints)
{
EditorUtility.DisplayDialog("Error!", "Please set GrabPoints field.", "Ok!");
return;
}
var grabPoint = new GameObject("GrabPoint");
grabPoint.transform.parent = SelectedGrabPoints.transform;
grabPoint.transform.localPosition = Vector3.zero;
var poser = grabPoint.AddComponent<HVRHandPoser>();
var posable = grabPoint.AddComponent<HVRPosableGrabPoint>();
posable.HandPoser = poser;
grabPoint.transform.localPosition = Vector3.zero;//.position = pose.SnappedLeft ? pose.LeftHand.Position : pose.RightHand.Position;
grabPoint.transform.localRotation = Quaternion.identity;
var clonedPose = posableHand.CreateFullHandPose(posableHand.MirrorAxis);
clonedPose.RightHand.Rotation = Quaternion.Inverse(grabPoint.transform.rotation) * clonedPose.RightHand.Rotation;
clonedPose.LeftHand.Rotation = Quaternion.Inverse(grabPoint.transform.rotation) * clonedPose.LeftHand.Rotation;
clonedPose.RightHand.Position = Vector3.zero;
clonedPose.LeftHand.Position = Vector3.zero;
poser.PrimaryPose = new HVRHandPoseBlend();
poser.PrimaryPose.Pose = clonedPose;
poser.PrimaryPose.SetDefaults();
var grabbable = grabPoint.GetComponentInParent<HVRGrabbable>();
string name;
if (grabbable)
{
name = grabbable.name + "-" + pose.name;
}
else
{
name = DateTime.Now.Ticks.ToString();
}
poser.PrimaryPose.Pose = HVRSettings.Instance.SavePoseToDefault(clonedPose, name, "");
//EditorUtility.SetDirty(pose);
//AssetDatabase.SaveAssets();
//AssetDatabase.Refresh();
})
{
text = "Attach"
};
var delete = new Button(() =>
{
row.RemoveFromHierarchy();
DestroyImmediate(clone);
})
{ text = "-" };
var focus = new Button(() =>
{
Selection.activeGameObject = clone;
SceneView.FrameLastActiveSceneView();
})
{ text = "Focus" };
attach.AddToClassList("poserow-button");
delete.AddToClassList("poserow-button");
focus.AddToClassList("poserow-button");
row.Add(focus);
row.Add(attach);
row.Add(delete);
listview.Insert(listview.childCount, row);
}
}
private void SetupButtons(VisualElement root)
{
var button = root.Q<Button>("SetGrabPoints");
button.clickable.clicked += () =>
{
if (Selection.activeGameObject) grabPointsObjectField.value = Selection.activeGameObject;
};
button = root.Q<Button>("SetGrabbable");
button.clickable.clicked += () =>
{
if (Selection.activeGameObject) grabbableObjectField.value = Selection.activeGameObject;
};
button = root.Q<Button>("ExpandGrabbable");
button.clickable.clicked += () =>
{
if (SelectedGrabbable) SelectedGrabbable.SetExpandedRecursive(true);
};
button = root.Q<Button>("CollapseGrabbable");
button.clickable.clicked += () =>
{
if (SelectedGrabbable) SelectedGrabbable.SetExpandedRecursive(false);
};
button = root.Q<Button>("ExpandGrabPoints");
button.clickable.clicked += () =>
{
if (SelectedGrabPoints) SelectedGrabPoints.SetExpandedRecursive(true);
};
button = root.Q<Button>("CollapseGrabPoints");
button.clickable.clicked += () =>
{
if (SelectedGrabPoints) SelectedGrabPoints.SetExpandedRecursive(false);
};
root.Q<Button>("SetupGrabbable").clickable.clicked += () =>
{
if (SelectedGrabbable == null || SelectedGrabbable != Selection.activeGameObject)
{
grabbableObjectField.value = Selection.activeGameObject;
AddGrabbable(Selection.activeGameObject);
}
else
{
AddGrabbable(SelectedGrabbable);
}
};
root.Q<Button>("AddGrabPoints").clickable.clicked += () =>
{
AddGrabPoints(SelectedGrabbable ? SelectedGrabbable : Selection.activeGameObject);
};
root.Q<Button>("AddGrabPointButton").clickable.clicked += () =>
{
if (!SelectedGrabPoints) return;
AddGrabPoint(SelectedGrabPoints);
SelectedGrabPoints.SetExpandedRecursive(true);
};
root.Q<Button>("SetupGrabPoints").clickable.clicked += () =>
{
if (!SelectedGrabbable) return;
var grabbable = SelectedGrabbable.GetComponent<HVRGrabbable>();
if (grabbable != null) grabbable.PopulateGrabPoints();
EditorUtility.SetDirty(grabbable);
};
root.Q<Button>("LoadPoses").clickable.clicked += () =>
{
var path = EditorUtility.OpenFolderPanel("Load poses", HVRSettings.Instance.GetRuntimePosesDirectory(), "");
if (string.IsNullOrWhiteSpace(path))
{
return;
}
var files = Directory.GetFiles(path);
var poses = new List<HVRHandPose>();
foreach (var file in files)
{
try
{
if (file.EndsWith(".asset"))
{
var start = file.IndexOf("Assets");
var localPath = file.Substring(start).Replace("\\", "/");
var pose = AssetDatabase.LoadAssetAtPath<HVRHandPose>(localPath);
poses.Add(pose);
}
}
catch (Exception e)
{
Debug.LogException(e);
}
}
SetupPosesListView(poses);
};
}
public Toggle ToggleSteam { get; set; }
public Toggle ToggleOculus { get; set; }
private void AddGrabbable(GameObject obj)
{
if (!obj) return;
var grabbable = obj.GetComponent<HVRGrabbable>();
var physicsGrabbable = obj.GetComponent<HVRPhysicsGrabbable>();
if (!grabbable && !physicsGrabbable)
{
obj.AddComponent<HVRGrabbable>();
}
if (AddGrabPoints(obj))
{
AddGrabPoint(SelectedGrabPoints);
}
obj.SetExpandedRecursive(true);
}
private GameObject AddGrabPoint(GameObject obj)
{
var grabPoint = new GameObject("GrabPoint");
grabPoint.transform.parent = obj.transform;
grabPoint.transform.ResetLocalProps();
var poser = grabPoint.AddComponent<HVRHandPoser>();
var posable = grabPoint.AddComponent<HVRPosableGrabPoint>();
posable.HandPoser = poser;
posableObjectField.value = grabPoint;
return grabPoint;
}
private bool AddGrabPoints(GameObject obj)
{
if (!obj)
return false;
var points = obj.GetComponentInChildren<HVRGrabPoints>()?.gameObject;
if (points)
{
if (!EditorUtility.DisplayDialog("Warning!", "GrabPoint component exists in children, add another?", "Yes", "No"))
{
Debug.Log($"This object already has a child VRGrabPoints");
grabPointsObjectField.value = points;
return false;
}
}
points = new GameObject("GrabPoints");
var vrGrabPoints = points.AddComponent<HVRGrabPoints>();
points.transform.parent = obj.transform;
points.transform.ResetLocalProps();
//vrGrabPoints.AddRunTimePoses();
//AddGrabPoint(points);
grabPointsObjectField.value = points;
obj.SetExpandedRecursive(true);
return true;
}
private void SetupObjectFields(VisualElement root)
{
posableObjectField = root.Q<ObjectField>("VRHandPoser");
posableObjectField.objectType = typeof(GameObject);
posableObjectField.RegisterValueChangedCallback(evt =>
{
if (evt.newValue)
{
var obj = evt.newValue as GameObject;
var poser = obj.GetComponent<HVRHandPoser>();
if (poser != null)
{
SetupPoser(root, poser);
}
else
{
CleanupPoserEditor();
}
}
else
{
CleanupPoserEditor();
}
});
grabbableObjectField = root.Q<ObjectField>("Grabbable");
grabbableObjectField.objectType = typeof(GameObject);
grabbableObjectField.RegisterValueChangedCallback(evt =>
{
});
if (posableObjectField.value)
{
var obj = posableObjectField.value as GameObject;
var poser = obj.GetComponent<HVRHandPoser>();
if (poser != null)
{
SetupPoser(root, poser);
}
}
grabPointsObjectField = root.Q<ObjectField>("GrabPointsObject");
grabPointsObjectField.objectType = typeof(GameObject);
}
private void SetupPoser(VisualElement root, HVRHandPoser poser)
{
CleanupPoserEditor();
_poserEditor = UnityEditor.Editor.CreateEditor(poser);
_poserRoot = _poserEditor.CreateInspectorGUI();
//root.Add(_poserRoot);
_scrollView.Add(_poserRoot);
_poserRoot.Unbind();
_poserRoot.Bind(_poserEditor.serializedObject);
}
private void CleanupPoserEditor()
{
if (_poserRoot != null)
{
_poserRoot.Clear();
_poserRoot.RemoveFromHierarchy();
}
if (_poserEditor != null)
{
DestroyImmediate(_poserEditor);
}
}
private void SetupAddPoser(VisualElement root)
{
var button = root.Q<ToolbarButton>("AddPoser");
button.clickable.clicked += () =>
{
if (!SelectedPoser) return;
var poser = SelectedPoser.GetComponent<HVRHandPoser>();
if (poser == null)
{
poser = SelectedPoser.AddComponent<HVRHandPoser>();
SetupPoser(root, poser);
}
};
}
private void SetupFocusButtons(VisualElement root)
{
root.Q<Button>("FocusPoser").clickable.clicked += () =>
{
if (SelectedPoser) Selection.activeGameObject = SelectedPoser;
};
root.Q<Button>("FocusGrabbable").clickable.clicked += () =>
{
if (SelectedGrabbable) Selection.activeGameObject = SelectedGrabbable;
};
root.Q<Button>("FocusGrabPoints").clickable.clicked += () =>
{
if (SelectedGrabPoints) Selection.activeGameObject = SelectedGrabPoints;
};
}
private void SetupPoseSelected(VisualElement root)
{
var button = root.Q<Button>("SetPoser");
button.clickable.clicked += () =>
{
if (Selection.activeGameObject != null) posableObjectField.value = Selection.activeGameObject;
};
}
private void OnDisable()
{
CleanupPoserEditor();
}
}
}

View File

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

View File

@@ -0,0 +1,124 @@
using System.Diagnostics.Tracing;
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRPhysicsButton))]
public class HVRPhysicsButtonEditor : UnityEditor.Editor
{
private SerializedProperty SP_StartPosition;
private SerializedProperty SP_EndPosition;
private SerializedProperty SP_Threshold;
private SerializedProperty SP_UpThreshold;
public HVRPhysicsButton component;
private bool _setupExpanded;
protected void OnEnable()
{
SP_StartPosition = serializedObject.FindProperty("StartPosition");
SP_EndPosition = serializedObject.FindProperty("EndPosition");
SP_Threshold = serializedObject.FindProperty("DownThreshold");
SP_UpThreshold = serializedObject.FindProperty("ResetThreshold");
component = target as HVRPhysicsButton;
}
public override void OnInspectorGUI()
{
var dir = SP_EndPosition.vector3Value - SP_StartPosition.vector3Value;
dir.Normalize();
_setupExpanded = EditorGUILayout.Foldout(_setupExpanded, "Setup Helpers");
if (_setupExpanded)
{
EditorGUILayout.HelpBox("1. Choose the local axis the button will move on.\r\n" +
"2. Save the start position of the button.\r\n" +
"3. Save the end position of the button.\r\n" +
"4. Save the down and reset positions.\r\n" +
"5. Return the transform to start by pressing the return button.\r\n" +
"6. If the Connected Body is left blank, the button will be jointed to the world and cannot be moved."
, MessageType.Info);
GUILayout.BeginHorizontal();
if (GUILayout.Button("Save Start"))
{
SP_StartPosition.vector3Value = component.transform.localPosition;
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("GoTo Start"))
{
component.transform.localPosition = SP_StartPosition.vector3Value;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Save End"))
{
SP_EndPosition.vector3Value = component.transform.localPosition;
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("GoTo End"))
{
component.transform.localPosition = SP_EndPosition.vector3Value;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Save Down"))
{
var delta = SP_StartPosition.vector3Value - component.transform.localPosition;
SP_Threshold.floatValue = delta.magnitude;
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("GoTo Down"))
{
component.transform.localPosition = SP_StartPosition.vector3Value + SP_Threshold.floatValue * dir;
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button("Save Reset"))
{
var delta = SP_StartPosition.vector3Value - component.transform.localPosition;
SP_UpThreshold.floatValue = delta.magnitude;
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("GoTo Reset"))
{
component.transform.localPosition = SP_StartPosition.vector3Value + SP_UpThreshold.floatValue * dir;
}
GUILayout.EndHorizontal();
}
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
}
}

View File

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

View File

@@ -0,0 +1,40 @@
using HurricaneVR.Framework.Components;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRPhysicsDial), true)]
public class HVRPhysicsDialEditor : UnityEditor.Editor
{
public SerializedProperty SP_StartRotation;
public HVRPhysicsDial Dial;
protected void OnEnable()
{
SP_StartRotation = serializedObject.FindProperty("JointStartRotation");
Dial = target as HVRPhysicsDial;
}
public override void OnInspectorGUI()
{
if (GUILayout.Button("Save Joint Start Rotation"))
{
SP_StartRotation.quaternionValue = Dial.transform.localRotation;
}
EditorGUILayout.HelpBox("Joints limits are based on their starting rotation and have a maximum limit of 177." +
"\r\n1. Rotate the transform to where you want the joint limits to start from and press 'Save Joint Start Rotation'. " +
"\r\n2. Rotate the transform to where you want it start at, making sure it's within your defined limit." +
"\r\n3. Choose the local axis of rotation." +
"\r\n4. If you needs limits larger than 177 degrees in either direction. Use HVRRotationTracker + HVRRotationLimiter."
, MessageType.Info);
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
}
}

View File

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

View File

@@ -0,0 +1,75 @@
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Shared;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRPhysicsDrawer))]
public class HVRPhysicsDrawerEditor : UnityEditor.Editor
{
private SerializedProperty SP_StartPosition;
private SerializedProperty SP_EndPosition;
private SerializedProperty SP_OpenPosition;
public HVRPhysicsDrawer component;
private bool _setupExpanded;
protected void OnEnable()
{
SP_StartPosition = serializedObject.FindProperty("StartPosition");
SP_EndPosition = serializedObject.FindProperty("EndPosition");
SP_OpenPosition = serializedObject.FindProperty("OpenPosition");
component = target as HVRPhysicsDrawer;
}
public override void OnInspectorGUI()
{
var dir = SP_EndPosition.vector3Value - SP_StartPosition.vector3Value;
dir.Normalize();
_setupExpanded = EditorGUILayout.Foldout(_setupExpanded, "Setup Helpers");
if (_setupExpanded)
{
EditorGUILayout.HelpBox("1. Choose the local axis the drawer will move on.\r\n" +
"2. Save the start position of the drawer.\r\n" +
"3. Save the end position of the drawer.\r\n" +
"4. Save the SFX threshold position of the drawer.\r\n", MessageType.Info);
DrawButtons("Start", SP_StartPosition);
DrawButtons("End", SP_EndPosition);
DrawButtons("SFX Position", SP_OpenPosition);
}
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
private void DrawButtons(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.vector3Value = component.transform.localPosition;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localPosition = property.vector3Value;
}
GUILayout.EndHorizontal();
}
}
}

View File

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

View File

@@ -0,0 +1,79 @@
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Components.Creators;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRPhysicsLeverCreator))]
public class HVRPhysicsLeverCreatorEditor : UnityEditor.Editor
{
protected void OnEnable()
{
}
public override void OnInspectorGUI()
{
EditorGUILayout.HelpBox("1. Add the anchor that will hold the RB to joint to..\r\n" +
"2. Add the lever that will hold the lever RB and necessary components.\r\n" +
"3. Press Create Lever", MessageType.Info);
var creator = target as HVRPhysicsLeverCreator;
var anchor = creator.Anchor;
var leverTransform = creator.Lever;
var axis = creator.Axis;
if (!anchor)
{
EditorGUILayout.HelpBox("Populate the Anchor field.", MessageType.Error);
}
if (!leverTransform)
{
EditorGUILayout.HelpBox("Populate the Lever field.", MessageType.Error);
}
if (GUILayout.Button("Create Lever") && anchor && leverTransform && anchor != leverTransform)
{
Undo.SetCurrentGroupName("LeverCreate");
var anchorRb = anchor.UndoEnsureComponent<Rigidbody>();
var tracker = new SerializedObject(leverTransform.gameObject.UndoEnsureComponent<HVRRotationTracker>());
var rb = leverTransform.UndoEnsureComponent<Rigidbody>();
var grabbable = new SerializedObject(leverTransform.UndoEnsureComponent<HVRGrabbable>());
var lever = new SerializedObject(leverTransform.UndoEnsureComponent<HVRPhysicsLever>());
anchorRb.isKinematic = true;
rb.useGravity = false;
rb.mass = creator.Mass;
grabbable.FindProperty("Stationary").boolValue = true;
grabbable.FindProperty("ForceGrabbable").boolValue = false;
tracker.FindProperty("Axis").enumValueIndex = (int)axis;
lever.FindProperty("ConnectedBody").objectReferenceValue = anchorRb;
lever.FindProperty("Axis").enumValueIndex = (int)axis;
lever.FindProperty("MinAngle").floatValue = creator.MinAngle;
lever.FindProperty("MaxAngle").floatValue = creator.MaxAngle;
lever.FindProperty("LimitRotation").boolValue = true;
lever.FindProperty("GrabbedDamper").floatValue = creator.GrabbedDamper;
lever.FindProperty("Damper").floatValue = creator.Damper;
lever.ApplyModifiedProperties();
grabbable.ApplyModifiedProperties();
tracker.ApplyModifiedProperties();
EditorUtility.SetDirty(anchorRb);
EditorUtility.SetDirty(rb);
Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
}
base.OnInspectorGUI();
}
}
}

View File

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

View File

@@ -0,0 +1,92 @@
using System;
using HurricaneVR.Framework.Core.HandPoser;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRPhysicsPoser))]
public class HVRPhysicsPoserEditor : UnityEditor.Editor
{
public HVRPhysicsPoser PhysicsPoser;
private VisualElement _editorContainer;
private VisualElement _root;
private void OnEnable()
{
try
{
PhysicsPoser = target as HVRPhysicsPoser;
}
catch (Exception e)
{
Debug.LogException(e);
}
}
public override VisualElement CreateInspectorGUI()
{
_root = new VisualElement();
var defaultUI = new VisualElement();
var iterator = serializedObject.GetIterator();
if (iterator.NextVisible(true))
{
do
{
var propertyField = new PropertyField(iterator.Copy()) { name = "PropertyField:" + iterator.propertyPath };
if (iterator.propertyPath == "m_Script" && serializedObject.targetObject != null)
propertyField.SetEnabled(value: false);
defaultUI.Add(propertyField);
}
while (iterator.NextVisible(false));
}
_root.Add(defaultUI);
_editorContainer = new VisualElement();
var editorTree = UnityEngine.Resources.Load<VisualTreeAsset>("HVRPhysicsPoserEditor");
editorTree.CloneTree(_editorContainer);
_root.Add(_editorContainer);
_root.Q<Button>("SetupButton").clickable.clicked += () =>
{
if(PhysicsPoser.Validate()) PhysicsPoser.Setup();
serializedObject.ApplyModifiedProperties();
};
_root.Q<Button>("ResetButton").clickable.clicked += () =>
{
PhysicsPoser.OpenFingers();
PhysicsPoser.ResetHand();
};
_root.Q<Button>("SimulateButton").clickable.clicked += () =>
{
PhysicsPoser.transform.SetLayerRecursive(HVRLayers.Hand);
PhysicsPoser.TestClose();
};
_root.Q<Button>("NextFingerButton").clickable.clicked += () =>
{
PhysicsPoser.NextFinger();
};
_root.Q<Button>("StepButton").clickable.clicked += () =>
{
PhysicsPoser.StepIteration();
};
_root.Q<Button>("StepBackButton").clickable.clicked += () =>
{
PhysicsPoser.BackStepIteration();
};
return _root;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 501f725b398d400198031761cf4bf5d2
timeCreated: 1597727990

View File

@@ -0,0 +1,326 @@
using System;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.HandPoser;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace HurricaneVR.Editor
{
//[CustomEditor(typeof(HVRPosableHand))]
//public class HVRPosableHandEditor : UnityEditor.Editor
//{
// private SerializedProperty SP_IsLeft;
// private SerializedProperty SP_HandPreview;
// private SerializedProperty SP_DoPreview;
// private SerializedProperty SP_SelectedPose;
// private PropertyField PropertyField_IsLeft;
// private VisualElement HandContainer;
// public HVRPosableHand ThisHand;
// private VisualElement _editorContainer;
// private VisualElement _root;
// public ObjectField SelectedPoseField { get; set; }
// public bool IsLeft => SP_IsLeft.boolValue;
// protected GameObject PreviewInstance
// {
// get
// {
// if (SP_HandPreview == null || SP_HandPreview.objectReferenceValue == null) return null;
// return SP_HandPreview.objectReferenceValue as GameObject;
// }
// set
// {
// if (SP_HandPreview != null) SP_HandPreview.objectReferenceValue = value;
// }
// }
// public HVRHandPose SelectedPose
// {
// get
// {
// return SP_SelectedPose.objectReferenceValue as HVRHandPose;
// }
// set
// {
// if (SP_SelectedPose == null) return;
// SP_SelectedPose.objectReferenceValue = value;
// }
// }
// private void OnEnable()
// {
// try
// {
// SP_IsLeft = serializedObject.FindProperty("IsLeft");
// SP_HandPreview = serializedObject.FindProperty("Preview");
// SP_DoPreview = serializedObject.FindProperty("DoPreview");
// SP_SelectedPose = serializedObject.FindProperty("SelectedPose");
// ThisHand = target as HVRPosableHand;
// }
// catch (Exception e)
// {
// Debug.LogException(e);
// }
// }
// public bool FullBody => HVRSettings.Instance.InverseKinematics;
// public override VisualElement CreateInspectorGUI()
// {
// _root = new VisualElement();
// var defaultUI = new VisualElement();
// var iterator = serializedObject.GetIterator();
// if (iterator.NextVisible(true))
// {
// do
// {
// var propertyField = new PropertyField(iterator.Copy()) { name = "PropertyField:" + iterator.propertyPath };
// if (iterator.propertyPath == "m_Script" && serializedObject.targetObject != null)
// propertyField.SetEnabled(value: false);
// defaultUI.Add(propertyField);
// }
// while (iterator.NextVisible(false));
// }
// var folder = new Foldout();
// folder.Add(defaultUI);
// folder.text = "Default Inspector";
// _root.Add(folder);
// _editorContainer = new VisualElement();
// var editorTree = UnityEngine.Resources.Load<VisualTreeAsset>("HVRHandPoseEditor");
// editorTree.CloneTree(_editorContainer);
// _editorContainer.Q<ObjectField>("SelectedPose").objectType = typeof(HVRHandPose);
// _root.Add(_editorContainer);
// PropertyField_IsLeft = _root.Q<PropertyField>("PropertyField:IsLeft");
// PropertyField_IsLeft.RegisterCallback(new EventCallback<ChangeEvent<bool>>(OnIsLeftChanged));
// HandContainer = _editorContainer.Q<VisualElement>("HandContainer");
// PreviewToggle = HandContainer.Q<Toggle>("Preview");
// PreviewToggle.BindProperty(SP_DoPreview);
// PreviewToggle.RegisterValueChangedCallback(OnPreviewChanged);
// UpdatePreview(SP_DoPreview.boolValue, true);
// SetupSelectedPose();
// SetupNewButton();
// SetupSaveAsButton();
// SetupSaveButton();
// SetupPreviewButton();
// return _root;
// }
// private void SetupNewButton()
// {
// var button = _root.Q<Button>("NewPose");
// button.clickable.clicked += () =>
// {
// var folder = HVRSettings.Instance.PosesDirectory;
// string path;
// if (string.IsNullOrWhiteSpace(folder))
// {
// path = EditorUtility.SaveFilePanelInProject("Save New Pose", "pose", "asset", "Message");
// }
// else
// {
// path = EditorUtility.SaveFilePanelInProject("Save New Pose", "pose", "asset", "Message", folder);
// }
// if (!string.IsNullOrEmpty(path))
// {
// var pose = ThisHand.CreateFullHandPose();
// AssetUtils.CreateOrReplaceAsset(pose, path);
// SP_SelectedPose.objectReferenceValue = pose;
// serializedObject.ApplyModifiedProperties();
// }
// };
// }
// private void SetupSaveAsButton()
// {
// var button = _root.Q<Button>("SaveAsPose");
// button.clickable.clicked += () =>
// {
// var folder = HVRSettings.Instance.PosesDirectory;
// string path;
// if (string.IsNullOrWhiteSpace(folder))
// {
// path = EditorUtility.SaveFilePanelInProject("Save New Pose", "pose", "asset", "Message");
// }
// else
// {
// path = EditorUtility.SaveFilePanelInProject("Save New Pose", "pose", "asset", "Message", folder);
// }
// if (!string.IsNullOrEmpty(path))
// {
// var pose = ThisHand.CreateFullHandPose();
// SelectedPose = AssetUtils.CreateOrReplaceAsset(pose, path);
// serializedObject.ApplyModifiedProperties();
// }
// };
// }
// private void SetupPreviewButton()
// {
// var button = _root.Q<Button>("Preview");
// button.clickable.clicked += () =>
// {
// if (!SelectedPose)
// return;
// Undo.RegisterFullObjectHierarchyUndo(ThisHand.gameObject, "PreviewPose");
// ThisHand.Pose(SelectedPose.GetPose(IsLeft));
// UpdatePreview(SP_DoPreview.boolValue, false);
// };
// }
// private void SetupSaveButton()
// {
// var button = _root.Q<Button>("SavePose");
// button.clickable.clicked += () =>
// {
// if (IsLeft)
// {
// SelectedPose.LeftHand = ThisHand.CreateHandPose();
// SelectedPose.RightHand = ThisHand.Mirror(ThisHand.MirrorAxis);
// }
// else
// {
// SelectedPose.RightHand = ThisHand.CreateHandPose();
// SelectedPose.LeftHand = ThisHand.Mirror(ThisHand.MirrorAxis);
// }
// EditorUtility.SetDirty(SelectedPose);
// AssetDatabase.SaveAssets();
// AssetDatabase.Refresh();
// };
// }
// private void SetupSelectedPose()
// {
// SelectedPoseField = _editorContainer.Q<ObjectField>("SelectedPose");
// SelectedPoseField.objectType = typeof(HVRHandPose);
// SelectedPoseField.RegisterValueChangedCallback(OnSelectedPoseChanged);
// }
// private void TrySetToDefault()
// {
// if (!ThisHand || !HVRSettings.Instance.OpenHandPose)
// return;
// ThisHand.Pose(HVRSettings.Instance.OpenHandPose);
// }
// private void OnSelectedPoseChanged(ChangeEvent<UnityEngine.Object> evt)
// {
// //if (Application.isPlaying)
// // return;
// //if (evt.newValue == null)
// //{
// // PreviewToggle.SetValueWithoutNotify(false);
// // if (PreviewInstance) DestroyImmediate(PreviewInstance);
// // _root.schedule.Execute(() => { TrySetToDefault(); });
// //}
// //else
// //{
// // var newPose = evt.newValue as HVRHandPose;
// // ThisHand.Pose(newPose.GetPose(IsLeft));
// // UpdatePreview(SP_DoPreview.boolValue, false);
// //}
// }
// private void OnPreviewChanged(ChangeEvent<bool> evt)
// {
// UpdatePreview(evt.newValue, false);
// }
// public Toggle PreviewToggle { get; set; }
// private void OnIsLeftChanged(ChangeEvent<bool> evt)
// {
// }
// private void UpdatePreview(bool preview, bool isRetained)
// {
// if (PreviewInstance && !isRetained)
// {
// DestroyImmediate(PreviewInstance);
// serializedObject.ApplyModifiedProperties();
// }
// if (!preview)
// {
// return;
// }
// if (isRetained && SP_HandPreview.objectReferenceValue != null) return;
// var source = IsLeft ? HVRSettings.Instance.RightHand : HVRSettings.Instance.LeftHand;
// var previewName = $"Mirror [{ThisHand.gameObject.name}]";
// var existing = GameObject.Find(previewName);
// if (existing)
// {
// PreviewInstance = existing;
// }
// else
// {
// PreviewInstance = Instantiate(source, ThisHand.transform.parent, false);
// PreviewInstance.name = previewName;
// }
// var hand = PreviewInstance.GetComponent<HVRPosableHand>();
// hand.DoPreview = false;
// hand.IsLeft = !ThisHand.IsLeft;
// serializedObject.ApplyModifiedProperties();
// if (hand != null)
// {
// var mirror = ThisHand.Mirror(MirrorAxis.X);
// var snapShot = ThisHand.CreateHandPose();
// //var mirror = snapShot.Mirror(ThisHand.MirrorAxis, ThisHand.transform);
// //hand.FingerSetup();
// hand.Pose(mirror);
// SceneView.RepaintAll();
// }
// else
// {
// Debug.Log($"Preview hand is missing VRPosableHand");
// }
// }
// private void OnDisable()
// {
// }
//}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 192a54905c104022bbde4eca5d554a92
timeCreated: 1597519653

View File

@@ -0,0 +1,27 @@
using System;
using HurricaneVR.Framework.Components;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRRotationLimiter))]
public class HVRRotationLimiterEditor : UnityEditor.Editor
{
protected void OnEnable()
{
}
public override void OnInspectorGUI()
{
EditorGUILayout.HelpBox("Used in conjunction with the HVRRotationTracker." +
$"{Environment.NewLine}Joint limits will be placed on the axis of rotation assigned on the tracker " +
"when the AngleFromStart reported by the tracker becomes in range of that limit.", MessageType.Info);
base.OnInspectorGUI();
}
}
}

View File

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

View File

@@ -0,0 +1,523 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using UnityEngine;
using UnityEngine.UIElements;
namespace HurricaneVR.Editor
{
public class HVRSetupWindow : EditorWindow
{
private const string URLHurricaneReview = "https://assetstore.unity.com/packages/tools/physics/hurricane-vr-physics-interaction-toolkit-177300#reviews";
private const string URLKofi = "https://ko-fi.com/cloudwalkingames";
private const string URLPatreon = "https://www.patreon.com/user?u=46531723&fan_landing=true";
private const string URLBasicGrabbableWithPose = "https://www.youtube.com/watch?v=HZQ6QdMmZ34";
private const string URLVRIKIntegrationSetup = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/integrations/finalik.html";
private const string LatestNotes = "HVRLatestReleaseNotes";
private const string URLManual = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/intro.html";
private const string URLHandGrabber = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/hands.html";
private const string URLSockets = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/sockets.html";
private const string URLSetup = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/setup.html";
private const string URLCustomHand = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/hand_setup.html";
private const string URLDoor = "https://cloudwalker2020.github.io/HurricaneVR-Docs/manual/components/door.html";
private const string URLDiscord = "https://discord.com/invite/7QUXEcuwKY";
private const string DEFINESteamVR = "HVR_STEAMVR";
private const string DEFINEOculus = "HVR_OCULUS";
//private const string DEFINEPun = "HVR_PUN";
private static HVRSetupWindow _window;
private VisualElement _root;
private List<VisualElement> _panels = new List<VisualElement>();
[MenuItem("Tools/HurricaneVR/Setup")]
public static void ShowWindow()
{
_window = GetWindow<HVRSetupWindow>(true);
_window.titleContent = new GUIContent("Hurricane v" + HVREditorManager.Version);
_window.minSize = new Vector2(800f, 600f);
}
#if CLOUDWALKER
[Shortcut("Refresh Window", KeyCode.F9)]
public static void Refresh()
{
if (_window)
{
_window.Close();
}
ShowWindow();
}
#endif
public void OnEnable()
{
_root = rootVisualElement;
var visualTree = UnityEngine.Resources.Load<VisualTreeAsset>("HVRSetupWindow");
_root.Add(visualTree.CloneTree());
var projectSetupPanel = _root.Q<VisualElement>("ProjectSetupPanel");
var notesPanel = _root.Q<VisualElement>("ReleaseNotesPanel");
var aboutPanel = _root.Q<VisualElement>("AboutPanel");
_panels.Add(projectSetupPanel);
_panels.Add(notesPanel);
_panels.Add(aboutPanel);
_root.Q<Button>("BtnProjectSetup").clickable.clicked += () =>
{
UpdatePanel(projectSetupPanel);
};
_root.Q<Button>("BtnAbout").clickable.clicked += () =>
{
UpdatePanel(aboutPanel);
};
_root.Q<Button>("BtnReleaseNotes").clickable.clicked += () =>
{
UpdatePanel(notesPanel);
};
_root.Q<Button>("BtnSetupLayers").clickable.clicked += SetupLayers;
_root.Q<Button>("BtnSetupPhysics").clickable.clicked += SetupPhysics;
_root.Q<Button>("BtnSetupMatrix").clickable.clicked += SetupMatrix;
var releaseNotes = _root.Q<TextElement>("TxtReleaseNotes");
var releaseText = Resources.Load<TextAsset>(LatestNotes);
if (releaseText)
{
releaseNotes.text = releaseText.text;
}
SetupUrl("BtnTutBasicGrabbable", URLBasicGrabbableWithPose);
SetupUrl("BtnVRIKSetup", URLVRIKIntegrationSetup);
SetupUrl("BtnReview", URLHurricaneReview);
SetupUrl("BtnKofi", URLKofi);
SetupUrl("btnDocs", URLManual);
SetupUrl("btnSockets", URLSockets);
SetupUrl("btnHandGrabber", URLHandGrabber);
SetupUrl("btnDiscord", URLDiscord);
SetupUrl("btnSetup", URLSetup);
SetupUrl("btnCustomHand", URLCustomHand);
SetupUrl("btnDoorSetup", URLDoor);
//SetupUrl("BtnPatreon", URLPatreon);
UpdatePanel(notesPanel);
SetupDefineButton("BtnEnableSteamVR", "BtnDisableSteamVR", DEFINESteamVR);
SetupDefineButton("BtnEnableOculus", "BtnDisableOculus", DEFINEOculus);
//SetupDefineButton("BtnEnablePUN", "BtnDisablePUN", DEFINEPun);
_root.Q<Button>("BtnExtractSteamVR").clickable.clicked += () =>
{
AssetDatabase.ImportPackage(Application.dataPath + "/HurricaneVR/Framework/Integrations/SteamVRIntegration.unitypackage", true);
};
_root.Q<Button>("BtnExtractOculus").clickable.clicked += () =>
{
AssetDatabase.ImportPackage(Application.dataPath + "/HurricaneVR/Framework/Integrations/OculusIntegration.unitypackage", true);
};
//_root.Q<Button>("BtnExtractPUN").clickable.clicked += () =>
//{
// AssetDatabase.ImportPackage(Application.dataPath + "/HurricaneVR/Framework/Integrations/PUN2Integration.unitypackage", true);
//};
}
private void SetupUrl(string buttonName, string url)
{
_root.Q<Button>(buttonName).clickable.clicked += () =>
{
Application.OpenURL(url);
};
}
private void UpdatePanel(VisualElement panel)
{
foreach (var p in _panels)
{
p.style.display = DisplayStyle.None;
}
panel.style.display = DisplayStyle.Flex;
}
private void SetupPhysics()
{
UnityEngine.Object[] asset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/DynamicsManager.asset");
if (asset.Length == 0)
{
Debug.Log($"Couldn't load DynamicsManager.asset");
return;
}
try
{
var so = new SerializedObject(asset[0]);
var prop = so.FindProperty("m_DefaultSolverIterations");
prop.intValue = 6;
prop = so.FindProperty("m_DefaultSolverVelocityIterations");
prop.intValue = 2;
prop = so.FindProperty("m_DefaultMaxAngularSpeed");
prop.floatValue = 30f;
so.ApplyModifiedProperties();
so.Update();
EditorUtility.SetDirty(asset[0]);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"Dynamics Manager Updated");
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void SetupMatrix()
{
UnityEngine.Object[] asset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/DynamicsManager.asset");
if (asset.Length == 0)
{
Debug.Log($"Couldn't load DynamicsManager.asset");
return;
}
try
{
var so = new SerializedObject(asset[0]);
SetLayer(HVRLayers.Player, HVRLayers.Grabbable);
SetLayer(HVRLayers.Player, HVRLayers.Hand);
SetLayer(HVRLayers.Player, HVRLayers.Player);
SetLayer(HVRLayers.Grabbable, HVRLayers.Hand, false);
SetLayer(HVRLayers.Grabbable, HVRLayers.Grabbable, false);
SetLayer(HVRLayers.Hand, HVRLayers.Hand, false);
so.ApplyModifiedProperties();
so.Update();
EditorUtility.SetDirty(asset[0]);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log($"Dynamics Manager Updated (Collision Matrix)");
}
catch (Exception e)
{
Debug.LogException(e);
}
}
private void IgnoreAllBut(HVRLayers one, HVRLayers but)
{
var layerOne = LayerMask.NameToLayer(one.ToString());
var layerTwo = LayerMask.NameToLayer(but.ToString());
if (layerOne < 0)
{
Debug.LogWarning($"{one} layer does not exist.");
}
if (layerTwo < 0)
{
Debug.LogWarning($"{but} layer does not exist.");
}
if (layerOne < 0 || layerTwo < 0)
return;
for (int i = 0; i < 32; i++)
{
if (i == layerTwo)
{
Physics.IgnoreLayerCollision(layerOne, i, false);
}
else
{
Physics.IgnoreLayerCollision(layerOne, i, true);
}
}
}
private void SetLayer(HVRLayers one, HVRLayers two, bool ignore = true)
{
var layerOne = LayerMask.NameToLayer(one.ToString());
var layerTwo = LayerMask.NameToLayer(two.ToString());
if (layerOne < 0)
{
Debug.LogWarning($"{one} layer does not exist.");
}
if (layerTwo < 0)
{
Debug.LogWarning($"{two} layer does not exist.");
}
if (layerOne < 0 || layerTwo < 0)
return;
Physics.IgnoreLayerCollision(layerOne, layerTwo, ignore);
}
private void SetLayer(HVRLayers one, int layerTwo, bool ignore = true)
{
var layerOne = LayerMask.NameToLayer(one.ToString());
if (layerOne < 0)
{
Debug.LogWarning($"{one} layer does not exist.");
}
if (layerOne < 0 || layerTwo < 0)
return;
Physics.IgnoreLayerCollision(layerOne, layerTwo, ignore);
}
private void SetupLayers()
{
var log = new StringBuilder();
UnityEngine.Object[] asset = AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset");
if ((asset != null) && (asset.Length > 0))
{
try
{
var tagManager = asset[0];
SerializedObject serializedObject = new SerializedObject(asset[0]);
SerializedProperty layers = serializedObject.FindProperty("layers");
//TryShiftOldPlayerLayer(layers);
CleanUpOldDynamicPoseLayers(layers);
TryUpdateLayer(layers, HVRConstants.PlayerLayer, HVRLayers.Player.ToString(), log);
log.AppendLine("-----------------");
TryUpdateLayer(layers, HVRConstants.GrabbableLayer, HVRLayers.Grabbable.ToString(), log);
log.AppendLine("-----------------");
TryUpdateLayer(layers, HVRConstants.HandLayer, HVRLayers.Hand.ToString(), log);
log.AppendLine("-----------------");
TryUpdateDynamicPoseLayer(layers, log);
serializedObject.ApplyModifiedProperties();
serializedObject.Update();
EditorUtility.SetDirty(tagManager);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("Layer Report", log.ToString(), "Ok");
Debug.Log($"TagManager saved.");
}
catch (Exception e)
{
Debug.LogException(e);
}
}
else
{
Debug.LogWarning($"Unable to load ProjectSettings/TagManager.asset");
}
}
//private static void TryShiftOldPlayerLayer(SerializedProperty layers)
//{
// var playerOldValue = layers.GetArrayElementAtIndex(HVRConstants.OldPlayerLayer).stringValue;
// var playerNewValue = layers.GetArrayElementAtIndex(HVRConstants.PlayerLayer).stringValue;
// if (playerOldValue == HVRLayers.Player.ToString() && string.IsNullOrWhiteSpace(playerNewValue))
// {
// layers.GetArrayElementAtIndex(HVRConstants.PlayerLayer).stringValue = HVRLayers.Player.ToString();
// layers.GetArrayElementAtIndex(HVRConstants.OldPlayerLayer).stringValue = null;
// }
//}
private static void TryUpdateDynamicPoseLayer(SerializedProperty layers, StringBuilder log)
{
var dynamicPoseSet = false;
for (int i = 8; i < layers.arraySize; ++i)
{
var layer = layers.GetArrayElementAtIndex(i).stringValue;
if (layer == HVRLayers.DynamicPose.ToString())
{
dynamicPoseSet = true;
break;
}
}
if (!dynamicPoseSet)
{
for (int i = 9; i < layers.arraySize; ++i)
{
if (string.IsNullOrWhiteSpace(layers.GetArrayElementAtIndex(i).stringValue))
{
layers.GetArrayElementAtIndex(i).stringValue = HVRLayers.DynamicPose.ToString();
log.AppendLine($"{HVRLayers.DynamicPose} assigned to layer {i}");
dynamicPoseSet = true;
break;
}
}
}
if (!dynamicPoseSet)
{
log.AppendLine($"{HVRLayers.DynamicPose} layer could not be set. Make space for an additional layer and try again.");
}
}
private static void CleanUpOldDynamicPoseLayers(SerializedProperty layers)
{
for (int i = 8; i < layers.arraySize; ++i)
{
var layer = layers.GetArrayElementAtIndex(i).stringValue;
if (layer == "LeftTarget" || layer == "RightTarget")
{
layers.GetArrayElementAtIndex(i).stringValue = null;
}
}
}
private void TryUpdateLayer(SerializedProperty layers, int layer, string layerName, StringBuilder log)
{
var anySpace = false;
for (var i = 8; i < layers.arraySize; ++i)
{
var layerN = layers.GetArrayElementAtIndex(i).stringValue;
if (string.IsNullOrWhiteSpace(layerN))
{
anySpace = true;
}
if (i == layer)
continue;
if (layerN == layerName)
{
log.AppendLine($"{layerName} was found at position {i}. Intended position is {layer}. Remove it and try again.");
return;
}
}
if (!anySpace)
{
log.AppendLine($"No layer space available for required layer '{layerName}'. Make space and try again.");
return;
}
var property = layers.GetArrayElementAtIndex(layer);
if (string.IsNullOrWhiteSpace(property.stringValue))
{
log.AppendLine($"{layerName} assigned to layer {layer}");
property.stringValue = layerName;
}
else if (property.stringValue != layerName)
{
log.AppendLine($"{property.stringValue} was found at position {layer}. Intended layer is {layerName}. Remove and try again, or manually place {layerName} in another slot and update any {layerName} objects accordingly.");
}
else
{
log.AppendLine($"{layerName} already exists at slot {layer}");
}
}
private void SetupDefineButton(string buttonNameEnable, string buttonNameDisable, string define)
{
_root.Q<Button>(buttonNameEnable).clickable.clicked += () =>
{
SetupDefine(define, true);
};
_root.Q<Button>(buttonNameDisable).clickable.clicked += () =>
{
SetupDefine(define, false);
};
}
public void SetupDefine(string define, bool enable)
{
if (enable)
{
string dir;
switch (define)
{
case DEFINEOculus:
dir = $"Oculus";
break;
case DEFINESteamVR:
dir = $"SteamVR";
break;
//case DEFINEPun:
// dir = "PUN";
// break;
default:
return;
}
var path = Path.Combine(HVRSettings.Instance.GetRootFrameworkDirectory(), "Integrations");
path = Path.Combine(path, dir);
if (!Directory.Exists(path))
{
EditorUtility.DisplayDialog("Error!", $"{path} does not exist. Extract the integration package before enabling the scripting define symbol", "Ok!");
return;
}
}
var definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Trim();
var allDefines = definesString.Split(';').ToList();
if (enable)
{
allDefines.Add(define);
allDefines = allDefines.Distinct().ToList();
}
else
{
var index = allDefines.IndexOf(define);
if (index >= 0)
{
allDefines.RemoveAt(index);
}
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(";", allDefines.ToArray()));
}
}
}

View File

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

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Linq;
using HurricaneVR.Framework.Core.Grabbers;
using HurricaneVR.Framework.Core.Sockets;
using HurricaneVR.Framework.Core.Utils;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRSocketable), editorForChildClasses: true)]
public class HVRSocketableEditor : UnityEditor.Editor
{
private bool _expand;
private HVRSocket _socket;
private HVRSocketable component;
private Vector3 _pos;
private Quaternion _rot;
private static Dictionary<HVRSocketable, HVRSocket> _cache = new Dictionary<HVRSocketable, HVRSocket>();
private void OnEnable()
{
component = target as HVRSocketable;
if (_cache.TryGetValue(component, out var socket))
{
_socket = socket;
}
}
public override void OnInspectorGUI()
{
// _expand = EditorGUILayout.Foldout(_expand, "Posing Interface");
EditorGUILayout.LabelField("Posing:");
//if (_expand)
{
var temp = _socket;
HVREditorExtensions.ObjectField("Socket", ref _socket);
if (_socket)
{
if (string.IsNullOrWhiteSpace(_socket.PoseTag))
{
EditorGUILayout.HelpBox("Socket's PoseTag field is not assigned.", MessageType.Warning);
}
else
{
// if (GUILayout.Button("Snapshot Transform"))
// {
// _pos = component.transform.position;
// _rot = component.transform.rotation;
// }
//
// if (GUILayout.Button("Restore Transform"))
// {
// Undo.RecordObject(component.transform, "Restore Socketable");
// component.transform.SetPositionAndRotation(_pos, _rot);
// }
if (_socket.ScaleGrabbable)
{
if (GUILayout.Button("Apply Socket Scale"))
{
Undo.RecordObject(component.transform, "Editor Socket Scale");
component.transform.localScale = _socket.ComputeScale(component);
}
if (GUILayout.Button("Reset Scale"))
{
Undo.RecordObject(component.transform, "Editor Socket Scale");
component.transform.localScale = Vector3.one;
}
}
if (GUILayout.Button("Move to Socket"))
{
Undo.RecordObject(component.transform, "Move to Socket");
component.transform.position = _socket.transform.position;
component.transform.rotation = _socket.transform.rotation;
}
if (GUILayout.Button("Save Pose"))
{
var poses = serializedObject.FindProperty("Poses");
var i = component.Poses.FindIndex(e => e.SocketTag == _socket.PoseTag);
if (i < 0)
{
i = poses.arraySize;
poses.InsertArrayElementAtIndex(i);
}
var pose = poses.GetArrayElementAtIndex(i);
pose.FindPropertyRelative("Position").vector3Value = _socket.transform.InverseTransformPoint(component.transform.position);
pose.FindPropertyRelative("EulerAngles").vector3Value = (Quaternion.Inverse(_socket.transform.rotation) * component.transform.rotation).eulerAngles;
pose.FindPropertyRelative("SocketTag").stringValue = _socket.PoseTag;
serializedObject.ApplyModifiedProperties();
}
}
}
else
{
if(GUILayout.Button("Find Closest Socket"))
{
var dist = float.MaxValue;
HVRSocket closest = null;
foreach (var socket in FindObjectsOfType<HVRSocket>())
{
if (socket.transform.IsChildOf(component.transform))
{
continue;
}
var d = Vector3.Distance(component.transform.position, socket.transform.position);
if (d < dist)
{
dist = d;
closest = socket;
}
}
_socket = closest;
}
}
if (temp && !_socket)
{
_cache[component] = null;
}
else if (!temp && _socket)
{
_cache[component] = _socket;
}
}
EditorGUILayout.Space();
base.OnInspectorGUI();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 50bc40950ea34e579fb36b46f4d10e85
timeCreated: 1661143344

View File

@@ -0,0 +1,60 @@
using HurricaneVR.Framework.Core.Sockets;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomPropertyDrawer(typeof(HVRSocketableTag))]
public class HVRSocketableTagDrawer : PropertyDrawer
{
private HVRSocketableTags _tags;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
var tagsProperty = property.FindPropertyRelative("Tags");
position.height = 16;
tagsProperty.objectReferenceValue = EditorGUI.ObjectField(position, tagsProperty.objectReferenceValue, typeof(HVRSocketableTags), false);
position.y += 18;
position.height = 16;
var tag = fieldInfo.GetValue(property.serializedObject.targetObject) as HVRSocketableTag;
var tags = tagsProperty.objectReferenceValue as HVRSocketableTags;
if (tags != null)
{
if (GUI.Button(position, tag.DisplayName, EditorStyles.layerMaskField))
{
var pop = ScriptableObject.CreateInstance<HVRSocketableTagDropDown>();
pop.Setup(property.serializedObject, tag, tags);
var popPosition = position;
popPosition.position = GUIUtility.GUIToScreenPoint(position.position);
pop.ShowAsDropDown(popPosition, pop.GetWindowSize(position));
}
}
if (tags != _tags)
{
OnTagsChanged(tags);
}
EditorGUI.EndProperty();
}
private void OnTagsChanged(HVRSocketableTags tags)
{
_tags = tags;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return 36;
}
}
}

View File

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

View File

@@ -0,0 +1,66 @@
using HurricaneVR.Framework.Core.Sockets;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
public class HVRSocketableTagDropDown : EditorWindow
{
private HVRSocketableTag _tag;
private HVRSocketableTags _tags;
private SerializedObject _o;
public void Setup(SerializedObject o, HVRSocketableTag tag, HVRSocketableTags tags)
{
_tag = tag;
_tags = tags;
_o = o;
}
public Vector2 GetWindowSize(Rect controlRect)
{
int h = Mathf.Min(_tags.GetCount(), 32);
float height = 18 * h + 38;
return new Vector2(controlRect.width, height);
}
public void OnGUI()
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
var updated = false;
foreach (var tag in _tags.GetNames())
{
if (string.IsNullOrWhiteSpace(tag))
continue;
var index = _tags.GetIndex(tag);
var hasBit = _tag[index];
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal();
var toggled = GUILayout.Toggle(hasBit, new GUIContent(tag));
_tag[index] = toggled;
EditorGUILayout.EndHorizontal();
if (EditorGUI.EndChangeCheck())
{
updated = true;
}
}
if (updated)
{
EditorUtility.SetDirty(_o.targetObject);
}
EditorGUILayout.EndVertical();
}
}
}

View File

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

View File

@@ -0,0 +1,47 @@
using HurricaneVR.Framework.Core.Sockets;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRSocketableTags))]
public class HVRSocketableTagsEditor : UnityEditor.Editor
{
private HVRSocketableTags tags;
private SerializedProperty SPIdentifier;
private void OnEnable()
{
tags = target as HVRSocketableTags;
SPIdentifier = serializedObject.FindProperty(nameof(HVRSocketableTags.Identifier));
}
public override void OnInspectorGUI()
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.PropertyField(SPIdentifier);
GUILayout.Space(5);
for (int i = 0; i < 32; i++)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField($"{i}", GUILayout.Width(50));
tags[i] = EditorGUILayout.TextField(tags[i]);
EditorGUILayout.EndHorizontal();
}
GUILayout.Space(5);
EditorGUILayout.EndVertical();
if (GUI.changed)
{
EditorUtility.SetDirty(tags);
}
}
}
}

View File

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

View File

@@ -0,0 +1,128 @@
using System.Linq;
using HurricaneVR.Framework.Core.Stabbing;
using HurricaneVR.Framework.Core.Utils;
using HurricaneVR.Framework.Shared.Utilities;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRStabber))]
public class HVRStabberEditor : UnityEditor.Editor
{
public HVRStabber Stabber;
public SerializedProperty SP_IgnoreColliders;
protected void OnEnable()
{
Stabber = target as HVRStabber;
SP_IgnoreColliders = serializedObject.FindProperty("CollidersToIgnore");
}
public override void OnInspectorGUI()
{
if (!Stabber.Settings)
{
EditorGUILayout.HelpBox("Settings missing. Defaults will be used at runtime.", MessageType.Warning);
}
if (!Stabber.Tip)
{
EditorGUILayout.HelpBox("Tip Transform Is Unassigned.", MessageType.Error);
}
if (!Stabber.Base)
{
EditorGUILayout.HelpBox("Base Transform Is Unassigned.", MessageType.Error);
}
if (Stabber.StabbingColliders == null || Stabber.StabbingColliders.Length == 0)
{
EditorGUILayout.HelpBox("Stabbing Colliders is empty.", MessageType.Error);
}
if (!Stabber.Tip || !Stabber.Base)
{
if (GUILayout.Button("Add Transforms"))
{
if (!Stabber.Tip)
{
var tipt = Stabber.transform.Find("Tip");
GameObject tip;
tip = tipt?.gameObject;
if (!tip)
{
tip = new GameObject("Tip");
tip.transform.parent = Stabber.transform;
tip.transform.ResetLocalProps();
}
Stabber.Tip = tip.transform;
serializedObject.ApplyModifiedProperties();
}
if (!Stabber.Base)
{
var baseTran = Stabber.transform.Find("Base");
GameObject baseObj;
baseObj = baseTran?.gameObject;
if (!baseObj)
{
baseObj = new GameObject("Base");
baseObj.transform.parent = Stabber.transform;
baseObj.transform.ResetLocalProps();
}
Stabber.Base = baseObj.transform;
serializedObject.ApplyModifiedProperties();
}
}
}
if (Stabber.CollidersToIgnore == null || Stabber.CollidersToIgnore.Length == 0)
{
EditorGUILayout.HelpBox("CollidersToIgnore is empty. Will Populate with all colliders.", MessageType.Warning);
}
if (GUILayout.Button("Ignore Object Colliders"))
{
foreach (var c in Stabber.GetComponents<Collider>().Where(c => Stabber.CollidersToIgnore == null || !Stabber.CollidersToIgnore.Contains(c)))
{
var index = SP_IgnoreColliders.arraySize;
SP_IgnoreColliders.InsertArrayElementAtIndex(index);
SP_IgnoreColliders.GetArrayElementAtIndex(index).objectReferenceValue = c;
}
serializedObject.ApplyModifiedProperties();
}
if (GUILayout.Button("Ignore Child Colliders"))
{
foreach (var c in Stabber.GetComponentsInChildren<Collider>().Where(c => Stabber.CollidersToIgnore == null || !Stabber.CollidersToIgnore.Contains(c)))
{
var index = SP_IgnoreColliders.arraySize;
SP_IgnoreColliders.InsertArrayElementAtIndex(index);
SP_IgnoreColliders.GetArrayElementAtIndex(index).objectReferenceValue = c;
}
serializedObject.ApplyModifiedProperties();
}
base.OnInspectorGUI();
if (GUILayout.Button("Test Lock"))
{
Stabber.Lock();
}
if(GUILayout.Button("Test Unlock"))
{
Stabber.Unlock();
}
}
}
}

View File

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

View File

@@ -0,0 +1,84 @@
using HurricaneVR.Framework.Weapons;
using HurricaneVR.Framework.Weapons.Guns;
using UnityEditor;
using UnityEngine;
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRTriggerAnimator))]
public class HVRTriggerAnimatorEditor : UnityEditor.Editor
{
private SerializedProperty StartRotation;
private SerializedProperty EndRotation;
private SerializedProperty ForwardPosition;
private SerializedProperty BackwardPosition;
public HVRTriggerAnimator component;
protected void OnEnable()
{
StartRotation = serializedObject.FindProperty("StartRotation");
EndRotation = serializedObject.FindProperty("EndRotation");
ForwardPosition = serializedObject.FindProperty("ForwardPosition");
BackwardPosition = serializedObject.FindProperty("BackwardPosition");
component = target as HVRTriggerAnimator;
}
public override void OnInspectorGUI()
{
DrawButtons("Start Rotation", StartRotation);
DrawButtons("End Rotation", EndRotation);
DrawButtons2("Forward", ForwardPosition);
DrawButtons2("Backward", BackwardPosition);
EditorGUILayout.Space();
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
private void DrawButtons(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.quaternionValue = component.transform.localRotation;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localRotation = property.quaternionValue;
}
GUILayout.EndHorizontal();
}
private void DrawButtons2(string label, SerializedProperty property)
{
GUILayout.BeginHorizontal();
if (GUILayout.Button($"Save {label}"))
{
property.vector3Value = component.transform.localPosition;
}
if (GUILayout.Button($"GoTo {label}"))
{
Undo.RecordObject(component.transform, $"Goto {label}");
component.transform.localPosition = property.vector3Value;
}
GUILayout.EndHorizontal();
}
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,68 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace HurricaneVR.Editor
{
public static class LayerMaskDrawer
{
public static int LayerMaskField(string label, int layermask)
{
return FieldToLayerMask(EditorGUILayout.MaskField(label, LayerMaskToField(layermask),
InternalEditorUtility.layers));
}
public static int LayerMaskField(Rect position, string label, int layermask)
{
return FieldToLayerMask(EditorGUI.MaskField(position, label, LayerMaskToField(layermask),
InternalEditorUtility.layers));
}
/// <summary>
/// Converts field LayerMask values to in game LayerMask values
/// </summary>
/// <param name="field"></param>
/// <returns></returns>
private static int FieldToLayerMask(int field)
{
if (field == -1) return -1;
int mask = 0;
var layers = InternalEditorUtility.layers;
for (int c = 0; c < layers.Length; c++)
{
if ((field & (1 << c)) != 0)
{
mask |= 1 << LayerMask.NameToLayer(layers[c]);
}
else
{
mask &= ~(1 << LayerMask.NameToLayer(layers[c]));
}
}
return mask;
}
/// <summary>
/// Converts in game LayerMask values to field LayerMask values
/// </summary>
/// <param name="mask"></param>
/// <returns></returns>
private static int LayerMaskToField(int mask)
{
if (mask == -1) return -1;
int field = 0;
var layers = InternalEditorUtility.layers;
for (int c = 0; c < layers.Length; c++)
{
if ((mask & (1 << LayerMask.NameToLayer(layers[c]))) != 0)
{
field |= 1 << c;
}
}
return field;
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f1b16ccb83a5e744a80d50be1fb4a872
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: 785f3246a16797d44be439a99ba8180e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Windows Store Apps: WindowsStoreApps
second:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cfb57f6507e7489b923c8dc88ba1f777
timeCreated: 1597514958

View File

@@ -0,0 +1,34 @@
.HandLabel {
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
flex-direction: row;
flex-grow: 0;
flex-basis: 20px;
}
.HandsContainer {
flex-direction: row;
flex-grow: 1;
}
.CurlContainer {
height: auto;
flex-direction: column;
flex-grow: 1;
}
.CurlContainer Label {
max-width: 75px;
min-width: 75px;
}
.FingerStartContainer Label {
max-width: 75px;
min-width: 75px;
}
.CurlContainer EnumField {
max-width: 150px;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 163382055bc6c7b42abf99ea3b47b0ad
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,55 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:BindableElement name="BlendEditorRoot" class="unity-box" style="height: auto; flex-grow: 1;">
<Style src="HVRBlendEditor.uss" />
<ui:VisualElement style="margin-top: 4px;">
<ui:Label text="Label" name="lblSelectedPose" style="font-size: 20px; -unity-font-style: bold; margin-left: 8px;" />
</ui:VisualElement>
<ui:VisualElement class="HandsContainer">
<ui:VisualElement name="CurlContainer" class="unity-box CurlContainer" style="flex-grow: 1;">
<ui:Label text="Finger Curls:" class="HandLabel" />
<uie:EnumField label="Thumb" value="Static" name="ThumbType" binding-path="ThumbType" type="HurricaneVR.Framework.Core.HandPoser.HVRFingerType, HurricaneVR.Framework" style="flex-basis: 20px; max-width: 150px;" />
<uie:EnumField label="Index" value="Close" name="IndexType" binding-path="IndexType" type="HurricaneVR.Framework.Core.HandPoser.HVRFingerType, HurricaneVR.Framework" />
<uie:EnumField label="Middle" value="Close" name="MiddleType" binding-path="MiddleType" type="HurricaneVR.Framework.Core.HandPoser.HVRFingerType, HurricaneVR.Framework" />
<uie:EnumField label="Ring" value="Close" name="RingType" binding-path="RingType" type="HurricaneVR.Framework.Core.HandPoser.HVRFingerType, HurricaneVR.Framework" />
<uie:EnumField label="Pinky" value="Close" name="PinkyType" binding-path="PinkyType" type="HurricaneVR.Framework.Core.HandPoser.HVRFingerType, HurricaneVR.Framework" />
</ui:VisualElement>
<ui:VisualElement name="FingerStartContainer" class="unity-box FingerStartContainer" style="flex-grow: 4;">
<ui:Label text="Finger Start" class="HandLabel" />
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider label="Thumb" value=".80" name="ThumbStart" binding-path="ThumbStart" high-value="1" style="flex-grow: 1; flex-basis: auto; flex-shrink: 0;" />
<uie:FloatField binding-path="ThumbStart" readonly="true" style="flex-grow: 0; flex-basis: 40px;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider label="Index" value="0" name="IndexStart" binding-path="IndexStart" high-value="1" style="flex-grow: 1;" />
<uie:FloatField binding-path="IndexStart" readonly="true" style="flex-grow: 0; flex-basis: 40px;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider label="Middle" value="0" name="MiddleStart" binding-path="MiddleStart" high-value="1" style="flex-grow: 1;" />
<uie:FloatField binding-path="MiddleStart" readonly="true" style="flex-grow: 0; flex-basis: 40px;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider label="Ring" value="0" name="RingStart" binding-path="RingStart" high-value="1" style="flex-grow: 1;" />
<uie:FloatField binding-path="RingStart" readonly="true" style="flex-grow: 0; flex-basis: 40px;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider label="Pinky" value="0" name="PinkyStart" binding-path="PinkyStart" high-value="1" style="flex-grow: 1;" />
<uie:FloatField binding-path="PinkyStart" readonly="true" style="flex-grow: 0; flex-basis: 40px;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
<uie:ObjectField label="Pose" binding-path="Pose" name="Pose" />
<ui:VisualElement style="flex-direction: row; flex-grow: 1; flex-basis: auto; height: auto;">
<ui:Slider name="Weight" label="Weight" binding-path="Weight" high-value="1" style="flex-grow: 1; flex-basis: auto; flex-shrink: 1;" />
<uie:FloatField binding-path="Weight" readonly="true" style="flex-grow: 0; flex-basis: 80px;" />
</ui:VisualElement>
<uie:FloatField label="Speed" value="1" binding-path="Speed" tooltip="Speed by deltaTime" name="Speed" />
<uie:EnumFlagsField label="Mask" value="All" binding-path="Mask" />
<uie:EnumField label="Type" binding-path="Type" name="Type" />
<ui:VisualElement style="flex-direction: row; flex-grow: 0; flex-basis: auto;">
<ui:TextField picking-mode="Ignore" label="Animation Parameter" binding-path="AnimationParameter" style="flex-grow: 1;" />
</ui:VisualElement>
<ui:Toggle label="Disabled" binding-path="Disabled" name="Disabled" />
<ui:Toggle label="Button Parameter?" name="ButtonParameter" binding-path="ButtonParameter" />
<uie:EnumField label="Button" value="Center" name="Button" binding-path="Button" />
</ui:BindableElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 46265eae23883104a87445cdb934c90f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,19 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:Template name="HandSettingsTemplate" src="HVRHandSettingsEditor.uxml" />
<ui:Box>
<Style src="HVRHandPoserEditor.uss" />
<ui:VisualElement style="flex-direction: row;">
<ui:VisualElement name="Buttons" style="flex-direction: row; flex-grow: 1; width: 83px; flex-basis: 41px;">
<ui:Button name="NewPose" text="New" />
<ui:Button name="SaveAsPose" text="Save As" />
<ui:Button name="SavePose" text="Save" />
<ui:Button name="Preview" text="Preview Selected" style="width : 125px"/>
</ui:VisualElement>
</ui:VisualElement>
<uie:ObjectField label="Selected Pose" binding-path="SelectedPose" name="SelectedPose" style="flex-direction: row;" />
<uie:EnumField label="MirrorAxis" value="X" name="MirrorAxis" binding-path="MirrorAxis" />
<ui:VisualElement name="HandContainer" class="unity-box HandContainer">
<ui:Toggle label="Preview Mirror" name="Preview" class="HandPreviewToggle" />
</ui:VisualElement>
</ui:Box>
</ui:UXML>

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c878c2004cc746c7a51051928cd83b8f
timeCreated: 1597519215

View File

@@ -0,0 +1,71 @@
#Buttons {
width: auto;
display: flex;
flex-direction: row;
}
#EditButtons {
width: auto;
display: flex;
flex-direction: row;
}
#SelectedPose {
display: flex;
flex-direction: column;
}
#PreviewButtons {
display: flex;
flex-direction: row;
}
Button {
width: 75px;
}
.primarypose {
}
#SelectedPoseRow {
display: flex;
flex-direction: column;
}
#ActivePose {
flex-grow: 2;
}
.HandContainer {
height: auto;
flex-direction: column;
flex-grow: 1;
}
.HandLabel {
border-left-width: 1px;
border-right-width: 1px;
border-top-width: 1px;
border-bottom-width: 1px;
flex-direction: row;
flex-grow: 0;
flex-basis: 20px;
}
.HandMirrorButton {
flex-grow: 0;
flex-basis: 26px;
width: -5px;
}
.HandPreviewToggle {
margin-top: 3px;
flex-grow: 0;
flex-basis: 15px;
align-items: center;
}
.HandsContainer {
flex-direction: row;
flex-grow: 1;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 439c386fb2511b442aca177bd48ae754
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,26 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:Template name="HandSettingsTemplate" src="HVRHandSettingsEditor.uxml" />
<ui:Template name="BlendEditorTemplate" src="HVRBlendEditor.uxml" />
<ui:Box>
<Style src="HVRHandPoserEditor.uss" />
<ui:VisualElement style="flex-direction: row; flex-shrink: 0;">
<ui:VisualElement name="Buttons" style="flex-direction: column; flex-grow: 1; width: 83px; flex-basis: 41px;">
<ui:Button name="AddBlendPose" text="Add" />
<ui:Button name="DeleteBlendPose" text="Remove" />
<ui:Button name="NewPose" text="New" />
<ui:Button name="SaveAsPose" text="Save As" />
<ui:Button name="SavePose" text="Save" />
</ui:VisualElement>
<ui:VisualElement name="PosesContainer" class="unity-box" style="flex-grow: 5;">
<ui:Label text="Poses:" style="font-size: 19px; border-bottom-width: 3px; border-bottom-color: rgb(173, 173, 173);" />
<ui:ListView name="Poses" style="flex-grow: 5;" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="warning">
<ui:Label text="Posing is not available while in Prefab Mode." style="height: 46px; color: rgb(217, 183, 9); -unity-font-style: bold; font-size: 20px; white-space: normal; margin-bottom: 10px;" />
</ui:VisualElement>
<uie:EnumField label="MirrorAxis" value="X" name="MirrorAxis" binding-path="MirrorAxis" />
<ui:Instance template="HandSettingsTemplate" name="boxPreview" />
<ui:Instance template="BlendEditorTemplate" />
</ui:Box>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: ee1b362ac4812234a88ce0fc8d995122
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,40 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement>
<Style src="HVRHandPoserEditor.uss" />
<ui:VisualElement name="lblAutoPoseWarning">
<ui:Label text="Rigidbody detected, if dynamic posing doesn&apos;t work, remove it temporarily." style="font-size: 18px; color: rgb(250, 235, 20); flex-wrap: nowrap; margin-bottom: 10px; height: 50px; white-space: normal;" />
</ui:VisualElement>
<ui:VisualElement class="HandsContainer">
<ui:VisualElement name="LeftHandContainer" class="unity-box HandContainer">
<ui:Label text="Left Hand:" class="HandLabel" />
<ui:Toggle label="Preview" name="PreviewLeft" class="HandPreviewToggle" />
<ui:Toggle label="Auto Pose" name="LeftAutoPose" class="HandPreviewToggle" />
<ui:VisualElement style="flex-direction: row; flex-basis: 28px;">
<ui:Button name="ButtonOpenLeft" text="Open" class="HandMirrorButton" style="flex-basis: auto; flex-grow: 1;" />
<ui:Button name="ButtonCloseLeft" text="Close" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-basis: 28px;">
<ui:Button name="ButtonMirrorRight" text="Mirror" class="HandMirrorButton" style="flex-basis: auto; flex-grow: 1;" />
<ui:Button name="ButtonFocusLeft" text="Focus" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
<ui:Button name="LeftExpand" text="+" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
<ui:Button name="LeftCollapse" text="-" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
</ui:VisualElement>
</ui:VisualElement>
<ui:VisualElement name="RightHandContainer" class="unity-box HandContainer">
<ui:Label text="Right Hand:" class="HandLabel" />
<ui:Toggle label="Preview" name="PreviewRight" class="HandPreviewToggle" />
<ui:Toggle label="Auto Pose" name="RightAutoPose" class="HandPreviewToggle" />
<ui:VisualElement style="flex-direction: row; flex-basis: 28px;">
<ui:Button name="ButtonOpenRight" text="Open" class="HandMirrorButton" style="flex-basis: auto; flex-grow: 1;" />
<ui:Button name="ButtonCloseRight" text="Close" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
</ui:VisualElement>
<ui:VisualElement style="flex-direction: row; flex-basis: 28px; flex-wrap: wrap;">
<ui:Button name="ButtonMirrorLeft" text="Mirror" class="HandMirrorButton" style="flex-basis: auto; flex-grow: 1;" />
<ui:Button name="ButtonFocusRight" text="Focus" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
<ui:Button name="RightExpand" text="+" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
<ui:Button name="RightCollapse" text="-" class="HandMirrorButton" style="flex-grow: 1; flex-basis: auto;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: b3909a95d4f9f714f82f11ed1843b432
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,29 @@
.field-select-button {
flex-basis: auto;
padding-left: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
width: 20px;
}
.poserow {
flex-direction: row;
min-height:20px;
}
.poserow-button {
flex-grow: 1;
}
.poserow-field {
flex-grow: 5;
}
.pose-field {
height : 20px
}
.recorded-poses{
flex-grow: 5; flex-basis: 300px
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 926c6e4191463d249a0fc1ed8b620773
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

View File

@@ -0,0 +1,61 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:ScrollView name="ScrollView">
<ui:Foldout text="Grabbable" name="GrabbableFoldout" class="unity-box">
<ui:VisualElement name="Grabbable" class="unity-box" style="border-left-width: 0; border-right-width: 0; border-top-width: 0; border-bottom-width: 0;">
<uie:Toolbar class="unity-box">
<uie:ToolbarButton text="Set Selected" name="SetGrabbable" />
<uie:ToolbarButton text="Focus" name="FocusGrabbable" />
<uie:ToolbarButton text="Setup" name="SetupGrabbable" />
<uie:ToolbarButton text="Populate GrabPoints" name="SetupGrabPoints" />
<uie:ToolbarButton text="Expand" name="ExpandGrabbable" />
<uie:ToolbarButton text="Collapse" name="CollapseGrabbable" />
</uie:Toolbar>
<ui:VisualElement class="unity-box" style="flex-direction: row;">
<uie:ObjectField label="Grabbable" name="Grabbable" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:Foldout>
<ui:Foldout text="GrabPoints" name="GrabPoints" class="unity-box">
<uie:Toolbar class="unity-box" style="flex-basis: 20px;">
<uie:ToolbarButton text="Set Selected" name="SetGrabPoints" />
<uie:ToolbarButton text="Focus" name="FocusGrabPoints" />
<uie:ToolbarButton text="Setup" name="AddGrabPoints" />
<uie:ToolbarButton text="Add" name="AddGrabPointButton" />
<uie:ToolbarButton text="Expand" name="ExpandGrabPoints" />
<uie:ToolbarButton text="Collapse" name="CollapseGrabPoints" />
</uie:Toolbar>
<ui:VisualElement class="unity-box">
<ui:TextField picking-mode="Ignore" label="Recorded Pose Prefix:" name="RecordedPrefixTextBox" />
<ui:VisualElement style="flex-direction: row;">
<uie:ObjectField label="GrabPoints" name="GrabPointsObject" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:Foldout>
<ui:Foldout text="Poser" name="PoserFoldout" class="unity-box">
<ui:VisualElement>
<uie:Toolbar class="unity-box" style="flex-basis: 20px;">
<uie:ToolbarButton text="Set Selected" name="SetPoser" />
<uie:ToolbarButton text="Focus" name="FocusPoser" />
<uie:ToolbarButton text="Setup" name="AddPoser" />
</uie:Toolbar>
<ui:VisualElement class="unity-box" style="flex-direction: row;">
<uie:ObjectField label="HandPoser" name="VRHandPoser" style="flex-grow: 1;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:Foldout>
<ui:Foldout text="Recorded Poses" name="RecordedPosesFoldout" class="unity-box" style="flex-direction: column; flex-grow: 1;">
<ui:VisualElement style="flex-direction: column; flex-grow: 1;">
<uie:Toolbar class="unity-box" style="flex-basis: 20px;">
<uie:ToolbarButton text="Load Poses" name="LoadPoses" />
<uie:ToolbarButton text="Setup" name="AddPoser" />
</uie:Toolbar>
<ui:VisualElement class="unity-box" style="flex-direction: column; flex-grow: 1;">
<ui:VisualElement name="RecordedPosesContainer" class="recorded-poses">
<ui:Label text="Poses:" style="font-size: 19px; border-bottom-width: 3px; border-bottom-color: rgb(173, 173, 173);" />
<ui:ScrollView name="RecordedPoses" style="flex-grow: 5;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:Foldout>
</ui:ScrollView>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d7ffb88ae90c7734189abb93a861f93b
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,13 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:Foldout text="Tools">
<Style src="HVRHandPoserEditor.uss" />
<uie:Toolbar style="flex-direction: row;">
<uie:ToolbarButton text="Setup" name="SetupButton" style="padding-left: 6px; padding-right: 6px;" />
<uie:ToolbarButton text="Open" name="ResetButton" style="padding-left: 6px; padding-right: 6px;" />
<uie:ToolbarButton text="Close" name="SimulateButton" />
<uie:ToolbarButton text="Next Finger" name="NextFingerButton" />
<uie:ToolbarButton text="+" name="StepButton" />
<uie:ToolbarButton text="-" name="StepBackButton" />
</uie:Toolbar>
</ui:Foldout>
</ui:UXML>

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b91c6b2ef78b483a8eb24c7feb9b729f
timeCreated: 1597727626

View File

@@ -0,0 +1,31 @@
.button {
width: 50%;
-unity-text-align: upper-center;
padding-left: 0;
padding-right: 0;
align-items: center;
justify-content: flex-start;
padding-top: 0;
padding-bottom: 0;
margin-left: 25%;
margin-right: 25%;
margin-bottom: 5px;
}
.buttonHeader {
-unity-text-align: upper-center;
flex-wrap: wrap;
margin-bottom: 7px;
align-items: flex-start;
}
.docs-button {
width: auto;
margin-left: 5px;
margin-right: 5px;
max-width: none;
min-width: auto;
margin-top: 2px;
margin-bottom: 2px;
-unity-text-align: upper-left;
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3360967efa8b94c428cdb0d6af79e902
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0

Some files were not shown because too many files have changed in this diff Show More