From 8c431a66b511a62cb9fb7246c37dec3a94306370 Mon Sep 17 00:00:00 2001 From: Sebastian Poetter <32681913+poetter-sebastian@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:49:39 +0200 Subject: [PATCH 1/8] Added new collection condition to basic conditions (#243) * Updated collection condition according (#243) * Merged the new condition to existing one (#243) * Updated the condition and added checker at the start. Tests for the counter have to added (#243) * Added tests for new counter of the object in collider condition Added one more constructor for MultipleSceneObjectReferences in unit tests (#243) * Removed unnecessary code and moved error checking at the condition where it's needed (#243) --- .../UI/MenuItems/ObjectInColliderMenuItem.cs | 2 +- .../ObjectInColliderCondition.cs | 86 ++++++++++-- .../ObjectInColliderConditionTests.cs | 132 +++++++++++++++++- 3 files changed, 201 insertions(+), 19 deletions(-) diff --git a/Source/Basic-Conditions-And-Behaviors/Editor/UI/MenuItems/ObjectInColliderMenuItem.cs b/Source/Basic-Conditions-And-Behaviors/Editor/UI/MenuItems/ObjectInColliderMenuItem.cs index d70048b18..dbf6f8c26 100644 --- a/Source/Basic-Conditions-And-Behaviors/Editor/UI/MenuItems/ObjectInColliderMenuItem.cs +++ b/Source/Basic-Conditions-And-Behaviors/Editor/UI/MenuItems/ObjectInColliderMenuItem.cs @@ -7,7 +7,7 @@ namespace VRBuilder.Editor.UI.Conditions public class ObjectInColliderMenuItem : MenuItem { /// - public override string DisplayedName { get; } = "Environment/Move Object in Collider"; + public override string DisplayedName { get; } = "Environment/Move Objects in Collider"; /// public override ICondition GetNewItem() diff --git a/Source/Basic-Conditions-And-Behaviors/Runtime/Conditions/PositionalConditions/ObjectInColliderCondition.cs b/Source/Basic-Conditions-And-Behaviors/Runtime/Conditions/PositionalConditions/ObjectInColliderCondition.cs index 78415b252..a8ebc6699 100644 --- a/Source/Basic-Conditions-And-Behaviors/Runtime/Conditions/PositionalConditions/ObjectInColliderCondition.cs +++ b/Source/Basic-Conditions-And-Behaviors/Runtime/Conditions/PositionalConditions/ObjectInColliderCondition.cs @@ -1,11 +1,14 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using UnityEngine; using UnityEngine.Scripting; using VRBuilder.Core.Attributes; using VRBuilder.Core.Properties; using VRBuilder.Core.SceneObjects; +using VRBuilder.Core.Settings; using VRBuilder.Core.Utils; namespace VRBuilder.Core.Conditions @@ -25,10 +28,10 @@ public class ObjectInColliderCondition : Condition - /// The object that has to enter the collider. + /// The objects that have to enter the collider. /// [DataMember] - [DisplayName("Object")] + [DisplayName("Objects")] public MultipleSceneObjectReference TargetObjects { get; set; } [DataMember] @@ -50,19 +53,34 @@ public class EntityData : IObjectInTargetData [Obsolete("Use TriggerObject instead.")] [LegacyProperty(nameof(TriggerObject))] public ScenePropertyReference TriggerProperty { get; set; } - + /// public bool IsCompleted { get; set; } /// [HideInProcessInspector] [IgnoreDataMember] - public string Name => $"Move {TargetObjects} in collider {TriggerObject}"; + public string Name + { + get + { + if (ObjectsRequiredInTrigger > 1 && TargetObjects.Values.Count() > 1) + { + return $"Move {ObjectsRequiredInTrigger} of {TargetObjects.Values.Count()} '{SceneObjectGroups.Instance.GetLabel(TargetObjects.Guids.First())}' in collider {TriggerObject}"; + } + + return $"Move {TargetObjects} in collider {TriggerObject}"; + } + } /// [DataMember] [DisplayName("Required seconds inside")] public float RequiredTimeInside { get; set; } + + [DataMember] + [DisplayName("Required Object count")] + public float ObjectsRequiredInTrigger { get; set; } /// public Metadata Metadata { get; set; } @@ -73,14 +91,19 @@ public ObjectInColliderCondition() : this(Guid.Empty, Guid.Empty) { } + public ObjectInColliderCondition(ColliderWithTriggerProperty targetPosition, IReadOnlyList multipleObjectsGuids, int requiredTimeInTarget, int objectsRequiredInTrigger) + : this(ProcessReferenceUtils.GetUniqueIdFrom(targetPosition), multipleObjectsGuids, requiredTimeInTarget, objectsRequiredInTrigger) + { + } + // ReSharper disable once SuggestBaseTypeForParameter - public ObjectInColliderCondition(ColliderWithTriggerProperty targetPosition, ISceneObject targetObject, float requiredTimeInTarget = 0) - : this(ProcessReferenceUtils.GetUniqueIdFrom(targetPosition), ProcessReferenceUtils.GetUniqueIdFrom(targetObject), requiredTimeInTarget) + public ObjectInColliderCondition(ColliderWithTriggerProperty targetPosition, ISceneObject targetObject, float requiredTimeInTarget = 0, float objectsRequiredInTrigger = 1) + : this(ProcessReferenceUtils.GetUniqueIdFrom(targetPosition), ProcessReferenceUtils.GetUniqueIdFrom(targetObject), requiredTimeInTarget, objectsRequiredInTrigger) { } [Obsolete("This constructor will be removed in the next major version.")] - public ObjectInColliderCondition(string targetPosition, string targetObject, float requiredTimeInTarget = 0) + public ObjectInColliderCondition(string targetPosition, string targetObject, float requiredTimeInTarget = 0, float objectsRequiredInTrigger = 1) { Guid triggerGuid = Guid.Empty; Guid targetGuid = Guid.Empty; @@ -89,13 +112,23 @@ public ObjectInColliderCondition(string targetPosition, string targetObject, flo Data.TriggerObject = new SingleScenePropertyReference(triggerGuid); Data.TargetObjects = new MultipleSceneObjectReference(targetGuid); Data.RequiredTimeInside = requiredTimeInTarget; + Data.ObjectsRequiredInTrigger = objectsRequiredInTrigger; } - public ObjectInColliderCondition(Guid targetPosition, Guid targetObject, float requiredTimeInTarget = 0) + public ObjectInColliderCondition(Guid targetPosition, Guid targetObject, float requiredTimeInTarget = 0, float objectsRequiredInTrigger = 1) { Data.TriggerObject = new SingleScenePropertyReference(targetPosition); Data.TargetObjects = new MultipleSceneObjectReference(targetObject); Data.RequiredTimeInside = requiredTimeInTarget; + Data.ObjectsRequiredInTrigger = objectsRequiredInTrigger; + } + + private ObjectInColliderCondition(Guid targetPosition, IReadOnlyList targetObject, int requiredTimeInTarget, int objectsRequiredInTrigger) + { + Data.TriggerObject = new SingleScenePropertyReference(targetPosition); + Data.TargetObjects = new MultipleSceneObjectReference(targetObject); + Data.RequiredTimeInside = requiredTimeInTarget; + Data.ObjectsRequiredInTrigger = objectsRequiredInTrigger; } private class ActiveProcess : ObjectInTargetActiveProcess @@ -104,17 +137,30 @@ public ActiveProcess(EntityData data) : base(data) { } + public override void Start() + { + if (Data.ObjectsRequiredInTrigger > Data.TargetObjects.Values.Count()) + { + Debug.LogWarning($"The required object count {Data.ObjectsRequiredInTrigger} is bigger then the target objects count of {Data.TargetObjects.Values.Count()} and not completable."); + } + if (Data.ObjectsRequiredInTrigger < 1) + { + Debug.LogWarning($"The required object count {Data.ObjectsRequiredInTrigger} is below 1 and always completed."); + } + base.Start(); + } + /// protected override bool IsInside() { - bool isTransformInsideTrigger = false; + int counter = 0; foreach (ISceneObject sceneObject in Data.TargetObjects.Values) { - isTransformInsideTrigger |= Data.TriggerObject.Value.IsTransformInsideTrigger(sceneObject.GameObject.transform); + counter += Data.TriggerObject.Value.IsTransformInsideTrigger(sceneObject.GameObject.transform)? 1 : 0; } - return isTransformInsideTrigger; + return counter >= Data.ObjectsRequiredInTrigger; } } @@ -127,10 +173,22 @@ public EntityAutocompleter(EntityData data) : base(data) /// public override void Complete() { - ISceneObject sceneObject = Data.TargetObjects.Values.FirstOrDefault(); - - if (sceneObject != null) + if (Data.ObjectsRequiredInTrigger > 1 && Data.TargetObjects.Values.Any()) + { + int counter = 0; + foreach (var objs in Data.TargetObjects.Values) + { + Data.TriggerObject.Value.FastForwardEnter(objs); + counter++; + if (counter >= Data.ObjectsRequiredInTrigger) + { + break; + } + } + } + else { + ISceneObject sceneObject = Data.TargetObjects.Values.FirstOrDefault(); Data.TriggerObject.Value.FastForwardEnter(sceneObject); } } diff --git a/Tests/Basic-Conditions-And-Behaviors/Conditions/ObjectInColliderConditionTests.cs b/Tests/Basic-Conditions-And-Behaviors/Conditions/ObjectInColliderConditionTests.cs index 38bc741bb..da3ceb77a 100644 --- a/Tests/Basic-Conditions-And-Behaviors/Conditions/ObjectInColliderConditionTests.cs +++ b/Tests/Basic-Conditions-And-Behaviors/Conditions/ObjectInColliderConditionTests.cs @@ -270,17 +270,16 @@ public IEnumerator AutoCompleteActive() Assert.AreEqual(Stage.Active, condition.LifeCycle.Stage); Assert.IsTrue(isColliding); Assert.IsTrue(condition.IsCompleted); - yield break; } [UnityTest] - public IEnumerator FastForwardDoesNotCompleteCondition() + public IEnumerator AutoCompleteActiveWithHigherRequiredObjects() { // Given an activated object in collider condition, - ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), TrackedProcessSceneObject); + ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), TrackedProcessSceneObject, 42); bool isColliding = false; - TargetProcessSceneObject.GetProperty().EnteredTrigger += (sender, args) => isColliding = true; + TargetProcessSceneObject.GetProperty().EnteredTrigger += (_, _) => isColliding = true; condition.LifeCycle.Activate(); @@ -298,5 +297,130 @@ public IEnumerator FastForwardDoesNotCompleteCondition() Assert.IsFalse(condition.IsCompleted); Assert.IsFalse(isColliding); } + + [UnityTest] + public IEnumerator AutoCompleteHigherRequiredCountInCollider() + { + // Given an activated object in collider condition, + ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), TrackedProcessSceneObject, 0, 42); + + bool isColliding = false; + TargetProcessSceneObject.GetProperty().EnteredTrigger += (_, _) => isColliding = true; + + condition.LifeCycle.Activate(); + + while (condition.LifeCycle.Stage != Stage.Active) + { + yield return null; + condition.Update(); + } + + // When you autocomplete it, + condition.Autocomplete(); + + // Then condition is activated and the object is moved into collider. + Assert.AreEqual(Stage.Active, condition.LifeCycle.Stage); + Assert.IsTrue(isColliding); + Assert.IsTrue(condition.IsCompleted); + } + + [UnityTest] + public IEnumerator UncompletableObjectCountInCollider() + { + // Move tracked object at the target position + TrackedObject.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget; + + yield return null; + + // Activate collider condition + ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), TrackedProcessSceneObject, 0, 42); + condition.LifeCycle.Activate(); + + float startTime = Time.time; + while (startTime + 5f > Time.time) + { + yield return null; + condition.Update(); + } + + // Assert that condition is now uncompleted + Assert.IsFalse(condition.IsCompleted, "TargetInColliderCondition should be not completed!"); + } + + [UnityTest] + public IEnumerator CompletableZeroObjectCountInCollider() + { + // Activate collider condition + ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), TrackedProcessSceneObject, 0, 0); + condition.LifeCycle.Activate(); + + yield return null; + condition.Update(); + + yield return null; + condition.Update(); + + while (condition.LifeCycle.Stage != Stage.Active) + { + yield return null; + condition.Update(); + } + + // Then condition is activated and the object is moved into collider. + Assert.AreEqual(Stage.Active, condition.LifeCycle.Stage); + Assert.IsTrue(condition.IsCompleted, "TargetInColliderCondition should always be completed!"); + } + + [UnityTest] + public IEnumerator CompletableObjectCountInCollider() + { + GameObject trackedObject2 = new GameObject("Tracked Object 2"); + trackedObject2.transform.position = PositionFarFromTarget; + trackedObject2.AddComponent(); + GameObject trackedObject3 = new GameObject("Tracked Object 3"); + trackedObject3.transform.position = PositionFarFromTarget; + trackedObject3.AddComponent(); + + MultipleSceneObjectReference multipleObjects = new MultipleSceneObjectReference( new [] + { + TrackedProcessSceneObject.GetComponent().Guid, + trackedObject2.GetComponent().Guid, + trackedObject3.GetComponent().Guid + }); + + // Move tracked object at the target position + TrackedObject.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget; + trackedObject2.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget; + trackedObject3.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget; + + // Activate collider condition + ObjectInColliderCondition condition = new ObjectInColliderCondition(TargetProcessSceneObject.GetProperty(), multipleObjects.Guids, 0, 3); + condition.LifeCycle.Activate(); + + yield return null; + + // Move tracked object to the target position + TrackedObject.transform.position = TargetPositionObject.transform.position; + + Assert.IsFalse(condition.IsCompleted); + yield return null; + condition.Update(); + + trackedObject2.transform.position = TargetPositionObject.transform.position; + + Assert.IsFalse(condition.IsCompleted); + yield return null; + condition.Update(); + + trackedObject3.transform.position = TargetPositionObject.transform.position; + + yield return null; + condition.Update(); + yield return null; + condition.Update(); + + // Assert that condition is now uncompleted + Assert.IsTrue(condition.IsCompleted, "TargetInColliderCondition should be completed!"); + } } } From 4f04b12a190703c408e8ca67eaf71accb2fb753b Mon Sep 17 00:00:00 2001 From: Marcello Tridenti Date: Fri, 20 Sep 2024 15:07:46 +0200 Subject: [PATCH 2/8] Extensible component settings (#244) * Snap zone settings is now a settings section * Abstracted ComponentSettings * Generic component settings section * Obsoleted redundant Settings property in ComponentSettings --- .../ComponentSettingsProvider.cs | 27 +++++++ .../ComponentSettingsProvider.cs.meta} | 0 .../ComponentSettingsSection.cs | 80 +++++++++++++++++++ .../ComponentSettingsSection.cs.meta | 11 +++ .../Core/Runtime/Utils/ComponentSettings.cs | 29 +++++++ .../Runtime/Utils/ComponentSettings.cs.meta | 11 +++ .../SnapZoneSettingsProvider.cs | 51 ------------ .../SnapZoneSettingsSection.cs | 20 +++++ .../SnapZoneSettingsSection.cs.meta | 11 +++ .../Properties/SnappablePropertyEditor.cs | 4 +- .../Editor/SnapZone/SnapZoneSettings.cs | 50 +----------- .../Runtime/SnapZoneTests.cs | 10 +-- 12 files changed, 200 insertions(+), 104 deletions(-) create mode 100644 Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs rename Source/{XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs.meta => Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs.meta} (100%) create mode 100644 Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs create mode 100644 Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs.meta create mode 100644 Source/Core/Runtime/Utils/ComponentSettings.cs create mode 100644 Source/Core/Runtime/Utils/ComponentSettings.cs.meta delete mode 100644 Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs create mode 100644 Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs create mode 100644 Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs.meta diff --git a/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs new file mode 100644 index 000000000..e714406f5 --- /dev/null +++ b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs @@ -0,0 +1,27 @@ +using UnityEditor; + +namespace VRBuilder.Editor.UI +{ + /// + /// Settings provider that groups global settings for scene components in separate sections. + /// + public class ComponentSettingsProvider : BaseSettingsProvider + { + private const string Path = "Project/VR Builder/Component Settings"; + + private UnityEditor.Editor editor; + + public ComponentSettingsProvider() : base(Path, SettingsScope.Project) { } + + [SettingsProvider] + public static SettingsProvider Provider() + { + SettingsProvider provider = new ComponentSettingsProvider(); + return provider; + } + + protected override void InternalDraw(string searchContext) + { + } + } +} diff --git a/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs.meta b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs.meta similarity index 100% rename from Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs.meta rename to Source/Core/Editor/UI/ProjectSettings/ComponentSettingsProvider.cs.meta diff --git a/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs new file mode 100644 index 000000000..1b9295f48 --- /dev/null +++ b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs @@ -0,0 +1,80 @@ +using System; +using System.Reflection; +using UnityEditor; +using UnityEngine; +using VRBuilder.Core.Runtime.Utils; + +namespace VRBuilder.Editor.UI +{ + /// + /// Settings section holding global settings for a specified scene component. + /// + /// The component that can be configured by this section. + /// The scriptable object holding the global settings. + public abstract class ComponentSettingsSection : IProjectSettingsSection where TObject : UnityEngine.Object where TSettings : ComponentSettings, new() + { + /// + public abstract string Title { get; } + + /// + /// Description of this settings section. Will be displayed below the title, before the settings in the scriptable object. + /// + public abstract string Description { get; } + + /// + public Type TargetPageProvider => typeof(ComponentSettingsProvider); + + /// + public abstract int Priority { get; } + + private UnityEditor.Editor editor; + private TSettings settings; + + /// + public void OnGUI(string searchContext) + { + EditorGUILayout.Space(); + GUIStyle labelStyle = BuilderEditorStyles.ApplyPadding(BuilderEditorStyles.Paragraph, 0); + GUILayout.Label(Description, labelStyle); + EditorGUILayout.Space(); + + editor.OnInspectorGUI(); + + if (GUILayout.Button("Apply settings in current scene")) + { + TObject[] objects = Resources.FindObjectsOfTypeAll(); + + foreach (TObject snapZone in objects) + { + GetSettingsInstance().ApplySettings(snapZone); + } + } + + EditorGUILayout.Space(20f); + } + + public ComponentSettingsSection() + { + editor = UnityEditor.Editor.CreateEditor(GetSettingsInstance()); + } + + private TSettings GetSettingsInstance() + { + if (settings != null) + { + return settings; + } + + Type closedGenericType = typeof(SettingsObject<>).MakeGenericType(typeof(TSettings)); + + PropertyInfo instanceProperty = closedGenericType.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); + + if (instanceProperty != null) + { + return instanceProperty.GetValue(null) as TSettings; + } + + return null; + } + } +} diff --git a/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs.meta b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs.meta new file mode 100644 index 000000000..cc5bcee11 --- /dev/null +++ b/Source/Core/Editor/UI/ProjectSettings/ComponentSettingsSection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2aa079765593fc14388c22309d78afce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Source/Core/Runtime/Utils/ComponentSettings.cs b/Source/Core/Runtime/Utils/ComponentSettings.cs new file mode 100644 index 000000000..34635c4c5 --- /dev/null +++ b/Source/Core/Runtime/Utils/ComponentSettings.cs @@ -0,0 +1,29 @@ +using System; +using UnityEngine; + +namespace VRBuilder.Core.Runtime.Utils +{ + /// + /// Settings object holding global settings for a specific scene component. + /// + /// The component these settings are for. + /// The scriptable object holding the global settings. + public abstract class ComponentSettings : SettingsObject where TSettings : ScriptableObject, new() where TObject : UnityEngine.Object + { + private static TSettings settings; + + /// + /// Loads the first existing settings found in the project. + /// If non are found, it creates and saves a new instance with default values. + /// + [Obsolete("This is redundant and will be removed in a future major version. Use SettingsObject.Instance instead. Note that saving settings outside a Resources folder is no longer supported.")] + public static TSettings Settings => RetrieveSettings(); + + public abstract void ApplySettings(TObject target); + + private static TSettings RetrieveSettings() + { + return Instance; + } + } +} diff --git a/Source/Core/Runtime/Utils/ComponentSettings.cs.meta b/Source/Core/Runtime/Utils/ComponentSettings.cs.meta new file mode 100644 index 000000000..9c596b721 --- /dev/null +++ b/Source/Core/Runtime/Utils/ComponentSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86268b16146680540884577cc4a0e05c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs b/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs deleted file mode 100644 index c4a5597a7..000000000 --- a/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsProvider.cs +++ /dev/null @@ -1,51 +0,0 @@ -using UnityEditor; -using UnityEngine; -using UnityEngine.UIElements; -using VRBuilder.Editor.XRInteraction; -using VRBuilder.XRInteraction; - -namespace VRBuilder.Editor.UI -{ - internal class SnapZoneSettingsProvider : SettingsProvider - { - const string Path = "Project/VR Builder/Snap Zones"; - - private UnityEditor.Editor editor; - - public SnapZoneSettingsProvider() : base(Path, SettingsScope.Project) { } - - public override void OnGUI(string searchContext) - { - EditorGUILayout.Space(); - GUIStyle labelStyle = BuilderEditorStyles.ApplyPadding(BuilderEditorStyles.Paragraph, 0); - GUILayout.Label("These settings help you to configure Snap Zones within your scenes. You can define colors and other values that will be set to Snap Zones created by clicking the 'Create Snap Zone' button of a Snappable Property.", labelStyle); - EditorGUILayout.Space(); - - editor.OnInspectorGUI(); - - EditorGUILayout.Space(20f); - - if (GUILayout.Button("Apply settings in current scene")) - { - SnapZone[] snapZones = Resources.FindObjectsOfTypeAll(); - - foreach (SnapZone snapZone in snapZones) - { - SnapZoneSettings.Instance.ApplySettingsToSnapZone(snapZone); - } - } - } - - public override void OnActivate(string searchContext, VisualElement rootElement) - { - editor = UnityEditor.Editor.CreateEditor(SnapZoneSettings.Instance); - } - - [SettingsProvider] - public static SettingsProvider Provider() - { - SettingsProvider provider = new SnapZoneSettingsProvider(); - return provider; - } - } -} \ No newline at end of file diff --git a/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs b/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs new file mode 100644 index 000000000..d5df001dc --- /dev/null +++ b/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs @@ -0,0 +1,20 @@ +using VRBuilder.Editor.XRInteraction; +using VRBuilder.XRInteraction; + +namespace VRBuilder.Editor.UI +{ + /// + /// Settings section for . + /// + public class SnapZoneSettingsSection : ComponentSettingsSection + { + /// + public override string Title => "Snap Zones"; + + /// + public override string Description => "These settings help you to configure Snap Zones within your scenes. You can define colors and other values that will be set to Snap Zones created by clicking the 'Create Snap Zone' button of a Snappable Property."; + + /// + public override int Priority => 1000; + } +} \ No newline at end of file diff --git a/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs.meta b/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs.meta new file mode 100644 index 000000000..0a307acc2 --- /dev/null +++ b/Source/XR-Interaction-Component/Source/Editor/ProjectSettings/SnapZoneSettingsSection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6cf4f2ea43c4dd247b3fa2678ddaa532 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Source/XR-Interaction-Component/Source/Editor/Properties/SnappablePropertyEditor.cs b/Source/XR-Interaction-Component/Source/Editor/Properties/SnappablePropertyEditor.cs index ed0d214c6..8409c1e2b 100644 --- a/Source/XR-Interaction-Component/Source/Editor/Properties/SnappablePropertyEditor.cs +++ b/Source/XR-Interaction-Component/Source/Editor/Properties/SnappablePropertyEditor.cs @@ -50,7 +50,7 @@ public override void OnInspectorGUI() private SnapZone CreateSnapZone(SnappableProperty snappable) { // Retrieves a SnapZoneSettings and creates a clone for the snappable object - SnapZoneSettings settings = SnapZoneSettings.Settings; + SnapZoneSettings settings = SnapZoneSettings.Instance; GameObject snapZoneBlueprint = DuplicateObject(snappable.gameObject, settings.HighlightMaterial); // Saves it as highlight prefab. @@ -70,7 +70,7 @@ private SnapZone CreateSnapZone(SnappableProperty snappable) SnapZone snapZone = snapObject.AddComponent().SnapZone; snapZone.ShownHighlightObject = snapZonePrefab; - settings.ApplySettingsToSnapZone(snapZone); + settings.ApplySettings(snapZone); GameObject snapPoint = new GameObject("SnapPoint"); snapPoint.transform.SetParent(snapZone.transform); diff --git a/Source/XR-Interaction-Component/Source/Editor/SnapZone/SnapZoneSettings.cs b/Source/XR-Interaction-Component/Source/Editor/SnapZone/SnapZoneSettings.cs index 0ddd6cdbe..d4a78e46a 100644 --- a/Source/XR-Interaction-Component/Source/Editor/SnapZone/SnapZoneSettings.cs +++ b/Source/XR-Interaction-Component/Source/Editor/SnapZone/SnapZoneSettings.cs @@ -3,9 +3,9 @@ using UnityEditor; using UnityEngine; using UnityEngine.Rendering; -using VRBuilder.XRInteraction; -using VRBuilder.Core.Runtime.Utils; using UnityEngine.XR.Interaction.Toolkit; +using VRBuilder.Core.Runtime.Utils; +using VRBuilder.XRInteraction; namespace VRBuilder.Editor.XRInteraction { @@ -13,10 +13,9 @@ namespace VRBuilder.Editor.XRInteraction /// Settings for s for e.g. automatic creation of such snap zones. /// [CreateAssetMenu(fileName = "SnapZoneSettings", menuName = "VR Builder/SnapZoneSettings", order = 1)] - public class SnapZoneSettings : SettingsObject + public class SnapZoneSettings : ComponentSettings { private const string MaterialsPath = "Assets/MindPort/VR Builder/Resources/SnapZones"; - private static SnapZoneSettings settings; /// /// Only Interactables with this LayerMask will interact with this . @@ -69,16 +68,10 @@ public class SnapZoneSettings : SettingsObject /// public Material InvalidMaterial => SetupInvalidMaterial(); - /// - /// Loads the first existing found in the project. - /// If non are found, it creates and saves a new instance with default values. - /// - public static SnapZoneSettings Settings => RetrieveSnapZoneSettings(); - /// /// Applies current settings to provided . /// - public void ApplySettingsToSnapZone(SnapZone snapZone) + public override void ApplySettings(SnapZone snapZone) { snapZone.interactionLayers = InteractionLayerMask; snapZone.HighlightMeshMaterial = HighlightMaterial; @@ -86,41 +79,6 @@ public void ApplySettingsToSnapZone(SnapZone snapZone) snapZone.InvalidMaterial = InvalidMaterial; } - private static SnapZoneSettings RetrieveSnapZoneSettings() - { - if (settings == null) - { - string filter = "t:ScriptableObject SnapZoneSettings"; - - foreach (string guid in AssetDatabase.FindAssets(filter)) - { - string assetPath = AssetDatabase.GUIDToAssetPath(guid); - return settings = AssetDatabase.LoadAssetAtPath(assetPath, typeof(SnapZoneSettings)) as SnapZoneSettings; - } - - settings = CreateNewConfiguration(); - } - - return settings; - } - - private static SnapZoneSettings CreateNewConfiguration() - { - SnapZoneSettings snapZoneSettings = CreateInstance(); - - string filePath = "Assets/MindPort/VR Builder/Resources"; - - if (Directory.Exists(filePath) == false) - { - Directory.CreateDirectory(filePath); - } - - AssetDatabase.CreateAsset(snapZoneSettings, $"{filePath}/{nameof(SnapZoneSettings)}.asset"); - AssetDatabase.Refresh(); - - return snapZoneSettings; - } - private Material SetupHighlightMaterial() { if (highlightMaterial == null) diff --git a/Tests/XR-Interaction-Component/Runtime/SnapZoneTests.cs b/Tests/XR-Interaction-Component/Runtime/SnapZoneTests.cs index 90f377919..9a26ad8aa 100644 --- a/Tests/XR-Interaction-Component/Runtime/SnapZoneTests.cs +++ b/Tests/XR-Interaction-Component/Runtime/SnapZoneTests.cs @@ -1,6 +1,6 @@ -using System.Collections; +using NUnit.Framework; +using System.Collections; using System.Collections.Generic; -using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; using UnityEngine.XR.Interaction.Toolkit; @@ -8,8 +8,8 @@ using VRBuilder.Core; using VRBuilder.Core.Configuration; using VRBuilder.Core.Configuration.Modes; -using VRBuilder.Editor.XRInteraction; using VRBuilder.Core.Tests.RuntimeUtils; +using VRBuilder.Editor.XRInteraction; using VRBuilder.XRInteraction.Properties; namespace VRBuilder.XRInteraction.Tests @@ -437,7 +437,7 @@ public IEnumerator FastForwardDoesNotCompleteCondition() public void SetSnapZoneWithSnapZoneSettings() { // Given a snap zone - SnapZoneSettings settings = SnapZoneSettings.Settings; + SnapZoneSettings settings = SnapZoneSettings.Instance; SnapZoneProperty snapZoneProperty = CreateSnapZoneProperty(); SnapZone snapZone = snapZoneProperty.SnapZone; @@ -461,7 +461,7 @@ public void SetSnapZoneWithSnapZoneSettings() settings.ValidationColor = testValidationColor; settings.InvalidColor = testInvalidColor; - settings.ApplySettingsToSnapZone(snapZone); + settings.ApplySettings(snapZone); // Then the snap zone is updated. #if XRIT_0_10_OR_NEWER From e94625bf34611c2746da6e6e85288b3b92bb91a6 Mon Sep 17 00:00:00 2001 From: Sebastian Poetter <32681913+poetter-sebastian@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:51:37 +0200 Subject: [PATCH 3/8] Every TTS provider can have specific configuration fields (#245) * Added first try of loading customizable provider * Started to refactor the tts configuration loading mechanic * Finished TextToSpeech provider and configuration refactoring * Added more documentation to new functions and classes/interfaces * Fixed Runtime loading error * Reworked configuration loading because of there is no provider at runtime * Removed the default Editor and added better description of editor and custom tts provider (#245) --- .../DefaultTextToSpeechConfiguration.cs | 10 ++ .../DefaultTextToSpeechConfiguration.cs.meta | 3 + .../TextToSpeechSectionProvider.cs | 10 +- .../Providers/DummyTextToSpeechProvider.cs | 8 +- .../MicrosoftSapiTextToSpeechProvider.cs | 17 +++- .../Providers/WebTextToSpeechProvider.cs | 11 ++- .../Editor/TextToSpeechEditorUtils.cs | 10 +- ...ditor.cs => TextToSpeechSettingsEditor.cs} | 91 ++++++++++++++----- ...eta => TextToSpeechSettingsEditor.cs.meta} | 0 .../Runtime/ITextToSpeechConfiguration.cs | 33 +++++++ .../ITextToSpeechConfiguration.cs.meta | 3 + .../MicrosoftTextToSpeechConfiguration.cs | 75 +++++++++++++++ ...icrosoftTextToSpeechConfiguration.cs.meta} | 0 .../Provider/FileTextToSpeechProvider.cs | 15 ++- .../Runtime/Provider/ITextToSpeechProvider.cs | 6 +- .../Runtime/RuntimeConfigurationExtensions.cs | 28 +++--- .../Runtime/TextToSpeechAudio.cs | 3 +- .../Runtime/TextToSpeechConfiguration.cs | 75 --------------- .../Runtime/TextToSpeechContent.cs | 5 +- .../Runtime/TextToSpeechProviderFactory.cs | 23 +++-- .../Runtime/TextToSpeechSettings.cs | 71 +++++++++++++++ .../Runtime/TextToSpeechSettings.cs.meta | 3 + .../Runtime/TextToSpeechUtils.cs | 11 ++- 23 files changed, 365 insertions(+), 146 deletions(-) create mode 100644 Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs create mode 100644 Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs.meta rename Source/TextToSpeech-Component/Editor/{TextToSpeechConfigurationEditor.cs => TextToSpeechSettingsEditor.cs} (50%) rename Source/TextToSpeech-Component/Editor/{TextToSpeechConfigurationEditor.cs.meta => TextToSpeechSettingsEditor.cs.meta} (100%) create mode 100644 Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs create mode 100644 Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs.meta create mode 100644 Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs rename Source/TextToSpeech-Component/Runtime/{TextToSpeechConfiguration.cs.meta => MicrosoftTextToSpeechConfiguration.cs.meta} (100%) delete mode 100644 Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs create mode 100644 Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs create mode 100644 Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs.meta diff --git a/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs b/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs new file mode 100644 index 000000000..cb959c86d --- /dev/null +++ b/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs @@ -0,0 +1,10 @@ +using UnityEngine; +using VRBuilder.Core.Runtime.Utils; + +namespace Source.TextToSpeech_Component.Editor +{ + public class DefaultTextToSpeechConfiguration: SettingsObject + { + + } +} \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs.meta b/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs.meta new file mode 100644 index 000000000..a9195cffe --- /dev/null +++ b/Source/TextToSpeech-Component/Editor/DefaultTextToSpeechConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 38723cbb9f1e433d9cea91b703547d67 +timeCreated: 1726585072 \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Editor/ProjectSettings/TextToSpeechSectionProvider.cs b/Source/TextToSpeech-Component/Editor/ProjectSettings/TextToSpeechSectionProvider.cs index 2842bebc2..9fb0809c4 100644 --- a/Source/TextToSpeech-Component/Editor/ProjectSettings/TextToSpeechSectionProvider.cs +++ b/Source/TextToSpeech-Component/Editor/ProjectSettings/TextToSpeechSectionProvider.cs @@ -23,12 +23,12 @@ public class TextToSpeechSectionProvider : IProjectSettingsSection /// public void OnGUI(string searchContext) { - GUILayout.Label("Configuration for your Text to Speech provider.", BuilderEditorStyles.ApplyPadding(BuilderEditorStyles.Label, 0)); + GUILayout.Label("General Configuration of Text to Speech.", BuilderEditorStyles.ApplyPadding(BuilderEditorStyles.Label, 0)); GUILayout.Space(8); - TextToSpeechConfiguration config = TextToSpeechConfiguration.Instance; - UnityEditor.Editor.CreateEditor(config, typeof(VRBuilder.Editor.TextToSpeech.UI.TextToSpeechConfigurationEditor)).OnInspectorGUI(); + TextToSpeechSettings config = TextToSpeechSettings.Instance; + UnityEditor.Editor.CreateEditor(config, typeof(TextToSpeechSettingsEditor)).OnInspectorGUI(); GUILayout.Space(8); @@ -38,9 +38,9 @@ public void OnGUI(string searchContext) ~TextToSpeechSectionProvider() { - if (EditorUtility.IsDirty(TextToSpeechConfiguration.Instance)) + if (EditorUtility.IsDirty(TextToSpeechSettings.Instance)) { - TextToSpeechConfiguration.Instance.Save(); + TextToSpeechSettings.Instance.Save(); } } } diff --git a/Source/TextToSpeech-Component/Editor/Providers/DummyTextToSpeechProvider.cs b/Source/TextToSpeech-Component/Editor/Providers/DummyTextToSpeechProvider.cs index 4195c3754..dcfe53183 100644 --- a/Source/TextToSpeech-Component/Editor/Providers/DummyTextToSpeechProvider.cs +++ b/Source/TextToSpeech-Component/Editor/Providers/DummyTextToSpeechProvider.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Source.TextToSpeech_Component.Runtime; using UnityEngine; using VRBuilder.TextToSpeech; using UnityEngine.Localization; @@ -18,8 +19,13 @@ public Task ConvertTextToSpeech(string text, Locale locale) return Task.FromResult(audioClip); } + public ITextToSpeechConfiguration LoadConfig() + { + return null; + } + /// - public void SetConfig(TextToSpeechConfiguration configuration) + public void SetConfig(ITextToSpeechConfiguration configuration) { } } diff --git a/Source/TextToSpeech-Component/Editor/Providers/MicrosoftSapiTextToSpeechProvider.cs b/Source/TextToSpeech-Component/Editor/Providers/MicrosoftSapiTextToSpeechProvider.cs index 0fda35ec7..568f1d0f2 100644 --- a/Source/TextToSpeech-Component/Editor/Providers/MicrosoftSapiTextToSpeechProvider.cs +++ b/Source/TextToSpeech-Component/Editor/Providers/MicrosoftSapiTextToSpeechProvider.cs @@ -3,9 +3,11 @@ using SpeechLib; using UnityEngine; using System.Threading.Tasks; +using Source.TextToSpeech_Component.Runtime; using VRBuilder.Core.Localization; using VRBuilder.TextToSpeech; using UnityEngine.Localization; +using VRBuilder.Core.Configuration; namespace VRBuilder.Editor.TextToSpeech { @@ -17,7 +19,8 @@ namespace VRBuilder.Editor.TextToSpeech /// public class MicrosoftSapiTextToSpeechProvider : ITextToSpeechProvider { - private TextToSpeechConfiguration configuration; + private ITextToSpeechConfiguration configuration; + private MicrosoftTextToSpeechConfiguration Configuration => configuration as MicrosoftTextToSpeechConfiguration; /// /// This is the template of the Speech Synthesis Markup Language (SSML) string used to change the language and voice. @@ -80,11 +83,17 @@ private static SpFileStream PrepareFileStreamToWrite(string path) } /// - public void SetConfig(TextToSpeechConfiguration configuration) + public void SetConfig(ITextToSpeechConfiguration configuration) { this.configuration = configuration; } + /// + public ITextToSpeechConfiguration LoadConfig() + { + return MicrosoftTextToSpeechConfiguration.Instance; + } + /// public Task ConvertTextToSpeech(string text, Locale locale) { @@ -92,7 +101,7 @@ public Task ConvertTextToSpeech(string text, Locale locale) // Check the validity of the voice in the configuration. // If it is invalid, change it to neutral. - string voice = configuration.Voice; + string voice = Configuration.Voice; switch (voice.ToLower()) { case "female": @@ -145,7 +154,7 @@ private float[] Synthesize(string text, string outputPath, string language, stri private string PrepareFilepathForText(string text, Locale locale) { string filename = configuration.GetUniqueTextToSpeechFilename(text, locale); - string directory = Path.Combine(Application.temporaryCachePath.Replace('/', Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, configuration.StreamingAssetCacheDirectoryName); + string directory = Path.Combine(Application.temporaryCachePath.Replace('/', Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar, RuntimeConfigurator.Configuration.GetTextToSpeechSettings().StreamingAssetCacheDirectoryName); Directory.CreateDirectory(directory); return Path.Combine(directory, filename); } diff --git a/Source/TextToSpeech-Component/Editor/Providers/WebTextToSpeechProvider.cs b/Source/TextToSpeech-Component/Editor/Providers/WebTextToSpeechProvider.cs index 55b40596a..045585c14 100644 --- a/Source/TextToSpeech-Component/Editor/Providers/WebTextToSpeechProvider.cs +++ b/Source/TextToSpeech-Component/Editor/Providers/WebTextToSpeechProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Threading.Tasks; +using Source.TextToSpeech_Component.Runtime; using VRBuilder.Unity; using UnityEngine; using UnityEngine.Networking; @@ -14,7 +15,7 @@ namespace VRBuilder.Editor.TextToSpeech /// public abstract class WebTextToSpeechProvider : ITextToSpeechProvider { - protected TextToSpeechConfiguration Configuration; + protected ITextToSpeechConfiguration Configuration; protected readonly UnityWebRequest UnityWebRequest; @@ -44,7 +45,7 @@ protected WebTextToSpeechProvider(UnityWebRequest unityWebRequest, IAudioConvert #region Public Interface /// - public void SetConfig(TextToSpeechConfiguration configuration) + public void SetConfig(ITextToSpeechConfiguration configuration) { Configuration = configuration; } @@ -57,6 +58,12 @@ public async Task ConvertTextToSpeech(string text,Locale locale) return await taskCompletion.Task; } + + public ITextToSpeechConfiguration LoadConfig() + { + return Configuration; + } + #endregion #region Download handling diff --git a/Source/TextToSpeech-Component/Editor/TextToSpeechEditorUtils.cs b/Source/TextToSpeech-Component/Editor/TextToSpeechEditorUtils.cs index d0ca32592..52e77f2c0 100644 --- a/Source/TextToSpeech-Component/Editor/TextToSpeechEditorUtils.cs +++ b/Source/TextToSpeech-Component/Editor/TextToSpeechEditorUtils.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Source.TextToSpeech_Component.Runtime; using UnityEditor; using UnityEngine; using UnityEngine.Localization; @@ -20,10 +21,10 @@ public static class TextToSpeechEditorUtils /// /// Generates TTS audio and creates a file. /// - public static async Task CacheAudioClip(string text, Locale locale, TextToSpeechConfiguration configuration) + public static async Task CacheAudioClip(string text, Locale locale, ITextToSpeechConfiguration configuration) { string filename = configuration.GetUniqueTextToSpeechFilename(text, locale); - string filePath = $"{configuration.StreamingAssetCacheDirectoryName}/{filename}"; + string filePath = $"{RuntimeConfigurator.Configuration.GetTextToSpeechSettings().StreamingAssetCacheDirectoryName}/{filename}"; ITextToSpeechProvider provider = TextToSpeechProviderFactory.Instance.CreateProvider(configuration); AudioClip audioClip = await provider.ConvertTextToSpeech(text, locale); @@ -63,7 +64,8 @@ private static bool CacheAudio(AudioClip audioClip, string filePath, IAudioConve /// public static async Task CacheTextToSpeechClips(IEnumerable clips, Locale locale, string localizationTable) { - TextToSpeechConfiguration configuration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); + ITextToSpeechConfiguration configuration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); + TextToSpeechSettings settings = RuntimeConfigurator.Configuration.GetTextToSpeechSettings(); ITextToSpeechContent[] validClips = clips.Where(clip => string.IsNullOrEmpty(clip.Text) == false).ToArray(); for (int i = 0; i < validClips.Length; i++) { @@ -72,7 +74,7 @@ public static async Task CacheTextToSpeechClips(IEnumerable - /// This class draws list of in . + /// This class draws list of in and other properties for text to speech settings. + /// If an Implementation of a is selected the linked gets loaded. /// - [CustomEditor(typeof(TextToSpeechConfiguration))] - public class TextToSpeechConfigurationEditor : UnityEditor.Editor + [CustomEditor(typeof(TextToSpeechSettings))] + public class TextToSpeechSettingsEditor : UnityEditor.Editor { - private TextToSpeechConfiguration textToSpeechConfiguration; + private TextToSpeechSettings textToSpeechSettings; + private string[] providers = { "Empty" }; + private string cacheDirectoryName = "TextToSpeech"; + + private ITextToSpeechProvider currentElement; + private ITextToSpeechConfiguration currentElementSettings; + + private string lastSelectedCacheDirectory = ""; private int providersIndex = 0; private int lastProviderSelectedIndex = 0; - - private void OnEnable() - { - textToSpeechConfiguration = (TextToSpeechConfiguration)target; - providers = ReflectionUtils.GetConcreteImplementationsOf().ToList().Where(type => type != typeof(FileTextToSpeechProvider)).Select(type => type.Name).ToArray(); - lastProviderSelectedIndex = providersIndex = string.IsNullOrEmpty(textToSpeechConfiguration.Provider) ? Array.IndexOf(providers, nameof(MicrosoftSapiTextToSpeechProvider)) : Array.IndexOf(providers, textToSpeechConfiguration.Provider); - textToSpeechConfiguration.Provider = providers[providersIndex]; - } - + /// public override void OnInspectorGUI() { - DrawDefaultInspector(); + EditorGUI.BeginChangeCheck(); + providersIndex = EditorGUILayout.Popup("Provider", providersIndex, providers); + lastSelectedCacheDirectory = EditorGUILayout.TextField("Streaming Asset Cache Directory Name", lastSelectedCacheDirectory); + + if (lastSelectedCacheDirectory != cacheDirectoryName) + { + cacheDirectoryName = lastSelectedCacheDirectory; + textToSpeechSettings.StreamingAssetCacheDirectoryName = lastSelectedCacheDirectory; + } + //check if a new provider is selected if (providersIndex != lastProviderSelectedIndex) { lastProviderSelectedIndex = providersIndex; - textToSpeechConfiguration.Provider = providers[providersIndex]; - textToSpeechConfiguration.Save(); + + GetProviderInstance(); + //save new config + textToSpeechSettings.Provider = providers[providersIndex]; + textToSpeechSettings.Configuration = currentElementSettings; + + textToSpeechSettings.Save(); } - + + //check selected element is + if (currentElementSettings is ScriptableObject scriptableObject) + { + GUILayout.Space(8); + + var customHeader = BuilderEditorStyles.Header; + customHeader.fixedHeight = 25f; + EditorGUILayout.LabelField("Provider specific settings", customHeader); + GUILayout.Space(8); + GUILayout.Label("Configuration for your Text to Speech provider.", BuilderEditorStyles.ApplyPadding(BuilderEditorStyles.Label, 0)); + UnityEditor.Editor.CreateEditor(scriptableObject).OnInspectorGUI(); + } + IProcess currentProcess = GlobalEditorHandler.GetCurrentProcess(); GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); @@ -70,7 +97,7 @@ public override void OnInspectorGUI() { string absolutePath = Application.streamingAssetsPath; string relativePath = absolutePath.Replace(Application.dataPath, "Assets"); - string directory = Path.Combine(relativePath, textToSpeechConfiguration.StreamingAssetCacheDirectoryName); + string directory = Path.Combine(relativePath, cacheDirectoryName); if (AssetDatabase.DeleteAsset(directory)) { @@ -83,7 +110,29 @@ public override void OnInspectorGUI() } } } - + + private void OnEnable() + { + textToSpeechSettings = (TextToSpeechSettings)target; + cacheDirectoryName = textToSpeechSettings.StreamingAssetCacheDirectoryName; + lastSelectedCacheDirectory = cacheDirectoryName; + providers = ReflectionUtils.GetConcreteImplementationsOf().ToList().Where(type => type != typeof(FileTextToSpeechProvider)).Select(type => type.Name).ToArray(); + lastProviderSelectedIndex = providersIndex = string.IsNullOrEmpty(textToSpeechSettings.Provider) ? Array.IndexOf(providers, nameof(MicrosoftSapiTextToSpeechProvider)) : Array.IndexOf(providers, textToSpeechSettings.Provider); + textToSpeechSettings.Provider = providers[providersIndex]; + + GetProviderInstance(); + } + + private void GetProviderInstance() + { + var currentProviderType = ReflectionUtils.GetConcreteImplementationsOf().FirstOrDefault(type => type.Name == providers[providersIndex]); + if (Activator.CreateInstance(currentProviderType) is ITextToSpeechProvider provider) + { + currentElement = provider; + currentElementSettings = currentElement.LoadConfig(); + } + } + private string GetAvailableLocales() { string availableLOcalesString = ""; diff --git a/Source/TextToSpeech-Component/Editor/TextToSpeechConfigurationEditor.cs.meta b/Source/TextToSpeech-Component/Editor/TextToSpeechSettingsEditor.cs.meta similarity index 100% rename from Source/TextToSpeech-Component/Editor/TextToSpeechConfigurationEditor.cs.meta rename to Source/TextToSpeech-Component/Editor/TextToSpeechSettingsEditor.cs.meta diff --git a/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs b/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs new file mode 100644 index 000000000..9abc8527e --- /dev/null +++ b/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs @@ -0,0 +1,33 @@ +using System.Linq; +using UnityEngine.Localization; +using VRBuilder.Core.Utils; +using VRBuilder.TextToSpeech; + +namespace Source.TextToSpeech_Component.Runtime +{ + /// + /// Base interface to implement a new text to speech configuration + /// + /// + /// It always should implement with SettingsObject to prevent type cast errors + /// + public interface ITextToSpeechConfiguration + { + /// + /// Get GetUniqueIdentifier to identify the text relative to the locale and hash value + /// + /// Text to get the identifier + /// Hashed text value + /// Used locale + /// A unique identifier of the text + string GetUniqueIdentifier(string text, string md5Hash, Locale locale); + + /// + /// Check if the localizedContent in the chosen locale is cached + /// + /// Used locale + /// Content to be checked + /// True if the localizedContent in the chosen locale is cached + bool IsCached(Locale locale, string localizedContent); + } +} \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs.meta b/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs.meta new file mode 100644 index 000000000..4e0fc7684 --- /dev/null +++ b/Source/TextToSpeech-Component/Runtime/ITextToSpeechConfiguration.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ea2ef2e9973c41ba95a803851252c0da +timeCreated: 1726591921 \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs b/Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs new file mode 100644 index 000000000..02570bd52 --- /dev/null +++ b/Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs @@ -0,0 +1,75 @@ +using System.IO; +using Source.TextToSpeech_Component.Runtime; +using UnityEngine; +using UnityEngine.Localization; +using VRBuilder.Core.Configuration; +using VRBuilder.Core.Runtime.Utils; + +namespace VRBuilder.TextToSpeech +{ + public class MicrosoftTextToSpeechConfiguration : SettingsObject, ITextToSpeechConfiguration + { + /// + /// Voice that should be used. + /// + [SerializeField] + private string voice = "Male"; + + /// + /// Property of + /// + public string Voice => voice; + + /// + /// Loads the first existing found in the project. + /// If any exist in the project it creates and saves a new instance with default values (editor only). + /// + /// When used in runtime, this method can only retrieve config files located under a Resources folder. + public static MicrosoftTextToSpeechConfiguration LoadConfiguration() + { + MicrosoftTextToSpeechConfiguration configuration = Resources.Load(nameof(MicrosoftTextToSpeechConfiguration)); + return configuration != null ? configuration : CreateNewConfiguration(); + } + + /// + public string GetUniqueIdentifier(string text, string md5Hash, Locale locale) + { + return $"TTS_{voice}_{locale.Identifier.Code}_{md5Hash.Replace("-", "")}"; + } + + /// + public bool IsCached(Locale locale, string localizedContent) + { + string filename = this.GetUniqueTextToSpeechFilename(localizedContent, locale); + string filePath = $"{RuntimeConfigurator.Configuration.GetTextToSpeechSettings().StreamingAssetCacheDirectoryName}/{filename}"; + return File.Exists(Path.Combine(Application.streamingAssetsPath, filePath)); + } + + private static MicrosoftTextToSpeechConfiguration CreateNewConfiguration() + { + MicrosoftTextToSpeechConfiguration microsoftTextToSpeechConfiguration = CreateInstance(); + RuntimeConfigurator.Configuration.SetTextToSpeechConfiguration(microsoftTextToSpeechConfiguration); + +#if UNITY_EDITOR + string resourcesPath = "Assets/MindPort/VR Builder/Resources/"; + string configFilePath = $"{resourcesPath}{nameof(MicrosoftTextToSpeechConfiguration)}.asset"; + + if (Directory.Exists(resourcesPath) == false) + { + Directory.CreateDirectory(resourcesPath); + } + + Debug.LogWarningFormat("No text to speech configuration found!\nA new configuration file was created at {0}", configFilePath); + UnityEditor.AssetDatabase.CreateAsset(microsoftTextToSpeechConfiguration, configFilePath); + UnityEditor.AssetDatabase.Refresh(); + + if (Application.isPlaying == false) + { + UnityEditor.Selection.activeObject = microsoftTextToSpeechConfiguration; + } +#endif + + return microsoftTextToSpeechConfiguration; + } + } +} \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs.meta b/Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs.meta similarity index 100% rename from Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs.meta rename to Source/TextToSpeech-Component/Runtime/MicrosoftTextToSpeechConfiguration.cs.meta diff --git a/Source/TextToSpeech-Component/Runtime/Provider/FileTextToSpeechProvider.cs b/Source/TextToSpeech-Component/Runtime/Provider/FileTextToSpeechProvider.cs index 5f1bffcef..0b9dd649d 100644 --- a/Source/TextToSpeech-Component/Runtime/Provider/FileTextToSpeechProvider.cs +++ b/Source/TextToSpeech-Component/Runtime/Provider/FileTextToSpeechProvider.cs @@ -3,7 +3,9 @@ using VRBuilder.Core.IO; using UnityEngine; using System.IO; +using Source.TextToSpeech_Component.Runtime; using UnityEngine.Localization; +using VRBuilder.Core.Configuration; namespace VRBuilder.TextToSpeech { @@ -15,9 +17,9 @@ namespace VRBuilder.TextToSpeech /// public class FileTextToSpeechProvider : ITextToSpeechProvider { - protected TextToSpeechConfiguration Configuration; + protected ITextToSpeechConfiguration Configuration; - public FileTextToSpeechProvider(TextToSpeechConfiguration configuration) + public FileTextToSpeechProvider(ITextToSpeechConfiguration configuration) { Configuration = configuration; } @@ -51,8 +53,13 @@ public async Task ConvertTextToSpeech(string text, Locale locale) return audioClip; } + public ITextToSpeechConfiguration LoadConfig() + { + return Configuration; + } + /// - public void SetConfig(TextToSpeechConfiguration configuration) + public void SetConfig(ITextToSpeechConfiguration configuration) { Configuration = configuration; } @@ -62,7 +69,7 @@ public void SetConfig(TextToSpeechConfiguration configuration) /// protected virtual string GetPathToFile(string filename) { - string directory = $"{Configuration.StreamingAssetCacheDirectoryName}/{filename}"; + string directory = $"{RuntimeConfigurator.Configuration.GetTextToSpeechSettings().StreamingAssetCacheDirectoryName}/{filename}"; return directory; } diff --git a/Source/TextToSpeech-Component/Runtime/Provider/ITextToSpeechProvider.cs b/Source/TextToSpeech-Component/Runtime/Provider/ITextToSpeechProvider.cs index e9acce70f..64f9e25d5 100644 --- a/Source/TextToSpeech-Component/Runtime/Provider/ITextToSpeechProvider.cs +++ b/Source/TextToSpeech-Component/Runtime/Provider/ITextToSpeechProvider.cs @@ -1,6 +1,8 @@ using System.Threading.Tasks; +using Source.TextToSpeech_Component.Runtime; using UnityEngine; using UnityEngine.Localization; +using VRBuilder.Core.Runtime.Utils; namespace VRBuilder.TextToSpeech { @@ -12,11 +14,13 @@ public interface ITextToSpeechProvider /// /// Used for setting the config file. /// - void SetConfig(TextToSpeechConfiguration configuration); + void SetConfig(ITextToSpeechConfiguration configuration); /// /// Loads the AudioClip file for the given text. /// Task ConvertTextToSpeech(string text, Locale locale); + + public ITextToSpeechConfiguration LoadConfig(); } } \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/RuntimeConfigurationExtensions.cs b/Source/TextToSpeech-Component/Runtime/RuntimeConfigurationExtensions.cs index 801b58159..ce0998a3a 100644 --- a/Source/TextToSpeech-Component/Runtime/RuntimeConfigurationExtensions.cs +++ b/Source/TextToSpeech-Component/Runtime/RuntimeConfigurationExtensions.cs @@ -1,4 +1,8 @@ -using VRBuilder.Core.Configuration; +using System; +using System.Linq; +using Source.TextToSpeech_Component.Runtime; +using VRBuilder.Core.Configuration; +using VRBuilder.Core.Utils; namespace VRBuilder.TextToSpeech { @@ -10,28 +14,28 @@ public static class RuntimeConfigurationExtensions /// /// Text to speech configuration. /// - private static TextToSpeechConfiguration textToSpeechConfiguration; + private static ITextToSpeechConfiguration TextToSpeechConfiguration; /// - /// Return loaded . + /// Return loaded . /// - public static TextToSpeechConfiguration GetTextToSpeechConfiguration(this BaseRuntimeConfiguration runtimeConfiguration) + public static ITextToSpeechConfiguration GetTextToSpeechConfiguration(this BaseRuntimeConfiguration runtimeConfiguration) { - if (textToSpeechConfiguration == null) - { - textToSpeechConfiguration = TextToSpeechConfiguration.LoadConfiguration(); - } + return GetTextToSpeechSettings(runtimeConfiguration).Configuration ?? MicrosoftTextToSpeechConfiguration.Instance; + } - return textToSpeechConfiguration; + public static TextToSpeechSettings GetTextToSpeechSettings(this BaseRuntimeConfiguration runtimeConfiguration) + { + return TextToSpeechSettings.Instance; } /// - /// Loads a new + /// Loads a new /// public static void SetTextToSpeechConfiguration(this BaseRuntimeConfiguration runtimeConfiguration, - TextToSpeechConfiguration ttsConfiguration) + ITextToSpeechConfiguration textToSpeechConfiguration) { - textToSpeechConfiguration = ttsConfiguration; + TextToSpeechConfiguration = textToSpeechConfiguration; } } } \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechAudio.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechAudio.cs index ef2b0a04e..bba0b70ff 100644 --- a/Source/TextToSpeech-Component/Runtime/TextToSpeechAudio.cs +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechAudio.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.Serialization; +using Source.TextToSpeech_Component.Runtime; using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; @@ -105,7 +106,7 @@ public async void InitializeAudioClip() try { - TextToSpeechConfiguration ttsConfiguration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); + ITextToSpeechConfiguration ttsConfiguration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); ITextToSpeechProvider provider = new FileTextToSpeechProvider(ttsConfiguration); AudioClip = await provider.ConvertTextToSpeech(GetLocalizedContent(), LanguageSettings.Instance.ActiveOrDefaultLocale); } diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs deleted file mode 100644 index 9c6ff46e0..000000000 --- a/Source/TextToSpeech-Component/Runtime/TextToSpeechConfiguration.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.IO; -using UnityEngine; -using VRBuilder.Core.Configuration; -using VRBuilder.Core.Runtime.Utils; - -namespace VRBuilder.TextToSpeech -{ - public class TextToSpeechConfiguration : SettingsObject - { - /// - /// Name of the . - /// - [HideInInspector] - public string Provider; - - /// - /// Voice that should be used. - /// - /// It depends on the chosen provider. - public string Voice = "Male"; - - /// - /// StreamingAsset directory name which is used to load/save audio files. - /// - public string StreamingAssetCacheDirectoryName = "TextToSpeech"; - - /// - /// Used to authenticate at the provider, if required. - /// - public string Auth; - - public TextToSpeechConfiguration() - { - Provider = "MicrosoftSapiTextToSpeechProvider"; - } - - /// - /// Loads the first existing found in the project. - /// If any exist in the project it creates and saves a new instance with default values (editor only). - /// - /// When used in runtime, this method can only retrieve config files located under a Resources folder. - public static TextToSpeechConfiguration LoadConfiguration() - { - TextToSpeechConfiguration configuration = Resources.Load(nameof(TextToSpeechConfiguration)); - return configuration != null ? configuration : CreateNewConfiguration(); - } - - private static TextToSpeechConfiguration CreateNewConfiguration() - { - TextToSpeechConfiguration textToSpeechConfiguration = CreateInstance(); - RuntimeConfigurator.Configuration.SetTextToSpeechConfiguration(textToSpeechConfiguration); - -#if UNITY_EDITOR - string resourcesPath = "Assets/MindPort/VR Builder/Resources/"; - string configFilePath = $"{resourcesPath}{nameof(TextToSpeechConfiguration)}.asset"; - - if (Directory.Exists(resourcesPath) == false) - { - Directory.CreateDirectory(resourcesPath); - } - - Debug.LogWarningFormat("No text to speech configuration found!\nA new configuration file was created at {0}", configFilePath); - UnityEditor.AssetDatabase.CreateAsset(textToSpeechConfiguration, configFilePath); - UnityEditor.AssetDatabase.Refresh(); - - if (Application.isPlaying == false) - { - UnityEditor.Selection.activeObject = textToSpeechConfiguration; - } -#endif - - return textToSpeechConfiguration; - } - } -} \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechContent.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechContent.cs index 43b0b8976..01d176e14 100644 --- a/Source/TextToSpeech-Component/Runtime/TextToSpeechContent.cs +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechContent.cs @@ -20,10 +20,7 @@ public abstract class TextToSpeechContent : ITextToSpeechContent, ILocalizedCont /// public virtual bool IsCached(Locale locale) { - TextToSpeechConfiguration ttsConfiguration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); - string filename = ttsConfiguration.GetUniqueTextToSpeechFilename(GetLocalizedContent(), locale); - string filePath = $"{ttsConfiguration.StreamingAssetCacheDirectoryName}/{filename}"; - return File.Exists(Path.Combine(Application.streamingAssetsPath, filePath)); + return RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration().IsCached(locale, GetLocalizedContent()); } } } \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechProviderFactory.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechProviderFactory.cs index 7de120f6e..127a787b5 100644 --- a/Source/TextToSpeech-Component/Runtime/TextToSpeechProviderFactory.cs +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechProviderFactory.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Source.TextToSpeech_Component.Runtime; +using VRBuilder.Core.Configuration; using VRBuilder.Core.Utils; using VRBuilder.Unity; @@ -16,7 +18,7 @@ public class TextToSpeechProviderFactory : Singleton @@ -35,10 +37,10 @@ public BaseCreator(Type textToSpeechProviderType) this.textToSpeechProviderType = textToSpeechProviderType; } - public ITextToSpeechProvider Create(TextToSpeechConfiguration configuration) + public ITextToSpeechProvider Create(ITextToSpeechConfiguration configuration) { ITextToSpeechProvider provider = Activator.CreateInstance(textToSpeechProviderType) as ITextToSpeechProvider; - provider.SetConfig(configuration); + provider?.SetConfig(configuration); return provider; } } @@ -73,26 +75,29 @@ public void RegisterProvider(Type textToSpeechProviderType) /// public ITextToSpeechProvider CreateProvider() { - TextToSpeechConfiguration ttsConfiguration = TextToSpeechConfiguration.LoadConfiguration(); + //get selected configuration + ITextToSpeechConfiguration ttsConfiguration = RuntimeConfigurator.Configuration.GetTextToSpeechConfiguration(); return CreateProvider(ttsConfiguration); } /// /// Creates a provider with given config. /// - public ITextToSpeechProvider CreateProvider(TextToSpeechConfiguration configuration) + public ITextToSpeechProvider CreateProvider(ITextToSpeechConfiguration configuration) { - if (string.IsNullOrEmpty(configuration.Provider)) + TextToSpeechSettings settings = RuntimeConfigurator.Configuration.GetTextToSpeechSettings(); + + if (string.IsNullOrEmpty(settings.Provider)) { throw new NoConfigurationFoundException($"There is not a valid provider set in '{configuration.GetType().Name}'!"); } - if (!registeredProvider.ContainsKey(configuration.Provider)) + if (!registeredProvider.ContainsKey(settings.Provider)) { - throw new NoMatchingProviderFoundException($"No matching provider with name '{configuration.Provider}' found!"); + throw new NoMatchingProviderFoundException($"No matching provider with name '{settings.Provider}' found!"); } - ITextToSpeechProvider provider = registeredProvider[configuration.Provider].Create(configuration); + ITextToSpeechProvider provider = registeredProvider[settings.Provider].Create(configuration); return provider; } diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs new file mode 100644 index 000000000..df9cec60d --- /dev/null +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs @@ -0,0 +1,71 @@ +using System.IO; +using Source.TextToSpeech_Component.Runtime; +using UnityEngine; +using VRBuilder.Core.Configuration; +using VRBuilder.Core.Runtime.Utils; + +namespace VRBuilder.TextToSpeech +{ + public class TextToSpeechSettings : SettingsObject + { + /// + /// Name of the . + /// + [HideInInspector] + public string Provider; + + /// + /// Configuration of the . + /// + [HideInInspector] + public ITextToSpeechConfiguration Configuration; + + /// + /// StreamingAsset directory name which is used to load/save audio files. + /// + public string StreamingAssetCacheDirectoryName = "TextToSpeech"; + + public TextToSpeechSettings() + { + Provider = "MicrosoftSapiTextToSpeechProvider"; + } + + /// + /// Loads the first existing found in the project. + /// If any exist in the project it creates and saves a new instance with default values (editor only). + /// + /// When used in runtime, this method can only retrieve config files located under a Resources folder. + //public static MicrosoftTextToSpeechConfiguration LoadConfiguration() + //{ + // MicrosoftTextToSpeechConfiguration configuration = Resources.Load(nameof(MicrosoftTextToSpeechConfiguration)); + // return configuration != null ? configuration : CreateNewConfiguration(); + //} + + private ITextToSpeechConfiguration CreateNewConfiguration() + { + ITextToSpeechConfiguration config = CreateInstance(Provider) as ITextToSpeechConfiguration; + RuntimeConfigurator.Configuration.SetTextToSpeechConfiguration(config); + +#if UNITY_EDITOR + string resourcesPath = "Assets/MindPort/VR Builder/Resources/"; + string configFilePath = $"{resourcesPath}{config.GetType().Name}.asset"; + + if (Directory.Exists(resourcesPath) == false) + { + Directory.CreateDirectory(resourcesPath); + } + + Debug.LogWarningFormat("No text to speech configuration found!\nA new configuration file was created at {0}", configFilePath); + UnityEditor.AssetDatabase.CreateAsset((ScriptableObject)config, configFilePath); + UnityEditor.AssetDatabase.Refresh(); + + if (Application.isPlaying == false) + { + UnityEditor.Selection.activeObject = (ScriptableObject)config; + } +#endif + + return config; + } + } +} \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs.meta b/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs.meta new file mode 100644 index 000000000..27727e94d --- /dev/null +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechSettings.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 71a2cbcb13cb436e804d531ae08850a1 +timeCreated: 1726572575 \ No newline at end of file diff --git a/Source/TextToSpeech-Component/Runtime/TextToSpeechUtils.cs b/Source/TextToSpeech-Component/Runtime/TextToSpeechUtils.cs index b9b9cf7c6..f05930f47 100644 --- a/Source/TextToSpeech-Component/Runtime/TextToSpeechUtils.cs +++ b/Source/TextToSpeech-Component/Runtime/TextToSpeechUtils.cs @@ -1,5 +1,6 @@ using System.Text; using System.Security.Cryptography; +using Source.TextToSpeech_Component.Runtime; using UnityEngine.Localization; namespace VRBuilder.TextToSpeech @@ -9,10 +10,9 @@ public static class TextToSpeechUtils /// /// Returns filename which uniquly identifies the audio by Backend, Language, Voice and also the text. /// - public static string GetUniqueTextToSpeechFilename(this TextToSpeechConfiguration configuration, string text, Locale locale, string format = "wav") + public static string GetUniqueTextToSpeechFilename(this ITextToSpeechConfiguration configuration, string text, Locale locale, string format = "wav") { - string hash = string.Format("{0}", text); - return string.Format(@"TTS_{0}_{1}_{2}.{3}", configuration.Voice, locale.Identifier.Code, GetMd5Hash(hash).Replace("-", ""), format); + return $"TTS_{configuration.GetUniqueIdentifier(text, GetMd5Hash($"{text}"), locale)}.{format}"; } /// @@ -31,6 +31,11 @@ public static float[] ShortsInByteArrayToFloats(byte[] shorts) return floats; } + /// + /// Hashed the input string + /// + /// Input string that has to be hashed + /// Hashed input as MD5 Hash private static string GetMd5Hash(string input) { using (MD5 md5Hash = MD5.Create()) From d55b5f246dfbe81d0e9bdb75f20e353cc772edab Mon Sep 17 00:00:00 2001 From: Marcello Tridenti Date: Mon, 30 Sep 2024 16:11:39 +0200 Subject: [PATCH 4/8] Added Base property to UserSceneObject (#246) --- .../Runtime/Properties/UserSceneObject.cs | 7 +- .../Resources/XR_Setup_Action_Based.prefab | 194 +++++++++++++++++- .../XR_Setup_Action_Based_HandTracking.prefab | 15 +- .../XR_Setup_Action_Based_Hands.prefab | 134 +++--------- 4 files changed, 244 insertions(+), 106 deletions(-) diff --git a/Source/Core/Runtime/Properties/UserSceneObject.cs b/Source/Core/Runtime/Properties/UserSceneObject.cs index 661719167..9654558d5 100644 --- a/Source/Core/Runtime/Properties/UserSceneObject.cs +++ b/Source/Core/Runtime/Properties/UserSceneObject.cs @@ -12,7 +12,7 @@ namespace VRBuilder.Core.Properties public class UserSceneObject : MonoBehaviour { [SerializeField] - private Transform head, leftHand, rightHand; + private Transform head, leftHand, rightHand, rigBase; /// /// Returns the user's head transform. @@ -40,5 +40,10 @@ public Transform Head /// Returns the user's right hand transform. /// public Transform RightHand => rightHand; + + /// + /// Returns the base of the rig. + /// + public Transform Base => rigBase; } } diff --git a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based.prefab b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based.prefab index 9683c5699..d32a13cf6 100644 --- a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based.prefab +++ b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based.prefab @@ -27,6 +27,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 8096380263314292854} - {fileID: 8232398725257180522} @@ -47,11 +48,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: f391ac734d94ea34697b6cde3269f11a, type: 3} m_Name: m_EditorClassIdentifier: - uniqueName: User - tags: [] head: {fileID: 7469053385970781433} leftHand: {fileID: 7978014071979369435} rightHand: {fileID: 7978014071415895673} + rigBase: {fileID: 8096380263314292854} --- !u!1 &2551566514137826033 GameObject: m_ObjectHideFlags: 0 @@ -78,6 +78,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4226580937276373881} m_RootOrder: 0 @@ -110,6 +111,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1153462130033586318} m_RootOrder: 3 @@ -141,6 +143,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: ab68ce6587aab0146b8dabefbd806791, type: 3} m_Name: m_EditorClassIdentifier: + m_SendPointerHoverToParent: 1 m_ClickSpeed: 0.3 m_MoveDeadzone: 0.6 m_RepeatDelay: 0.5 @@ -193,6 +196,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4640717108899920631} m_RootOrder: 0 @@ -224,6 +228,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1153462130033586318} m_RootOrder: 1 @@ -272,6 +277,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 8828615551242472943} m_Father: {fileID: 9052434312264737045} @@ -478,6 +484,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 7779212132400271959, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 70e6ddba-3f4d-4426-adf0-8e696375216e + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: fd842369-b8db-4ac6-b060-6ce9696a9c4b + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &7151388554539386832 MonoBehaviour: @@ -580,6 +610,7 @@ MonoBehaviour: m_SampleFrequency: 20 m_HitDetectionType: 0 m_SphereCastRadius: 0 + m_ConeCastAngle: 6 m_RaycastMask: serializedVersion: 2 m_Bits: 32 @@ -591,6 +622,7 @@ MonoBehaviour: m_AutoDeselect: 0 m_TimeToAutoDeselect: 3 m_EnableUIInteraction: 1 + m_BlockUIOnInteractableSelection: 1 m_AllowAnchorControl: 1 m_UseForceGrab: 1 m_RotateSpeed: 180 @@ -606,6 +638,7 @@ MonoBehaviour: m_EnableARRaycasting: 0 m_OccludeARHitsWith3DObjects: 0 m_OccludeARHitsWith2DObjects: 0 + m_ScaleMode: 0 --- !u!120 &4401965616013762662 LineRenderer: m_ObjectHideFlags: 0 @@ -617,6 +650,7 @@ LineRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 0 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 @@ -853,6 +887,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -883,6 +919,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1153462130033586318} m_RootOrder: 2 @@ -931,6 +968,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7978014070532965596} m_RootOrder: 0 @@ -1095,7 +1133,6 @@ MonoBehaviour: m_Action: Rotation m_Flags: 0 m_Flags: 0 - m_HasMigratedActions: 1 --- !u!1 &7485168110108878041 GameObject: m_ObjectHideFlags: 0 @@ -1131,6 +1168,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7978014070532965596} m_Father: {fileID: 1153462130033586318} @@ -1391,6 +1429,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7978014071979369435} m_RootOrder: 0 @@ -1425,6 +1464,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 9052434312753700112} m_Father: {fileID: 9052434312264737045} @@ -1631,6 +1671,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 7779212132400271959, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 886c868b-0658-4cb7-901d-ea3df914adc2 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: deeb8aee-a73f-45d3-80dc-34d365c0d985 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &7978014070459812427 MonoBehaviour: @@ -1733,6 +1797,7 @@ MonoBehaviour: m_SampleFrequency: 20 m_HitDetectionType: 0 m_SphereCastRadius: 0 + m_ConeCastAngle: 6 m_RaycastMask: serializedVersion: 2 m_Bits: 256 @@ -1744,6 +1809,7 @@ MonoBehaviour: m_AutoDeselect: 0 m_TimeToAutoDeselect: 3 m_EnableUIInteraction: 1 + m_BlockUIOnInteractableSelection: 1 m_AllowAnchorControl: 1 m_UseForceGrab: 1 m_RotateSpeed: 180 @@ -1759,6 +1825,7 @@ MonoBehaviour: m_EnableARRaycasting: 0 m_OccludeARHitsWith3DObjects: 0 m_OccludeARHitsWith2DObjects: 0 + m_ScaleMode: 0 --- !u!120 &7978014070459812426 LineRenderer: m_ObjectHideFlags: 0 @@ -1770,6 +1837,7 @@ LineRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 0 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 @@ -2011,6 +2079,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -2040,6 +2110,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7469053385970781433} - {fileID: 9052434312264737045} @@ -2076,6 +2147,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 9052434313405598513} m_Father: {fileID: 9052434312966663560} @@ -2282,6 +2354,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 875253871413052681, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 02820269-c422-456b-9050-c8549c5d87b1 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: 6d43fe91-6a2a-4859-a82f-35d91f4e85ca + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &8424491340227888840 MonoBehaviour: @@ -2417,6 +2513,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 9052434314099892218} m_Father: {fileID: 9052434312966663560} @@ -2623,6 +2720,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 875253871413052681, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 130b4baa-c4d3-43d4-9375-ba42cbc78551 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: fa152e14-1195-4f22-a449-76525edd13f2 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &7978014071796457455 MonoBehaviour: @@ -2725,6 +2846,7 @@ MonoBehaviour: m_SampleFrequency: 20 m_HitDetectionType: 0 m_SphereCastRadius: 0 + m_ConeCastAngle: 6 m_RaycastMask: serializedVersion: 2 m_Bits: 256 @@ -2736,6 +2858,7 @@ MonoBehaviour: m_AutoDeselect: 0 m_TimeToAutoDeselect: 3 m_EnableUIInteraction: 1 + m_BlockUIOnInteractableSelection: 1 m_AllowAnchorControl: 1 m_UseForceGrab: 1 m_RotateSpeed: 180 @@ -2751,6 +2874,7 @@ MonoBehaviour: m_EnableARRaycasting: 0 m_OccludeARHitsWith3DObjects: 0 m_OccludeARHitsWith2DObjects: 0 + m_ScaleMode: 0 --- !u!120 &7978014071796457450 LineRenderer: m_ObjectHideFlags: 0 @@ -2762,6 +2886,7 @@ LineRenderer: m_CastShadows: 0 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 0 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 @@ -3000,6 +3125,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -3032,6 +3159,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7783503986401448238} m_Father: {fileID: 9052434312264737045} @@ -3238,6 +3366,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 7779212132400271959, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 0575f569-8335-4fa6-a853-f7f04b1da2c8 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: b4d22712-601a-4542-bfda-bff78399d193 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &3983429610902661409 MonoBehaviour: @@ -3373,6 +3525,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 2670089473688130368} m_Father: {fileID: 9052434312966663560} @@ -3579,6 +3732,30 @@ MonoBehaviour: m_SingletonActionBindings: [] m_Flags: 0 m_Reference: {fileID: 875253871413052681, guid: c348712bda248c246b8c49b3db54643f, type: 3} + m_ScaleToggleAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Toggle + m_Type: 1 + m_ExpectedControlType: + m_Id: 04e506d2-729f-4771-bf00-a07e902435a8 + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} + m_ScaleDeltaAction: + m_UseReference: 0 + m_Action: + m_Name: Scale Delta + m_Type: 0 + m_ExpectedControlType: Vector2 + m_Id: 7488543f-f658-4e18-9c24-d708fba6fafe + m_Processors: + m_Interactions: + m_SingletonActionBindings: [] + m_Flags: 0 + m_Reference: {fileID: 0} m_ButtonPressPoint: 0.5 --- !u!114 &8070011684469424022 MonoBehaviour: @@ -3681,6 +3858,7 @@ MonoBehaviour: m_SampleFrequency: 20 m_HitDetectionType: 0 m_SphereCastRadius: 0 + m_ConeCastAngle: 6 m_RaycastMask: serializedVersion: 2 m_Bits: 32 @@ -3692,6 +3870,7 @@ MonoBehaviour: m_AutoDeselect: 0 m_TimeToAutoDeselect: 3 m_EnableUIInteraction: 1 + m_BlockUIOnInteractableSelection: 1 m_AllowAnchorControl: 1 m_UseForceGrab: 1 m_RotateSpeed: 180 @@ -3707,6 +3886,7 @@ MonoBehaviour: m_EnableARRaycasting: 0 m_OccludeARHitsWith3DObjects: 0 m_OccludeARHitsWith2DObjects: 0 + m_ScaleMode: 0 --- !u!120 &8657554238946022645 LineRenderer: m_ObjectHideFlags: 0 @@ -3718,6 +3898,7 @@ LineRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 0 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 @@ -3954,6 +4135,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -3984,6 +4167,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7978014071979369435} - {fileID: 7978014070459812424} @@ -4087,6 +4271,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7978014070459812424} m_RootOrder: 0 @@ -4118,6 +4303,7 @@ Transform: m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 7978014071415895673} - {fileID: 7978014071796457454} @@ -4221,6 +4407,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7978014071415895673} m_RootOrder: 0 @@ -4251,6 +4438,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7978014071796457454} m_RootOrder: 0 diff --git a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_HandTracking.prefab b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_HandTracking.prefab index 129c48154..ca16eca13 100644 --- a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_HandTracking.prefab +++ b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_HandTracking.prefab @@ -2480,6 +2480,8 @@ MonoBehaviour: m_StopLineAtSelection: 1 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 6402786117102733902} m_LineOriginOffset: 0 @@ -2908,6 +2910,8 @@ MonoBehaviour: m_StopLineAtSelection: 1 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 1308491568808473266} m_LineOriginOffset: 0.0375 @@ -3561,6 +3565,8 @@ MonoBehaviour: m_StopLineAtSelection: 1 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 6402786116742138543} m_LineOriginOffset: 0 @@ -4168,11 +4174,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: f391ac734d94ea34697b6cde3269f11a, type: 3} m_Name: m_EditorClassIdentifier: - uniqueName: User - tags: [] head: {fileID: 6402786116653345324} leftHand: {fileID: 6402786117102733902} rightHand: {fileID: 6402786116742138543} + rigBase: {fileID: 5695965693681382256} --- !u!1 &4212536449683465375 GameObject: m_ObjectHideFlags: 0 @@ -6443,6 +6448,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 6402786117102733902} m_LineOriginOffset: 0 @@ -8702,6 +8709,8 @@ MonoBehaviour: m_StopLineAtSelection: 1 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 4724445456448047939} m_LineOriginOffset: 0.0375 @@ -10505,6 +10514,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 6402786116742138543} m_LineOriginOffset: 0 diff --git a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_Hands.prefab b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_Hands.prefab index c3919b636..6adfe3fb1 100644 --- a/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_Hands.prefab +++ b/Source/XR-Interaction-Component/Source/Resources/XR_Setup_Action_Based_Hands.prefab @@ -23,13 +23,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 588686159} - serializedVersion: 2 m_LocalRotation: {x: 0.36650118, y: 0, z: 0, w: 0.9304176} m_LocalPosition: {x: 0.0447, y: -0.0476, z: 0.0131} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894391224387629} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 43, y: 0, z: 0} --- !u!1 &1238420757 GameObject: @@ -54,13 +54,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1238420757} - serializedVersion: 2 m_LocalRotation: {x: 0.2164396, y: 0, z: 0, w: 0.97629607} m_LocalPosition: {x: 0.0215, y: 0.0244, z: -0.0387} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390589475231} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 25, y: 0, z: 0} --- !u!1 &1328646383745684218 GameObject: @@ -85,13 +85,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1328646383745684218} - serializedVersion: 2 m_LocalRotation: {x: 0.2164396, y: 0, z: 0, w: 0.97629607} m_LocalPosition: {x: -0.0215, y: 0.0244, z: -0.0387} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390966364989} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 25, y: 0, z: 0} --- !u!1 &2002894390038460955 GameObject: @@ -119,7 +119,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390038460955} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -127,6 +126,7 @@ Transform: m_Children: - {fileID: 5583681650576868220} m_Father: {fileID: 2002894391949438518} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390038461159 MonoBehaviour: @@ -453,17 +453,9 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390038460955} m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 m_IsTrigger: 1 - m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 2 m_Radius: 0.05 m_Center: {x: 0, y: 0, z: 0} --- !u!1 &2002894390107448170 @@ -491,7 +483,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390107448170} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -502,6 +493,7 @@ Transform: - {fileID: 2002894390682587463} - {fileID: 2002894391758073219} m_Father: {fileID: 0} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &5421335889177590500 MonoBehaviour: @@ -515,12 +507,10 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: f391ac734d94ea34697b6cde3269f11a, type: 3} m_Name: m_EditorClassIdentifier: - uniqueName: User - uniqueId: - tags: [] head: {fileID: 2002894391982667492} leftHand: {fileID: 2002894390038461156} rightHand: {fileID: 2002894391344309348} + rigBase: {fileID: 2002894391948394052} --- !u!114 &2600886989601060523 MonoBehaviour: m_ObjectHideFlags: 0 @@ -560,7 +550,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390395887887} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -570,6 +559,7 @@ Transform: - {fileID: 2002894391949438518} - {fileID: 2002894392108743033} m_Father: {fileID: 2002894391948394052} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2002894390565357945 GameObject: @@ -595,13 +585,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390565357945} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390107448171} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390565357947 MonoBehaviour: @@ -644,7 +634,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390589475230} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -652,6 +641,7 @@ Transform: m_Children: - {fileID: 1238420758} m_Father: {fileID: 2002894392108743033} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390589475227 MonoBehaviour: @@ -1011,7 +1001,6 @@ MonoBehaviour: m_ScaleMode: 0 --- !u!120 &2002894390589475225 LineRenderer: - serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -1108,20 +1097,16 @@ LineRenderer: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 numCornerVertices: 4 numCapVertices: 4 alignment: 0 textureMode: 0 - textureScale: {x: 1, y: 1} shadowBias: 0.5 generateLightingData: 0 - m_MaskInteraction: 0 m_UseWorldSpace: 1 m_Loop: 0 - m_ApplyActiveColorSpace: 0 --- !u!114 &2002894390589475224 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1194,7 +1179,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_InvalidColorGradient: @@ -1224,7 +1208,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_BlockedColorGradient: @@ -1254,7 +1237,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 m_TreatSelectionAsValidState: 0 @@ -1267,6 +1249,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -1294,13 +1278,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390682587462} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390107448171} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390682587456 MonoBehaviour: @@ -1343,7 +1327,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390917405155} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -1351,6 +1334,7 @@ Transform: m_Children: - {fileID: 6481465182480156920} m_Father: {fileID: 2002894391949438518} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390917405160 MonoBehaviour: @@ -1710,7 +1694,6 @@ MonoBehaviour: m_ScaleMode: 0 --- !u!120 &2002894390917405166 LineRenderer: - serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -1805,20 +1788,16 @@ LineRenderer: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 numCornerVertices: 4 numCapVertices: 4 alignment: 0 textureMode: 0 - textureScale: {x: 1, y: 1} shadowBias: 0.5 generateLightingData: 0 - m_MaskInteraction: 0 m_UseWorldSpace: 1 m_Loop: 0 - m_ApplyActiveColorSpace: 0 --- !u!114 &2002894390917405165 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1891,7 +1870,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_InvalidColorGradient: @@ -1921,7 +1899,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_BlockedColorGradient: @@ -1951,7 +1928,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 m_TreatSelectionAsValidState: 0 @@ -1964,6 +1940,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -1994,7 +1972,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894390966364988} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -2002,6 +1979,7 @@ Transform: m_Children: - {fileID: 5159526950358397249} m_Father: {fileID: 2002894391949438518} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894390966364985 MonoBehaviour: @@ -2361,7 +2339,6 @@ MonoBehaviour: m_ScaleMode: 0 --- !u!120 &2002894390966364991 LineRenderer: - serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -2461,20 +2438,16 @@ LineRenderer: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 numCornerVertices: 4 numCapVertices: 4 alignment: 0 textureMode: 0 - textureScale: {x: 1, y: 1} shadowBias: 0 generateLightingData: 0 - m_MaskInteraction: 0 m_UseWorldSpace: 1 m_Loop: 0 - m_ApplyActiveColorSpace: 0 --- !u!114 &2002894390966364990 MonoBehaviour: m_ObjectHideFlags: 0 @@ -2547,7 +2520,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_InvalidColorGradient: @@ -2577,7 +2549,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_BlockedColorGradient: @@ -2607,7 +2578,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 m_TreatSelectionAsValidState: 0 @@ -2620,6 +2590,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -2650,7 +2622,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391224387628} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -2658,6 +2629,7 @@ Transform: m_Children: - {fileID: 588686160} m_Father: {fileID: 2002894392108743033} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894391224387625 MonoBehaviour: @@ -3017,7 +2989,6 @@ MonoBehaviour: m_ScaleMode: 0 --- !u!120 &2002894391224387631 LineRenderer: - serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -3112,20 +3083,16 @@ LineRenderer: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 numCornerVertices: 4 numCapVertices: 4 alignment: 0 textureMode: 0 - textureScale: {x: 1, y: 1} shadowBias: 0.5 generateLightingData: 0 - m_MaskInteraction: 0 m_UseWorldSpace: 1 m_Loop: 0 - m_ApplyActiveColorSpace: 0 --- !u!114 &2002894391224387630 MonoBehaviour: m_ObjectHideFlags: 0 @@ -3198,7 +3165,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_InvalidColorGradient: @@ -3228,7 +3194,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 3 m_NumAlphaKeys: 3 m_BlockedColorGradient: @@ -3258,7 +3223,6 @@ MonoBehaviour: atime6: 0 atime7: 0 m_Mode: 0 - m_ColorSpace: -1 m_NumColorKeys: 2 m_NumAlphaKeys: 2 m_TreatSelectionAsValidState: 0 @@ -3271,6 +3235,8 @@ MonoBehaviour: m_StopLineAtSelection: 0 m_SnapEndpointIfAvailable: 1 m_LineBendRatio: 0.5 + m_BendingEnabledInteractionLayers: + m_Bits: 4294967295 m_OverrideInteractorLineOrigin: 1 m_LineOriginTransform: {fileID: 0} m_LineOriginOffset: 0 @@ -3300,7 +3266,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391344315291} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3308,6 +3273,7 @@ Transform: m_Children: - {fileID: 2002894391468460883} m_Father: {fileID: 2002894392108743033} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894391344309351 MonoBehaviour: @@ -3634,17 +3600,9 @@ SphereCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391344315291} m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 m_IsTrigger: 1 - m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 2 m_Radius: 0.05 m_Center: {x: 0, y: 0, z: 0} --- !u!1 &2002894391468460882 @@ -3670,7 +3628,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391468460882} - serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3678,6 +3635,7 @@ Transform: m_Children: - {fileID: 1425447693803533075} m_Father: {fileID: 2002894391344309348} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2002894391758073218 GameObject: @@ -3704,13 +3662,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391758073218} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390107448171} + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894391758073229 MonoBehaviour: @@ -3798,7 +3756,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391948394107} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3806,6 +3763,7 @@ Transform: m_Children: - {fileID: 2002894390395887880} m_Father: {fileID: 2002894390107448171} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894391948394061 MonoBehaviour: @@ -3983,17 +3941,9 @@ CharacterController: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391948394107} m_Material: {fileID: 0} - m_IncludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_ExcludeLayers: - serializedVersion: 2 - m_Bits: 0 - m_LayerOverridePriority: 0 m_IsTrigger: 0 - m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 2 m_Height: 1.36144 m_Radius: 0.1 m_SlopeLimit: 45 @@ -4068,7 +4018,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391949438517} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -4078,6 +4027,7 @@ Transform: - {fileID: 2002894390966364989} - {fileID: 2002894390917405164} m_Father: {fileID: 2002894390395887880} + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894391949438519 MonoBehaviour: @@ -4176,13 +4126,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894391982667291} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390395887880} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!20 &2002894391982667489 Camera: @@ -4198,17 +4148,9 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -4376,7 +4318,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2002894392108743032} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -4386,6 +4327,7 @@ Transform: - {fileID: 2002894390589475231} - {fileID: 2002894391224387629} m_Father: {fileID: 2002894390395887880} + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2002894392108743034 MonoBehaviour: @@ -4480,7 +4422,6 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3544370734085250980} - serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -4488,6 +4429,7 @@ Transform: m_Children: - {fileID: 5248721344884395100} m_Father: {fileID: 2002894390038461156} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &6749825676455373053 GameObject: @@ -4512,20 +4454,19 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6749825676455373053} - serializedVersion: 2 m_LocalRotation: {x: 0.36650118, y: 0, z: 0, w: 0.9304176} m_LocalPosition: {x: -0.0447, y: -0.0476, z: 0.0131} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2002894390917405164} + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 43, y: 0, z: 0} --- !u!1001 &4071642445300941959 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: - serializedVersion: 3 m_TransformParent: {fileID: 2002894391468460883} m_Modifications: - target: {fileID: 2306551884257668398, guid: bde71cb35b3a69e478307d53a56242c0, type: 3} @@ -4577,9 +4518,6 @@ PrefabInstance: value: 90 objectReference: {fileID: 0} m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: bde71cb35b3a69e478307d53a56242c0, type: 3} --- !u!4 &1425447693803533075 stripped Transform: @@ -4596,7 +4534,6 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: - serializedVersion: 3 m_TransformParent: {fileID: 5583681650576868220} m_Modifications: - target: {fileID: 2306551884257668398, guid: 5efae94d4b2087b4dac0f1d210369580, type: 3} @@ -4648,9 +4585,6 @@ PrefabInstance: value: 90 objectReference: {fileID: 0} m_RemovedComponents: [] - m_RemovedGameObjects: [] - m_AddedGameObjects: [] - m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 5efae94d4b2087b4dac0f1d210369580, type: 3} --- !u!4 &3164170168341630643 stripped Transform: From f1f9ff1363691def51f7dbbe0ed88b8f6eb1e66e Mon Sep 17 00:00:00 2001 From: Markus Wellmann Date: Wed, 2 Oct 2024 12:39:40 +0200 Subject: [PATCH 5/8] Fixed auto focus of step inspector window after recompile (#247) Added static focusWindow variable --- Source/Core/Editor/UI/Windows/StepWindow.cs | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Source/Core/Editor/UI/Windows/StepWindow.cs b/Source/Core/Editor/UI/Windows/StepWindow.cs index 56d247323..dbd941ee3 100644 --- a/Source/Core/Editor/UI/Windows/StepWindow.cs +++ b/Source/Core/Editor/UI/Windows/StepWindow.cs @@ -15,6 +15,15 @@ namespace VRBuilder.Editor.UI.Windows /// internal class StepWindow : EditorWindow, IStepView { + + /// + /// Static flag to track domain reloads like enter play mode or recompile. + /// + /// + /// A static variable is reset after each domain reload. + /// + private static bool domainReload = true; + private const int border = 4; private IStep step; @@ -31,11 +40,20 @@ internal class StepWindow : EditorWindow, IStepView /// public static void ShowInspector() { + //we are not using GetInstance(true) because of an issue with duplicated step inspectors PR#89 StepWindow window = GetInstance(); window.Repaint(); - window.Focus(); - } + if (domainReload) + { + domainReload = false; + } + else + { + // Only focus on user interactions but not on domain reloads. + window.Focus(); + } + } public static StepWindow GetInstance(bool focus = false) { return GetWindow("Step Inspector", focus); From 19a623918a78f89ab46c2273791bfae6137c3f1c Mon Sep 17 00:00:00 2001 From: Marcello Tridenti Date: Tue, 8 Oct 2024 14:19:41 +0200 Subject: [PATCH 6/8] Play audio behavior now stops audio before aborting (#250) --- .../Runtime/Behaviors/PlayAudioBehavior.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Source/Basic-Conditions-And-Behaviors/Runtime/Behaviors/PlayAudioBehavior.cs b/Source/Basic-Conditions-And-Behaviors/Runtime/Behaviors/PlayAudioBehavior.cs index eb1c0c8a4..2cad4e063 100644 --- a/Source/Basic-Conditions-And-Behaviors/Runtime/Behaviors/PlayAudioBehavior.cs +++ b/Source/Basic-Conditions-And-Behaviors/Runtime/Behaviors/PlayAudioBehavior.cs @@ -140,6 +140,28 @@ public override void FastForward() } } + private class AbortingProcess : InstantProcess + { + public AbortingProcess(EntityData data) : base(data) + { + } + + public override void Start() + { + Debug.Log("Aborting"); + if (Data.AudioPlayer != null) + { + Data.AudioPlayer.Stop(); + } + else + { + IProcessAudioPlayer audioPlayer = RuntimeConfigurator.Configuration.ProcessAudioPlayer; + audioPlayer.Stop(); + audioPlayer.Reset(); + } + } + } + [JsonConstructor, Preserve] protected PlayAudioBehavior() : this(null, BehaviorExecutionStages.None) { @@ -169,5 +191,10 @@ public override IStageProcess GetDeactivatingProcess() { return new PlayAudioProcess(BehaviorExecutionStages.Deactivation, Data); } + + public override IStageProcess GetAbortingProcess() + { + return new AbortingProcess(Data); + } } } From 63f4bd96cdd2efe4e38895e9b0b4252012e1bc15 Mon Sep 17 00:00:00 2001 From: Marcello Tridenti Date: Fri, 18 Oct 2024 15:44:26 +0200 Subject: [PATCH 7/8] If a condition is a lockable property provider, lockable properties are retrieved using the condition's API instead of a helper method (#253) --- .../Core/Runtime/Properties/PropertyReflectionHelper.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Source/Core/Runtime/Properties/PropertyReflectionHelper.cs b/Source/Core/Runtime/Properties/PropertyReflectionHelper.cs index d8a5c30e7..1308e5a59 100644 --- a/Source/Core/Runtime/Properties/PropertyReflectionHelper.cs +++ b/Source/Core/Runtime/Properties/PropertyReflectionHelper.cs @@ -36,7 +36,14 @@ public static List ExtractLockablePropertiesFromStep(IStep { foreach (ICondition condition in transition.Data.Conditions) { - result.AddRange(ExtractLockablePropertiesFromCondition(condition.Data)); + if (condition is ILockablePropertiesProvider lockablePropertiesProvider) + { + result.AddRange(lockablePropertiesProvider.GetLockableProperties()); + } + else + { + result.AddRange(ExtractLockablePropertiesFromCondition(condition.Data)); + } } } From 78ba2517e0d3f0441f1d1b06552f957324be5c07 Mon Sep 17 00:00:00 2001 From: Marcello Tridenti Date: Thu, 31 Oct 2024 16:48:02 +0100 Subject: [PATCH 8/8] Version and changelog --- CHANGELOG.md | 18 +++++++++++++++++- package.json | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3174eedb6..83a366a2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ # Changelog - VR Builder -**v4.3.0 (2024/09/12 - Current)** +**v4.4.0 (2024/10/31 - Current)** + +*[Added]* +- The `Object in Collider` condition now supports multiple object references and lets the user specify a number of objects that needs to be in the collider. +- Every text-to-speech provider implementation can now have custom configuration fields. This makes it easier to implement custom TTS providers. +- `UserSceneObject` now has a `Base` property corresponding to the position of the user's feet. + + +*[Changed]* +- Standardized component configuration sections in Project Settings (like the SnapZone settings) to make it easier to create more. + +*[Fixed]* +- Fixed automatically focusing the Step Inspector window when recompiling. +- Play Audio behavior now stops playing before aborting. +- If a condition is a lockable property provider, lockable properties are retrieved using the condition's API instead of a helper method. This makes it easier to implement custom conditions that return a specific set of lockable properties. + +**v4.3.0 (2024/09/12)** *[Added]* - The Parallel Execution node now lets you create optional paths. You can make a path optional by clicking the new button next to its name. An optional path will be interrupted when all non-optional paths have completed, and execution will immediately proceed to the next node. This can be useful to create background looping animations, recurring hints and so on. An optional path can even be an endless loop and it will still be interrupted. diff --git a/package.json b/package.json index 15ade1d76..e730ed27d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "VR Builder", "name": "co.mindport.vrbuilder.core", - "version": "4.3.0", + "version": "4.4.0", "unity": "2021.3", "description": "VR Builder core functionality.", "keywords": [