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
5 changes: 5 additions & 0 deletions GDevelop.js/Bindings/Bindings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,11 @@ interface ObjectsContainer {
[Value] VectorObjectFolderOrObject GetAllObjectFolderOrObjects();
[Ref] ObjectGroupsContainer GetObjectGroups();

void SerializeObjectsTo([Ref] SerializerElement element);
void UnserializeObjectsFrom([Ref] Project project, [Const, Ref] SerializerElement element);
void SerializeFoldersTo([Ref] SerializerElement element);
void UnserializeFoldersFrom([Ref] Project project, [Const, Ref] SerializerElement element);

[Const, Value] DOMString FREE_GetTypeOfBehavior(
[Const, Ref] ObjectsContainer layout,
[Const] DOMString name,
Expand Down
4 changes: 4 additions & 0 deletions GDevelop.js/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,10 @@ export class ObjectsContainer extends EmscriptenObject {
getRootFolder(): ObjectFolderOrObject;
getAllObjectFolderOrObjects(): VectorObjectFolderOrObject;
getObjectGroups(): ObjectGroupsContainer;
serializeObjectsTo(element: SerializerElement): void;
unserializeObjectsFrom(project: Project, element: SerializerElement): void;
serializeFoldersTo(element: SerializerElement): void;
unserializeFoldersFrom(project: Project, element: SerializerElement): void;
getTypeOfBehavior(layout: ObjectsContainer, name: string, searchInGroups: boolean): string;
getTypeOfObject(layout: ObjectsContainer, name: string, searchInGroups: boolean): string;
getBehaviorsOfObject(layout: ObjectsContainer, name: string, searchInGroups: boolean): VectorString;
Expand Down
4 changes: 4 additions & 0 deletions GDevelop.js/types/gdobjectscontainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ declare class gdObjectsContainer {
getRootFolder(): gdObjectFolderOrObject;
getAllObjectFolderOrObjects(): gdVectorObjectFolderOrObject;
getObjectGroups(): gdObjectGroupsContainer;
serializeObjectsTo(element: gdSerializerElement): void;
unserializeObjectsFrom(project: gdProject, element: gdSerializerElement): void;
serializeFoldersTo(element: gdSerializerElement): void;
unserializeFoldersFrom(project: gdProject, element: gdSerializerElement): void;
getTypeOfBehavior(layout: gdObjectsContainer, name: string, searchInGroups: boolean): string;
getTypeOfObject(layout: gdObjectsContainer, name: string, searchInGroups: boolean): string;
getBehaviorsOfObject(layout: gdObjectsContainer, name: string, searchInGroups: boolean): gdVectorString;
Expand Down
23 changes: 23 additions & 0 deletions newIDE/app/scripts/import-libGD.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ if (shell.test('-f', path.join(sourceDirectory, 'libGD.js'))) {
);

const getBranchFromGitRef = gitRef => {
// Prefer a remote-tracking branch that already contains this commit:
// some build/deployment setups reuse a git checkout across builds and
// only reset it to the new commit, without renaming the local branch to
// match - so the local branch below can be a leftover, unrelated name.
// A commit that was just pushed is normally only "contained" in the
// remote branch(es) it was pushed to, so this is a more reliable source
// of truth than the local branch name whenever it's available.
const containingBranchesString = shell.exec(
`git branch -r --contains "${gitRef}"`,
{ silent: true }
);
if (!containingBranchesString.stderr && !containingBranchesString.code) {
const containingBranch = (containingBranchesString.stdout || '')
.split('\n')
.map(line => line.trim())
.filter(Boolean)[0];
if (containingBranch) {
// Strip the remote name prefix ("origin/development" -> "development").
const branchName = containingBranch.replace(/^[^/]+\//, '');
if (branchName) return branchName;
}
}

const branchShellString = shell.exec(
`git rev-parse --abbrev-ref "${gitRef}"`,
{
Expand Down
45 changes: 21 additions & 24 deletions newIDE/app/src/CompactPropertiesEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ import {
getDisabled,
} from '../PropertiesEditor';

export type FieldModificationContext = {| +fieldName?: string |};

type Props = {|
onInstancesModified?: Instances => void,
onInstancesModified?: (Instances, ?FieldModificationContext) => void,
onRefreshAllFields: () => void,
instances: Instances,
schema: Schema,
Expand Down Expand Up @@ -196,19 +198,14 @@ const CompactPropertiesEditor = ({
const forceUpdate = useForceUpdate();

const onFieldChanged = React.useCallback(
({
instances,
hasImpactOnAllOtherFields,
}: {|
instances: Instances,
hasImpactOnAllOtherFields: ?boolean,
|}) => {
({ instances, field }: {| instances: Instances, field: Field |}) => {
// This properties editor is dealing with fields that are
// responsible to update their state (see field.setValue).

if (unsavedChanges) unsavedChanges.triggerUnsavedChanges();
if (onInstancesModified) onInstancesModified(instances);
if (hasImpactOnAllOtherFields) {
if (onInstancesModified)
onInstancesModified(instances, { fieldName: field.name || undefined });
if (field.hasImpactOnAllOtherFields) {
// $FlowFixMe[constant-condition]
if (onRefreshAllFields) onRefreshAllFields();
}
Expand Down Expand Up @@ -257,7 +254,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand Down Expand Up @@ -289,7 +286,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
},
disabled: getDisabled({ instances, field, mixedValues }),
Expand All @@ -300,7 +297,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => onClickEndAdornment(i));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
},
getValueFromDisplayedValue: field.getValueFromDisplayedValue,
Expand Down Expand Up @@ -365,7 +362,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, rgbString));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand All @@ -392,7 +389,7 @@ const CompactPropertiesEditor = ({
);
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand All @@ -416,7 +413,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand All @@ -436,7 +433,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, text || ''));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
value={
Expand Down Expand Up @@ -479,7 +476,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue || ''));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
},

Expand All @@ -491,7 +488,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => onClickEndAdornment(i));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
},
};
Expand Down Expand Up @@ -575,7 +572,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, parseFloat(newValue) || 0));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand All @@ -597,7 +594,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue || ''));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand Down Expand Up @@ -685,7 +682,7 @@ const CompactPropertiesEditor = ({
);
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
},
};
Expand Down Expand Up @@ -734,7 +731,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand Down Expand Up @@ -775,7 +772,7 @@ const CompactPropertiesEditor = ({
instances.forEach(i => setValue(i, newValue));
onFieldChanged({
instances,
hasImpactOnAllOtherFields: field.hasImpactOnAllOtherFields,
field,
});
}}
disabled={getDisabled({ instances, field, mixedValues })}
Expand Down
16 changes: 16 additions & 0 deletions newIDE/app/src/EmbeddedGame/EmbeddedGameFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ let onSetCameraState:
let onChangeViewPosition:
| null
| ((command: ChangeViewPositionCommand) => void) = null;
let onFocusEmbeddedGameFrame: null | (() => boolean) = null;

