Skip to content

Commit d7d1740

Browse files
Fix error accessing deleted objects after an object is deleted from a scene (#7612)
1 parent b219d50 commit d7d1740

14 files changed

+91
-7
lines changed

Extensions/Physics3DBehavior/JsExtension.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ module.exports = {
227227

228228
behaviorProperties
229229
.getOrCreate('object3D')
230-
.setValue(behaviorContent.getChild('Object3D').getStringValue())
230+
.setValue(behaviorContent.getChild('object3D').getStringValue())
231231
.setType('Behavior')
232232
.setLabel('3D capability')
233233
.setQuickCustomizationVisibility(gd.QuickCustomization.Hidden)

newIDE/app/src/MainFrame/EditorContainers/AskAi/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export type AskAiEditorInterface = {|
5959
scene: gdLayout,
6060
objectWithContext: ObjectWithContext
6161
) => void,
62+
onSceneObjectsDeleted: (scene: gdLayout) => void,
6263
|};
6364

6465
const noop = () => {};
@@ -109,6 +110,7 @@ export const AskAi = React.memo<Props>(
109110
forceUpdateEditor: noop,
110111
onEventsBasedObjectChildrenEdited: noop,
111112
onSceneObjectEdited: noop,
113+
onSceneObjectsDeleted: noop,
112114
}));
113115

