Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Core/GDCore/Project/Effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ void Effect::SerializeTo(SerializerElement& element) const {
if (!IsEnabled()) {
element.SetBoolAttribute("disabled", true);
}
// Always written: when it's missing, it's deduced from "disabled" (see
// UnserializeFrom).
element.SetBoolAttribute("hiddenInEditor", IsHiddenInEditor());
SerializerElement& doubleParametersElement =
element.AddChild("doubleParameters");
for (auto& parameter : doubleParameters)
Expand Down Expand Up @@ -48,6 +51,9 @@ void Effect::UnserializeFrom(const SerializerElement& element) {
));
SetFolded(element.GetBoolAttribute("folded", false));
SetEnabled(!element.GetBoolAttribute("disabled", false));
// Compatibility with GD <= 5.6.283: a disabled effect was not applied in the
// editor either, so it stays hidden in the editor.
SetHiddenInEditor(element.GetBoolAttribute("hiddenInEditor", !IsEnabled()));

doubleParameters.clear();
const SerializerElement& doubleParametersElement =
Expand Down
14 changes: 13 additions & 1 deletion Core/GDCore/Project/Effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ class GD_CORE_API Effect {
}
bool IsEnabled() const { return isEnabled; }

/**
* \brief Set if the effect is hidden in the editor.
*
* This only affects the editor: the effect is still applied in the game
* (unless it's disabled, see SetEnabled).
*/
void SetHiddenInEditor(bool hiddenInEditor_) {
hiddenInEditor = hiddenInEditor_;
}
bool IsHiddenInEditor() const { return hiddenInEditor; }

