Avoid weird skewing when both rotating and scaling a group with transformControls

I’m building a small tool that allows group selection. I’m doing this by dynamically creating a new group, attaching the selected objects to it and then adding the transformControls to the group. And when deselecting, I clone each object, add them back into the scene and apply the group matrix to each.

This mostly works… but some transformations are not kept, causing the object to “jump” when deselected.

Specifically rotate and scale can be very messy. See gif below and this jsfiddle (click and drag to select both object)

ungroup-apply-matrix

Is there a way to avoid this?

I noticed that Mozilla’s Spoke handles this properly, but it seems like they use their own transformControls gizmo and a different approach for adjusting objects. I looked at the code but it’s quite complicated, my understanding is that they work directly with the matrix but I’m pretty lost on how.

mozilla-spoke

Any help or pointers? My goal overall is to make sure that when I “degroup” the objects don’t “jump around”. I’d slightly prefer the Spoke’s approach but it seems like a lot of work, if it really implies re-implementing transformControls.

Thanks.

Just to keep the post updated with what I’m attempting: instead of adding the objects to a group, I’m trying to add an “empty” pivot object at the center of the selected objects, add transform controls to it and then apply a matrix to the selected objects based on the pivot when the transform controls dispatch an “objectChange” event.

Jsfiddle here: https://jsfiddle.net/jacopocolo/1nvs8f2h/82/

If I understand this answer on Stackoverflow correctly it should be possible but haven’t managed yet.

EDIT:

This is not solved but I found a brute force approach that will work for me. Essentially, I’m cloning the selected objects, adding those to the group, making them invisible and keeping them in sync with the original objects via worldPosition, worldQuaternion and worldScale then I’m just deleting the group on deselect. Here’s a Jsfiddle. This avoids the skewing that can be applied to children by the group transformation.

I could not entirely figure out the other option but got decently far: my attempt was to apply matrix transformations to all the selected objects using a delta between the matrixWorld at the beginning of the transformation and the matrixWorld at the end of the transformation. It works very well for position (the delta there is easy) but I’m having a lot of trouble with deltas for scale and quaternion. Again, here’s a jsfiddle in case anyone finds it useful as a basis to start from.