114116
const aiRequestChatRef = React.useRef<AiRequestChatInterface | null>(

newIDE/app/src/MainFrame/EditorContainers/BaseEditor.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export type RenderEditorContainerProps = {|
151151
scene: gdLayout,
152152
objectWithContext: ObjectWithContext
153153
) => void,
154+
onSceneObjectsDeleted: (scene: gdLayout) => void,
154155

155156
onExtractAsExternalLayout: (name: string) => void,
156157
onExtractAsEventBasedObject: (

newIDE/app/src/MainFrame/EditorContainers/CustomObjectEditorContainer.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,15 @@ export class CustomObjectEditorContainer extends React.Component<RenderEditorCon
237237
onObjectEdited={() =>
238238
this.props.onEventsBasedObjectChildrenEdited(eventsBasedObject)
239239
}
240+
onObjectsDeleted={() =>
241+
this.props.onEventsBasedObjectChildrenEdited(eventsBasedObject)
242+
}
240243
onObjectGroupEdited={() =>
241244
this.props.onEventsBasedObjectChildrenEdited(eventsBasedObject)
242245
}
246+
onObjectGroupsDeleted={() =>
247+
this.props.onEventsBasedObjectChildrenEdited(eventsBasedObject)
248+
}
243249
onEventsBasedObjectChildrenEdited={
244250
this.props.onEventsBasedObjectChildrenEdited
245251
}

newIDE/app/src/MainFrame/EditorContainers/DebuggerEditorContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ export class DebuggerEditorContainer extends React.Component<
5757
// No thing to be done.
5858
}
5959

60+
onSceneObjectsDeleted(scene: gdLayout) {
61+
// No thing to be done.
62+
}
63+
6064
// To be updated, see https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops.
6165
UNSAFE_componentWillReceiveProps() {
6266
this._checkUserHasSubscription();

newIDE/app/src/MainFrame/EditorContainers/EventsEditorContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export class EventsEditorContainer extends React.Component<RenderEditorContainer
5353
// No thing to be done.
5454
}
5555

56+
onSceneObjectsDeleted(scene: gdLayout) {
57+
// No thing to be done.
58+
}
59+
5660
getLayout(): ?gdLayout {
5761
const { project, projectItemName } = this.props;
5862
if (

newIDE/app/src/MainFrame/EditorContainers/EventsFunctionsExtensionEditorContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export class EventsFunctionsExtensionEditorContainer extends React.Component<Ren
4646
// No thing to be done.
4747
}
4848

49+
onSceneObjectsDeleted(scene: gdLayout) {
50+
// No thing to be done.
51+
}
52+
4953
shouldComponentUpdate(nextProps: RenderEditorContainerProps) {
5054
// We stop updates when the component is inactive.
5155
// If it's active, was active or becoming active again we let update propagate.

newIDE/app/src/MainFrame/EditorContainers/ExternalEventsEditorContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ export class ExternalEventsEditorContainer extends React.Component<
9090
// No thing to be done.
9191
}
9292

93+
onSceneObjectsDeleted(scene: gdLayout) {
94+
// No thing to be done.
95+
}
96+
9397
getExternalEvents(): ?gdExternalEvents {
9498
const { project, projectItemName } = this.props;
9599
if (!project || !projectItemName) return null;

newIDE/app/src/MainFrame/EditorContainers/ExternalLayoutEditorContainer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ export class ExternalLayoutEditorContainer extends React.Component<
138138
}
139139
}
140140

141+
onSceneObjectsDeleted(scene: gdLayout) {
142+
const { editor } = this;
143+
const externalLayout = this.getExternalLayout();
144+
if (!externalLayout) {
145+
return;
146+
}
147+
if (externalLayout.getAssociatedLayout() !== scene.getName()) {
148+
return;
149+
}
150+
if (editor) {
151+
editor.forceUpdateObjectsList();
152+
}
153+
}
154+
141155
getExternalLayout(): ?gdExternalLayout {
142156
const { project, projectItemName } = this.props;
143157
if (!project || !projectItemName) return null;
@@ -266,8 +280,10 @@ export class ExternalLayoutEditorContainer extends React.Component<
266280
onObjectEdited={objectWithContext =>
267281
this.props.onSceneObjectEdited(layout, objectWithContext)
268282
}
283+
onObjectsDeleted={() => this.props.onSceneObjectsDeleted(layout)}
269284
// It's only used to refresh events-based object variants.
270285
onObjectGroupEdited={() => {}}
286+
onObjectGroupsDeleted={() => {}}
271287
// Nothing to do as events-based objects can't have external layout.
272288
onEventsBasedObjectChildrenEdited={() => {}}
273289
onExtensionInstalled={this.props.onExtensionInstalled}

newIDE/app/src/MainFrame/EditorContainers/HomePage/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export type HomePageEditorInterface = {|
169169
scene: gdLayout,
170170
objectWithContext: ObjectWithContext
171171
) => void,
172+
onSceneObjectsDeleted: (scene: gdLayout) => void,
172173
|};
173174

174175
export const HomePage = React.memo<Props>(
@@ -482,12 +483,17 @@ export const HomePage = React.memo<Props>(
482483
[]
483484
);
484485

486+
const onSceneObjectsDeleted = React.useCallback((scene: gdLayout) => {
487+
// No thing to be done.
488+
}, []);
489+
485490
React.useImperativeHandle(ref, () => ({
486491
getProject,
487492
updateToolbar,
488493
forceUpdateEditor,
489494
onEventsBasedObjectChildrenEdited,
490495
onSceneObjectEdited,
496+
onSceneObjectsDeleted,
491497
}));
492498

493499
const onUserSurveyStarted = React.useCallback(() => {

newIDE/app/src/MainFrame/EditorContainers/ResourcesEditorContainer.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ export class ResourcesEditorContainer extends React.Component<RenderEditorContai
4141
// No thing to be done.
4242
}
4343

44+
onSceneObjectsDeleted(scene: gdLayout) {
45+
// No thing to be done.
46+
}
47+
4448
componentDidUpdate(prevProps: RenderEditorContainerProps) {
4549
if (
4650
this.editor &&

newIDE/app/src/MainFrame/EditorContainers/SceneEditorContainer.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,20 @@ export class SceneEditorContainer extends React.Component<RenderEditorContainerP
7979
}
8080
}
8181

82+
onSceneObjectsDeleted(scene: gdLayout) {
83+
const layout = this.getLayout();
84+
if (!layout) {
85+
return;
86+
}
87+
if (layout !== scene) {
88+
return;
89+
}
90+
const { editor } = this;
91+
if (editor) {
92+
editor.forceUpdateObjectsList();
93+
}
94+
}
95+
8296
getLayout(): ?gdLayout {
8397
const { project, projectItemName } = this.props;
8498
if (
@@ -160,8 +174,10 @@ export class SceneEditorContainer extends React.Component<RenderEditorContainerP
160174
onObjectEdited={objectWithContext =>
161175
this.props.onSceneObjectEdited(layout, objectWithContext)
162176
}
177+
onObjectsDeleted={() => this.props.onSceneObjectsDeleted(layout)}
163178
// It's only used to refresh events-based object variants.
164179
onObjectGroupEdited={() => {}}
180+
onObjectGroupsDeleted={() => {}}
165181
// Nothing to do as scenes are not events-based objects.
166182
onEventsBasedObjectChildrenEdited={() => {}}
167183
/>

newIDE/app/src/MainFrame/index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,6 +2350,18 @@ const MainFrame = (props: Props) => {
23502350
[state.editorTabs]
23512351
);
23522352
2353+
const onSceneObjectsDeleted = React.useCallback(
2354+
(scene: gdLayout) => {
2355+
for (const editor of state.editorTabs.editors) {
2356+
const { editorRef } = editor;
2357+
if (editorRef) {
2358+
editorRef.onSceneObjectsDeleted(scene);
2359+
}
2360+
}
2361+
},
2362+
[state.editorTabs]
2363+
);
2364+
23532365
const _onProjectItemModified = () => {
23542366
triggerUnsavedChanges();
23552367
forceUpdate();
@@ -4048,6 +4060,7 @@ const MainFrame = (props: Props) => {
40484060
onDeleteEventsBasedObjectVariant: deleteEventsBasedObjectVariant,
40494061
onEventsBasedObjectChildrenEdited: onEventsBasedObjectChildrenEdited,
40504062
onSceneObjectEdited: onSceneObjectEdited,
4063+
onSceneObjectsDeleted: onSceneObjectsDeleted,
40514064
onExtensionInstalled: onExtensionInstalled,
40524065
gamesList,
40534066
gamesPlatformFrameTools,

newIDE/app/src/SceneEditor/index.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ type Props = {|
119119
eventsBasedObject: gdEventsBasedObject
120120
) => void,
121121

122+
onObjectsDeleted: () => void,
123+
onObjectGroupsDeleted: () => void,
124+
122125
setToolbar: (?React.Node) => void,
123126
resourceManagementProps: ResourceManagementProps,
124127
isActive: boolean,
@@ -973,7 +976,7 @@ export default class SceneEditor extends React.Component<Props, State> {
973976
objectsWithContext: ObjectWithContext[],
974977
done: boolean => void
975978
) => {
976-
const { project, layout, eventsBasedObject, onObjectEdited } = this.props;
979+
const { project, layout, eventsBasedObject, onObjectsDeleted } = this.props;
977980

978981
objectsWithContext.forEach(objectWithContext => {
979982
const { object, global } = objectWithContext;
@@ -1005,12 +1008,11 @@ export default class SceneEditor extends React.Component<Props, State> {
10051008
}
10061009
});
10071010

1011+
// Note: done() actually does the deletion of the objects,
1012+
// so ensure objectsWithContext are not used after this call.
10081013
done(true);
1014+
onObjectsDeleted();
10091015

1010-
objectsWithContext.forEach(objectWithContext => {
1011-
// TODO Avoid to do this N times.
1012-
onObjectEdited(objectWithContext);
1013-
});
10141016
// We modified the selection, so force an update of editors dealing with it.
10151017
this.forceUpdatePropertiesEditor();
10161018
this.updateToolbar();
@@ -1207,8 +1209,10 @@ export default class SceneEditor extends React.Component<Props, State> {
12071209
groupWithContext: GroupWithContext,
12081210
done: boolean => void
12091211
) => {
1212+
// done() actually does the deletion of the object group,
1213+
// so ensure groupWithContext is not used after this call.
12101214
done(true);
1211-
this.props.onObjectGroupEdited(groupWithContext);
1215+
this.props.onObjectGroupsDeleted();
12121216
};
12131217

12141218
_onRenameObjectGroup = (

0 commit comments

Comments
 (0)