void SetDoubleParameter(const gd::String &name, double value) {
doubleParameters[name] = value;
}
Expand Down Expand Up @@ -110,7 +121,8 @@ class GD_CORE_API Effect {
bool folded;
gd::String name; ///< The name of the layer.
gd::String effectType; ///< The name of the effect to apply.
bool isEnabled = true; ///< Enable the effect at the beginning of the scene, at its object creation or in the editor.
bool isEnabled = true; ///< Enable the effect at the beginning of the scene or at its object creation.
bool hiddenInEditor = false; ///< True if the effect is not applied in the editor.
std::map<gd::String, double> doubleParameters; ///< Values of parameters being doubles, keyed by names.
std::map<gd::String, gd::String> stringParameters; ///< Values of parameters being strings, keyed by names.
std::map<gd::String, bool> booleanParameters; ///< Values of parameters being booleans, keyed by names.
Expand Down
3 changes: 3 additions & 0 deletions Core/GDCore/Project/InitialInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void InitialInstance::UnserializeFrom(gd::Project &project,
SetSealed(element.GetBoolAttribute("sealed", false));
SetShouldKeepRatio(element.GetBoolAttribute("keepRatio", false));
SetHidden(element.GetBoolAttribute("hidden", false));
SetHiddenInEditor(element.GetBoolAttribute("hiddenInEditor", false));

persistentUuid = element.GetStringAttribute("persistentUuid");
if (persistentUuid.empty()) ResetPersistentUuid();
Expand Down Expand Up @@ -156,6 +157,8 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
if (IsSealed()) element.SetAttribute("sealed", IsSealed());
if (ShouldKeepRatio()) element.SetAttribute("keepRatio", ShouldKeepRatio());
if (IsHidden()) element.SetAttribute("hidden", IsHidden());
if (IsHiddenInEditor())
element.SetAttribute("hiddenInEditor", IsHiddenInEditor());

if (persistentUuid.empty()) persistentUuid = UUID::MakeUuid4();
element.SetStringAttribute("persistentUuid", persistentUuid);
Expand Down
15 changes: 15 additions & 0 deletions Core/GDCore/Project/InitialInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,19 @@ class GD_CORE_API InitialInstance {
*/
void SetHidden(bool enable = true) { hidden = enable; }

/**
* \brief Return true if the instance is hidden in the editor.
*
* This only affects the editor: the instance is still displayed in the game
* (unless it's hidden when the scene starts, see SetHidden).
*/
bool IsHiddenInEditor() const { return hiddenInEditor; };

/**
* \brief Set if the instance is hidden in the editor.
*/
void SetHiddenInEditor(bool enable = true) { hiddenInEditor = enable; }

///@}

/** \name Variable management
Expand Down Expand Up @@ -498,6 +511,8 @@ class GD_CORE_API InitialInstance {
/// should keep the same ratio.
bool hidden = false; ///< True if the instance is hidden when
/// the scene starts.
bool hiddenInEditor = false; ///< True if the instance is hidden in the
/// editor.
mutable gd::String persistentUuid; ///< A persistent random version 4 UUID,
/// useful for hot reloading.

Expand Down
8 changes: 8 additions & 0 deletions Core/GDCore/Project/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Layer::Layer()
defaultCameraBehavior("top-left-anchored-if-never-moved"),
isVisible(true),
isLocked(false),
isHiddenInEditor(false),
isLightingLayer(false),
followBaseLayerCamera(false),
camera3DNearPlaneDistance(3),
Expand Down Expand Up @@ -47,6 +48,9 @@ void Layer::SerializeTo(SerializerElement& element) const {
}
element.SetAttribute("visibility", GetVisibility());
element.SetAttribute("isLocked", IsLocked());
// Always written: when it's missing, it's deduced from the visibility (see
// UnserializeFrom).
element.SetAttribute("isHiddenInEditor", IsHiddenInEditor());
element.SetAttribute("isLightingLayer", IsLightingLayer());
element.SetAttribute("followBaseLayerCamera", IsFollowingBaseLayerCamera());
element.SetAttribute("ambientLightColorR", (int)GetAmbientLightColorRed());
Expand Down Expand Up @@ -90,6 +94,10 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
SetDefaultCameraBehavior(element.GetStringAttribute("defaultCameraBehavior", "top-left-anchored-if-never-moved"));
SetVisibility(element.GetBoolAttribute("visibility", true, "Visibility"));
SetLocked(element.GetBoolAttribute("isLocked", false));
// Compatibility with GD <= 5.6.283: the visibility was used for both the game
// and the editor, so a layer hidden in the game stays hidden in the editor.
SetHiddenInEditor(
element.GetBoolAttribute("isHiddenInEditor", !GetVisibility()));
SetLightingLayer(element.GetBoolAttribute("isLightingLayer", false));
SetFollowBaseLayerCamera(
element.GetBoolAttribute("followBaseLayerCamera", false));
Expand Down
16 changes: 16 additions & 0 deletions Core/GDCore/Project/Layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ class GD_CORE_API Layer {
*/
bool GetVisibility() const { return isVisible; }

/**
* \brief Change if the layer is hidden in the editor.
*
* This only affects the editor: the layer is still displayed in the game
* (unless its visibility is set to false).
*/
void SetHiddenInEditor(bool isHiddenInEditor_) {
isHiddenInEditor = isHiddenInEditor_;
}

/**
* \brief Return true if the layer is hidden in the editor.
*/
bool IsHiddenInEditor() const { return isHiddenInEditor; }

/**
* \brief Change if layer can be modified or not.
*/
Expand Down Expand Up @@ -287,6 +302,7 @@ class GD_CORE_API Layer {
gd::String cameraType;
bool isVisible; ///< True if the layer is visible
bool isLocked; ///< True if the layer is locked
bool isHiddenInEditor; ///< True if the layer is hidden in the editor
bool isLightingLayer; ///< True if the layer is used to display lights and
///< renders an ambient light.
bool followBaseLayerCamera; ///< True if the layer automatically follows the
Expand Down
70 changes: 65 additions & 5 deletions GDJS/Runtime/InGameEditor/InGameEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ namespace gdjs {
getTransformControlsMode: () => this._getTransformControlsMode(),
setTransformControlsMode: (mode: 'translate' | 'rotate' | 'scale') =>
this._setTransformControlsMode(mode),
focusOnSelection: () => this._focusOnSelection(),
focusOnSelection: () => this.focusOnSelection(),
switchToFreeCamera: () => this._getEditorCamera().switchToFreeCamera(),
switchToOrbitCamera: () =>
this._getEditorCamera().switchToOrbitAroundZ0(4000),
Expand Down Expand Up @@ -1585,6 +1585,49 @@ namespace gdjs {
sceneAndCustomObject;
this._currentScene = scene;
this._editedInstanceContainer = customObjectInstanceContainer;
// The edited variant layers, instances and effects follow the
// editor visibility, not the in-game one. They were created before
// the container was known as edited, so apply it now.
for (const layerData of editedLayerDataList) {
if (!customObjectInstanceContainer.hasLayer(layerData.name)) {
continue;
}
const layer = customObjectInstanceContainer.getLayer(
layerData.name
);
layer.show(!layerData.isHiddenInEditor);
for (const effectData of layerData.effects) {
if (layer.hasEffect(effectData.name)) {
layer.enableEffect(
effectData.name,
!customObjectInstanceContainer.isEffectDisabled(effectData)
);
}
}
}
for (const object of customObjectInstanceContainer.getAdhocListOfAllInstances()) {
const instanceData = editedInstanceDataList.find(
(data) => data.persistentUuid === object.persistentUuid
);
if (instanceData && instanceData.hiddenInEditor) {
object.hide(true);
}
const objectData = customObjectInstanceContainer._objects.get(
object.getName()
);
if (objectData) {
for (const effectData of objectData.effects) {
if (object.hasEffect(effectData.name)) {
object.enableEffect(
effectData.name,
!customObjectInstanceContainer.isEffectDisabled(
effectData
)
);
}
}
}
}
}
this.setInstancesEditorSettings(
eventsBasedObjectVariantData.editionSettings
Expand Down Expand Up @@ -2207,7 +2250,11 @@ namespace gdjs {
);
}

private _focusOnSelection() {
/**
* Frame the selected objects in the visible screen area (the "F" shortcut
* of the editor).
*/
focusOnSelection() {
const selectedObjects = this._selection.getSelectedObjects();
if (selectedObjects.length === 0) {
return;
Expand All @@ -2232,7 +2279,7 @@ namespace gdjs {
'IN_GAME_EDITOR_FOCUS_ON_SELECTION'
)
) {
this._focusOnSelection();
this.focusOnSelection();
}

if (
Expand Down Expand Up @@ -2695,7 +2742,12 @@ namespace gdjs {
for (const object of editedInstanceContainer.getAdhocListOfAllInstances()) {
if (!object.persistentUuid) continue;
const instanceData = this._getInstanceData(object.persistentUuid);
if (!instanceData || !instanceData.hidden) continue;
if (
!instanceData ||
!instanceData.hidden ||
instanceData.hiddenInEditor
)
continue;

const objectLayer = this.getEditorLayer(object.getLayer());
const threeGroup =
Expand Down Expand Up @@ -3591,6 +3643,7 @@ namespace gdjs {
// Not modified by the InGameEditor (which always shows instances,
// even those hidden at start), but must be preserved:
hidden: oldData ? oldData.hidden : undefined,
hiddenInEditor: oldData ? oldData.hiddenInEditor : undefined,
// Not modified by the InGameEditor itself: the editor only lowers
// the opacity for edition, and flipping is changed from the IDE
// (which then sends the updated instance data). But they must be
Expand Down Expand Up @@ -3665,7 +3718,11 @@ namespace gdjs {

isInstanceSealed(object: gdjs.RuntimeObject): boolean {
const instanceData = this._getInstanceData(object.persistentUuid);
return !!instanceData && !!instanceData.sealed;
// Instances hidden in the editor can't be selected by clicking on them.
return (
!!instanceData &&
(!!instanceData.sealed || !!instanceData.hiddenInEditor)
);
}

/**
Expand Down Expand Up @@ -4133,6 +4190,9 @@ namespace gdjs {
}
runtimeObject.setAngle(instance.angle);
runtimeObject.setLayer(instance.layer);
// Instances hidden at start stay visible in the editor: only the
// ones hidden in the editor are hidden.
runtimeObject.hide(!!instance.hiddenInEditor);
if (is3D(runtimeObject)) {
runtimeObject.setZ(instance.z === undefined ? 0 : instance.z);
runtimeObject.setRotationX(
Expand Down
41 changes: 40 additions & 1 deletion GDJS/Runtime/RuntimeInstanceContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,14 @@ namespace gdjs {
// Instances hidden at start are not hidden in the in-game editor:
// they must stay visible to be seen and manipulated (like in the
// 2D editor).
if (instanceData.hidden && !this.getGame().isInGameEdition()) {
// Instances hidden in the editor are only hidden in the in-game
// editor. Children of custom objects are always displayed (like in
// the 2D editor), unless their variant is the one being edited.
if (
this.getGame().isInGameEdition()
? instanceData.hiddenInEditor && this.isUsingEditorVisibility()
: instanceData.hidden
) {
newObject.hide(true);
}
newObject
Expand All @@ -403,6 +410,38 @@ namespace gdjs {
}
}

/**
* Check if the instances, layers and effects of this container are
* displayed according to their visibility in the editor, instead of the
* one in the game.
*
* It's the case for the scene and the custom object variant edited in the
* in-game editor. Other custom objects are displayed like in the game.
*/
isUsingEditorVisibility(): boolean {
const game = this.getGame();
if (!game.isInGameEdition()) return false;
if (this instanceof gdjs.RuntimeScene) return true;
const inGameEditor = game.getInGameEditor();
return (
!!inGameEditor && inGameEditor.getEditedInstanceContainer() === this
);
}

/**
* Check if an effect of an object or a layer of this container must be
* disabled.
*
* The in-game editor applies the effects disabled in the game (like
* instances hidden at start are shown), but not the effects hidden in the
* editor.
*/
isEffectDisabled(effectData: EffectData): boolean {
return this.isUsingEditorVisibility()
? !!effectData.hiddenInEditor
: !!effectData.disabled;
}

/**
* Get the data representing the initial shared data of the scene for the specified behavior.
* @param name The name of the behavior
Expand Down
10 changes: 8 additions & 2 deletions GDJS/Runtime/RuntimeLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ namespace gdjs {
this._defaultCameraBehavior = getDefaultCameraBehaviorFromString(
layerData.defaultCameraBehavior || 'top-left-anchored-if-never-moved'
);
this._hidden = !layerData.visibility;
// The in-game editor shows scene layers hidden in the game (like the 2D
// editor), but hides layers hidden in the editor.
// Layers of custom objects are displayed like in the game, unless their
// variant is the one being edited.
this._hidden = instanceContainer.isUsingEditorVisibility()
? !!layerData.isHiddenInEditor
: !layerData.visibility;
this._initialCamera3DFieldOfView = layerData.camera3DFieldOfView || 45;
this._initialCamera3DNearPlaneDistance =
layerData.camera3DNearPlaneDistance || 0.1;
Expand Down Expand Up @@ -127,7 +133,7 @@ namespace gdjs {
for (let i = 0; i < layerData.effects.length; ++i) {
const effectData = layerData.effects[i];
this.addEffect(effectData);
if (effectData.disabled) {
if (instanceContainer.isEffectDisabled(effectData)) {
this.enableEffect(effectData.name, false);
}
}
Expand Down
4 changes: 4 additions & 0 deletions GDJS/Runtime/debugger-client/abstract-debugger-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,10 @@ namespace gdjs {
// TODO: use data.payload.visibleScreenArea
inGameEditor.centerViewOnLastSelectedInstance();
}
} else if (data.command === 'focusOnSelection') {
if (inGameEditor) {
inGameEditor.focusOnSelection();
}
} else if (data.command === 'updateInnerArea') {
if (inGameEditor) {
inGameEditor.updateInnerArea(
Expand Down
Loading
Loading