Skip to content

Commit dea081a

Browse files
authored
Fix AI not always aware of properties not changed properly (#8183)
1 parent fb0117e commit dea081a

File tree

3 files changed

+388
-20
lines changed

3 files changed

+388
-20
lines changed

Extensions/TextObject/TextObject.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,28 @@ bool TextObject::UpdateProperty(const gd::String& propertyName,
7272
return true;
7373
}
7474
if (propertyName == "textAlignment") {
75-
textAlignment = newValue;
75+
if (newValue.LowerCase() == "left") {
76+
textAlignment = "left";
77+
} else if (newValue.LowerCase() == "center") {
78+
textAlignment = "center";
79+
} else if (newValue.LowerCase() == "right") {
80+
textAlignment = "right";
81+
} else {
82+
return false;
83+
}
84+
7685
return true;
7786
}
7887
if (propertyName == "verticalTextAlignment") {
79-
verticalTextAlignment = newValue;
88+
if (newValue.LowerCase() == "top") {
89+
verticalTextAlignment = "top";
90+
} else if (newValue.LowerCase() == "center") {
91+
verticalTextAlignment = "center";
92+
} else if (newValue.LowerCase() == "bottom") {
93+
verticalTextAlignment = "bottom";
94+
} else {
95+
return false;
96+
}
8097
return true;
8198
}
8299
if (propertyName == "isOutlineEnabled") {

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

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,228 @@ describe('editorFunctions', () => {
628628
});
629629
});
630630