export const setEmbeddedGameFramePreviewLocation = ({
previewIndexHtmlLocation,
Expand Down Expand Up @@ -165,6 +166,15 @@ export const changeViewPosition = (command: ChangeViewPositionCommand) => {
onChangeViewPosition(command);
};

/**
* Give the keyboard focus to the embedded game frame, so the in-game
* editor shortcuts work. Return false if there is no frame to focus.
*/
export const focusEmbeddedGameFrame = (): boolean => {
if (!onFocusEmbeddedGameFrame) return false;
return onFocusEmbeddedGameFrame();
};

const logSwitchingInfo = ({
editorId,
sceneName,
Expand Down Expand Up @@ -493,6 +503,12 @@ export const EmbeddedGameFrame = ({
});
});
};
onFocusEmbeddedGameFrame = () => {
const iframe = iframeRef.current;
if (!iframe || !iframe.contentWindow) return false;
iframe.contentWindow.focus();
return true;
};
},
[
previewDebuggerServer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import * as React from 'react';
import { Trans } from '@lingui/macro';
import { type I18n as I18nType } from '@lingui/core';
import { type FieldModificationContext } from '../../CompactPropertiesEditor';

import CompactPropertiesEditor, {
Separator,
Expand Down Expand Up @@ -117,7 +118,10 @@ type Props = {|
projectScopedContainersAccessor: ProjectScopedContainersAccessor,
instances: Array<gdInitialInstance>,
editObjectInPropertiesPanel: string => void,
onInstancesModified?: (Array<gdInitialInstance>) => void,
onInstancesModified?: (
Array<gdInitialInstance>,
?FieldModificationContext
) => void,
onGetInstanceSize: gdInitialInstance => [number, number, number],
editInstanceVariables: gdInitialInstance => void,
unsavedChanges?: ?UnsavedChanges,
Expand Down
78 changes: 53 additions & 25 deletions newIDE/app/src/InstancesEditor/InstancesRenderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,57 @@ export default class InstancesRenderer {
return this._basicProfilingCounters;
}

_getOrCreateLayerRenderer(
layer: gdLayer,
// $FlowFixMe[value-as-type]
pixiRenderer: PIXI.Renderer
): LayerRenderer {
const layerName = layer.getName();
let layerRenderer = this.layersRenderers[layerName];
if (!layerRenderer) {
this.layersRenderers[layerName] = layerRenderer = new LayerRenderer({
project: this.project,
globalObjectsContainer: this.globalObjectsContainer,
objectsContainer: this.objectsContainer,
instances: this.instances,
viewPosition: this.viewPosition,
layer: layer,
onInstanceClicked: this.onInstanceClicked,
onInstanceRightClicked: this.onInstanceRightClicked,
onInstanceDoubleClicked: this.onInstanceDoubleClicked,
onOverInstance: this.onOverInstance,
onOutInstance: this.onOutInstance,
onMoveInstance: this.onMoveInstance,
onMoveInstanceEnd: this.onMoveInstanceEnd,
onDownInstance: this.onDownInstance,
onUpInstance: this.onUpInstance,
pixiRenderer: pixiRenderer,
showObjectInstancesIn3D: this._showObjectInstancesIn3D,
});
this.pixiContainer.addChild(layerRenderer.getPixiContainer());
}
return layerRenderer;
}

/**
* Create the renderers of the layers that don't have one yet. They are
* normally created lazily at the first render: call this to measure
* instances (see `getInstanceMeasurer`) before it happened - for example
* right after the renderers were remounted, as the measurer falls back
* to a zero-sized rectangle at the instance origin without them.
*/
ensureLayerRenderersExist(
// $FlowFixMe[value-as-type]
pixiRenderer: PIXI.Renderer
) {
for (let i = 0; i < this.layersContainer.getLayersCount(); i++) {
this._getOrCreateLayerRenderer(
this.layersContainer.getLayerAt(i),
pixiRenderer
);
}
}

render(
// $FlowFixMe[value-as-type]
pixiRenderer: PIXI.Renderer,
Expand Down Expand Up @@ -232,31 +283,8 @@ export default class InstancesRenderer {

for (let i = 0; i < this.layersContainer.getLayersCount(); i++) {
const layer = this.layersContainer.getLayerAt(i);
const layerName = layer.getName();

let layerRenderer = this.layersRenderers[layerName];
if (!layerRenderer) {
this.layersRenderers[layerName] = layerRenderer = new LayerRenderer({
project: this.project,
globalObjectsContainer: this.globalObjectsContainer,
objectsContainer: this.objectsContainer,
instances: this.instances,
viewPosition: this.viewPosition,
layer: layer,
onInstanceClicked: this.onInstanceClicked,
onInstanceRightClicked: this.onInstanceRightClicked,
onInstanceDoubleClicked: this.onInstanceDoubleClicked,
onOverInstance: this.onOverInstance,
onOutInstance: this.onOutInstance,
onMoveInstance: this.onMoveInstance,
onMoveInstanceEnd: this.onMoveInstanceEnd,
onDownInstance: this.onDownInstance,
onUpInstance: this.onUpInstance,
pixiRenderer: pixiRenderer,
showObjectInstancesIn3D: this._showObjectInstancesIn3D,
});
this.pixiContainer.addChild(layerRenderer.getPixiContainer());
}

const layerRenderer = this._getOrCreateLayerRenderer(layer, pixiRenderer);

// /!\ Objects representing layers can be deleted at any moment and replaced
// by new one, for example when two layers are swapped.
Expand Down
Loading
Loading