From b8b4496d84a2bc5134b4501a7221e0310f88212f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pasteau?= <4895034+ClementPasteau@users.noreply.github.com> Date: Wed, 30 Sep 2026 16:30:00 +0200 Subject: [PATCH 1/2] Allow extensions to know if an instance is hidden at start. This fixes hidden lights wrongly showing lightning in the editor. --- GDJS/Runtime/InGameEditor/InGameEditor.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/GDJS/Runtime/InGameEditor/InGameEditor.tsx b/GDJS/Runtime/InGameEditor/InGameEditor.tsx index 9db1d49fce00..90d71f3c780c 100644 --- a/GDJS/Runtime/InGameEditor/InGameEditor.tsx +++ b/GDJS/Runtime/InGameEditor/InGameEditor.tsx @@ -3347,6 +3347,15 @@ namespace gdjs { return !!instanceData && !!instanceData.sealed; } + /** + * Instances hidden at start stay visible in the editor, but extensions + * can use this to disable what can't be shown as "hidden" (like lights). + */ + isInstanceHiddenAtStart(object: gdjs.RuntimeObject): boolean { + const instanceData = this._getInstanceData(object.persistentUuid); + return !!instanceData && !!instanceData.hidden; + } + private _addInstances(addedInstances: Array) { for (const addedInstance of addedInstances) { this._editedInstanceDataList.push(addedInstance); From 04edd18c3fb6c15b0c68abce2ea68bd063903271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pasteau?= <4895034+ClementPasteau@users.noreply.github.com> Date: Wed, 30 Sep 2026 16:41:25 +0200 Subject: [PATCH 2/2] Keep 3D instances with 0 opacity visible in the editor --- GDJS/Runtime/InGameEditor/InGameEditor.tsx | 1 + GDJS/Runtime/RuntimeInstanceContainer.ts | 3 +++ GDJS/Runtime/debugger-client/hot-reloader.ts | 3 +++ GDJS/Runtime/runtimeobject.ts | 16 ++++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/GDJS/Runtime/InGameEditor/InGameEditor.tsx b/GDJS/Runtime/InGameEditor/InGameEditor.tsx index 90d71f3c780c..31ef726773b7 100644 --- a/GDJS/Runtime/InGameEditor/InGameEditor.tsx +++ b/GDJS/Runtime/InGameEditor/InGameEditor.tsx @@ -3813,6 +3813,7 @@ namespace gdjs { ); } runtimeObject.extraInitializationFromInitialInstance(instance); + gdjs.RuntimeObject.applyInGameEditorMinimumOpacity(runtimeObject); } }); this._updateInstances(instances); diff --git a/GDJS/Runtime/RuntimeInstanceContainer.ts b/GDJS/Runtime/RuntimeInstanceContainer.ts index a8476a8235f5..e1320a0cc33c 100644 --- a/GDJS/Runtime/RuntimeInstanceContainer.ts +++ b/GDJS/Runtime/RuntimeInstanceContainer.ts @@ -396,6 +396,9 @@ namespace gdjs { .getVariables() .initFrom(instanceData.initialVariables, true); newObject.extraInitializationFromInitialInstance(instanceData); + if (this.getGame().isInGameEdition()) { + gdjs.RuntimeObject.applyInGameEditorMinimumOpacity(newObject); + } } } } diff --git a/GDJS/Runtime/debugger-client/hot-reloader.ts b/GDJS/Runtime/debugger-client/hot-reloader.ts index d13149ab219b..1708289cc2ad 100644 --- a/GDJS/Runtime/debugger-client/hot-reloader.ts +++ b/GDJS/Runtime/debugger-client/hot-reloader.ts @@ -1990,6 +1990,9 @@ namespace gdjs { ); if (numberPropertiesChanged || stringPropertiesChanged || sizeChanged) { runtimeObject.extraInitializationFromInitialInstance(newInstance); + if (this._runtimeGame.isInGameEdition()) { + gdjs.RuntimeObject.applyInGameEditorMinimumOpacity(runtimeObject); + } somethingChanged = true; } if (somethingChanged) { diff --git a/GDJS/Runtime/runtimeobject.ts b/GDJS/Runtime/runtimeobject.ts index da5ffd03374b..39819f5fb6b2 100644 --- a/GDJS/Runtime/runtimeobject.ts +++ b/GDJS/Runtime/runtimeobject.ts @@ -453,6 +453,22 @@ namespace gdjs { static supportsReinitialization = false; + /** + * Like in the 2D editor, transparent instances stay partially visible in + * the in-game editor so they can't be lost or misplaced. + */ + static applyInGameEditorMinimumOpacity(object: gdjs.RuntimeObject): void { + const objectWithOpacity = object as gdjs.RuntimeObject & + Partial; + if (!objectWithOpacity.getOpacity || !objectWithOpacity.setOpacity) { + return; + } + const minimumOpacity = 255 / 2; + if (objectWithOpacity.getOpacity() < minimumOpacity) { + objectWithOpacity.setOpacity(minimumOpacity); + } + } + /** * Return the time elapsed since the last frame, * in milliseconds, for the object.