631+
describe('change_object_property', () => {
632+
let project: gdProject;
633+
let testScene: gdLayout;
634+
635+
beforeEach(() => {
636+
project = new gd.ProjectHelper.createNewGDJSProject();
637+
testScene = project.insertNewLayout('TestScene', 0);
638+
639+
// Add font resources to the project
640+
const fontResource1 = new gd.FontResource();
641+
fontResource1.setName('font1.ttf');
642+
fontResource1.setFile('font1.ttf');
643+
project.getResourcesManager().addResource(fontResource1);
644+
645+
// Create a TextObject with a font property (resource type)
646+
const testSceneObjects = testScene.getObjects();
647+
const textObject = testSceneObjects.insertNewObject(
648+
project,
649+
'TextObject::Text',
650+
'MyTextObject',
651+
testSceneObjects.getObjectsCount()
652+
);
653+
// Set the font property to an existing resource
654+
textObject.getConfiguration().updateProperty('font', 'font1.ttf');
655+
});
656+
657+
afterEach(() => {
658+
project.delete();
659+
});
660+
661+
it('handles various property types: resource, non-existing, boolean, and number with sanitization warning', async () => {
662+
const result: EditorFunctionGenericOutput = await editorFunctions.change_object_property.launchFunction(
663+
{
664+
...makeFakeLaunchFunctionOptionsWithProject(project),
665+
args: {
666+
scene_name: 'TestScene',
667+
object_name: 'MyTextObject',
668+
changed_properties: [
669+
// Valid change but a property name with a typo
670+
{
671+
property_name: 'Character-size_',
672+
new_value: '56',
673+
},
674+
// Change a choice
675+
{
676+
property_name: 'textAlignment',
677+
new_value: 'INVALID_CHOICE',
678+
},
679+
{
680+
property_name: 'verticalTextAlignment',
681+
new_value: 'BoTTOm',
682+
},
683+
// Try to change a non-existing property
684+
{
685+
property_name: 'nonExistingProperty',
686+
new_value: 'someValue',
687+
},
688+
// Change a boolean property with "true"
689+
{
690+
property_name: 'bold',
691+
new_value: 'YES',
692+
},
693+
{
694+
property_name: 'isShadowEnabled',
695+
new_value: '1',
696+
},
697+
// Change a boolean property with "FALSE"
698+
{
699+
property_name: 'italic',
700+
new_value: 'FALSE',
701+
},
702+
// Change a number property with a value that will be sanitized
703+
{
704+
property_name: 'shadowAngle',
705+
new_value: '20,40 , 50',
706+
},
707+
{
708+
property_name: 'shadowDistance',
709+
new_value: '20X 40 X 50',
710+
},
711+
{
712+
property_name: 'shadowBlurRadius',
713+
new_value: '20.41 × 50',
714+
},
715+
],
716+
},
717+
}
718+
);
719+
720+
// The operation should succeed overall (some changes were made)
721+
expect(result.success).toBe(true);
722+
expect(result.message).toMatchInlineSnapshot(`
723+
"Successfully done some changes but some issues were found - see the warnings.
724+
Changed property \\"characterSize\\" of object \\"MyTextObject\\" to \\"56\\".
725+
Changed property \\"verticalTextAlignment\\" of object \\"MyTextObject\\" to \\"bottom\\".
726+
Changed property \\"bold\\" of object \\"MyTextObject\\" to \\"true\\".
727+
Changed property \\"isShadowEnabled\\" of object \\"MyTextObject\\" to \\"true\\".
728+
Changed property \\"italic\\" of object \\"MyTextObject\\" to \\"false\\".
729+
Changed property \\"shadowAngle\\" of object \\"MyTextObject\\" to \\"20\\".
730+
Changed property \\"shadowDistance\\" of object \\"MyTextObject\\" to \\"0\\".
731+
Changed property \\"shadowBlurRadius\\" of object \\"MyTextObject\\" to \\"20.41\\".
732+
Warnings:
733+
Could not change property \\"textAlignment\\" of object \\"MyTextObject\\". The value might be invalid, of the wrong type or not allowed.
734+
Property not found: nonExistingProperty on object MyTextObject.
735+
Property \\"shadowAngle\\" of object \\"MyTextObject\\" was changed to 20 - but the original requested value (20,40 , 50) looks like a size with multiple dimensions. This is not supported, only a number is allowed here.
736+
Property \\"shadowDistance\\" of object \\"MyTextObject\\" was changed to 0 - but the original requested value (20X 40 X 50) looks like a size with multiple dimensions. This is not supported, only a number is allowed here.
737+
Property \\"shadowBlurRadius\\" of object \\"MyTextObject\\" was changed to 20.41 - but the original requested value (20.41 × 50) looks like a size with multiple dimensions. This is not supported, only a number is allowed here."
738+
`);
739+
740+
// Verify the properties were actually changed
741+
const textObject = testScene.getObjects().getObject('MyTextObject');
742+
const properties = textObject.getConfiguration().getProperties();
743+
744+
expect(properties.get('characterSize').getValue()).toBe('56');
745+
expect(properties.get('bold').getValue()).toBe('true');
746+
expect(properties.get('italic').getValue()).toBe('false');
747+
expect(properties.get('shadowAngle').getValue()).toBe('20');
748+
});
749+
});
750+
751+
describe('change_behavior_property', () => {
752+
let project: gdProject;
753+
let testScene: gdLayout;
754+
755+
beforeEach(() => {
756+
project = new gd.ProjectHelper.createNewGDJSProject();
757+
testScene = project.insertNewLayout('TestScene', 0);
758+
759+
// Create a Sprite object and add a PlatformerObject behavior to it
760+
const testSceneObjects = testScene.getObjects();
761+
const spriteObject = testSceneObjects.insertNewObject(
762+
project,
763+
'Sprite',
764+
'MySprite',
765+
testSceneObjects.getObjectsCount()
766+
);
767+
768+
// Add PlatformerObject behavior
769+
spriteObject.addNewBehavior(
770+
project,
771+
'PlatformBehavior::PlatformerObjectBehavior',
772+
'PlatformerObject'
773+
);
774+
});
775+
776+
afterEach(() => {
777+
project.delete();
778+
});
779+
780+
it('changes behavior properties with warnings for invalid values', async () => {
781+
const result: EditorFunctionGenericOutput = await editorFunctions.change_behavior_property.launchFunction(
782+
{
783+
...makeFakeLaunchFunctionOptionsWithProject(project),
784+
args: {
785+
scene_name: 'TestScene',
786+
object_name: 'MySprite',
787+
behavior_name: 'PlatformerObject',
788+
changed_properties: [
789+
// Change number properties
790+
{
791+
property_name: 'GRAVITY',
792+
new_value: '1500',
793+
},
794+
{
795+
property_name: 'JumpSpeed',
796+
new_value: '800',
797+
},
798+
{
799+
property_name: 'Max_speed',
800+
new_value: '300 x 20',
801+
},
802+
// Change a boolean property with "true"
803+
{
804+
property_name: 'CanGrabPlatforms',
805+
new_value: 'true',
806+
},
807+
// Change a boolean property with "FALSE"
808+
{
809+
property_name: 'IgnoreDefaultControls',
810+
new_value: 'FALSE',
811+
},
812+
// Try to change a non-existing property
813+
{
814+
property_name: 'nonExistingProperty',
815+
new_value: 'someValue',
816+
},
817+
],
818+
},
819+
}
820+
);
821+
822+
// The operation should succeed overall (some changes were made)
823+
expect(result.success).toBe(true);
824+
expect(result.message).toMatchInlineSnapshot(`
825+
"Successfully done some changes but some issues were found - see the warnings.
826+
Changed property \\"Gravity\\" of behavior \\"PlatformerObject\\" to \\"1500\\".
827+
Changed property \\"JumpSpeed\\" of behavior \\"PlatformerObject\\" to \\"800\\".
828+
Changed property \\"MaxSpeed\\" of behavior \\"PlatformerObject\\" to \\"300\\".
829+
Changed property \\"CanGrabPlatforms\\" of behavior \\"PlatformerObject\\" to \\"true\\".
830+
Changed property \\"IgnoreDefaultControls\\" of behavior \\"PlatformerObject\\" to \\"false\\".
831+
Warnings:
832+
Property \\"MaxSpeed\\" of behavior \\"PlatformerObject\\" was changed to 300 - but the original requested value (300 x 20) looks like a size with multiple dimensions. This is not supported, only a number is allowed here.
833+
Property \\"nonExistingProperty\\" not found on behavior \\"PlatformerObject\\" of object \\"MySprite\\"."
834+
`);
835+
836+
// Verify the behavior properties were actually changed
837+
const spriteObject = testScene.getObjects().getObject('MySprite');
838+
const behavior = spriteObject.getBehavior('PlatformerObject');
839+
const behaviorProperties = behavior.getProperties();
840+
841+
expect(behaviorProperties.get('Gravity').getValue()).toBe('1500');
842+
expect(behaviorProperties.get('JumpSpeed').getValue()).toBe('800');
843+
expect(behaviorProperties.get('MaxSpeed').getValue()).toBe('300');
844+
expect(behaviorProperties.get('CanGrabPlatforms').getValue()).toBe(
845+
'true'
846+
);
847+
expect(behaviorProperties.get('IgnoreDefaultControls').getValue()).toBe(
848+
'false'
849+
);
850+
});
851+
});
852+
631853
describe('add_scene_events', () => {
632854
let project: gdProject;
633855
let testScene: gdLayout;

0 commit comments

Comments
 (0)