diff --git a/newIDE/app/src/EditorFunctions/EditorFunctions.spec.js b/newIDE/app/src/EditorFunctions/EditorFunctions.spec.js index 57a1626c52..ca282ae1e4 100644 --- a/newIDE/app/src/EditorFunctions/EditorFunctions.spec.js +++ b/newIDE/app/src/EditorFunctions/EditorFunctions.spec.js @@ -1892,6 +1892,59 @@ describe('editorFunctions', () => { }); }); + // Regression test: creating instances with the "none" brush used to leave + // every new instance at the origin (0,0) instead of at brush_position. + it('creates new instances at brush_position with the none brush', async () => { + await putInstances({ + brush_kind: 'none', + brush_position: '200,300', + new_instances_count: 2, + }); + + expect(getInstancePositions(testScene)).toEqual([ + { x: 200, y: 300 }, + { x: 200, y: 300 }, + ]); + }); + + // The none brush must still leave existing instances where they are. + it('does not move an existing instance edited with the none brush', async () => { + await putInstances({ + brush_kind: 'point', + brush_position: '100,200', + new_instances_count: 1, + }); + const [created] = getInstances(testScene); + + await putInstances({ + brush_kind: 'none', + brush_position: '640,360', + existing_instance_ids: created.uuid, + instances_size: '48,48', + }); + + expect(getInstancePositions(testScene)).toEqual([{ x: 100, y: 200 }]); + }); + + // Editing an existing instance with the none brush and no brush_position + // must not snap it to the scene-center fallback. + it('does not move an existing instance edited with the none brush and no brush_position', async () => { + await putInstances({ + brush_kind: 'point', + brush_position: '100,200', + new_instances_count: 1, + }); + const [created] = getInstances(testScene); + + await putInstances({ + brush_kind: 'none', + existing_instance_ids: created.uuid, + instances_opacity: 128, + }); + + expect(getInstancePositions(testScene)).toEqual([{ x: 100, y: 200 }]); + }); + // line/grid need an end position to spread instances. Omitting it must fail // up front (and create nothing) rather than silently dropping every // instance at the default origin. diff --git a/newIDE/app/src/EditorFunctions/index.js b/newIDE/app/src/EditorFunctions/index.js index 27d1c007f2..73c2a611bd 100644 --- a/newIDE/app/src/EditorFunctions/index.js +++ b/newIDE/app/src/EditorFunctions/index.js @@ -3128,6 +3128,13 @@ const put2dInstances: EditorFunction = { 'The brush kind is unknown and was considered to be "none" instead.' ); } + // "none" keeps existing instances in place; new ones still need a position. + modifiedAndCreatedInstances.forEach(instance => { + if (!existingInstanceStates.has(instance)) { + instance.setX(brushPosition[0]); + instance.setY(brushPosition[1]); + } + }); } const instancesSize = SafeExtractor.parseCommaSeparatedTwoFiniteNumbers( @@ -3177,7 +3184,10 @@ const put2dInstances: EditorFunction = { objectSizeInfo.height !== null ? [objectSizeInfo.width, objectSizeInfo.height] : null; - if (brush_kind === 'point' && effectiveSize) { + if ( + (brush_kind === 'point' || brush_kind === 'none') && + effectiveSize + ) { attrs.push( `origin at this position, each occupies ${getOccupiedSpaceDescription( brushPosition, @@ -3773,6 +3783,14 @@ const put3dInstances: EditorFunction = { 'The brush kind is unknown and was considered to be "none" instead.' ); } + // "none" keeps existing instances in place; new ones still need a position. + modifiedAndCreatedInstances.forEach(instance => { + if (!existingInstanceStates.has(instance)) { + instance.setX(brushPosition[0]); + instance.setY(brushPosition[1]); + instance.setZ(brushPosition[2]); + } + }); } const instancesSizeArray = SafeExtractor.parseCommaSeparatedThreeFiniteNumbers( @@ -3820,7 +3838,10 @@ const put3dInstances: EditorFunction = { objectSizeInfo.depth !== null ? [objectSizeInfo.width, objectSizeInfo.height, objectSizeInfo.depth] : null; - if (brush_kind === 'point' && effectiveSize) { + if ( + (brush_kind === 'point' || brush_kind === 'none') && + effectiveSize + ) { attrs.push( `origin at this position, each occupies ${getOccupiedSpaceDescription( brushPosition,