Skip to content

Commit f463a3c

Browse files
author
David Kline
authored
Merge pull request #2951 from StephenHodgson/vNEXT-CopyProfiles
Added Copy/Paste functionality to configuration profiles.
2 parents 70b612d + f4d0e35 commit f463a3c

22 files changed

+200
-75
lines changed

Assets/MixedRealityToolkit-SDK/Profiles/DefaultMixedRealityBoundaryVisualizationProfile.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!114 &11400000
44
MonoBehaviour:
55
m_ObjectHideFlags: 0
6-
m_PrefabParentObject: {fileID: 0}
6+
m_CorrespondingSourceObject: {fileID: 0}
77
m_PrefabInternal: {fileID: 0}
88
m_GameObject: {fileID: 0}
99
m_Enabled: 1

Assets/MixedRealityToolkit-SDK/Profiles/DefaultMixedRealityCameraProfile.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!114 &11400000
44
MonoBehaviour:
55
m_ObjectHideFlags: 0
6-
m_PrefabParentObject: {fileID: 0}
6+
m_CorrespondingSourceObject: {fileID: 0}
77
m_PrefabInternal: {fileID: 0}
88
m_GameObject: {fileID: 0}
99
m_Enabled: 1

Assets/MixedRealityToolkit-SDK/Profiles/DefaultMixedRealityGesturesProfile.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!114 &11400000
44
MonoBehaviour:
55
m_ObjectHideFlags: 0
6-
m_PrefabParentObject: {fileID: 0}
6+
m_CorrespondingSourceObject: {fileID: 0}
77
m_PrefabInternal: {fileID: 0}
88
m_GameObject: {fileID: 0}
99
m_Enabled: 1

Assets/MixedRealityToolkit-SDK/Profiles/DefaultMixedRealityInputActionsProfile.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!114 &11400000
44
MonoBehaviour:
55
m_ObjectHideFlags: 0
6-
m_PrefabParentObject: {fileID: 0}
6+
m_CorrespondingSourceObject: {fileID: 0}
77
m_PrefabInternal: {fileID: 0}
88
m_GameObject: {fileID: 0}
99
m_Enabled: 1

Assets/MixedRealityToolkit-SDK/Profiles/DefaultMixedRealityInputSystemProfile.asset

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
--- !u!114 &11400000
44
MonoBehaviour:
55
m_ObjectHideFlags: 0
6-
m_PrefabParentObject: {fileID: 0}
6+
m_CorrespondingSourceObject: {fileID: 0}
77
m_PrefabInternal: {fileID: 0}
88
m_GameObject: {fileID: 0}
99
m_Enabled: 1

Assets/MixedRealityToolkit/_Core/Definitions/MixedRealityToolkitConfigurationProfile.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public SystemType InputSystemType
130130
/// </summary>
131131
public bool IsBoundarySystemEnabled
132132
{
133-
get { return boundarySystemType != null && boundarySystemType.Type != null && enableBoundarySystem; }
133+
get { return boundarySystemType != null && boundarySystemType.Type != null && enableBoundarySystem && boundaryVisualizationProfile != null; }
134134
private set { enableInputSystem = value; }
135135
}
136136

