scene2d.ui Selection

scene2d.ui’s List has never been terribly feature-packed, mostly because it only really sees use in SelectBox. I ended up needing it for skinning in Spine, so it got some love.

First, it can now draw a background which makes it easier to use outside of a ScrollPane. I figured even a Label has a background in its style, so why not.

Next I needed multiple selection, so I set off implementing it. While this seems like such a simple task, just managing a list of selected objects, it turns a proper implementation is quite a chunk of code: more than 250 lines. This is literally larger than the rest of the List implementation! SelectBox and Tree also have selection, and their implementations aren’t really complete. Given this, I decided to create a class called Selection which handles that, and List, SelectBox, and Tree can use it.

Selection turned out pretty nice. At its core it is an ObjectSet with set, add, remove, clear methods. The choose method handles the logic for changing the selection based on user interaction and has features like multiple selection, holding ctrl, toggle, etc. When the selection is changed a ChangeEvent is fired on an actor. If the event is cancelled, the change to the selection is reverted.

Now the bad news, List, SelectBox, and Tree had to change to accomodate the new class. Here are the API changes that may impact you:

  • List and SelectBox previously used strings for the items and you had to correlate the string or selected index back to your list of actual objects. Now they use generics, so you can store your actual objects in the widget, eg List. To get the old behavior, use List or SelectBox.
  • List and SelectBox no longer take items in their constructor. Instead, call setItems after construction. There is now a setItems that takes varargs, which is convenient.
  • Most selection methods having moved to Selection, which you get from getSelection(), but a few stayed behind:
    • getSelection() -> getSelected() or getSelection().first()
    • setSelection() -> setSelected() or getSelection().set()
    • getSelectionIndex() -> getSelectedIndex()

As always, sorry for the API breakage! This effort and your pain is for the greater good. I had to fix up my 50k+ LOC scene2d.ui application so, as your dad probably used to say, this hurts me more than it hurts you. 😉

Libgdx minimal Android version is 2.2 from now on


Missleading screenshot

It had to happen. After years of refusing to drop support for Android 1.5 (yes, we actually supported this until today), we finally gave in and say good bye to support for our old Magics and HTC Heroes. It’s been a good ride, but all good things come to an end.

This change allows us to clean up a few things in the Android backend, before we move on and rip out OpenGL ES 1.x support for good.

There are also some other upcoming fancy things, like 3D particles, thanks to our awesome community members!

PolygonSpriteBatch implements Batch

We have a little-known class called PolygonSpriteBatch which renders textured polygons. This can be used to save fill rate by avoiding drawing transparent pixels. A while ago we refactored SpriteBatch to use an interface called Batch (which should probably be called QuadBatch). This lets you change the SpriteBatch implementation, which is pretty neat. Today I made PolygonSpriteBatch implement Batch, which means you can use it anywhere that takes a Batch.

For example, you can now use scene2d with a PolygonSpriteBatch. Why do that? Maybe inside scene2d you are using Spine skeletons that have meshes. Rendering meshes requires PolygonSpriteBatch, so by using a PolygonSpriteBatch for the whole scene you won’t have to switch back and forth between SpriteBatch and PolygonSpriteBatch, which would cause many batch flushes.

There are some performance differences between SpriteBatch and PolygonSpriteBatch. SpriteBatch uses indices set up for quads, so it only needs to transfer vertex colors and positions to the GPU each frame. PolygonSpriteBatch has to transfer indices, vertex colors, and positions. How much does this affect things? It depends, so give it a try!

Edit: Cuellarjmcg reports the performance difference is minimal, even on an antique device.