Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
5b84c0c
Fix a memory corruption when updating an extension without function f…
D8H Jun 9, 2026
0ce410a
Fix possible mistakes when the AI tries to manipulate events (#8689)
ClementPasteau Jun 9, 2026
e4f85fb
Fix a crash when opening an extension tab where the function tree is …
D8H Jun 10, 2026
8417eac
Add script to submit an appx to the Microsoft Store (Partner Center) …
4ian Jun 10, 2026
258a541
Fix build of games with parameter or property resources in custom ext…
D8H Jun 11, 2026
33dd671
Fix an error when building a project that uses object variables (#8697)
D8H Jun 11, 2026
b5d1a17
Fix TypeScript error in submit-appx-to-microsoft-store.js (#8698)
4ian Jun 11, 2026
5735730
[Auto PR] Update translations (#8683)
github-actions[bot] Jun 11, 2026
a7325d4
Merge chat/build modes into one + rework first creation experience (#…
ClementPasteau Jun 11, 2026
359379b
[Auto PR] Update translations (#8700)
github-actions[bot] Jun 11, 2026
7d9e558
Fix event changes applied at the same path clobbering each other (#8702)
4ian Jun 12, 2026
6d9b57f
Display group properties in the side panel when a group is selected (…
D8H Jun 12, 2026
cd77fcb
[Auto PR] Update translations (#8703)
github-actions[bot] Jun 12, 2026
98ae195
Fix property title layout in the extension editor on mobile (#8706)
D8H Jun 12, 2026
03ad84a
Suggestions from the AI do not block the input anymore (#8705)
ClementPasteau Jun 12, 2026
91dfd50
[Auto PR] Update translations (#8704)
github-actions[bot] Jun 12, 2026
94a542d
Fix custom object with circular dependencies no longer shown as disab…
D8H Jun 12, 2026
bfff067
Improve hints when inspecting or positioning an object in 3D (#8707)
ClementPasteau Jun 12, 2026
969c3ba
[Auto PR] Update translations (#8709)
github-actions[bot] Jun 12, 2026
6ad57c0
Rework polling interval to introduce backoff (#8715)
4ian Jun 15, 2026
3fe88ca
Fix expression type selector choices (#8720)
D8H Jun 15, 2026
26cfcdc
Fix invalid object parameter when copy-pasting a function from a cust…
D8H Jun 15, 2026
d1905f8
Fix allow to to add behavior parameters without needing to declare al…
D8H Jun 15, 2026
6044bd9
Allow hiding AI form in the New Project Dialog (#8719)
ClementPasteau Jun 15, 2026
4290999
Fix project loading when 2 extensions uses each other custom objects …
D8H Jun 15, 2026
dcc7047
Fix extra padding at bottom of some dialogs
4ian Jun 15, 2026
4c5ab58
handle Fulfilment problem report tool call (#8722)
ClementPasteau Jun 16, 2026
f6872bd
Migrate Spine extension to @esotericsoftware/spine-pixi-v7 (#8595)
malec-palec Jun 16, 2026
c5c1901
Fix the type of variables added from the drop-down menu (#8725)
D8H Jun 16, 2026
be10577
multiple improvements of the UX of the AI unique mode (#8726)
ClementPasteau Jun 16, 2026
83622d4
[Auto PR] Update translations (#8717)
github-actions[bot] Jun 16, 2026
4278901
Fix textures broken because of wrong import (#8728)
ClementPasteau Jun 17, 2026
b584df4
Fix Spine upgrade wrongly breaking require calls (#8730)
ClementPasteau Jun 17, 2026
8881547
[Auto PR] Update translations (#8729)
github-actions[bot] Jun 17, 2026
7785fd6
Fix 2D put instance tool stacking objects in some cases (#8732)
ClementPasteau Jun 17, 2026
5fd50e5
Bump newIDE version
4ian Jun 17, 2026
e325803
Adjust button icon/label spacings (#8731)
LuniMoon Jun 17, 2026
7df3a3b
Improve Instance list panel design (#8573)
LuniMoon Jun 17, 2026
9cf3242
Fix being able to select fonts & atlas on iOS (#8736)
ClementPasteau Jun 18, 2026
a83cdd4
Fix group variables not refreshing when selecting another group (#8739)
D8H Jun 19, 2026
f5ea284
Better warnings when positioning instances with tools (#8738)
ClementPasteau Jun 19, 2026
79d10bf
Small improvements when object is renamed or created without asset (#…
ClementPasteau Jun 19, 2026
83af7b6
Ai can set a scene as first (#8742)
ClementPasteau Jun 19, 2026
1854715
Feedback when setting first scene (#8743)
ClementPasteau Jun 19, 2026
6bdddb5
Fix Tabs hover & drop not working all the time (#8746)
ClementPasteau Jun 22, 2026
7860c22
Fix initial value displayed for optional Boolean parameters with defa…
ClementPasteau Jun 22, 2026
b0b5554
Better management of undo/redo and unsaved notification dot for ForEa…
ClementPasteau Jun 22, 2026
c822d4f
New simplified design for subscription dialog (#8744)
4ian Jun 22, 2026
b5c44d9
Fix possible crashes when serializing large projects (#8749)
ClementPasteau Jun 22, 2026
8301365
Improve the editor typing (#8735)
D8H Jun 22, 2026
3358d5e
Fix showing default parameter values as errored in the event sheet (#…
ClementPasteau Jun 23, 2026
c73ce6f
Save state extended (#8752)
ClementPasteau Jun 23, 2026
f8bcccf
[Auto PR] Update translations (#8747)
github-actions[bot] Jun 23, 2026
2aa0fde
Fix checking resource types on every parameter when launching preview…
ClementPasteau Jun 23, 2026
008cf80
Improve metrics to follow usage trends (creating/editing projects) (#…
LuniMoon Jun 24, 2026
7bb2416
Fix instance creation error message (#8759)
4ian Jun 24, 2026
b13ccf3
Collapse Physics world properties by default in the scene properties …
D8H Jun 24, 2026
4d5ea2f
Allow to change behavior property values on object instances from the…
D8H Jun 25, 2026
387e8c3
Prevent tab closing when renaming Scene, Extensions, External events …
ClementPasteau Jun 25, 2026
1cb5562
[Auto PR] Update translations (#8755)
github-actions[bot] Jun 25, 2026
4db3fd3
Fix empty number properties of behavior initial value (#8763)
D8H Jun 25, 2026
733c560
Fix behavior overriding for Physics2, Physics3D, Multiplayer and Save…
D8H Jun 25, 2026
d365cbe
Merge origin/master into feature/breakpoints
malec-palec Jun 25, 2026
0fafa68
Consolidate preview CDP snippets into a single file
malec-palec Jun 25, 2026
194a2f4
Inline JSDoc typedefs and trim comments in PreviewWindow.js
malec-palec Jun 25, 2026
4ab1b78
Extract breakpoint session logic out of EventsSheet
malec-palec Jun 25, 2026
13387fe
Register local-variable containers explicitly for the debugger
malec-palec Jun 25, 2026
e948397
Align beta editor with GDevelop 5.6.270 (keep build-editor.yml)
malec-palec Jul 1, 2026
92c15b9
Merge branch 'feature/breakpoints' into release/beta-editor-5.6.270
malec-palec Jul 1, 2026
15747f2
Trigger build-editor workflow on PR merge, not every push to release/…
malec-palec Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
33 changes: 24 additions & 9 deletions .github/workflows/build-editor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the GDevelop desktop editor and publish a GitHub prerelease on every
# push to release/beta-editor.
# Build the GDevelop desktop editor and publish a GitHub prerelease whenever a
# pull request is merged into release/beta-editor.
#
# Pipeline:
# 1) build-gdevelop-js (Linux): compiles GDevelop.js (libGD.js / libGD.wasm)
Expand All @@ -19,29 +19,32 @@
#
# Heavy steps (emsdk, libGD build, npm installs, electron-builder, release
# creation, installer upload) are gated by the DRY_RUN env below. Default is
# "false" on this branch so every push produces installers and a prerelease.
# "false" on this branch so every merge produces installers and a prerelease.
# Set DRY_RUN to "true" temporarily to exercise the workflow without building.
#
# Concurrency: rapid consecutive pushes cancel in-flight runs for the same
# branch - the newest push is what we want to ship.
# Concurrency: rapid consecutive merges cancel in-flight runs for the same
# target branch - the newest merge is what we want to ship.
#
# Required permissions: contents: write (create tags, releases, upload
# assets). Provided by the default GITHUB_TOKEN on the fork; no PAT needed.
#
# Not intended to be merged to master - lives on the `release/beta-editor`
# branch only so upstream sync is not disturbed. Since workflow_dispatch is
# not available for workflows that do not exist on the default branch, the
# only trigger is push to release/beta-editor.
# only trigger is a merged pull request targeting release/beta-editor (a
# closed-but-not-merged PR, e.g. rejected/closed without merging, is ignored
# via the per-job `if:` check below).

name: Build Editor (Windows & macOS)

on:
push:
pull_request:
types: [closed]
branches:
- release/beta-editor

concurrency:
group: build-editor-${{ github.ref }}
group: build-editor-${{ github.event.pull_request.base.ref }}
cancel-in-progress: true

permissions:
Expand All @@ -59,12 +62,17 @@ env:
jobs:
build-gdevelop-js:
name: Build GDevelop.js (Linux)
if: github.event.pull_request.merged == true
runs-on: ubuntu-24.04
outputs:
build_version: ${{ steps.version.outputs.value }}
steps:
# Check out the actual merge commit landed on the base branch (not the
# ephemeral refs/pull/:number/merge test-merge ref) so the build reflects
# exactly what is now on release/beta-editor.
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 1

# Version format: <upstream>-beta.<github.run_number>. Upstream base is read
Expand Down Expand Up @@ -148,6 +156,7 @@ jobs:
# does nothing.
prepare-release:
name: Prepare GitHub prerelease
if: github.event.pull_request.merged == true
needs: build-gdevelop-js
runs-on: ubuntu-latest
steps:
Expand All @@ -156,13 +165,15 @@ jobs:
- uses: actions/checkout@v4
if: ${{ env.DRY_RUN != 'true' }}
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 0

- name: Create empty prerelease
if: ${{ env.DRY_RUN != 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: v${{ needs.build-gdevelop-js.outputs.build_version }}
TARGET_SHA: ${{ github.event.pull_request.merge_commit_sha }}
shell: bash
run: |
if gh release view "$TAG" >/dev/null 2>&1; then
Expand All @@ -172,7 +183,7 @@ jobs:
--prerelease \
--title "$TAG" \
--generate-notes \
--target "${{ github.sha }}"
--target "$TARGET_SHA"
fi

- name: Dry-run summary
Expand All @@ -184,6 +195,7 @@ jobs:

build-editor-windows:
name: Build Editor (Windows)
if: github.event.pull_request.merged == true
needs: [build-gdevelop-js, prepare-release]
runs-on: windows-latest
env:
Expand All @@ -196,6 +208,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 1

- uses: actions/setup-node@v4
Expand Down Expand Up @@ -286,6 +299,7 @@ jobs:

build-editor-macos:
name: Build Editor (macOS)
if: github.event.pull_request.merged == true
needs: [build-gdevelop-js, prepare-release]
runs-on: macos-latest
env:
Expand All @@ -305,6 +319,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
fetch-depth: 1

- uses: actions/setup-node@v4
Expand Down
15 changes: 13 additions & 2 deletions Core/GDCore/IDE/Events/InstructionSentenceFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,20 @@ InstructionSentenceFormatter::GetAsFormattedText(
TextFormatting format;
format.userData = firstParamIndex;

const gd::ParameterMetadata &parameterMetadata =
metadata.GetParameter(firstParamIndex);
const gd::String &parameterValue =
instr.GetParameter(firstParamIndex).GetPlainString();
// Use the default value when the parameter is left empty, so that the
// displayed text matches what is actually generated as code (see
// `gd::ParameterMetadataTools::IterateOverParametersWithIndex`).
const gd::String &parameterValueOrDefault =
parameterValue.empty() && parameterMetadata.IsOptional()
? parameterMetadata.GetDefaultValue()
: parameterValue;

gd::String text = GetFormattedParameterValue(
instr.GetParameter(firstParamIndex).GetPlainString(),
metadata.GetParameter(firstParamIndex).GetType());
parameterValueOrDefault, parameterMetadata.GetType());
std::replace(text.Raw().begin(),
text.Raw().end(),
'\n',
Expand Down
19 changes: 6 additions & 13 deletions Core/GDCore/IDE/Events/UsedExtensionsFinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
namespace gd {

void UsedExtensionsResult::AddUsedExtension(const gd::PlatformExtension& extension) {
if (extension.GetName().empty()) {
// The extension was not found and `extension` is
// `gd::MetadataProvider::badExtension`.
return;
}
usedExtensions.insert(extension.GetName());

usedSourceFiles.insert(usedSourceFiles.end(),
Expand Down Expand Up @@ -216,20 +221,8 @@ void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
if (node.child) node.child->Visit(*this);
};

// Add extensions bound to Objects/Behaviors/Functions
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode &node) {
auto type = gd::ExpressionTypeFinder::GetType(
project.GetCurrentPlatform(), GetProjectScopedContainers(), rootType, node);
if (gd::ParameterMetadata::IsObject(type) ||
GetObjectsContainersList().HasObjectOrGroupNamed(node.identifierName)) {
// An object or object variable is used.
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), node.identifierName);
result.AddUsedExtension(metadata.GetExtension());
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
result.AddUsedIncludeFiles(includeFile);
}
}
// Object parameters or object variables won't help detect extension usages.
};

void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
Expand Down
28 changes: 15 additions & 13 deletions Core/GDCore/IDE/InstructionValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ ParameterValidationResult InstructionValidator::ValidateParameter(
const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value) {
std::size_t parameterIndex) {
ParameterValidationResult result;

if (parameterIndex >= instruction.GetParametersCount() ||
Expand All @@ -45,11 +45,23 @@ ParameterValidationResult InstructionValidator::ValidateParameter(
? "number"
: parameterMetadata.GetType();

// The parameter value as stored in the project: empty for an unset optional
// parameter or for the base layer. This is what must be validated, as opposed
// to the value formatted for display which may show a default value.
const gd::String &value =
instruction.GetParameter(parameterIndex).GetPlainString();

bool shouldNotBeValidated = parameterType == "layer" && value.empty();
if (shouldNotBeValidated) {
return result; // Valid by default, no deprecation warning
}

// An optional parameter left empty is valid: the default value is used when
// generating the code.
if (parameterMetadata.IsOptional() && value.empty()) {
return result; // Valid by default, no deprecation warning
}

if (gd::ParameterMetadata::IsExpression("number", parameterType) ||
gd::ParameterMetadata::IsExpression("string", parameterType) ||
gd::ParameterMetadata::IsExpression("variable", parameterType)) {
Expand Down Expand Up @@ -113,9 +125,9 @@ bool InstructionValidator::IsParameterValid(
const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value) {
std::size_t parameterIndex) {
return ValidateParameter(platform, projectScopedContainers, instruction,
metadata, parameterIndex, value)
metadata, parameterIndex)
.isValid;
}

Expand All @@ -131,16 +143,6 @@ gd::String InstructionValidator::GetRootVariableName(const gd::String &name) {
: squareBracketPosition);
};

bool InstructionValidator::HasDeprecationWarnings(
const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value) {
return ValidateParameter(platform, projectScopedContainers, instruction,
metadata, parameterIndex, value)
.hasDeprecationWarning;
}

bool InstructionValidator::HasRequiredBehaviors(
const gd::Instruction &instruction,
const gd::InstructionMetadata &instructionMetadata,
Expand Down
20 changes: 4 additions & 16 deletions Core/GDCore/IDE/InstructionValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ class GD_CORE_API InstructionValidator {
* \brief Validate a parameter and check for deprecation warnings in a single
* pass.
*
* This method is more efficient than calling IsParameterValid and
* HasDeprecationWarnings separately as it only parses the expression once.
* The parameter value is read from the instruction itself, so the displayed
* (possibly defaulted) value doesn't have to be passed.
*/
static ParameterValidationResult ValidateParameter(
const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value);
std::size_t parameterIndex);

/**
* \brief Check if a parameter is valid.
Expand All @@ -59,19 +59,7 @@ class GD_CORE_API InstructionValidator {
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction,
const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value);

/**
* \brief Check if a parameter expression has deprecation warnings.
* \deprecated Use ValidateParameter instead for better performance when you
* also need to check for validity.
*/
static bool
HasDeprecationWarnings(const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction,
const InstructionMetadata &metadata,
std::size_t parameterIndex, const gd::String &value);
std::size_t parameterIndex);

static gd::String GetRootVariableName(const gd::String &name);

Expand Down
22 changes: 21 additions & 1 deletion Core/GDCore/IDE/Project/ArbitraryResourceWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,33 @@ bool ResourceWorkerInEventsWorker::DoVisitInstruction(gd::Instruction& instructi
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());

auto& resourcesContainersList = GetProjectScopedContainers().GetResourcesContainersList();

gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(),
[this, &instruction](
[this, &instruction, &resourcesContainersList](
const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterExpression, size_t parameterIndex,
const gd::String &lastObjectName, size_t lastObjectIndex) {
// Only resource parameters can refer to a resource. Prevent this expensive lookup for the
// many non-resource parameters (numbers, strings, objects, expressions...).
if (!parameterMetadata.GetValueTypeMetadata().IsResource()) {
return;
}

const String& parameterValue = parameterExpression.GetPlainString();
const auto resourceSourceType =
resourcesContainersList.GetResourcesContainerSourceType(
parameterValue);
// The actual resources referred by parameters or properties into
// events of extensions are detected on the instructions or objects
// that use these extensions.
if (resourceSourceType ==
gd::ResourcesContainer::SourceType::Properties ||
resourceSourceType ==
gd::ResourcesContainer::SourceType::Parameters) {
return;
}
if (parameterMetadata.GetType() == "fontResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeFont(updatedParameterValue);
Expand Down
2 changes: 1 addition & 1 deletion Core/GDCore/IDE/Project/ArbitraryResourceWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class GD_CORE_API ArbitraryResourceWorker {
* Launch the specified resource worker on every resource referenced in the
* events.
*/
class ResourceWorkerInEventsWorker : public gd::ArbitraryEventsWorker {
class ResourceWorkerInEventsWorker : public gd::ArbitraryEventsWorkerWithContext {
public:
ResourceWorkerInEventsWorker(const gd::Project &project_,
gd::ArbitraryResourceWorker &worker_)
Expand Down
Loading
Loading