Replace UltimateXR with HurricaneVR
This commit is contained in:
8
Assets/HurricaneVR.meta
Normal file
8
Assets/HurricaneVR.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed18a0babc8b032438b8b4758d1d90f4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/HurricaneVR/Documentation.meta
Normal file
8
Assets/HurricaneVR/Documentation.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 281637870489c904da4051738c7900e6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/HurricaneVR/Documentation/HVR Project Setup.pdf
Normal file
BIN
Assets/HurricaneVR/Documentation/HVR Project Setup.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ff21fe5616684e4383d0aa958bf111f
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1402
Assets/HurricaneVR/Documentation/ReleaseNotes.txt
Normal file
1402
Assets/HurricaneVR/Documentation/ReleaseNotes.txt
Normal file
File diff suppressed because it is too large
Load Diff
7
Assets/HurricaneVR/Documentation/ReleaseNotes.txt.meta
Normal file
7
Assets/HurricaneVR/Documentation/ReleaseNotes.txt.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 975def741748acc49afc0f7490930658
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/HurricaneVR/Framework.meta
Normal file
8
Assets/HurricaneVR/Framework.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d1bb57c7847e5343b5f70d65b53da5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e57bd9c082580bf4f8a951b1ec95dc1e
|
||||
guid: 5d8c74653f3e7d74aa56a7d95be90f1e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
55
Assets/HurricaneVR/Framework/Editor/CustomContexts.cs
Normal file
55
Assets/HurricaneVR/Framework/Editor/CustomContexts.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2d14f6a173045b08af8717e276df756
|
||||
timeCreated: 1666239275
|
||||
35
Assets/HurricaneVR/Framework/Editor/DefaultEditor.cs
Normal file
35
Assets/HurricaneVR/Framework/Editor/DefaultEditor.cs
Normal 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;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/DefaultEditor.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/DefaultEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d70d4fbf097b11b4085d726d4d5d9a2f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
97
Assets/HurricaneVR/Framework/Editor/DrawIfPropertyDrawer.cs
Normal file
97
Assets/HurricaneVR/Framework/Editor/DrawIfPropertyDrawer.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 586560ba4b0d37d43ace1af227ee903b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
49
Assets/HurricaneVR/Framework/Editor/EmbeddedAssetDrawer.cs
Normal file
49
Assets/HurricaneVR/Framework/Editor/EmbeddedAssetDrawer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3003c99effe439d9d06c4e9334443ba
|
||||
timeCreated: 1666146629
|
||||
181
Assets/HurricaneVR/Framework/Editor/EmbeddedAssetEditor.cs
Normal file
181
Assets/HurricaneVR/Framework/Editor/EmbeddedAssetEditor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63f79aabdd614d20a214af69939cd772
|
||||
timeCreated: 1666142031
|
||||
47
Assets/HurricaneVR/Framework/Editor/EnumFlagDrawer.cs
Normal file
47
Assets/HurricaneVR/Framework/Editor/EnumFlagDrawer.cs
Normal 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
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65081c63cc3a470592efc2d38872c555
|
||||
timeCreated: 1599786045
|
||||
78
Assets/HurricaneVR/Framework/Editor/HVRButtonEditor.cs
Normal file
78
Assets/HurricaneVR/Framework/Editor/HVRButtonEditor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRButtonEditor.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRButtonEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec43d29e2cf2b7e41ae13941d16c76a0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b3aafea37b7e734fba0f8e4670b19f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/HurricaneVR/Framework/Editor/HVRCommentsInspector.cs
Normal file
42
Assets/HurricaneVR/Framework/Editor/HVRCommentsInspector.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23433d973f5e337409ea8e0d7f5a4e1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
63
Assets/HurricaneVR/Framework/Editor/HVREditorExtensions.cs
Normal file
63
Assets/HurricaneVR/Framework/Editor/HVREditorExtensions.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b719d979594d6d14cb08512dcd23a176
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
35
Assets/HurricaneVR/Framework/Editor/HVREditorManager.cs
Normal file
35
Assets/HurricaneVR/Framework/Editor/HVREditorManager.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVREditorManager.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVREditorManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca460b047514fc245932d2ad590f64cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
Assets/HurricaneVR/Framework/Editor/HVREditorPreferences.cs
Normal file
50
Assets/HurricaneVR/Framework/Editor/HVREditorPreferences.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3adfb6cabe631f40a72c285abbb95d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
58
Assets/HurricaneVR/Framework/Editor/HVRGunBoltEditor.cs
Normal file
58
Assets/HurricaneVR/Framework/Editor/HVRGunBoltEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRGunBoltEditor.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRGunBoltEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f09a0f197de2dbf48963da0855f6eb05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
852
Assets/HurricaneVR/Framework/Editor/HVRGunCreator.cs
Normal file
852
Assets/HurricaneVR/Framework/Editor/HVRGunCreator.cs
Normal 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
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRGunCreator.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRGunCreator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e605f2614760bc241bb4c8d3a5837b45
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
55
Assets/HurricaneVR/Framework/Editor/HVRGunPartEditor.cs
Normal file
55
Assets/HurricaneVR/Framework/Editor/HVRGunPartEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRGunPartEditor.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRGunPartEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eef108aaab0786c4cb8d79e1a5cb165c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1590
Assets/HurricaneVR/Framework/Editor/HVRHandPoserEditor.cs
Normal file
1590
Assets/HurricaneVR/Framework/Editor/HVRHandPoserEditor.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 564c582cd2911434cbb0213817a07414
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
885
Assets/HurricaneVR/Framework/Editor/HVRHandSetup.cs
Normal file
885
Assets/HurricaneVR/Framework/Editor/HVRHandSetup.cs
Normal 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
|
||||
}
|
||||
}
|
||||
3
Assets/HurricaneVR/Framework/Editor/HVRHandSetup.cs.meta
Normal file
3
Assets/HurricaneVR/Framework/Editor/HVRHandSetup.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f0472cefbaa9584b954464702dc8c64
|
||||
timeCreated: 1636698677
|
||||
513
Assets/HurricaneVR/Framework/Editor/HVRManagementWindow.cs
Normal file
513
Assets/HurricaneVR/Framework/Editor/HVRManagementWindow.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b31c0ac23bc7f61479f2acc0ed0f1f46
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
124
Assets/HurricaneVR/Framework/Editor/HVRPhysicsButtonEditor.cs
Normal file
124
Assets/HurricaneVR/Framework/Editor/HVRPhysicsButtonEditor.cs
Normal 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();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dcc4cd864758ca48b692598f4728d84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
40
Assets/HurricaneVR/Framework/Editor/HVRPhysicsDialEditor.cs
Normal file
40
Assets/HurricaneVR/Framework/Editor/HVRPhysicsDialEditor.cs
Normal 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();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d84dbddaa4b8c24caf500b9b4e26b1f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1de5fb46519d604193554fc38d3ddc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a1950017ffcb864289a868c5cebf1ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
92
Assets/HurricaneVR/Framework/Editor/HVRPhysicsPoserEditor.cs
Normal file
92
Assets/HurricaneVR/Framework/Editor/HVRPhysicsPoserEditor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 501f725b398d400198031761cf4bf5d2
|
||||
timeCreated: 1597727990
|
||||
326
Assets/HurricaneVR/Framework/Editor/HVRPosableHandEditor.cs
Normal file
326
Assets/HurricaneVR/Framework/Editor/HVRPosableHandEditor.cs
Normal 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()
|
||||
// {
|
||||
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 192a54905c104022bbde4eca5d554a92
|
||||
timeCreated: 1597519653
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03d09e0e8a32fca41bd270aea026c9a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
523
Assets/HurricaneVR/Framework/Editor/HVRSetupWindow.cs
Normal file
523
Assets/HurricaneVR/Framework/Editor/HVRSetupWindow.cs
Normal 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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRSetupWindow.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRSetupWindow.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67090cbd51e5b834b8590d9c8f5569b6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
146
Assets/HurricaneVR/Framework/Editor/HVRSocketableEditor.cs
Normal file
146
Assets/HurricaneVR/Framework/Editor/HVRSocketableEditor.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50bc40950ea34e579fb36b46f4d10e85
|
||||
timeCreated: 1661143344
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af126f1c61f04494f9d14a5bb99401a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ddf74826ad344df428cde4815d8a3857
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00aaee8668a7dd048a29af68c04053fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
128
Assets/HurricaneVR/Framework/Editor/HVRStabberEditor.cs
Normal file
128
Assets/HurricaneVR/Framework/Editor/HVRStabberEditor.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/HVRStabberEditor.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/HVRStabberEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cf54d201e5fb5a4ca1097b7cc4a8e30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a79f342c0ec6853469d5ee95d4e0163f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "HurricaneVR.Editor",
|
||||
"references": [
|
||||
"HurricaneVR.Framework"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f09fe70053914dc4d9bbc4bcbffdbe7f
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
Assets/HurricaneVR/Framework/Editor/LayerMaskDrawer.cs
Normal file
68
Assets/HurricaneVR/Framework/Editor/LayerMaskDrawer.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/HurricaneVR/Framework/Editor/LayerMaskDrawer.cs.meta
Normal file
11
Assets/HurricaneVR/Framework/Editor/LayerMaskDrawer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf704307b8045f3479514f563b334012
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/HurricaneVR/Framework/Editor/Libs.meta
Normal file
8
Assets/HurricaneVR/Framework/Editor/Libs.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1b16ccb83a5e744a80d50be1fb4a872
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/HurricaneVR/Framework/Editor/Libs/HurricaneVR.Update.dll
Normal file
BIN
Assets/HurricaneVR/Framework/Editor/Libs/HurricaneVR.Update.dll
Normal file
Binary file not shown.
@@ -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:
|
||||
3
Assets/HurricaneVR/Framework/Editor/Resources.meta
Normal file
3
Assets/HurricaneVR/Framework/Editor/Resources.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfb57f6507e7489b923c8dc88ba1f777
|
||||
timeCreated: 1597514958
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 46265eae23883104a87445cdb934c90f
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c878c2004cc746c7a51051928cd83b8f
|
||||
timeCreated: 1597519215
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee1b362ac4812234a88ce0fc8d995122
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -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'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>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3909a95d4f9f714f82f11ed1843b432
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7ffb88ae90c7734189abb93a861f93b
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b91c6b2ef78b483a8eb24c7feb9b729f
|
||||
timeCreated: 1597727626
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user