Skip to content

Commit 0d8c9f6

Browse files
Merge branch 'development' of https://github.com/Unity-Technologies/EditorVR into features/jono/undo-redo-flick
# Conflicts: # Menus/MainMenu/MainMenu.cs # Scripts/Core/EditorVR.cs
2 parents f71e815 + e515e00 commit 0d8c9f6

38 files changed

Lines changed: 1255 additions & 485 deletions

Editor/EditingContextManagerEditor.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ void Awake()
2121
public override void OnInspectorGUI()
2222
{
2323
GUILayout.Label("Available Contexts");
24-
EditingContextManager.DoGUI(m_ContextNames, ref m_SelectedContextIndex, () => { m_Settings.defaultContextName = m_ContextNames[m_SelectedContextIndex]; });
24+
25+
m_SelectedContextIndex = EditorGUILayout.Popup(string.Empty, m_SelectedContextIndex, m_ContextNames);
26+
if (GUI.changed)
27+
{
28+
m_Settings.defaultContextName = m_ContextNames[m_SelectedContextIndex];
29+
GUIUtility.ExitGUI();
30+
}
2531

2632
EditorGUILayout.Space();
2733

Editor/ProxyFeedbackEditor.cs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEditor.Experimental.EditorVR.Modules;
4+
using UnityEditor.Experimental.EditorVR.Proxies;
5+
using UnityEngine;
6+
7+
namespace UnityEditor.Experimental.EditorVR.UI
8+
{
9+
sealed class ProxyFeedbackEditor : EditorWindow
10+
{
11+
readonly Dictionary<Type, SerializedProxyFeedback> m_SerializedFeedback = new Dictionary<Type, SerializedProxyFeedback>();
12+
Vector2 m_Scroll;
13+
14+
[MenuItem("Edit/Project Settings/EditorXR/Proxy Feedback")]
15+
static void Init()
16+
{
17+
GetWindow<ProxyFeedbackEditor>("Proxy Feedback Editor").Show();
18+
}
19+
20+
void OnEnable()
21+
{
22+
Refresh();
23+
}
24+
25+
void OnGUI()
26+
{
27+
if (Event.current.Equals(Event.KeyboardEvent("^w")))
28+
{
29+
Close();
30+
GUIUtility.ExitGUI();
31+
}
32+
33+
if (GUILayout.Button("Reload Data"))
34+
Refresh();
35+
36+
if (GUILayout.Button("Clear Data"))
37+
{
38+
ClearData();
39+
Refresh();
40+
}
41+
42+
if (GUILayout.Button("Save Data"))
43+
{
44+
SaveData();
45+
Refresh();
46+
}
47+
48+
m_Scroll = GUILayout.BeginScrollView(m_Scroll);
49+
var hasFeedback = false;
50+
foreach (var kvp in m_SerializedFeedback)
51+
{
52+
GUILayout.Label(kvp.Key.Name, EditorStyles.boldLabel);
53+
DrawPreferences(kvp.Value);
54+
hasFeedback = true;
55+
}
56+
57+
if (!hasFeedback)
58+
GUILayout.Label("No serialized feedback");
59+
60+
GUILayout.EndScrollView();
61+
}
62+
63+
static void DrawPreferences(SerializedProxyFeedback feedback)
64+
{
65+
GUILayout.Label("Left Hand");
66+
DrawNode(feedback.leftNode);
67+
GUILayout.Label("Right Hand");
68+
DrawNode(feedback.rightNode);
69+
}
70+
71+
static void DrawNode(SerializedProxyNodeFeedback node)
72+
{
73+
var keys = node.keys;
74+
var values = node.values;
75+
for (var i = 0; i < keys.Length; i++)
76+
{
77+
var data = values[i];
78+
data.presentations = EditorGUILayout.IntField(keys[i].ToString(), data.presentations);
79+
}
80+
}
81+
82+
void Refresh()
83+
{
84+
m_SerializedFeedback.Clear();
85+
var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences);
86+
if (preferences == null)
87+
return;
88+
89+
foreach (var kvp in preferences.items)
90+
{
91+
var type = kvp.Key;
92+
if (typeof(TwoHandedProxyBase).IsAssignableFrom(type))
93+
{
94+
var item = kvp.Value;
95+
Type payloadType = null;
96+
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
97+
{
98+
payloadType = assembly.GetType(item.payloadType);
99+
if (payloadType != null)
100+
break;
101+
}
102+
103+
if (payloadType == null)
104+
continue;
105+
106+
var payload = (SerializedProxyFeedback)JsonUtility.FromJson(item.payload, payloadType);
107+
m_SerializedFeedback[kvp.Key] = payload;
108+
}
109+
}
110+
}
111+
112+
static void ClearData()
113+
{
114+
var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences);
115+
if (preferences == null)
116+
return;
117+
118+
foreach (var kvp in new Dictionary<Type, SerializedPreferencesModule.SerializedPreferenceItem>(preferences.items))
119+
{
120+
var type = kvp.Key;
121+
if (typeof(TwoHandedProxyBase).IsAssignableFrom(type))
122+
preferences.Remove(type);
123+
}
124+
125+
Core.EditorVR.serializedPreferences = JsonUtility.ToJson(preferences);
126+
}
127+
128+
void SaveData()
129+
{
130+
var preferences = SerializedPreferencesModule.DeserializePreferences(Core.EditorVR.serializedPreferences);
131+
if (preferences == null)
132+
return;
133+
134+
var items = preferences.items;
135+
foreach (var kvp in m_SerializedFeedback)
136+
{
137+
items[kvp.Key].payload = JsonUtility.ToJson(kvp.Value);
138+
}
139+
140+
Core.EditorVR.serializedPreferences = JsonUtility.ToJson(preferences);
141+
}
142+
}
143+
}

