NEW HVR 2.9.1f

This commit is contained in:
2023-03-25 03:17:58 +03:00
parent f0bf64ed45
commit 91acc4d728
243 changed files with 16657 additions and 11137 deletions
@@ -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
@@ -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
@@ -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
@@ -43,6 +43,10 @@ namespace HurricaneVR.Editor
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)
{
@@ -9,7 +9,7 @@ namespace HurricaneVR.Editor
public class HVREditorManager
{
private const string HurricaneVRUploader = "HurricaneVRUploader";
public const string Version = "2.8.4";
public const string Version = "2.9.1f";
[InitializeOnLoadMethod]
private static void Hook()
@@ -7,13 +7,14 @@ 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;
using Zero;
namespace HurricaneVR.Editor
{
@@ -26,8 +27,8 @@ namespace HurricaneVR.Editor
//private const string TwoHandPistol = "HandSettings/HVR_Pistol_TwoHand";
//private const string TwoHandLarge = "HandSettings/HVR_LargeWeapon_TwoHanded";
private const string TwoHandLargeStabilizer = "HandSettings/HVR_Stabilizer_TwoHanded";
private const string TwoHandPistolStabilizer = "HandSettings/HVR_Pistol_Stabilizer_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";
@@ -48,7 +49,7 @@ namespace HurricaneVR.Editor
private float _gunMass = 1.5f;
private float _bulletSpeed = 80f;
private int _rpm = 900;
private FireType _firingType;
private GunFireType _firingType;
private HVRHandPose _gripPose;
private HVRHandPose _stabilizerPose;
@@ -67,9 +68,9 @@ namespace HurricaneVR.Editor
private bool _stabilizerRequiresGripGrabbed = true;
private bool _stabilizerDropsOnGripReleased = true;
private float _cycleTime = .05f;
private HVRJointSettings _gripOneHand;
private HVRJointSettings _gripTwoHand;
private HVRJointSettings _stabilizerTwoHand;
private PDStrength _gripOneHand;
private PDStrength _gripTwoHand;
private PDStrength _stabilizerTwoHand;
private bool _ejectedBulletPooled = true;
private HVRRecoilSettings _recoilSettings;
private Vector2 _scrollPosition;
@@ -127,7 +128,7 @@ namespace HurricaneVR.Editor
HVREditorExtensions.IntField("Rounds Per Minute", ref _rpm);
HVREditorExtensions.FloatField("Bullet Speed", ref _bulletSpeed);
_firingType = (FireType)EditorGUILayout.EnumPopup("Firing Mode", _firingType);
_firingType = (GunFireType)EditorGUILayout.EnumPopup("Firing Mode", _firingType);
var currentType = _gunType;
_gunType = (HVRGunType)EditorGUILayout.EnumPopup("Type", _gunType);
_hitLayerMask = LayerMaskDrawer.LayerMaskField("Hit Layer Mask", _hitLayerMask);
@@ -179,9 +180,9 @@ namespace HurricaneVR.Editor
// PopulateDefaultHandSettings();
//}
HVREditorExtensions.JointField("Grip One Handed", ref _gripOneHand);
HVREditorExtensions.JointField("Grip Two Handed", ref _gripTwoHand);
HVREditorExtensions.JointField("Stabilizer Two Handed", ref _stabilizerTwoHand);
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");
@@ -377,8 +378,8 @@ namespace HurricaneVR.Editor
Undo.RegisterCreatedObjectUndo(root, _gunPrefab.name);
gunGrabbable = AddGrabbable(root, out var poser, out var gp);
gunGrabbable.OneHandJointSettings = _gripOneHand;
gunGrabbable.TwoHandJointSettings = _gripTwoHand;
gunGrabbable.OneHandStrength = _gripOneHand;
gunGrabbable.TwoHandStrength = _gripTwoHand;
poser.PrimaryPose.Pose = _gripPose;
gunGrabbable.HoldType = HVRHoldType.Swap;
gunGrabbable.RequireOverlapClearance = true;
@@ -398,19 +399,19 @@ namespace HurricaneVR.Editor
private GameObject CreatePistol()
{
var root = CreateGun<ExtGunBase>(out var gunGrabbable, out var model, out var gun);
var root = CreateGun<HVRPistol>(out var gunGrabbable, out var model, out var gun);
return root;
}
private GameObject CreateAutomatic()
{
var root = CreateGun<ExtGunBase>(out var gunGrabbable, out var model, out var gun);
var root = CreateGun<HVRAutomaticGun>(out var gunGrabbable, out var model, out var gun);
return root;
}
private GameObject CreatePumpShotgun()
{
var root = CreateGun<ExtGunShotgun>(out var gunGrabbable, out var model, out var gun);
var root = CreateGun<HVRShotgun>(out var gunGrabbable, out var model, out var gun);
var mag = root.AddComponent<HVRShotgunMagazine>();
gun.ChambersAfterFiring = false;
mag.MaxCount = 5;
@@ -454,9 +455,8 @@ namespace HurricaneVR.Editor
//grabbable.TrackingType = HVRGrabTracking.None;
grabbable.HoldType = HVRHoldType.OneHand;
grabbable.DisableHandCollision = true;
grabbable.PoseImmediately = true;
grabbable.ForceGrabbable = false;
grabbable.TwoHandJointSettings = _stabilizerTwoHand;
grabbable.TwoHandStrength = _stabilizerTwoHand;
grabbable.ExtraIgnoreCollisionParents = new List<Transform>() { gunGrabbable.Rigidbody.transform };
if (_stabilizerRequiresGripGrabbed)
@@ -500,6 +500,10 @@ namespace HurricaneVR.Editor
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);
@@ -14,6 +14,12 @@ using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
#if UNITY_2021_2_OR_NEWER
using UnityEditor.SceneManagement;
#else
using UnityEditor.Experimental.SceneManagement;
#endif
namespace HurricaneVR.Editor
{
[CustomEditor(typeof(HVRHandPoser))]
@@ -108,10 +114,7 @@ namespace HurricaneVR.Editor
private HVRHandPoseBlend PrimaryPose
{
get
{
return Poser.PrimaryPose;
}
get { return Poser.PrimaryPose; }
set
{
Poser.PrimaryPose = value;
@@ -121,10 +124,7 @@ namespace HurricaneVR.Editor
public HVRHandPose SelectedPose
{
get
{
return SelectedBlendPose?.Pose;
}
get { return SelectedBlendPose?.Pose; }
set
{
if (SelectedBlendPose == null) return;
@@ -184,7 +184,6 @@ namespace HurricaneVR.Editor
{
SceneView.duringSceneGui -= OnSceneGUI2;
SceneView.duringSceneGui += OnSceneGUI2;
}
@@ -225,7 +224,6 @@ namespace HurricaneVR.Editor
}
foreach (var c in cleanup) _map.Remove(c);
}
private void GetHands(ref HVRPosableHand leftHand, ref HVRPosableHand rightHand)
@@ -414,6 +412,7 @@ namespace HurricaneVR.Editor
{
selectedFinger = i;
}
selectedBone = bone.Transform;
}
}
@@ -425,6 +424,9 @@ namespace HurricaneVR.Editor
}
}
private bool _inPrefabMode;
private bool _active;
private void OnEnable()
{
Poser = target as HVRHandPoser;
@@ -452,13 +454,30 @@ namespace HurricaneVR.Editor
_root = new VisualElement();
_tree = UnityEngine.Resources.Load<VisualTreeAsset>("HVRHandPoserEditor");
var stage = PrefabStageUtility.GetPrefabStage(Poser.gameObject);
_inPrefabMode = stage != null;
_active = true;
var s = _root.schedule.Execute(EditorUpdate);
s.Every(1000);
s.Until(() => !_active);
}
private void EditorUpdate()
{
CheckRigidBody();
}
private void OnDisable()
{
_active = false;
}
private void CreatePoseIfNeeded()
{
if (PrimaryPose.Pose == null && HVRSettings.Instance.OpenHandPose)
{
_root.schedule.Execute(() =>
{
PrimaryPose.SetDefaults();
@@ -473,7 +492,6 @@ namespace HurricaneVR.Editor
public override VisualElement CreateInspectorGUI()
{
_root.Clear();
_tree.CloneTree(_root);
@@ -495,99 +513,111 @@ namespace HurricaneVR.Editor
SetupHandButtons();
SetupAutoPoseButtons();
//can't remember why I would add this field on the ui...
//_selectionIndexField = new IntegerField("SelectedIndex");
//_selectionIndexField.bindingPath = "SelectionIndex";
//_selectionIndexField.RegisterValueChangedCallback(evt =>
//{
// if (PosesListView.selectedIndex != evt.newValue) PosesListView.selectedIndex = evt.newValue;
//});
//_root.Add(_selectionIndexField);
_selectionIndexField = new IntegerField("SelectedIndex");
_selectionIndexField.bindingPath = "SelectionIndex";
_selectionIndexField.RegisterValueChangedCallback(evt =>
if (_inPrefabMode)
{
if (PosesListView.selectedIndex != evt.newValue) PosesListView.selectedIndex = evt.newValue;
});
_root.Add(_selectionIndexField);
PreviewLeftToggle = _root.Q<Toggle>("PreviewLeft");
PreviewLeftToggle.BindProperty(SP_PreviewLeft);
PreviewRightToggle = _root.Q<Toggle>("PreviewRight");
PreviewRightToggle.BindProperty(SP_PreviewRight);
PreviewLeftToggle.RegisterValueChangedCallback(OnPreviewLeftChanged);
PreviewRightToggle.RegisterValueChangedCallback(OnPreviewRightChanged);
ToggleLeftAutoPose = _root.Q<Toggle>("LeftAutoPose");
ToggleLeftAutoPose.BindProperty(SP_LeftAutoPose);
ToggleRightAutoPose = _root.Q<Toggle>("RightAutoPose");
ToggleRightAutoPose.BindProperty(SP_RightAutoPose);
ToggleLeftAutoPose.RegisterValueChangedCallback(OnLeftAutoPoseChanged);
ToggleRightAutoPose.RegisterValueChangedCallback(OnRightAutoPoseChanged);
if (SelectedIndex >= PosesListView.itemsSource.Count + PrimaryIndex)
{
Debug.Log($"Stored SelectedIndex is higher than pose count.");
SelectedIndex = PosesListView.itemsSource.Count - PrimaryIndex - 1;
serializedObject.ApplyModifiedProperties();
}
PosesListView.selectedIndex = SelectedIndex;
GetPhysicsPosers();
if (FullBody)
{
var body = GameObject.Find(_bodyId);
if (body)
{
SP_BodyPreview.objectReferenceValue = body;
}
UpdateBodyPreview(SelectedPose != null ? SelectedPose.LeftHand : null, SelectedPose != null ? SelectedPose.RightHand : null, PreviewLeft, PreviewRight);
_root.Q("MirrorAxis").style.display = DisplayStyle.None;
_root.Q("boxPreview").style.display = DisplayStyle.None;
}
else
{
SP_PreviewLeft.boolValue = SP_LeftHandPreview.objectReferenceValue != null;
SP_PreviewRight.boolValue = SP_RightHandPreview.objectReferenceValue != null;
_root.Q("warning").style.display = DisplayStyle.None;
if (!SP_PreviewLeft.boolValue)
PreviewLeftToggle = _root.Q<Toggle>("PreviewLeft");
PreviewLeftToggle.BindProperty(SP_PreviewLeft);
PreviewRightToggle = _root.Q<Toggle>("PreviewRight");
PreviewRightToggle.BindProperty(SP_PreviewRight);
PreviewLeftToggle.RegisterValueChangedCallback(OnPreviewLeftChanged);
PreviewRightToggle.RegisterValueChangedCallback(OnPreviewRightChanged);
ToggleLeftAutoPose = _root.Q<Toggle>("LeftAutoPose");
ToggleLeftAutoPose.BindProperty(SP_LeftAutoPose);
ToggleRightAutoPose = _root.Q<Toggle>("RightAutoPose");
ToggleRightAutoPose.BindProperty(SP_RightAutoPose);
ToggleLeftAutoPose.RegisterValueChangedCallback(OnLeftAutoPoseChanged);
ToggleRightAutoPose.RegisterValueChangedCallback(OnRightAutoPoseChanged);
if (SelectedIndex >= PosesListView.itemsSource.Count + PrimaryIndex)
{
FindPreviewHand(true, out var left);
if (left)
Debug.Log($"Stored SelectedIndex is higher than pose count.");
SelectedIndex = PosesListView.itemsSource.Count - PrimaryIndex - 1;
serializedObject.ApplyModifiedProperties();
}
PosesListView.selectedIndex = SelectedIndex;
GetPhysicsPosers();
if (FullBody)
{
var body = GameObject.Find(_bodyId);
if (body)
{
SP_PreviewLeft.boolValue = true;
SP_LeftHandPreview.objectReferenceValue = left;
SP_BodyPreview.objectReferenceValue = body;
}
}
if (!SP_PreviewRight.boolValue)
UpdateBodyPreview(SelectedPose != null ? SelectedPose.LeftHand : null, SelectedPose != null ? SelectedPose.RightHand : null, PreviewLeft, PreviewRight);
}
else
{
FindPreviewHand(false, out var right);
if (right)
SP_PreviewLeft.boolValue = SP_LeftHandPreview.objectReferenceValue != null;
SP_PreviewRight.boolValue = SP_RightHandPreview.objectReferenceValue != null;
if (!SP_PreviewLeft.boolValue)
{
SP_PreviewRight.boolValue = true;
SP_RightHandPreview.objectReferenceValue = right;
FindPreviewHand(true, out var left);
if (left)
{
SP_PreviewLeft.boolValue = true;
SP_LeftHandPreview.objectReferenceValue = left;
}
}
if (!SP_PreviewRight.boolValue)
{
FindPreviewHand(false, out var right);
if (right)
{
SP_PreviewRight.boolValue = true;
SP_RightHandPreview.objectReferenceValue = right;
}
}
UpdatePreview(false, SP_PreviewRight.boolValue, SelectedPose != null ? SelectedPose.LeftHand : null);
UpdatePreview(true, SP_PreviewLeft.boolValue, SelectedPose != null ? SelectedPose.RightHand : null);
}
UpdatePreview(false, SP_PreviewRight.boolValue, SelectedPose != null ? SelectedPose.LeftHand : null);
UpdatePreview(true, SP_PreviewLeft.boolValue, SelectedPose != null ? SelectedPose.RightHand : null);
if (_leftPhysicsPoser)
{
SP_LeftAutoPose.boolValue = _leftPhysicsPoser.LiveUpdate;
}
else
{
SP_LeftAutoPose.boolValue = false;
}
if (_rightPhysicsPoser)
{
SP_RightAutoPose.boolValue = _rightPhysicsPoser.LiveUpdate;
}
else
{
SP_RightAutoPose.boolValue = false;
}
}
if (_leftPhysicsPoser)
{
SP_LeftAutoPose.boolValue = _leftPhysicsPoser.LiveUpdate;
}
else
{
SP_LeftAutoPose.boolValue = false;
}
if (_rightPhysicsPoser)
{
SP_RightAutoPose.boolValue = _rightPhysicsPoser.LiveUpdate;
}
else
{
SP_RightAutoPose.boolValue = false;
}
serializedObject.ApplyModifiedProperties();
@@ -650,6 +680,7 @@ namespace HurricaneVR.Editor
{
return;
}
_rightPhysicsPoser.LiveUpdate = evt.newValue;
}
}
@@ -663,6 +694,7 @@ namespace HurricaneVR.Editor
{
return;
}
_leftPhysicsPoser.LiveUpdate = evt.newValue;
}
}
@@ -709,12 +741,10 @@ namespace HurricaneVR.Editor
{
_rightPhysicsPoser.LiveUpdate = SP_RightAutoPose.boolValue;
}
}
private void OnPreviewLeftChanged(ChangeEvent<bool> evt)
{
CreatePoseIfNeeded();
if (FullBody)
@@ -757,6 +787,18 @@ namespace HurricaneVR.Editor
}
}
private void CheckRigidBody()
{
var g = Poser.GetComponentInParent<HVRGrabbable>();
Rigidbody rb = null;
if (g)
{
rb = g.gameObject.GetComponent<Rigidbody>();
}
_root.Q("lblAutoPoseWarning").style.display = rb ? DisplayStyle.Flex : DisplayStyle.None;
}
private void UpdateBodyPreview(HVRHandPoseData leftpose, HVRHandPoseData rightpose, bool previewLeft, bool previewRight, bool poseChanged = false)
{
if (!previewRight && !previewLeft)
@@ -769,6 +811,7 @@ namespace HurricaneVR.Editor
SetupIKTarget(previewLeft, "LeftIKTarget", out var dummy);
SetupIKTarget(previewRight, "RightIKTarget", out var dummy2);
}
return;
}
@@ -863,7 +906,6 @@ namespace HurricaneVR.Editor
}
SceneView.RepaintAll();
serializedObject.ApplyModifiedProperties();
@@ -958,6 +1000,9 @@ namespace HurricaneVR.Editor
private void OnSelectedPoseChanged(ChangeEvent<Object> evt)
{
if (_inPrefabMode)
return;
if (evt.newValue != null)
{
var newPose = evt.newValue as HVRHandPose;
@@ -1289,7 +1334,6 @@ namespace HurricaneVR.Editor
rightHand.Pose(right);
}
}
};
var mirrorLeft = _root.Q<Button>("ButtonMirrorLeft");
@@ -1328,8 +1372,6 @@ namespace HurricaneVR.Editor
leftHand.Pose(left);
}
}
};
}
@@ -1391,10 +1433,7 @@ namespace HurricaneVR.Editor
SelectedPoseField.bindingPath = "Pose";
//SelectedPoseField.RegisterValueChangedCallback(OnSelectedPoseChanged);
////unity decide to fk with everything in 2020, hack to handle selected pose field from firing it's change event on enable that didn't happen in 2019..
var schedule = container.schedule.Execute(() =>
{
SelectedPoseField.RegisterValueChangedCallback(OnSelectedPoseChanged);
});
var schedule = container.schedule.Execute(() => { SelectedPoseField.RegisterValueChangedCallback(OnSelectedPoseChanged); });
schedule.StartingIn(1000);
}
@@ -1417,7 +1456,6 @@ namespace HurricaneVR.Editor
#if UNITY_2021_1_OR_NEWER
PosesListView.onSelectionChange += OnPoseSelectionChanged;
#else
@@ -1455,6 +1493,9 @@ namespace HurricaneVR.Editor
SelectedIndex = PosesListView.selectedIndex;
var poseName = SelectedPose == null ? "None" : SelectedPose.name;
blendEditorRoot.Q<Label>("lblSelectedPose").text = $"Selected Pose: {poseName}";
BindBlendContainer();
}
@@ -1469,7 +1510,6 @@ namespace HurricaneVR.Editor
if (index == PrimaryIndex)
{
label.AddToClassList("primarypose");
}
if (index < Poser.PoseNames.Count)
@@ -1509,7 +1549,11 @@ namespace HurricaneVR.Editor
serializedObject.ApplyModifiedProperties();
#if UNITY_2021_2_OR_NEWER
PosesListView?.Rebuild();
#else
PosesListView?.Refresh();
#endif
}
}
@@ -207,8 +207,8 @@ namespace HurricaneVR
Left.localPosition = Vector3.zero;
Right.localPosition = Vector3.zero;
var leftPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(Left.gameObject, "Assets/LeftHandPrefab.prefab", InteractionMode.UserAction);
var rightPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(Right.gameObject, "Assets/RightHandPrefab.prefab", InteractionMode.UserAction);
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");
@@ -248,6 +248,35 @@ namespace HurricaneVR
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);
//}
};
}
@@ -454,8 +483,8 @@ namespace HurricaneVR
if (GUILayout.Button("Detect Mirror"))
{
LeftHand.DetectBoneAxes(RightHand, LeftHand.transform.parent.forward, LeftHand.transform.parent.up);
RightHand.DetectBoneAxes(LeftHand, LeftHand.transform.parent.forward, LeftHand.transform.parent.up);
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;
@@ -477,6 +506,40 @@ namespace HurricaneVR
}
}
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++)
@@ -514,9 +577,8 @@ namespace HurricaneVR
" 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. If the finger has Tip / End transforms already, enable 'Has Tip', otherwise they will be auto generated on the last bone.\r\n" +
"\r\n6. 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\n7. 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);
"\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;
@@ -532,7 +594,6 @@ namespace HurricaneVR
HVREditorExtensions.EnumField("Finger", ref s.Finger);
HVREditorExtensions.IntField("Bones", ref s.BoneCount);
HVREditorExtensions.IntField("Root Offset", ref s.BoneOffset);
HVREditorExtensions.Toggle("Has Tip", ref s.HasTip);
//if (GUILayout.Button("^"))
//{
@@ -673,7 +734,6 @@ namespace HurricaneVR
animator.DefaultPoseHand = false;
animator.PoseHand = true;
animator.PhysicsPoser = physicsPoser;
animator.Hand = hand;
animator.DefaultPoser = poser;
@@ -725,35 +785,25 @@ namespace HurricaneVR
if (finger.Bones.Count > 0)
{
if (!s.HasTip)
var last = finger.Bones.Last();
var tipName = s.Finger.ToString() + " Tip";
var existing = last.Transform.Find(tipName);
if (!existing)
{
var last = finger.Bones.Last();
var tipName = s.Finger.ToString() + " Tip";
var existing = last.Transform.Find(tipName);
var tip = new GameObject(tipName);
tip.transform.parent = last.Transform;
tip.transform.ResetLocalProps();
finger.Tip = tip.transform;
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;
}
Undo.RegisterCreatedObjectUndo(tip, $"Add {tipName} to {last.Transform.name}");
}
else
{
var last = finger.Bones.Last();
if (s.HasTip && last.Transform.childCount > 0)
{
finger.Tip = last.Transform.GetChild(0);
}
finger.Tip = existing;
}
finger.Root = finger.Bones[0].Transform;
}
@@ -825,7 +875,6 @@ namespace HurricaneVR
public Finger Finger;
public int BoneCount = 3;
public int BoneOffset = 0;
public bool HasTip = false;
public int Index;
}
@@ -29,7 +29,8 @@ namespace HurricaneVR.Editor
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";
@@ -116,6 +117,8 @@ namespace HurricaneVR.Editor
SetupUrl("btnHandGrabber", URLHandGrabber);
SetupUrl("btnDiscord", URLDiscord);
SetupUrl("btnSetup", URLSetup);
SetupUrl("btnCustomHand", URLCustomHand);
SetupUrl("btnDoorSetup", URLDoor);
//SetupUrl("BtnPatreon", URLPatreon);
UpdatePanel(notesPanel);
@@ -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
@@ -8,15 +8,20 @@ namespace HurricaneVR.Editor
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++)
@@ -1,9 +1,7 @@
{
"name": "HurricaneVR.Editor",
"rootNamespace": "",
"references": [
"HurricaneVR.Framework",
"Zero"
"HurricaneVR.Framework"
],
"includePlatforms": [
"Editor"
@@ -1,6 +1,9 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:BindableElement name="BlendEditorRoot" style="height: auto; flex-grow: 1;">
<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" />
@@ -16,8 +16,11 @@
<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" />
<ui:Instance template="HandSettingsTemplate" name="boxPreview" />
<ui:Instance template="BlendEditorTemplate" />
</ui:Box>
</ui:UXML>
@@ -1,6 +1,9 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements">
<ui:VisualElement>
<Style src="HVRHandPoserEditor.uss" />
<ui:VisualElement name="lblAutoPoseWarning">
<ui:Label text="Rigidbody detected, if dynamic posing doesn&apos;t work, remove it temporarily." style="font-size: 18px; color: rgb(250, 235, 20); flex-wrap: nowrap; margin-bottom: 10px; height: 50px; white-space: normal;" />
</ui:VisualElement>
<ui:VisualElement class="HandsContainer">
<ui:VisualElement name="LeftHandContainer" class="unity-box HandContainer">
<ui:Label text="Left Hand:" class="HandLabel" />
@@ -25,7 +28,7 @@
<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;">
<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;" />
@@ -9,6 +9,8 @@
<ui:Button text="Grabbable w/ Pose" name="BtnTutBasicGrabbable" class="tutorial-button docs-button" />
<ui:Button text="Sockets" name="btnSockets" class="docs-button" />
<ui:Button text="FinalIK (VRIK)" name="BtnVRIKSetup" class="docs-button" />
<ui:Button text="Custom Hand Setup" name="btnCustomHand" class="docs-button" />
<ui:Button text="Door Setup" name="btnDoorSetup" class="docs-button" />
<ui:Label text="Other" style="padding-top: 12px;" />
<ui:Button text="Discord Server" name="btnDiscord" class="docs-button" />
</ui:VisualElement>