Assets/MixedRealityToolkit/_Core/Extensions/EditorClassExtensions/ScriptableObjectExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ public static class ScriptableObjectExtensions
1919
/// <param name="scriptableObject"><see cref="ScriptableObject"/> you want to create an asset file for.</param>
2020
/// <param name="path">Optional path for the new asset.</param>
2121
/// <param name="fileName">Optional filename for the new asset.</param>
22-
public static void CreateAsset(this ScriptableObject scriptableObject, string path = null, string fileName = null)
22+
public static ScriptableObject CreateAsset(this ScriptableObject scriptableObject, string path = null, string fileName = null)
2323
{
2424
var name = string.IsNullOrEmpty(fileName) ? $"{scriptableObject.GetType().Name}" : fileName;
2525

2626
if (string.IsNullOrEmpty(path))
2727
{
28-
path = "Assets/MixedRealityToolkit-SDK/Profiles";
28+
path = "Assets";
2929
}
3030

3131
if (Path.GetExtension(path) != string.Empty)
@@ -47,6 +47,7 @@ public static void CreateAsset(this ScriptableObject scriptableObject, string pa
4747
EditorUtility.FocusProjectWindow();
4848
Selection.activeObject = scriptableObject;
4949
EditorGUIUtility.PingObject(scriptableObject);
50+
return scriptableObject;
5051
}
5152

5253
/// <summary>

Assets/MixedRealityToolkit/_Core/Inspectors/MixedRealityToolkitInspector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public override void OnInspectorGUI()
5353
"Would you like to create one now?", "OK", "Later"))
5454
{
5555
ScriptableObject profile = CreateInstance(nameof(MixedRealityToolkitConfigurationProfile));
56-
profile.CreateAsset();
56+
profile.CreateAsset("Assets/MixedRealityToolkit-Generated/CustomProfiles");
5757
activeProfile.objectReferenceValue = profile;
5858
Selection.activeObject = profile;
5959
EditorGUIUtility.PingObject(profile);

Assets/MixedRealityToolkit/_Core/Inspectors/Profiles/MixedRealityBaseConfigurationProfileInspector.cs

Lines changed: 116 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4+
using Microsoft.MixedReality.Toolkit.Core.Definitions;
45
using Microsoft.MixedReality.Toolkit.Core.Extensions.EditorClassExtensions;
6+
using Microsoft.MixedReality.Toolkit.Core.Services;
7+
using Microsoft.MixedReality.Toolkit.Core.Utilities.Async;
58
using Microsoft.MixedReality.Toolkit.Core.Utilities.Editor.Setup;
69
using UnityEditor;
710
using UnityEngine;
@@ -10,6 +13,8 @@ namespace Microsoft.MixedReality.Toolkit.Core.Inspectors.Profiles
1013
{
1114
public abstract class MixedRealityBaseConfigurationProfileInspector : BaseMixedRealityInspector
1215
{
16+
private const string IsCustomProfileProperty = "isCustomProfile";
17+
1318
private static readonly GUIContent NewProfileContent = new GUIContent("+", "Create New Profile");
1419

1520
[SerializeField]
@@ -18,6 +23,10 @@ public abstract class MixedRealityBaseConfigurationProfileInspector : BaseMixedR
1823
[SerializeField]
1924
private Texture2D logoDarkTheme = null;
2025

26+
private static BaseMixedRealityProfile profile;
27+
private static SerializedObject targetProfile;
28+
private static BaseMixedRealityProfile profileToCopy;
29+
2130
protected virtual void Awake()
2231
{
2332
if (logoLightTheme == null)
@@ -31,6 +40,68 @@ protected virtual void Awake()
3140
}
3241
}
3342

43+
protected virtual void OnEnable()
44+
{
45+
targetProfile = serializedObject;
46+
profile = target as BaseMixedRealityProfile;
47+
}
48+
49+
[MenuItem("CONTEXT/BaseMixedRealityProfile/Create Copy from Profile Values", false, 0)]
50+
protected static async void CreateCopyProfileValues()
51+
{
52+
profileToCopy = profile;
53+
ScriptableObject newProfile = CreateInstance(profile.GetType().ToString());
54+
profile = newProfile.CreateAsset("Assets/MixedRealityToolkit-Generated/CustomProfiles") as BaseMixedRealityProfile;
55+
Debug.Assert(profile != null);
56+
57+
await new WaitUntil(() => profileToCopy != profile);
58+
59+
Selection.activeObject = null;
60+
PasteProfileValues();
61+
Selection.activeObject = profile;
62+
63+
if (!profileToCopy.IsCustomProfile)
64+
{
65+
// For now we only replace it if it's the master configuration profile.
66+
// Sub-profiles are easy to update in the master configuration inspector.
67+
if (MixedRealityToolkit.Instance.ActiveProfile.GetType() == profile.GetType())
68+
{
69+
MixedRealityToolkit.Instance.ActiveProfile = profile as MixedRealityToolkitConfigurationProfile;
70+
}
71+
}
72+
}
73+
74+
[MenuItem("CONTEXT/BaseMixedRealityProfile/Copy Profile Values", false, 1)]
75+
private static void CopyProfileValues()
76+
{
77+
profileToCopy = profile;
78+
}
79+
80+
[MenuItem("CONTEXT/BaseMixedRealityProfile/Paste Profile Values", true)]
81+
private static bool PasteProfileValuesValidation()
82+
{
83+
return profile != null &&
84+
targetProfile != null &&
85+
profileToCopy != null &&
86+
targetProfile.FindProperty(IsCustomProfileProperty).boolValue &&
87+
profile.GetType() == profileToCopy.GetType();
88+
}
89+
90+
[MenuItem("CONTEXT/BaseMixedRealityProfile/Paste Profile Values", false, 2)]
91+
private static void PasteProfileValues()
92+
{
93+
Undo.RecordObject(profile, "Paste Profile Values");
94+
bool targetIsCustom = targetProfile.FindProperty(IsCustomProfileProperty).boolValue;
95+
string originalName = targetProfile.targetObject.name;
96+
EditorUtility.CopySerialized(profileToCopy, targetProfile.targetObject);
97+
targetProfile.Update();
98+
targetProfile.FindProperty(IsCustomProfileProperty).boolValue = targetIsCustom;
99+
targetProfile.ApplyModifiedProperties();
100+
targetProfile.targetObject.name = originalName;
101+
Debug.Assert(targetProfile.FindProperty(IsCustomProfileProperty).boolValue == targetIsCustom);
102+
AssetDatabase.SaveAssets();
103+
}
104+
34105
/// <summary>
35106
/// Render the Mixed Reality Toolkit Logo.
36107
/// </summary>
@@ -44,6 +115,15 @@ protected void RenderMixedRealityToolkitLogo()
44115
GUILayout.Space(12f);
45116
}
46117

118+
protected static void CheckProfileLock(Object target)
119+
{
120+
if (MixedRealityPreferences.LockProfiles && !((BaseMixedRealityProfile)target).IsCustomProfile)
121+
{
122+
EditorGUILayout.HelpBox("This profile is part of the default set from the Mixed Reality Toolkit SDK. You can make a copy of this profile, and customize it if needed.", MessageType.Warning);
123+
GUI.enabled = false;
124+
}
125+
}
126+
47127
protected static bool RenderProfile(SerializedProperty property)
48128
{
49129
bool changed = false;
@@ -52,19 +132,50 @@ protected static bool RenderProfile(SerializedProperty property)
52132

53133
if (property.objectReferenceValue == null)
54134
{
55-
if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(32f)))
135+
if (GUILayout.Button(NewProfileContent, EditorStyles.miniButton, GUILayout.Width(20f)))
56136
{
57137
var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
58138
Debug.Assert(profileTypeName != null, "No Type Found");
59-
ScriptableObject profile = CreateInstance(profileTypeName);
60-
profile.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject));
61-
property.objectReferenceValue = profile;
139+
ScriptableObject instance = CreateInstance(profileTypeName);
140+
var newProfile = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
141+
property.objectReferenceValue = newProfile;
142+
property.serializedObject.ApplyModifiedProperties();
62143
changed = true;
63144
}
64145
}
146+
else
147+
{
148+
var renderedProfile = property.objectReferenceValue as BaseMixedRealityProfile;
149+
Debug.Assert(renderedProfile != null);
150+
151+
if (!renderedProfile.IsCustomProfile && profile.IsCustomProfile)
152+
{
153+
if (GUILayout.Button(new GUIContent("</>", "Replace with a copy of the default profile."), EditorStyles.miniButton, GUILayout.Width(32f)))
154+
{
155+
profileToCopy = renderedProfile;
156+
var profileTypeName = property.type.Replace("PPtr<$", string.Empty).Replace(">", string.Empty);
157+
Debug.Assert(profileTypeName != null, "No Type Found");
158+
159+
ScriptableObject instance = CreateInstance(profileTypeName);
160+
var newProfile = instance.CreateAsset(AssetDatabase.GetAssetPath(Selection.activeObject)) as BaseMixedRealityProfile;
161+
property.objectReferenceValue = newProfile;
162+
property.serializedObject.ApplyModifiedProperties();
163+
PasteProfileValuesDelay(newProfile);
164+
changed = true;
165+
}
166+
}
167+
}
65168