Editor/ProxyFeedbackEditor.cs.meta

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Menus/MainMenu/MainMenu.cs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ void OnButtonHovered(Transform rayOrigin, Type buttonType, string buttonDescript
332332
this.PreviewInToolMenuButton(rayOrigin, buttonType, buttonDescription);
333333
}
334334

335+
void OnToggleHovered(Transform rayOrigin)
336+
{
337+
this.Pulse(this.RequestNodeFromRayOrigin(rayOrigin), m_ButtonHoverPulse);
338+
}
339+
335340
void SendVisibilityPulse()
336341
{
337342
this.Pulse(node, m_MenuHideFlags == 0 ? m_HidePulse : m_ShowPulse);
@@ -366,12 +371,29 @@ void AddSettingsMenu(ISettingsMenuProvider provider, MainMenuUI.ButtonData butto
366371
{
367372
buttonData.sectionName = k_SettingsMenuSectionName;
368373

369-
CreateFaceButton(buttonData, tooltip, () =>
374+
var button = CreateFaceButton(buttonData, tooltip, () =>
370375
{
371376
var instance = m_MainMenuUI.AddSubmenu(k_SettingsMenuSectionName, provider.settingsMenuPrefab);
372377
m_SettingsMenus[provider] = instance;
373378
provider.settingsMenuInstance = instance;
379+
AddToggleHaptics(instance);
374380
});
381+
382+
button.hovered += OnButtonHovered;
383+
button.clicked += OnButtonClicked;
384+
}
385+
386+
void AddToggleHaptics(GameObject menuInstance)
387+
{
388+
var toggles = menuInstance.GetComponentsInChildren<MainMenuToggle>();
389+
if (toggles != null && toggles.Length > 0)
390+
{
391+
foreach (var toggle in toggles)
392+
{
393+
toggle.hovered += OnToggleHovered;
394+
toggle.clicked += OnButtonClicked;
395+
}
396+
}
375397
}
376398

377399
public void RemoveSettingsMenu(ISettingsMenuProvider provider)
@@ -392,6 +414,7 @@ public void AddSettingsMenuItem(ISettingsMenuItemProvider provider)
392414
var instance = m_MainMenuUI.CreateCustomButton(provider.settingsMenuItemPrefab, k_SettingsMenuSectionName);
393415
m_SettingsMenuItems[provider] = instance;
394416
provider.settingsMenuItemInstance = instance;
417+
AddToggleHaptics(instance);
395418
}
396419

397420
public void RemoveSettingsMenuItem(ISettingsMenuItemProvider provider)

Menus/MainMenu/Prefabs/MenuActionButton.prefab

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,11 @@ MonoBehaviour:
319319
m_Script: {fileID: 11500000, guid: d6fdf9e0896ac3f4e94809a2cb14ceb8, type: 3}
320320
m_Name:
321321
m_EditorClassIdentifier:
322+
m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2}
323+
m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2}
324+
m_Description: {fileID: 114846824440974548}
325+
m_Title: {fileID: 114097649684237516}
322326
m_Button: {fileID: 114000011038114608}
323-
m_ButtonDescription: {fileID: 114846824440974548}
324-
m_ButtonTitle: {fileID: 114097649684237516}
325327
--- !u!114 &114000012975115684
326328
MonoBehaviour:
327329
m_ObjectHideFlags: 1
@@ -727,7 +729,7 @@ RectTransform:
727729
m_LocalEulerAnglesHint: {x: 0, y: 0, z: -90}
728730
m_AnchorMin: {x: 0.20215935, y: -1.0582141}
729731
m_AnchorMax: {x: 0.4918094, y: 2.0516362}
730-
m_AnchoredPosition: {x: 0, y: 0.0000038146973}
732+
m_AnchoredPosition: {x: 0, y: 0}
731733
m_SizeDelta: {x: 0, y: 0}
732734
m_Pivot: {x: 0.5, y: 0.5}
733735
--- !u!224 &224000011878397100
@@ -763,7 +765,7 @@ RectTransform:
763765
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
764766
m_AnchorMin: {x: 0, y: 0}
765767
m_AnchorMax: {x: 1, y: 1}
766-
m_AnchoredPosition: {x: 2.6, y: -0.0024712086}
768+
m_AnchoredPosition: {x: 0, y: 0}
767769
m_SizeDelta: {x: 5.3, y: 0}
768770
m_Pivot: {x: 0.5, y: 0.5}
769771
--- !u!224 &224000013226195212
@@ -801,7 +803,7 @@ RectTransform:
801803
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
802804
m_AnchorMin: {x: 0.00008987377, y: 0.006534843}
803805
m_AnchorMax: {x: 0.9659295, y: 1}
804-
m_AnchoredPosition: {x: 4.737492, y: 0}
806+
m_AnchoredPosition: {x: 0, y: 0}
805807
m_SizeDelta: {x: 9.475, y: 0}
806808
m_Pivot: {x: 0.5, y: 0.5}
807809
--- !u!224 &224000013707443896

