Skip to content

Commit

Permalink
v1.2.3-beta (#8)
Browse files Browse the repository at this point in the history
* bugfix: NPE in SkinnedMeshRenderer recorder module when sharedMesh was null

* Add version switch for XRITK to work with 2.x and 3.x

* Bump version
  • Loading branch information
cjaverliat authored Oct 22, 2024
1 parent f26e00c commit 15639ea
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 43 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.3-beta]

### Fixed

- Fix issue when SkinnedMeshRenderer sharedMesh is null, causing the recorder to fail with a NPE.

### Added

- Ensure XRITK compatibility for v2 and v3 by adding a macro to automatically switch between version 2.x and 3.x in the XRBaseInteractableRecorderModule and XRBaseInteractorRecorderModule.

## [1.2.2-beta]

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,28 @@ protected override void OnObjectMarkedCreated(SkinnedMeshRendererSafeRef objSafe
updateSample.RootBoneId = GetComponentIdentifierPayload(rootBoneRef);
updateSample.Bones = new SkinnedMeshRendererUpdate.Types.Bones();

foreach (var bone in objSafeRef.Component.bones)
if (objSafeRef.Component.bones != null)
{
var boneRef = ctx.ObjectSafeRefProvider.GetOrCreateComponentSafeRef(bone);
updateSample.Bones.Ids.Add(GetComponentIdentifierPayload(boneRef));
foreach (var bone in objSafeRef.Component.bones)
{
var boneRef = ctx.ObjectSafeRefProvider.GetOrCreateComponentSafeRef(bone);
updateSample.Bones.Ids.Add(GetComponentIdentifierPayload(boneRef));
}
}

updateSample.BlendShapeWeights = new SkinnedMeshRendererUpdate.Types.BlendShapeWeights();

for (var i = 0; i < objSafeRef.Component.sharedMesh.blendShapeCount; i++)
if (objSafeRef.Component.sharedMesh != null)
{
updateSample.BlendShapeWeights.Weights.Add(
new SkinnedMeshRendererUpdate.Types.BlendShapeWeights.Types.BlendShapeWeight
{
Index = i,
Weight = objSafeRef.Component.GetBlendShapeWeight(i)
});
for (var i = 0; i < objSafeRef.Component.sharedMesh.blendShapeCount; i++)
{
updateSample.BlendShapeWeights.Weights.Add(
new SkinnedMeshRendererUpdate.Types.BlendShapeWeights.Types.BlendShapeWeight
{
Index = i,
Weight = objSafeRef.Component.GetBlendShapeWeight(i)
});
}
}

_createSamples[objSafeRef] = new SkinnedMeshRendererCreate
Expand Down
50 changes: 32 additions & 18 deletions Runtime/Base/Module/Unity/XRITK/XRBaseInteractableRecorderModule.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
#if XRITK_ENABLED
#if USE_XRITK_2 || USE_XRITK_3
using System.Collections.Generic;
using PLUME.Core.Recorder;
using PLUME.Core.Recorder.Module.Frame;
using PLUME.Sample.Unity.XRITK;
using UnityEngine.Scripting;
using UnityEngine.XR.Interaction.Toolkit;
using static PLUME.Core.Utils.SampleUtils;
using XRBaseInteractableSafeRef = PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable>;

#if USE_XRITK_2
using XRBaseInteractableSafeRef =
PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable>;
#elif USE_XRITK_3
using XRBaseInteractableSafeRef =
PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.Interactables.XRBaseInteractable>;
#endif

namespace PLUME.Base.Module.Unity.XRITK
{
[Preserve]
public class XRBaseInteractableRecorderModule : ComponentRecorderModule<XRBaseInteractable, XRBaseInteractableFrameData>
#if USE_XRITK_2
public class XRBaseInteractableRecorderModule : ComponentRecorderModule<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractable, XRBaseInteractableFrameData>
#elif USE_XRITK_3
public class XRBaseInteractableRecorderModule : ComponentRecorderModule<
UnityEngine.XR.Interaction.Toolkit.Interactables.XRBaseInteractable, XRBaseInteractableFrameData>
#endif
{
private readonly Dictionary<XRBaseInteractableSafeRef, XRBaseInteractableCreate> _createSamples = new();
private readonly Dictionary<XRBaseInteractableSafeRef, XRBaseInteractableDestroy> _destroySamples = new();
private readonly Dictionary<XRBaseInteractableSafeRef, XRBaseInteractableUpdate> _updateSamples = new();

private RecorderContext _ctx;

protected override void OnStartRecording(RecorderContext ctx)
Expand All @@ -37,7 +49,7 @@ protected override void OnStartRecordingObject(XRBaseInteractableSafeRef objSafe
interactable.activated.AddListener(args => OnActivated(objSafeRef, args));
interactable.deactivated.AddListener(args => OnDeactivated(objSafeRef, args));
}

protected override void OnStopRecordingObject(XRBaseInteractableSafeRef objSafeRef,
RecorderContext ctx)
{
Expand All @@ -54,24 +66,26 @@ protected override void OnStopRecordingObject(XRBaseInteractableSafeRef objSafeR
protected override void OnObjectMarkedCreated(XRBaseInteractableSafeRef objSafeRef, RecorderContext ctx)
{
base.OnObjectMarkedCreated(objSafeRef, ctx);

var interactable = objSafeRef.Component;
var interactableUpdate = GetOrCreateUpdateSample(objSafeRef);
interactableUpdate.Enabled = interactable.enabled;
_createSamples[objSafeRef] = new XRBaseInteractableCreate {Id = GetComponentIdentifierPayload(objSafeRef)};
_createSamples[objSafeRef] = new XRBaseInteractableCreate
{ Id = GetComponentIdentifierPayload(objSafeRef) };
}

protected override void OnObjectMarkedDestroyed(XRBaseInteractableSafeRef objSafeRef, RecorderContext ctx)
{
base.OnObjectMarkedDestroyed(objSafeRef, ctx);
_destroySamples[objSafeRef] = new XRBaseInteractableDestroy {Id = GetComponentIdentifierPayload(objSafeRef)};
_destroySamples[objSafeRef] = new XRBaseInteractableDestroy
{ Id = GetComponentIdentifierPayload(objSafeRef) };
}

private void OnHoverEntered(XRBaseInteractableSafeRef objSafeRef, HoverEnterEventArgs args)
{
if (!_ctx.IsRecording)
return;

var interactableHoverEnter = new XRBaseInteractableHoverEnter
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -85,7 +99,7 @@ private void OnHoverExited(XRBaseInteractableSafeRef objSafeRef, HoverExitEventA
{
if (!_ctx.IsRecording)
return;

var interactableHoverExit = new XRBaseInteractableHoverExit
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -99,7 +113,7 @@ private void OnSelectEntered(XRBaseInteractableSafeRef objSafeRef, SelectEnterEv
{
if (!_ctx.IsRecording)
return;

var interactableSelectEnter = new XRBaseInteractableSelectEnter
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -113,7 +127,7 @@ private void OnSelectExited(XRBaseInteractableSafeRef objSafeRef, SelectExitEven
{
if (!_ctx.IsRecording)
return;

var interactableSelectExit = new XRBaseInteractableSelectExit
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -127,7 +141,7 @@ private void OnActivated(XRBaseInteractableSafeRef objSafeRef, ActivateEventArgs
{
if (!_ctx.IsRecording)
return;

var interactableActivated = new XRBaseInteractableActivateEnter
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -136,12 +150,12 @@ private void OnActivated(XRBaseInteractableSafeRef objSafeRef, ActivateEventArgs

_ctx.CurrentRecord.RecordTimestampedManagedSample(interactableActivated);
}

private void OnDeactivated(XRBaseInteractableSafeRef objSafeRef, DeactivateEventArgs args)
{
if (!_ctx.IsRecording)
return;

var interactableDeactivated = new XRBaseInteractableActivateExit
{
Id = GetComponentIdentifierPayload(objSafeRef),
Expand All @@ -150,12 +164,12 @@ private void OnDeactivated(XRBaseInteractableSafeRef objSafeRef, DeactivateEvent

_ctx.CurrentRecord.RecordTimestampedManagedSample(interactableDeactivated);
}

private XRBaseInteractableUpdate GetOrCreateUpdateSample(XRBaseInteractableSafeRef objSafeRef)
{
if (_updateSamples.TryGetValue(objSafeRef, out var sample))
return sample;
sample = new XRBaseInteractableUpdate {Id = GetComponentIdentifierPayload(objSafeRef)};
sample = new XRBaseInteractableUpdate { Id = GetComponentIdentifierPayload(objSafeRef) };
_updateSamples[objSafeRef] = sample;
return sample;
}
Expand All @@ -168,7 +182,7 @@ protected override XRBaseInteractableFrameData CollectFrameData(FrameInfo frameI
frameData.AddUpdateSamples(_updateSamples.Values);
return frameData;
}

protected override void AfterCollectFrameData(FrameInfo frameInfo, RecorderContext ctx)
{
base.AfterCollectFrameData(frameInfo, ctx);
Expand Down
35 changes: 24 additions & 11 deletions Runtime/Base/Module/Unity/XRITK/XRBaseInteractorRecorderModule.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
#if XRITK_ENABLED
#if USE_XRITK_2 || USE_XRITK_3
using System.Collections.Generic;
using PLUME.Core.Recorder;
using PLUME.Core.Recorder.Module.Frame;
using PLUME.Sample.Unity.XRITK;
using UnityEngine.Scripting;
using UnityEngine.XR.Interaction.Toolkit;
using static PLUME.Core.Utils.SampleUtils;
using XRBaseInteractorSafeRef = PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractor>;

#if USE_XRITK_2
using XRBaseInteractorSafeRef =
PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractor>;
#elif USE_XRITK_3
using XRBaseInteractorSafeRef =
PLUME.Core.Object.SafeRef.IComponentSafeRef<UnityEngine.XR.Interaction.Toolkit.Interactors.XRBaseInteractor>;
#endif

namespace PLUME.Base.Module.Unity.XRITK
{
[Preserve]
public class XRBaseInteractorRecorderModule : ComponentRecorderModule<XRBaseInteractor, XRBaseInteractorFrameData>
#if USE_XRITK_2
public class XRBaseInteractorRecorderModule : ComponentRecorderModule<UnityEngine.XR.Interaction.Toolkit.XRBaseInteractor, XRBaseInteractorFrameData>
#elif USE_XRITK_3
public class XRBaseInteractorRecorderModule : ComponentRecorderModule<
UnityEngine.XR.Interaction.Toolkit.Interactors.XRBaseInteractor, XRBaseInteractorFrameData>
#endif
{
private readonly Dictionary<XRBaseInteractorSafeRef, XRBaseInteractorCreate> _createSamples = new();
private readonly Dictionary<XRBaseInteractorSafeRef, XRBaseInteractorDestroy> _destroySamples = new();
private readonly Dictionary<XRBaseInteractorSafeRef, XRBaseInteractorUpdate> _updateSamples = new();

private RecorderContext _ctx;

protected override void OnStartRecording(RecorderContext ctx)
Expand All @@ -40,14 +52,14 @@ protected override void OnStopRecordingObject(XRBaseInteractorSafeRef objSafeRef
RecorderContext ctx)
{
base.OnStopRecordingObject(objSafeRef, ctx);

var interactor = objSafeRef.Component;
interactor.hoverEntered.RemoveListener(args => OnHoverEntered(objSafeRef, args));
interactor.hoverExited.RemoveListener(args => OnHoverExited(objSafeRef, args));
interactor.selectEntered.RemoveListener(args => OnSelectEntered(objSafeRef, args));
interactor.selectExited.RemoveListener(args => OnSelectExited(objSafeRef, args));
}

protected override void OnObjectMarkedCreated(XRBaseInteractorSafeRef objSafeRef, RecorderContext ctx)
{
base.OnObjectMarkedCreated(objSafeRef, ctx);
Expand All @@ -56,11 +68,12 @@ protected override void OnObjectMarkedCreated(XRBaseInteractorSafeRef objSafeRef
interactorUpdate.Enabled = interactor.enabled;
_createSamples[objSafeRef] = new XRBaseInteractorCreate { Id = GetComponentIdentifierPayload(objSafeRef) };
}

protected override void OnObjectMarkedDestroyed(XRBaseInteractorSafeRef objSafeRef, RecorderContext ctx)
{
base.OnObjectMarkedDestroyed(objSafeRef, ctx);
_destroySamples[objSafeRef] = new XRBaseInteractorDestroy { Id = GetComponentIdentifierPayload(objSafeRef) };
_destroySamples[objSafeRef] = new XRBaseInteractorDestroy
{ Id = GetComponentIdentifierPayload(objSafeRef) };
}

private void OnHoverEntered(XRBaseInteractorSafeRef objSafeRef, HoverEnterEventArgs args)
Expand Down Expand Up @@ -127,16 +140,16 @@ protected override XRBaseInteractorFrameData CollectFrameData(FrameInfo frameInf
frameData.AddUpdateSamples(_updateSamples.Values);
return frameData;
}

private XRBaseInteractorUpdate GetOrCreateUpdateSample(XRBaseInteractorSafeRef objSafeRef)
{
if (_updateSamples.TryGetValue(objSafeRef, out var sample))
return sample;
sample = new XRBaseInteractorUpdate {Id = GetComponentIdentifierPayload(objSafeRef)};
sample = new XRBaseInteractorUpdate { Id = GetComponentIdentifierPayload(objSafeRef) };
_updateSamples[objSafeRef] = sample;
return sample;
}

protected override void AfterCollectFrameData(FrameInfo frameInfo, RecorderContext ctx)
{
base.AfterCollectFrameData(frameInfo, ctx);
Expand Down
2 changes: 1 addition & 1 deletion Runtime/Core/Recorder/Recorder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public sealed partial class PlumeRecorder : IDisposable
Name = "PLUME Recorder (Beta)",
Major = "1",
Minor = "2",
Patch = "2",
Patch = "3",
};

private readonly RecorderContext _context;
Expand Down
9 changes: 7 additions & 2 deletions Runtime/PLUME.Recorder.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,13 @@
},
{
"name": "com.unity.xr.interaction.toolkit",
"expression": "0",
"define": "XRITK_ENABLED"
"expression": "[2.0,3.0)",
"define": "USE_XRITK_2"
},
{
"name": "com.unity.xr.interaction.toolkit",
"expression": "[3.0,4.0)",
"define": "USE_XRITK_3"
},
{
"name": "com.unity.textmeshpro",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fr.liris.plume.recorder",
"version": "1.2.2-beta",
"version": "1.2.3-beta",
"displayName": "PLUME-Recorder",
"description": "PLUME: PLugin for Unity to Monitor Experiments",
"unity": "2022.3",
Expand Down

0 comments on commit 15639ea

Please sign in to comment.