66169
EditorGUILayout.EndHorizontal();
67170
return changed;
68171
}
172+
173+
private static async void PasteProfileValuesDelay(BaseMixedRealityProfile newProfile)
174+
{
175+
await new WaitUntil(() => profile == newProfile);
176+
Selection.activeObject = null;
177+
PasteProfileValues();
178+
Selection.activeObject = newProfile;
179+
}
69180
}
70-
}
181+
}

Assets/MixedRealityToolkit/_Core/Inspectors/Profiles/MixedRealityBoundaryVisualizationProfileInspector.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ public class MixedRealityBoundaryVisualizationProfileInspector : MixedRealityBas
3434
private readonly GUIContent scaleContent = new GUIContent("Scale");
3535
private readonly GUIContent materialContent = new GUIContent("Material");
3636

37-
private void OnEnable()
37+
protected override void OnEnable()
3838
{
39+
base.OnEnable();
40+
3941
if (!CheckMixedRealityConfigured(false))
4042
{
4143
return;
@@ -84,10 +86,7 @@ public override void OnInspectorGUI()
8486
}
8587
EditorGUILayout.Space();
8688

87-
if (MixedRealityPreferences.LockProfiles && !((BaseMixedRealityProfile)target).IsCustomProfile)
88-
{
89-
GUI.enabled = false;
90-
}
89+
CheckProfileLock(target);
9190

9291
serializedObject.Update();
9392
EditorGUILayout.PropertyField(boundaryHeight);

0 commit comments

Comments
 (0)