Skip to content

Commit 077f3a5

Browse files
Improvement when positioning objects with brush none
1 parent ce0d2f0 commit 077f3a5

2 files changed

Lines changed: 75 additions & 11 deletions

File tree

newIDE/app/src/EditorFunctions/EditorFunctions.spec.js

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2824,22 +2824,33 @@ describe('editorFunctions', () => {
28242824
expect(getInstancePositions(testScene)).toEqual([{ x: 300, y: 400 }]);
28252825
});
28262826

2827-
// The none brush must still leave existing instances where they are.
2828-
it('does not move an existing instance edited with the none brush', async () => {
2827+
// A position passed with the none brush would be silently ignored, which
2828+
// agents misread as a move failure: the call must fail explicitly.
2829+
it('fails when a brush_position is passed with the none brush', async () => {
28292830
await putInstances({
28302831
brush_kind: 'point',
28312832
brush_position: '100,200',
28322833
new_instances_count: 1,
28332834
});
28342835
const [created] = getInstances(testScene);
28352836

2836-
await putInstances({
2837-
brush_kind: 'none',
2838-
brush_position: '640,360',
2839-
existing_instance_ids: created.uuid,
2840-
instances_size: '48,48',
2837+
const result = await editorFunctions.put_2d_instances.launchFunction({
2838+
...makeFakeLaunchFunctionOptionsWithProject(project),
2839+
args: {
2840+
scene_name: 'TestScene',
2841+
object_name: 'Player',
2842+
layer_name: '',
2843+
brush_kind: 'none',
2844+
brush_position: '640,360',
2845+
existing_instance_ids: created.uuid,
2846+
instances_size: '48,48',
2847+
},
28412848
});
28422849

2850+
expect(result.success).toBe(false);
2851+
expect(result.message).toEqual(
2852+
expect.stringContaining('never moves instances')
2853+
);
28432854
expect(getInstancePositions(testScene)).toEqual([{ x: 100, y: 200 }]);
28442855
});
28452856

@@ -3370,6 +3381,37 @@ describe('editorFunctions', () => {
33703381
expect(getInstancePositions(testScene)).toEqual([]);
33713382
});
33723383

3384+
// A position passed with the none brush would be silently ignored, which
3385+
// agents misread as a move failure: the call must fail explicitly.
3386+
it('fails when a brush_position is passed with the none brush', async () => {
3387+
await putInstances({
3388+
brush_kind: 'point',
3389+
brush_position: '10,20,30',
3390+
new_instances_count: 1,
3391+
});
3392+
const [created] = getInstances(testScene);
3393+
3394+
const result = await editorFunctions.put_3d_instances.launchFunction({
3395+
...makeFakeLaunchFunctionOptionsWithProject(project),
3396+
args: {
3397+
scene_name: 'TestScene',
3398+
object_name: 'Player',
3399+
layer_name: '',
3400+
brush_kind: 'none',
3401+
brush_position: '10,20,150',
3402+
existing_instance_ids: created.uuid,
3403+
},
3404+
});
3405+
3406+
expect(result.success).toBe(false);
3407+
expect(result.message).toEqual(
3408+
expect.stringContaining('never moves instances')
3409+
);
3410+
expect(getInstancePositions(testScene)).toEqual([
3411+
{ x: 10, y: 20, z: 30 },
3412+
]);
3413+
});
3414+
33733415
// The created id in the message closes the loop "create then adjust":
33743416
// it must be directly usable as `existing_instance_ids`.
33753417
it('reports the created instance id, usable to modify it in a follow-up call', async () => {

newIDE/app/src/EditorFunctions/index.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3497,6 +3497,13 @@ const put2dInstances: EditorFunction = {
34973497
: `A valid \`brush_position\` is required for the "${brush_kind}" brush (or use the "none" brush to modify existing instances without moving them).`
34983498
);
34993499
}
3500+
// The "none" brush never applies a position: fail instead of silently
3501+
// ignoring it, so the caller switches to a placement brush to move.
3502+
if (brush_kind === 'none' && parsedBrushPosition) {
3503+
return makeGenericFailure(
3504+
'The "none" brush never moves instances: remove `brush_position`, or use the "point" brush to move (it sets the exact position of every matched instance — one call per target position).'
3505+
);
3506+
}
35003507
// After the guard, a missing position can only happen when nothing is
35013508
// created nor moved ("none" brush only): the fallback is never used.
35023509
const brushPosition: [number, number] = parsedBrushPosition || [0, 0];
@@ -3879,14 +3886,18 @@ const put2dInstances: EditorFunction = {
38793886
return makeGenericFailure(
38803887
`Matched ${matchedCount} existing instance${
38813888
matchedCount > 1 ? 's' : ''
3882-
} but no change was requested — provide a value to modify (see the tool parameters for what can be edited).`
3889+
} but no change was requested — provide a value to modify, or use the "point" brush with \`brush_position\` to move.`
38833890
);
38843891
}
38853892

38863893
return makeGenericFailure(
38873894
`Matched ${matchedCount} existing instance${
38883895
matchedCount > 1 ? 's' : ''
3889-
} but the requested values are identical to their current ones, so nothing changed.`
3896+
} but the requested values are identical to their current ones, so nothing changed.${
3897+
hasPositionBrush
3898+
? ''
3899+
: ' To move instances, use the "point" brush with `brush_position` (the "none" brush never changes position).'
3900+
}`
38903901
);
38913902
}
38923903

@@ -4241,6 +4252,13 @@ const put3dInstances: EditorFunction = {
42414252
: `A valid \`brush_position\` is required for the "${brush_kind}" brush (or use the "none" brush to modify existing instances without moving them).`
42424253
);
42434254
}
4255+
// The "none" brush never applies a position: fail instead of silently
4256+
// ignoring it, so the caller switches to a placement brush to move.
4257+
if (brush_kind === 'none' && parsedBrushPosition) {
4258+
return makeGenericFailure(
4259+
'The "none" brush never moves instances: remove `brush_position`, or use the "point" brush to move (it sets the exact X, Y and Z of every matched instance — one call per target position).'
4260+
);
4261+
}
42444262
// After the guard, a missing position can only happen when nothing is
42454263
// created nor moved ("none" brush only): the fallback is never used.
42464264
const brushPosition: [number, number, number] = parsedBrushPosition || [
@@ -4565,14 +4583,18 @@ const put3dInstances: EditorFunction = {
45654583
return makeGenericFailure(
45664584
`Matched ${matchedCount} existing instance${
45674585
matchedCount > 1 ? 's' : ''
4568-
} but no change was requested — provide a value to modify (see the tool parameters for what can be edited).`
4586+
} but no change was requested — provide a value to modify, or use the "point" brush with \`brush_position\` to move.`
45694587
);
45704588
}
45714589

45724590
return makeGenericFailure(
45734591
`Matched ${matchedCount} existing instance${
45744592
matchedCount > 1 ? 's' : ''
4575-
} but the requested values are identical to their current ones, so nothing changed.`
4593+
} but the requested values are identical to their current ones, so nothing changed.${
4594+
hasPositionBrush
4595+
? ''
4596+
: ' To move instances, use the "point" brush with `brush_position` (the "none" brush never changes position).'
4597+
}`
45764598
);
45774599
}
45784600

0 commit comments

Comments
 (0)