The ManipulationHandler event OnManipulationEnded doesn't seem to fire at the end of a rotation or scale, only at the end of an object translation.
Create a component which, on Start, adds a BoundingBox and ManipulationHandler components. For example:
private void Start()
{
boundingBox = gameObject.AddComponent<BoundingBox>();
boundingBox.BoundingBoxActivation = BoundingBox.BoundingBoxActivationType.ActivateByProximityAndPointer;
manipulationHandler = gameObject.AddComponent<ManipulationHandler>();
manipulationHandler.OneHandRotationModeFar = ManipulationHandler.RotateInOneHandType.MaintainOriginalRotation;
manipulationHandler.OneHandRotationModeNear = ManipulationHandler.RotateInOneHandType.MaintainOriginalRotation;
manipulationHandler.ConstraintOnRotation = Toolkit.Utilities.RotationConstraintType.YAxisOnly;
manipulationHandler.OnManipulationEnded.AddListener(FinishManipulation);
nearGrabbable = gameObject.AddComponent<NearInteractionGrabbable>();
boundingBox.Active = false;
}
Implement FinishManipulation(ManipulationEventData) to do something clearly visible (e.g. return the object to its starting point).
Attach the component to an object (e.g. cube) in the scene and run the scene.
If you move the object, its FinishManipulation gets called. If you rotate or scale the object using the boundingbox handles, the object will be properly rotated or scaled, but there will be no callback at the end.
ManipulationEnded event should fire for any type of manipulation.
I think the reason for this is
BoundingBox.HandleType does not include Translate.I'm not 100% certain about this because the BoundingBox class is huge ... we should really separate the graphics elements from the transform logic there.
That's true lukas, and 100% agree bounding box is massive....would love to have one of us dedicate some time to refactoring bounding box after GA and other bugs are fixed.
I think this is technically by design, since "manipulation ended" event would need to be raised by the bounding box.
Note that you could rotate or scale using two hand manip, and then manipulationended would get called.
there's also rotate and scale events on the bounding box you could subscribe to.
I'll close this now as per design - we can think about having better events in bounding box when we do the big refactor post GA. Created a follow up issue: https://github.com/microsoft/MixedRealityToolkit-Unity/issues/5340
Recapping here:
1) ManiuplationEnded may or may not get called depending on whether you are using one or two handed.
2) Suggested workaround is to handle manipulationHandler.ManipulationEnded for translate and two handed rotate/scale, but then boundingbox.RotateStopped/ScaleStopped for rotation and scale manipulations?
3) I hate to ask, but will RotateStopped/ScaleStopped get called redundantly with ManipulationEnded for two handed rotate/scale, or does two handed rotation not trigger boundingBox.RotateStopped?
I think a way that will help to think about this is that Manipulation* events come from the manipulation handler, not bounding box. When you rotate / scale an object using one of the bounding box handles, you are using the bounding box component. When you move / scale / rotate by interacting with the object's collidable, you are using manipulation handler.
ManiuplationEnded may or may not get called depending on whether you are using one or two handed.
Not entirely. if you grab and move the object, you'll get manipulation ended. If you grab affordances you'll be using bounding box which doesn't raise those event.
Suggested workaround is to handle manipulationHandler.ManipulationEnded for translate and two handed rotate/scale, but then boundingbox.RotateStopped/ScaleStopped for rotation and scale manipulations?
That sounds right. Can you think of a better way to design it? For example, should bounding box also just raise ManipulationStarted/Ended events?
I hate to ask, but will RotateStopped/ScaleStopped get called redundantly with ManipulationEnded for two handed rotate/scale, or does two handed rotation not trigger boundingBox.RotateStopped?
No, RotateStopped/ScaleStopped will only be called when you are using the BoundingBox.
Thanks @julenka , that explanation helps a lot. I'm still trying to get a reasonable solution for my situation, but I think you've given me enough understanding that I should be able to accomplish what I need.
On your design question, I do think that from the user's perspective it would be more convenient and less complex if the various manipulation events were routed through a common handler, and the ManipulationHandler seems perfectly appropriate for that.
Bernie assures me that the BoundingBox has more pressing needs from a refactor, but that might be something to consider during the upcoming refactor.
Thanks again for the clarity!