Needed feature for pointerDragBehavior

Hey all,

So I am using pointerDragBehavior and I wanted to use my own observable when dragging to make a limit to how far the user can drag a mesh. The problem is that it doesn’t seem very straight forward to do this. I know I can get the tagetPosition of where the mesh will end up by applying the dragDelta (from the event passed to the onDragObservable) to the current position, and that’s fine, but that would require me to implement my own drag ratio logic to make it smooth and I would really like to make use of what’s already there.

So in the pointerDragBehavior, the mesh is actually moved in this function (line 188):

this._beforeRenderObserver = this._scene.onBeforeRenderObservable.add(() => {
                if (this._moving && this.moveAttached) {
                    BoundingBoxGizmo._RemoveAndStorePivotPoint(this._attachedNode);
                    // Slowly move mesh to avoid jitter
                    this._targetPosition.subtractToRef((this._attachedNode).absolutePosition, this._tmpVector);
                    this._tmpVector.scaleInPlace(this.dragDeltaRatio);
                    (this._attachedNode).getAbsolutePosition().addToRef(this._tmpVector, this._tmpVector);
                    (this._attachedNode).setAbsolutePosition(this._tmpVector);
                    BoundingBoxGizmo._RestorePivotPoint(this._attachedNode);
                }
            });

And it would be really cool if we could just add a function that gets called as predicate to determine if the mesh should actually be moved to the new drag location but still allow the delayed movement, such as this:

this._beforeRenderObserver = this._scene.onBeforeRenderObservable.add(() => {
if (this._moving && this.moveAttached) {
BoundingBoxGizmo._RemoveAndStorePivotPoint(this._attachedNode);
// Slowly move mesh to avoid jitter

                 if(!this.validateDrag || this.validateDrag(this._targetPosition)){
                     this._lastValidTargetPosition = this._targetPosition;
                     this._targetPosition.subtractToRef((this._attachedNode).absolutePosition,this._tmpVector);
                }else{
                     this._lastValidTargetPosition .subtractToRef((this._attachedNode).absolutePosition,this._tmpVector);
                }
                this._tmpVector.scaleInPlace(this.dragDeltaRatio);
                (this._attachedNode).getAbsolutePosition().addToRef(this._tmpVector, this._tmpVector);
                (this._attachedNode).setAbsolutePosition(this._tmpVector);
                BoundingBoxGizmo._RestorePivotPoint(this._attachedNode);
            }
        });

And then in our custom code we could set the validation function with out own logic:

behavior.validateDrag = (targetPosition)=>{ /check distance, etc/ return true; };

I know I can do all this in the onDragObservable, but I would basically be copying the code of the beforeRenderObservable above and that seems redundant if we can make a way to hook into the existing code. Am I missing an easier way to do this?

Thanks

Pinging @trevordev

@Zephos sure, does this PR (https://github.com/BabylonJS/Babylon.js/pull/5661 ) fix your issue? If this is merged it’s usage would look like this Babylon.js Playground

Yeah that looks great. Just what I was thinking of. Sorry for taking so long to get back to you. Holidays and such. Thanks!

2 Likes

Hi there,
Sorry to bother, but I am not sure to understand how ‘validateDrag’ helps us at all. In the code it is said that validateDrag always returns true. Am I missing something ?

  public validateDrag = (target: Vector3) => {
        return true;
    };

You can replace validateDrag with your own function and do custom validation if the target position is ok to be used or not.

Oh I see, thank you !