Menus/MainMenu/Prefabs/MenuButton.prefab

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,11 @@ MonoBehaviour:
127127
m_Script: {fileID: 11500000, guid: d6fdf9e0896ac3f4e94809a2cb14ceb8, type: 3}
128128
m_Name:
129129
m_EditorClassIdentifier:
130+
m_ClickPulse: {fileID: 11400000, guid: f66cb0a158f54124aa4158bbad3ed702, type: 2}
131+
m_HoverPulse: {fileID: 11400000, guid: dd561ccb8162d1040adba0a7ea60eadc, type: 2}
132+
m_Description: {fileID: 114538117545747488}
133+
m_Title: {fileID: 114736413251300290}
130134
m_Button: {fileID: 114000011038114608}
131-
m_ButtonDescription: {fileID: 114538117545747488}
132-
m_ButtonTitle: {fileID: 114736413251300290}
133135
--- !u!114 &114000013676702038
134136
MonoBehaviour:
135137
m_ObjectHideFlags: 1

Menus/MainMenu/Scripts/MainMenuButton.cs

Lines changed: 25 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,89 +6,69 @@
66
using UnityEngine.EventSystems;
77
using UnityEngine.UI;
88

9-
#if INCLUDE_TEXT_MESH_PRO
10-
using TMPro;
11-
#endif
12-
139
[assembly: OptionalDependency("TMPro.TextMeshProUGUI", "INCLUDE_TEXT_MESH_PRO")]
1410

