Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow flexibility on DragControls for multi-part GLTF models & other hierarchical objects #26134

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

diarmidmackenzie
Copy link
Contributor

@diarmidmackenzie diarmidmackenzie commented May 25, 2023

I haven't raised a related issue - I can do so if required

Description

DragControls doesn't offer the flexibility needed to use DragControls with multi-part GLTF models (or other smilar hierarchical objects).

DragControls can be configured on an array of object3Ds. The drag behaviour then operates on all these objects, and all their descendants.

When dragging happens, it is applied to the object3D that the raycaster hit. If this is a descendant of an object specified in the array, then the descendant will be dragged independently of the ancestor object.

So if I have a multi-part GLTF, which gets mapped into a hierarchy of object3Ds, I can't use DragControls to move the GLTF as a whole. If I click and drag on it, I'll end up dragging the part of the model I clicked on, rather than the whole model.

DragControls does have a config option transformGroup which results in the entire group of objects being transformed (ignoring where the raycaster hit completely). However this can only be used when DragControls is being used on a single object. It can't be used when I want a single instance of DragControls to allow dragging of multiple objects.

Proposed fix is another flag, "transformDescendants". This is set to "true" by defult, preserving current behaviour.

When this is set to "false" (and transformGroup is also "false"), then the logic for which object to move is as follows:

  • if the object hit by the raycaster is in the specified aray of objects, allow it to be dragged
  • else look for the closest ancestor that is in the specified array of objects, and apply the drag to that object instead.

So far this fix has been tested in various A-Frame contexts: SeregPie/aframe-drag-controls#2

However the same issue exists for vanilla Three.js when using multi-part GLTF models. Happy to create a pure Three.js example to illustrate the problem if that would be helpful.

@diarmidmackenzie diarmidmackenzie changed the title Drag controls descendants Allow flexibility on DragControls for multi-part GLTF models & other hierarchical objects May 25, 2023
@diarmidmackenzie diarmidmackenzie marked this pull request as ready for review May 25, 2023 14:36
@Mugen87
Copy link
Collaborator

Mugen87 commented Oct 6, 2023

Can you please check if #26747 solved your issue.

@brainexcerpts
Copy link

brainexcerpts commented Oct 7, 2023

@Mugen87 No, unfortunately the recursive property added in #26747 does not seem to solve the use case presented here.

The code pen below shows that setting dragControls.recursive = false prevents to select anything when only groups of objects are in the list of draggable objects:
Code pen recursive property test
(you can change g_dragControl_recursive to false or true at the top of the js file)

This PR successfully solve the issue:
Code pen transformDescendants
(you can change g_dragControl_transformDescendants to false or true at the top of the js file)

@diarmidmackenzie
Copy link
Contributor Author

diarmidmackenzie commented Oct 11, 2023

#26747 solves a slightly different problem from this PR.

Suppose we have an object A, with children B, C.

If you set DragControls on A, standard behaviour (prior to #26747) is that any of A, B or C can now be dragged as an independent entity.

#26747 gives the ability to turn off recursive raycasting, so that only A can be dragged (and B & C will be dragged with it).

This will work well for the case e.g. where A is a box, and B & C are small decorations on that box (i.e. A constitutes the bulk of the geometry you might want to raycast against).

But in the case of a multipart GLTF (which is what this PR addresses), A is typically a Group that has no geometry, and so can't be hit with a raycaster at all. B & C are the parts that make up the object (e.g. a head and body).

With current functionality, the only options would be:

  • recursive = true: drag each of A, B or C independently.
  • recursive = false: can only drag A. But that doesn't work, because A has no geometry of its own.

This PR delivers functionality where (by setting transformDescendants: false) it's possible to drag either B or C, and all of A, B & C will move together. The movement is referred up to the nearest draggable ancestor object (in this case, A).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants