@@ -134,25 +134,26 @@ export function createGizmoManager(context: SceneContext) {
134134 }
135135
136136 function computeWorldTransform ( entity : EcsEntity ) : TransformType {
137- const { positionGizmoEnabled, scaleGizmoEnabled, rotationGizmoEnabled } = gizmoManager
138- // Compute the updated transform based on the current node position
137+ const { positionGizmoEnabled, rotationGizmoEnabled } = gizmoManager
139138 const worldMatrix = entity . computeWorldMatrix ( true )
140139 const position = new Vector3 ( )
141- const scale = new Vector3 ( )
142140 const rotation = new Quaternion ( )
143- worldMatrix . decompose ( scale , rotation , position )
141+
142+ // Extract only position and rotation from world matrix
143+ const scale = entity . scaling . clone ( ) // Keep original scale
144+ worldMatrix . decompose ( new Vector3 ( ) , rotation , position ) // Ignore decomposed scale
144145
145146 return {
146147 position : positionGizmoEnabled ? snapPosition ( position ) : position ,
147- scale : scaleGizmoEnabled ? snapScale ( scale ) : scale ,
148+ scale : scale , // Always use original scale
148149 rotation : rotationGizmoEnabled ? snapRotation ( rotation ) : rotation
149150 }
150151 }
151152
152153 function getTransform ( entity : EcsEntity ) : TransformType {
153154 return {
154155 position : entity . position ,
155- scale : entity . scaling ,
156+ scale : entity . scaling . clone ( ) , // Clone to prevent reference issues
156157 rotation : entity . rotationQuaternion ?? Quaternion . Zero ( ) ,
157158 parent : getParent ( entity )
158159 }
@@ -183,17 +184,28 @@ export function createGizmoManager(context: SceneContext) {
183184 */
184185 function updateTransform ( ) {
185186 fixRotationGizmoAlignment ( getTransform ( getFirstEntity ( ) ) )
187+
186188 for ( const entity of selectedEntities ) {
187189 const originalParent = getParent ( entity )
188190 const parent = context . getEntityOrNull ( originalParent ?? context . rootNode . entityId )
191+ const originalScale = entity . scaling . clone ( )
189192
190193 entity . setParent ( parent )
191194 const transform = parent === context . rootNode ? computeWorldTransform ( entity ) : getTransform ( entity )
192195
193- updateEntityTransform ( entity . entityId , { ...transform , parent : originalParent } )
196+ // Create a new transform that only updates position and rotation
197+ const newTransform = {
198+ position : transform . position ,
199+ scale : originalScale , // Always keep original scale
200+ rotation : transform . rotation ,
201+ parent : originalParent
202+ }
203+
204+ updateEntityTransform ( entity . entityId , newTransform )
194205 }
195206
196207 void context . operations . dispatch ( )
208+ restoreParents ( )
197209 }
198210
199211 // Check if a transform node for the gizmo already exists, or create one
@@ -204,10 +216,20 @@ export function createGizmoManager(context: SceneContext) {
204216 }
205217
206218 function restoreParents ( ) {
219+ const originalParents = new Map < EcsEntity , Entity > ( )
220+
221+ // Store original parent relationships
207222 for ( const entity of selectedEntities ) {
208- const originalParent = getParent ( entity )
223+ const parent = getParent ( entity )
224+ originalParents . set ( entity , parent )
225+ }
226+
227+ // Restore original parent relationships
228+ for ( const [ entity , originalParent ] of originalParents ) {
209229 const parent = context . getEntityOrNull ( originalParent ?? context . rootNode . entityId )
210- entity . setParent ( parent )
230+ if ( parent ) {
231+ entity . setParent ( parent )
232+ }
211233 }
212234 }
213235
@@ -226,15 +248,36 @@ export function createGizmoManager(context: SceneContext) {
226248 const centroidRotation = calculateAverageRotation ( rotations )
227249 const dummyNode = getDummyNode ( )
228250
229- // Set the dummy node transform
251+ // Set the dummy node transform with uniform scale
230252 dummyNode . position = centroidPosition
231253 dummyNode . rotationQuaternion = centroidRotation
232254 dummyNode . scaling = new Vector3 ( 1 , 1 , 1 )
233255
256+ // Store original parent-child relationships
257+ const originalParents = new Map < EcsEntity , Entity > ( )
258+ const rootEntities = new Set < EcsEntity > ( )
259+
260+ // First pass: identify root entities and store parent relationships
234261 for ( const entity of selectedEntities ) {
262+ const parent = getParent ( entity )
263+ originalParents . set ( entity , parent )
264+
265+ // If parent is not selected, this is a root entity
266+ if ( ! selectedEntities . some ( ( e ) => e . entityId === parent ) ) {
267+ rootEntities . add ( entity )
268+ }
269+ }
270+
271+ // Second pass: only move root entities under dummy node
272+ for ( const entity of rootEntities ) {
273+ // Store original scale before moving under dummy node
274+ const originalScale = entity . scaling . clone ( )
235275 entity . setParent ( dummyNode )
276+ // Restore original scale after moving
277+ entity . scaling = originalScale
236278 }
237279
280+ // Attach gizmo to the dummy node
238281 gizmoManager . attachToNode ( dummyNode )
239282 }
240283
@@ -296,6 +339,7 @@ export function createGizmoManager(context: SceneContext) {
296339 gizmoManager . positionGizmoEnabled = false
297340 gizmoManager . rotationGizmoEnabled = false
298341 gizmoManager . scaleGizmoEnabled = false
342+ restoreParents ( )
299343 events . emit ( 'change' )
300344 }
301345
0 commit comments