[libgdx] Drag and drop with scene2d tree

I’m working an an editor for our game. A main component of the editor is a tree, that displays nodes.

The editor must be able to reorder nodes in the tree or move entire branches onto a different parent node. To do this I see two possibilities:

  1. Implement it with drag and drop, so the user can just drag a node and move it to the appropriate position.
  2. Add up/down buttons to the nodes for reordering and add a new button to change the parent of a selected node.

While I would want to do it with drag and drop, I don’t want to spend too much time on this (we need to concentrate on the game itself, this would simply be a nice to have). Does the scene2d tree actor support drag or can someone point me into the direction on how to do it, so I can see if it is too much effort to do?

I have seen that LibGDX has a DragAndDrop class. From what I see in the DragAndDrop test ( https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/DragAndDropTest.java ) I could do something like this:

  • Create empty nodes (drop target) around normal nodes in the tree. These are used to preview where the node will be inserted to. (I created an image to illustrate this http://imgur.com/rcXDcOi . The red lines represent those drop target nodes).
  • When a node is dragged, remove it temporary from the tree (or hide it).
  • When the drag is released, a check needs to be made if the target is a valid position. If so then move the node to that position. If the position is invalid, the node is put back at the original place.
  • When moved, some drop targets need to be added / removed.

Am I completely on the wrong track, or would this be the way to go?

Use DragAndDrop, add the tree as both a source and target. In the source, use the selected nodes for what to drag (can select the node under the mouse if nothing is selected). In the target, use Tree#getNodeAt(float y) to determine where the drop would happen. If getNodeAt is null and the mouse is over the tree, you know you are after the last visible node. Position an actor that is a sibling to the tree if you want to show where the drop will insert.

Hey thanks very much, I got it working now how I wanted.

Here I don’t use the selection because the selection is only updated after the drag started. Means if I select the third node but then go with the mouse over the second node and start dragging, still the third node would be dragged, which is a bit strange.

Other than that it worked great for changing the parent. I needed to add some more code to enable the reordering.

// Select node under mouse if not over the selection.
Node overNode = tree.getNodeAt(y);
if (overNode == null && tree.getSelection().isEmpty()) return null;
if (overNode != null && !tree.getSelection().contains(overNode)) tree.getSelection().set(overNode);

Nice, thanks. This is a better than my solution, as it selects the hovered node, when it is not selected yet. Definitely better from a user perspective, as the user now sees clearly which node he is moving.