1511
namespace UnityEditor.Experimental.EditorVR.Menus
1612
{
17-
sealed class MainMenuButton : MonoBehaviour, ITooltip, IRayEnterHandler, IRayExitHandler, IPointerClickHandler
13+
sealed class MainMenuButton : MainMenuSelectable, ITooltip, IRayEnterHandler, IRayExitHandler, IPointerClickHandler
1814
{
1915
[SerializeField]
2016
Button m_Button;
2117

22-
#if INCLUDE_TEXT_MESH_PRO
23-
[SerializeField]
24-
TextMeshProUGUI m_ButtonDescription;
25-
#endif
26-
27-
#if INCLUDE_TEXT_MESH_PRO
28-
[SerializeField]
29-
TextMeshProUGUI m_ButtonTitle;
30-
#endif
31-
32-
Color m_OriginalColor;
18+
CanvasGroup m_CanvasGroup;
3319

3420
public Button button { get { return m_Button; } }
3521

3622
public string tooltipText { get { return tooltip != null ? tooltip.tooltipText : null; } }
3723

3824
public ITooltip tooltip { private get; set; }
3925

40-
public Type toolType { get; set; }
41-
42-
public bool selected
43-
{
44-
set
45-
{
46-
if (value)
47-
{
48-
m_Button.transition = Selectable.Transition.None;
49-
m_Button.targetGraphic.color = m_Button.colors.highlightedColor;
50-
}
51-
else
52-
{
53-
m_Button.transition = Selectable.Transition.ColorTint;
54-
m_Button.targetGraphic.color = m_OriginalColor;
55-
}
56-
}
57-
}
58-
5926
public event Action<Transform, Type, string> hovered;
6027
public event Action<Transform> clicked;
6128

62-
void Awake()
29+
new void Awake()
6330
{
31+
m_Selectable = m_Button;
6432
m_OriginalColor = m_Button.targetGraphic.color;
6533
}
6634

67-
public void SetData(string name, string description)
35+
void Start()
6836
{
69-
#if INCLUDE_TEXT_MESH_PRO
70-
m_ButtonTitle.text = name;
71-
m_ButtonDescription.text = description;
72-
#endif
37+
m_CanvasGroup = m_Button.GetComponentInParent<CanvasGroup>();
7338
}
7439

7540
public void OnRayEnter(RayEventData eventData)
7641
{
42+
if (m_CanvasGroup && !m_CanvasGroup.interactable)
43+
return;
44+
7745
#if INCLUDE_TEXT_MESH_PRO
78-
if (hovered != null)
79-
hovered(eventData.rayOrigin, toolType, m_ButtonDescription.text);
46+
if (button.interactable && hovered != null)
47+
{
48+
var descriptionText = string.Empty;
49+
// We can't use ?? because it breaks on destroyed references
50+
if (m_Description)
51+
descriptionText = m_Description.text;
52+
hovered(eventData.rayOrigin, toolType, descriptionText);
53+
}
8054
#endif
8155
}
8256

8357
public void OnRayExit(RayEventData eventData)
8458
{
85-
if (hovered != null)
59+
if (m_CanvasGroup && !m_CanvasGroup.interactable)
60+
return;
61+
62+
if (button.interactable && hovered != null)
8663
hovered(eventData.rayOrigin, null, null);
8764
}
8865

8966
public void OnPointerClick(PointerEventData eventData)
9067
{
91-
if (clicked != null)
68+
if (m_CanvasGroup && !m_CanvasGroup.interactable)
69+
return;
70+
71+
if (button.interactable && clicked != null)
9272
clicked(null); // Pass null to perform the selection haptic pulse on both nodes
9373
}
9474
}

0 commit comments

Comments
 (0)