Files
dungeons/Assets/HurricaneVR/Framework/Editor/HVRManagementWindow.cs

513 lines
17 KiB
C#

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();
}
}
}