mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
26 Commits
experiment
...
object-cap
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d0dd8b8a18 | ||
![]() |
e60545c146 | ||
![]() |
4225df8203 | ||
![]() |
34495bbdb5 | ||
![]() |
968c6be9d7 | ||
![]() |
3b28cc6c63 | ||
![]() |
8c83677671 | ||
![]() |
5154936baf | ||
![]() |
2311d94207 | ||
![]() |
b47d38d75b | ||
![]() |
592c5555c3 | ||
![]() |
05671dd8b8 | ||
![]() |
9be969b263 | ||
![]() |
47835c7a99 | ||
![]() |
aff102e52f | ||
![]() |
715287abef | ||
![]() |
3c80a5d7da | ||
![]() |
f840a337ce | ||
![]() |
03186b66fb | ||
![]() |
483d768962 | ||
![]() |
568b2cd129 | ||
![]() |
d1b2a4d9d2 | ||
![]() |
40a194656f | ||
![]() |
a8fafef48e | ||
![]() |
3cfd831d45 | ||
![]() |
b305acddba |
@@ -62,10 +62,9 @@ jobs:
|
||||
|
||||
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
|
||||
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing).
|
||||
# To test signing the code in the CI, add "export CSC_FOR_PULL_REQUEST=true && " before the command.
|
||||
- run:
|
||||
name: Build GDevelop IDE
|
||||
command: export CSC_FOR_PULL_REQUEST=true && export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && CI=false npm run build -- --mac --publish=never
|
||||
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && CI=false npm run build -- --mac --publish=never
|
||||
|
||||
- run:
|
||||
name: Clean dist folder to keep only installers/binaries.
|
||||
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"image": "mcr.microsoft.com/devcontainers/universal:2",
|
||||
"onCreateCommand": "cd newIDE/app && npm install && cd ../electron-app && npm install",
|
||||
"forwardPorts": [3000],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vscode.cpptools",
|
||||
"flowtype.flow-for-vscode"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
8
.github/workflows/build-storybook.yml
vendored
8
.github/workflows/build-storybook.yml
vendored
@@ -9,10 +9,6 @@ name: Build Storybook
|
||||
on:
|
||||
# Launch on all commits.
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**" # Don't run on new tags
|
||||
# Allows to run this workflow manually from the Actions tab,
|
||||
# to publish on Chromatic (not done by default).
|
||||
workflow_dispatch:
|
||||
@@ -28,8 +24,8 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "npm"
|
||||
cache-dependency-path: "newIDE/app/package-lock.json"
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
|
||||
- name: Configure AWS Credentials
|
||||
uses: aws-actions/configure-aws-credentials@v2
|
||||
|
10
.github/workflows/extract-translations.yml
vendored
10
.github/workflows/extract-translations.yml
vendored
@@ -4,10 +4,6 @@ name: Extract translations
|
||||
on:
|
||||
# Execute for all commits (to ensure translations extraction works)
|
||||
push:
|
||||
branches:
|
||||
- "**"
|
||||
tags-ignore:
|
||||
- "**" # Don't run on new tags
|
||||
# Allows to run this workflow manually from the Actions tab.
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -19,14 +15,14 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "npm"
|
||||
cache-dependency-path: "newIDE/app/package-lock.json"
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
|
||||
- name: Install gettext
|
||||
run: sudo apt update && sudo apt install gettext -y
|
||||
|
||||
- name: Install newIDE dependencies
|
||||
run: npm ci
|
||||
run: npm install
|
||||
working-directory: newIDE/app
|
||||
|
||||
- name: Extract translations
|
||||
|
6
.github/workflows/update-translations.yml
vendored
6
.github/workflows/update-translations.yml
vendored
@@ -7,8 +7,6 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags-ignore:
|
||||
- "**" # Don't run on new tags
|
||||
# Allows to run this workflow manually from the Actions tab.
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -20,8 +18,8 @@ jobs:
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: "npm"
|
||||
cache-dependency-path: "newIDE/app/package-lock.json"
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'newIDE/app/package-lock.json'
|
||||
|
||||
- name: Install gettext
|
||||
run: sudo apt update && sudo apt install gettext -y
|
||||
|
257
.vscode/settings.json
vendored
257
.vscode/settings.json
vendored
@@ -1,134 +1,131 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.associations": {
|
||||
"*.idl": "java",
|
||||
"Fastfile": "ruby",
|
||||
"iosfwd": "cpp",
|
||||
"functional": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"random": "cpp",
|
||||
"__config": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"exception": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"new": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"complex": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"memory": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"hashtable": "cpp",
|
||||
"tuple": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"deque": "cpp",
|
||||
"iterator": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"queue": "cpp",
|
||||
"regex": "cpp",
|
||||
"set": "cpp",
|
||||
"stack": "cpp",
|
||||
"string": "cpp",
|
||||
"vector": "cpp",
|
||||
"iostream": "cpp",
|
||||
"__functional_03": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__tree": "cpp",
|
||||
"bitset": "cpp",
|
||||
"__bit_reference": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"fstream": "cpp",
|
||||
"ios": "cpp",
|
||||
"__locale": "cpp",
|
||||
"valarray": "cpp",
|
||||
"freeglut_spaceball.c": "cpp",
|
||||
"__tuple": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"hash_set": "cpp",
|
||||
"system_error": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"__functional_base": "cpp",
|
||||
"__functional_base_03": "cpp",
|
||||
"chrono": "cpp",
|
||||
"ratio": "cpp",
|
||||
"atomic": "cpp",
|
||||
"locale": "cpp",
|
||||
"string_view": "cpp",
|
||||
"__string": "cpp",
|
||||
"cstring": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"mutex": "cpp",
|
||||
"__hash": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"numeric": "cpp",
|
||||
"__memory": "cpp",
|
||||
"__errc": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"bit": "cpp",
|
||||
"optional": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"xfacet": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"xlocale": "cpp",
|
||||
"xlocinfo": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"xloctime": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xstddef": "cpp",
|
||||
"xstring": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xmemory0": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"__bits": "cpp",
|
||||
"__verbose_abort": "cpp",
|
||||
"variant": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
"Binaries/Output": true,
|
||||
"GDJS/Runtime-dist": true,
|
||||
"docs": true,
|
||||
"newIDE/electron-app/dist": true,
|
||||
"newIDE/app/build": true,
|
||||
"newIDE/app/resources/GDJS": true,
|
||||
"newIDE/electron-app/app/www": true
|
||||
},
|
||||
// Support for Flowtype (for newIDE):
|
||||
"javascript.validate.enable": false,
|
||||
"flow.useNPMPackagedFlow": true,
|
||||
"files.associations": {
|
||||
"*.idl": "java",
|
||||
"Fastfile": "ruby",
|
||||
"iosfwd": "cpp",
|
||||
"functional": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"random": "cpp",
|
||||
"__config": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"exception": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"new": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"complex": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"memory": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"hashtable": "cpp",
|
||||
"tuple": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"deque": "cpp",
|
||||
"iterator": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"queue": "cpp",
|
||||
"regex": "cpp",
|
||||
"set": "cpp",
|
||||
"stack": "cpp",
|
||||
"string": "cpp",
|
||||
"vector": "cpp",
|
||||
"iostream": "cpp",
|
||||
"__functional_03": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__tree": "cpp",
|
||||
"bitset": "cpp",
|
||||
"__bit_reference": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"fstream": "cpp",
|
||||
"ios": "cpp",
|
||||
"__locale": "cpp",
|
||||
"valarray": "cpp",
|
||||
"freeglut_spaceball.c": "cpp",
|
||||
"__tuple": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"hash_set": "cpp",
|
||||
"system_error": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"__functional_base": "cpp",
|
||||
"__functional_base_03": "cpp",
|
||||
"chrono": "cpp",
|
||||
"ratio": "cpp",
|
||||
"atomic": "cpp",
|
||||
"locale": "cpp",
|
||||
"string_view": "cpp",
|
||||
"__string": "cpp",
|
||||
"cstring": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"mutex": "cpp",
|
||||
"__hash": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"numeric": "cpp",
|
||||
"__memory": "cpp",
|
||||
"__errc": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"bit": "cpp",
|
||||
"optional": "cpp",
|
||||
"filesystem": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"xfacet": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xiosbase": "cpp",
|
||||
"xlocale": "cpp",
|
||||
"xlocinfo": "cpp",
|
||||
"xlocmon": "cpp",
|
||||
"xlocnum": "cpp",
|
||||
"xloctime": "cpp",
|
||||
"xmemory": "cpp",
|
||||
"xstddef": "cpp",
|
||||
"xstring": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xmemory0": "cpp",
|
||||
"memory_resource": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
"Binaries/Output": true,
|
||||
"GDJS/Runtime-dist": true,
|
||||
"docs": true,
|
||||
"newIDE/electron-app/dist": true,
|
||||
"newIDE/app/build": true,
|
||||
"newIDE/app/resources/GDJS": true,
|
||||
"newIDE/electron-app/app/www": true
|
||||
},
|
||||
// Support for Flowtype (for newIDE):
|
||||
"javascript.validate.enable": false,
|
||||
"flow.useNPMPackagedFlow": true,
|
||||
|
||||
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
|
||||
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
|
||||
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
|
||||
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_
|
||||
endif()
|
||||
|
||||
#Activate C++11
|
||||
set(CMAKE_CXX_STANDARD 11) # Upgrading to C++17 would need to remove usage of bind2nd (should be easy).
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Mark some warnings as errors
|
||||
@@ -77,8 +77,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
-Wno-unused-private-field
|
||||
|
||||
# Make as much warnings considered as errors as possible (only one for now).
|
||||
-Werror=return-stack-address
|
||||
-Werror=return-type)
|
||||
-Werror=return-stack-address)
|
||||
endif()
|
||||
|
||||
# Define common directories:
|
||||
|
@@ -45,39 +45,10 @@ ForEachChildVariableEvent::GetAllActionsVectors() const {
|
||||
return allActions;
|
||||
}
|
||||
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() {
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("scenevar");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&iterableVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&valueIteratorVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&keyIteratorVariableName, metadata));
|
||||
|
||||
return allExpressionsWithMetadata;
|
||||
}
|
||||
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() const {
|
||||
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("scenevar");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&iterableVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&valueIteratorVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&keyIteratorVariableName, metadata));
|
||||
|
||||
return allExpressionsWithMetadata;
|
||||
}
|
||||
|
||||
void ForEachChildVariableEvent::SerializeTo(SerializerElement& element) const {
|
||||
element.AddChild("iterableVariableName").SetValue(iterableVariableName.GetPlainString());
|
||||
element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName.GetPlainString());
|
||||
element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName.GetPlainString());
|
||||
element.AddChild("iterableVariableName").SetValue(iterableVariableName);
|
||||
element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName);
|
||||
element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName);
|
||||
gd::EventsListSerialization::SerializeInstructionsTo(
|
||||
conditions, element.AddChild("conditions"));
|
||||
gd::EventsListSerialization::SerializeInstructionsTo(
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#define FOREACHCHILDVARIABLEEVENT_H
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Expression.h"
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class Project;
|
||||
@@ -45,7 +44,7 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
|
||||
*
|
||||
* It is the structure variable that will be iterated on.
|
||||
*/
|
||||
const gd::String& GetIterableVariableName() const { return iterableVariableName.GetPlainString(); };
|
||||
const gd::String& GetIterableVariableName() const { return iterableVariableName; };
|
||||
|
||||
/**
|
||||
* \brief Set the iterable variable name attached to the event.
|
||||
@@ -57,15 +56,15 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
|
||||
/**
|
||||
* \brief Get the value iterator variable attached to the event.
|
||||
*
|
||||
* It is the variable that will contain the value of the
|
||||
* It is the variable that will contain the value of the
|
||||
* iterable's child being iterated on.
|
||||
*/
|
||||
const gd::String& GetValueIteratorVariableName() const { return valueIteratorVariableName.GetPlainString(); };
|
||||
const gd::String& GetValueIteratorVariableName() const { return valueIteratorVariableName; };
|
||||
|
||||
/**
|
||||
* \brief Set the value iterator variable attached to the event.
|
||||
*
|
||||
* It is the variable that will contain the value of the
|
||||
* It is the variable that will contain the value of the
|
||||
* iterable's child being iterated on.
|
||||
*/
|
||||
void SetValueIteratorVariableName(gd::String newName) { valueIteratorVariableName = newName; };
|
||||
@@ -73,15 +72,15 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
|
||||
/**
|
||||
* \brief Get the key iterator variable attached to the event.
|
||||
*
|
||||
* It is the variable that will contain the name of the
|
||||
* It is the variable that will contain the name of the
|
||||
* iterable's child being iterated on.
|
||||
*/
|
||||
const gd::String& GetKeyIteratorVariableName() const { return keyIteratorVariableName.GetPlainString(); };
|
||||
const gd::String& GetKeyIteratorVariableName() const { return keyIteratorVariableName; };
|
||||
|
||||
/**
|
||||
* \brief Set the key iterator variable attached to the event.
|
||||
*
|
||||
* It is the variable that will contain the name of the
|
||||
* It is the variable that will contain the name of the
|
||||
* iterable's child being iterated on.
|
||||
*/
|
||||
void SetKeyIteratorVariableName(gd::String newName) { keyIteratorVariableName = newName; };
|
||||
@@ -93,19 +92,14 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
|
||||
virtual std::vector<gd::InstructionsList*> GetAllConditionsVectors();
|
||||
virtual std::vector<gd::InstructionsList*> GetAllActionsVectors();
|
||||
|
||||
virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
GetAllExpressionsWithMetadata() const;
|
||||
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
GetAllExpressionsWithMetadata();
|
||||
|
||||
virtual void SerializeTo(SerializerElement& element) const;
|
||||
virtual void UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element);
|
||||
|
||||
private:
|
||||
gd::Expression valueIteratorVariableName;
|
||||
gd::Expression keyIteratorVariableName;
|
||||
gd::Expression iterableVariableName;
|
||||
gd::String valueIteratorVariableName;
|
||||
gd::String keyIteratorVariableName;
|
||||
gd::String iterableVariableName;
|
||||
gd::InstructionsList conditions;
|
||||
gd::InstructionsList actions;
|
||||
gd::EventsList events;
|
||||
|
@@ -64,6 +64,12 @@ class GD_CORE_API ForEachEvent : public gd::BaseEvent {
|
||||
virtual void UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element);
|
||||
|
||||
std::vector<gd::Expression*> GetAllObjectExpressions() {
|
||||
std::vector<gd::Expression*> allObjectExpressions;
|
||||
allObjectExpressions.push_back(&objectsToPick);
|
||||
return allObjectExpressions;
|
||||
}
|
||||
|
||||
private:
|
||||
gd::Expression objectsToPick;
|
||||
gd::InstructionsList conditions;
|
||||
|
@@ -131,36 +131,30 @@ void LinkEvent::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
void LinkEvent::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
|
||||
|
||||
SetTarget(element.GetChild("target", 0, "Scene").GetValue().GetString());
|
||||
|
||||
// Compatibility with GD <= 5
|
||||
if (element.HasChild("include", "Limites")) {
|
||||
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
|
||||
if (includeElement.HasAttribute("includeAll")) {
|
||||
// Compatibility with GDevelop <= 4.0.92
|
||||
if (includeElement.GetBoolAttribute("includeAll", true)) {
|
||||
SetIncludeAllEvents();
|
||||
} else {
|
||||
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
|
||||
includeElement.GetIntAttribute("end"));
|
||||
}
|
||||
if (includeElement.HasAttribute("includeAll")) {
|
||||
// Compatibility with GDevelop <= 4.0.92
|
||||
if (includeElement.GetBoolAttribute("includeAll", true)) {
|
||||
SetIncludeAllEvents();
|
||||
} else {
|
||||
// GDevelop > 4.0.92
|
||||
IncludeConfig config = static_cast<IncludeConfig>(
|
||||
includeElement.GetIntAttribute("includeConfig", 0));
|
||||
if (config == INCLUDE_ALL)
|
||||
SetIncludeAllEvents();
|
||||
else if (config == INCLUDE_EVENTS_GROUP)
|
||||
SetIncludeEventsGroup(includeElement.GetStringAttribute("eventsGroup"));
|
||||
else if (config == INCLUDE_BY_INDEX)
|
||||
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
|
||||
includeElement.GetIntAttribute("end"));
|
||||
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
|
||||
includeElement.GetIntAttribute("end"));
|
||||
}
|
||||
} else {
|
||||
// Since GDevelop 5, links always include all events.
|
||||
SetIncludeAllEvents();
|
||||
// GDevelop > 4.0.92
|
||||
IncludeConfig config = static_cast<IncludeConfig>(
|
||||
includeElement.GetIntAttribute("includeConfig", 0));
|
||||
if (config == INCLUDE_ALL)
|
||||
SetIncludeAllEvents();
|
||||
else if (config == INCLUDE_EVENTS_GROUP)
|
||||
SetIncludeEventsGroup(includeElement.GetStringAttribute("eventsGroup"));
|
||||
else if (config == INCLUDE_BY_INDEX)
|
||||
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
|
||||
includeElement.GetIntAttribute("end"));
|
||||
}
|
||||
// end of compatibility code
|
||||
}
|
||||
|
||||
bool LinkEvent::AcceptVisitor(gd::EventVisitor &eventVisitor) {
|
||||
|
@@ -35,7 +35,7 @@ vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
RepeatEvent::GetAllExpressionsWithMetadata() {
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("number");
|
||||
auto metadata = gd::ParameterMetadata().SetType("expression");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&repeatNumberExpression, metadata));
|
||||
|
||||
@@ -61,7 +61,7 @@ vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
RepeatEvent::GetAllExpressionsWithMetadata() const {
|
||||
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("number");
|
||||
auto metadata = gd::ParameterMetadata().SetType("expression");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&repeatNumberExpression, metadata));
|
||||
|
||||
|
@@ -15,48 +15,16 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void EffectsCodeGenerator::DoVisitObject(gd::Object &object) {
|
||||
auto &effects = object.GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
|
||||
auto &effect = effects.GetEffect(e);
|
||||
AddEffectIncludeFiles(effect);
|
||||
}
|
||||
};
|
||||
|
||||
void EffectsCodeGenerator::AddEffectIncludeFiles(const gd::Effect &effect) {
|
||||
// TODO: this browse all the extensions every time we're trying to find
|
||||
// a new effect. Might be a good idea to rework MetadataProvider to be
|
||||
// faster (not sure if it is a bottleneck at all though - but could be
|
||||
// for events code generation).
|
||||
const gd::EffectMetadata &effectMetadata =
|
||||
MetadataProvider::GetEffectMetadata(platform, effect.GetEffectType());
|
||||
|
||||
for (auto &includeFile : effectMetadata.GetIncludeFiles())
|
||||
includeFiles.insert(includeFile);
|
||||
};
|
||||
|
||||
void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
const gd::Platform &platform,
|
||||
gd::Project &project,
|
||||
std::set<gd::String> &includeFiles) {
|
||||
// TODO Add unit tests on this function.
|
||||
|
||||
// TODO Merge with UsedExtensionsFinder.
|
||||
// Default lights rely on the fact that UsedExtensionsFinder doesn't find
|
||||
// extension usages for effects. This has the happy side effect of not
|
||||
// including Three.js when no 3D object are in the scenes.
|
||||
// We need to make something explicit to avoid future bugs.
|
||||
|
||||
void ExposeProjectEffects(
|
||||
const gd::Project& project,
|
||||
const std::function<void(const gd::Effect& effect)>& worker) {
|
||||
// See also gd::Project::ExposeResources for a method that traverse the whole
|
||||
// project (this time for resources) and
|
||||
// WholeProjectRefactorer::ExposeProjectEvents.
|
||||
|
||||
EffectsCodeGenerator effectsCodeGenerator(platform, includeFiles);
|
||||
|
||||
// Add layouts effects
|
||||
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
||||
auto& layout = project.GetLayout(s);
|
||||
@@ -65,13 +33,47 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
auto& effects = layout.GetLayer(l).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
effectsCodeGenerator.AddEffectIncludeFiles(effect);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < layout.GetObjectsCount(); i++) {
|
||||
auto& object = layout.GetObject(i);
|
||||
auto& effects = object.GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add objects effects
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator);
|
||||
// Add global object effects
|
||||
for (std::size_t s = 0; s < project.GetObjectsCount(); s++) {
|
||||
auto& effects = project.GetObject(s).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
std::set<gd::String>& includeFiles) {
|
||||
ExposeProjectEffects(
|
||||
project, [&platform, &includeFiles](const gd::Effect& effect) {
|
||||
// TODO: this browse all the extensions every time we're trying to find
|
||||
// a new effect. Might be a good idea to rework MetadataProvider to be
|
||||
// faster (not sure if it is a bottleneck at all though - but could be
|
||||
// for events code generation).
|
||||
const gd::EffectMetadata& effectMetadata =
|
||||
MetadataProvider::GetEffectMetadata(platform,
|
||||
effect.GetEffectType());
|
||||
|
||||
for (auto& includeFile : effectMetadata.GetIncludeFiles())
|
||||
includeFiles.insert(includeFile);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,18 +3,16 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef GDCORE_EffectsCodeGenerator_H
|
||||
#define GDCORE_EffectsCodeGenerator_H
|
||||
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class Platform;
|
||||
class Effect;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -22,26 +20,16 @@ namespace gd {
|
||||
/**
|
||||
* \brief Internal class used to generate code from events
|
||||
*/
|
||||
class GD_CORE_API EffectsCodeGenerator : public ArbitraryObjectsWorker {
|
||||
public:
|
||||
class GD_CORE_API EffectsCodeGenerator {
|
||||
public:
|
||||
/**
|
||||
* \brief Add all the include files required by the project effects.
|
||||
*/
|
||||
static void GenerateEffectsIncludeFiles(const gd::Platform& platform,
|
||||
gd::Project& project,
|
||||
const gd::Project& project,
|
||||
std::set<gd::String>& includeFiles);
|
||||
|
||||
private:
|
||||
EffectsCodeGenerator(const gd::Platform &platform_,
|
||||
std::set<gd::String> &includeFiles_)
|
||||
: platform(platform_), includeFiles(includeFiles_){};
|
||||
|
||||
void AddEffectIncludeFiles(const gd::Effect& effect);
|
||||
|
||||
void DoVisitObject(gd::Object &object) override;
|
||||
|
||||
const gd::Platform &platform;
|
||||
std::set<gd::String> &includeFiles;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EffectsCodeGenerator_H
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -296,11 +295,17 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
gd::String objectInParameter =
|
||||
condition.GetParameter(pNb).GetPlainString();
|
||||
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) {
|
||||
auto& parameterObjectType = instrInfos.parameters[pNb].GetValueTypeMetadata().GetObjectType().GetName();
|
||||
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter) !=
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
} else if (!parameterObjectType.empty() && parameterObjectType !=
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter)) {
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -310,13 +315,16 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
gd::String objectName = condition.GetParameter(0).GetPlainString();
|
||||
if (!objectName.empty() && !instrInfos.parameters.empty()) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Set up the context
|
||||
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
|
||||
const ObjectMetadata& objInfo =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
|
||||
if (objInfo.IsSupportedBaseObjectCapability(
|
||||
instrInfos.GetRequiredBaseObjectCapability())) {
|
||||
AddIncludeFiles(objInfo.includeFiles);
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
@@ -333,14 +341,21 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
context);
|
||||
|
||||
context.SetNoCurrentObject();
|
||||
} else {
|
||||
conditionCode +=
|
||||
"/* Object with unsupported capability - skipped. */\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||
gd::String objectName = condition.GetParameter(0).GetPlainString();
|
||||
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(condition.GetParameter(1).GetPlainString());
|
||||
gd::String behaviorType =
|
||||
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
condition.GetParameter(1).GetPlainString());
|
||||
if (instrInfos.parameters.size() >= 2) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
const BehaviorMetadata& autoInfo =
|
||||
@@ -470,11 +485,18 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) {
|
||||
|
||||
auto& parameterObjectType = instrInfos.parameters[pNb].GetValueTypeMetadata().GetObjectType().GetName();
|
||||
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter) !=
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
} else if (!parameterObjectType.empty() && parameterObjectType !=
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter)) {
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -486,13 +508,16 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
|
||||
if (!instrInfos.parameters.empty()) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
|
||||
const ObjectMetadata& objInfo =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
|
||||
if (objInfo.IsSupportedBaseObjectCapability(
|
||||
instrInfos.GetRequiredBaseObjectCapability())) {
|
||||
AddIncludeFiles(objInfo.includeFiles);
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
@@ -509,15 +534,21 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
optionalAsyncCallbackName);
|
||||
|
||||
context.SetNoCurrentObject();
|
||||
} else {
|
||||
actionCode += "/* Object with unsupported capability - skipped. */\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||
gd::String objectName = action.GetParameter(0).GetPlainString();
|
||||
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(action.GetParameter(1).GetPlainString());
|
||||
gd::String behaviorType =
|
||||
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
action.GetParameter(1).GetPlainString());
|
||||
|
||||
if (instrInfos.parameters.size() >= 2) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
const BehaviorMetadata& autoInfo =
|
||||
@@ -893,6 +924,41 @@ gd::String EventsCodeGenerator::ConvertToStringExplicit(
|
||||
return "\"" + ConvertToString(plainString) + "\"";
|
||||
}
|
||||
|
||||
std::vector<gd::String> EventsCodeGenerator::ExpandObjectsName(
|
||||
const gd::String& objectName,
|
||||
const EventsCodeGenerationContext& context) const {
|
||||
// Note: this logic is duplicated in EventsContextAnalyzer::ExpandObjectsName
|
||||
std::vector<gd::String> realObjects;
|
||||
if (globalObjectsAndGroups.GetObjectGroups().Has(objectName))
|
||||
realObjects = globalObjectsAndGroups.GetObjectGroups()
|
||||
.Get(objectName)
|
||||
.GetAllObjectsNames();
|
||||
else if (objectsAndGroups.GetObjectGroups().Has(objectName))
|
||||
realObjects =
|
||||
objectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
else
|
||||
realObjects.push_back(objectName);
|
||||
|
||||
// If current object is present, use it and only it.
|
||||
if (find(realObjects.begin(),
|
||||
realObjects.end(),
|
||||
context.GetCurrentObject()) != realObjects.end()) {
|
||||
realObjects.clear();
|
||||
realObjects.push_back(context.GetCurrentObject());
|
||||
}
|
||||
|
||||
// Ensure that all returned objects actually exists.
|
||||
for (std::size_t i = 0; i < realObjects.size();) {
|
||||
if (!objectsAndGroups.HasObjectNamed(realObjects[i]) &&
|
||||
!globalObjectsAndGroups.HasObjectNamed(realObjects[i]))
|
||||
realObjects.erase(realObjects.begin() + i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return realObjects;
|
||||
}
|
||||
|
||||
void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
|
||||
for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) {
|
||||
if (events[eId].CanHaveSubEvents()) // Process sub events, if any
|
||||
@@ -909,8 +975,6 @@ void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
|
||||
*/
|
||||
void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) {
|
||||
for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) {
|
||||
if (listEvent[i].IsDisabled()) continue;
|
||||
|
||||
listEvent[i].Preprocess(*this, listEvent, i);
|
||||
if (i <
|
||||
listEvent.GetEventsCount()) { // Be sure that that there is still an
|
||||
@@ -994,7 +1058,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
// Prepare call
|
||||
// Add a static_cast if necessary
|
||||
gd::String objectFunctionCallNamePart =
|
||||
(!instrInfos.parameters[0].GetExtraInfo().empty())
|
||||
(!instrInfos.parameters[0].GetValueTypeMetadata().GetObjectType().IsBaseObject())
|
||||
? "static_cast<" + objInfo.className + "*>(" +
|
||||
GetObjectListName(objectName, context) + "[i])->" +
|
||||
instrInfos.codeExtraInformation.functionCallName
|
||||
@@ -1208,24 +1272,12 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
|
||||
return argumentsStr;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesContainer& propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor& property,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "getProperty" + property.GetName() + "()";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "getParameter" + parameter.GetName() + "()";
|
||||
}
|
||||
|
||||
EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
|
||||
const gd::Layout& layout,
|
||||
const gd::Platform& platform_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project_, layout)),
|
||||
globalObjectsAndGroups(project_),
|
||||
objectsAndGroups(layout),
|
||||
hasProjectAndLayout(true),
|
||||
project(&project_),
|
||||
scene(&layout),
|
||||
@@ -1237,9 +1289,11 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
|
||||
|
||||
EventsCodeGenerator::EventsCodeGenerator(
|
||||
const gd::Platform& platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_)
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer& objectsAndGroups_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsAndGroups(globalObjectsAndGroups_),
|
||||
objectsAndGroups(objectsAndGroups_),
|
||||
hasProjectAndLayout(false),
|
||||
project(nullptr),
|
||||
scene(nullptr),
|
||||
|
@@ -13,14 +13,12 @@
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
namespace gd {
|
||||
class EventsList;
|
||||
class Expression;
|
||||
class Project;
|
||||
class Layout;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class ExternalEvents;
|
||||
class ParameterMetadata;
|
||||
class ObjectMetadata;
|
||||
@@ -59,7 +57,8 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* objects/groups and platform
|
||||
*/
|
||||
EventsCodeGenerator(const gd::Platform& platform,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_);
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer& objectsAndGroups_);
|
||||
virtual ~EventsCodeGenerator(){};
|
||||
|
||||
/**
|
||||
@@ -327,12 +326,18 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
bool ErrorOccurred() const { return errorOccurred; };
|
||||
|
||||
const gd::ObjectsContainersList& GetObjectsContainersList() const {
|
||||
return projectScopedContainers.GetObjectsContainersList();
|
||||
};
|
||||
/**
|
||||
* \brief Get the global objects/groups used for code generation.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
|
||||
return globalObjectsAndGroups;
|
||||
}
|
||||
|
||||
const gd::ProjectScopedContainers& GetProjectScopedContainers() const {
|
||||
return projectScopedContainers;
|
||||
/**
|
||||
* \brief Get the objects/groups used for code generation.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetObjectsAndGroups() const {
|
||||
return objectsAndGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,6 +363,22 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
const gd::Platform& GetPlatform() const { return platform; }
|
||||
|
||||
/**
|
||||
* \brief Convert a group name to the full list of objects contained in the
|
||||
* group.
|
||||
*
|
||||
* Get a list containing the "real" objects name when the events refers to \a
|
||||
* objectName :<br> If \a objectName is really an object, the list will only
|
||||
* contains \a objectName unchanged.<br> If \a objectName is a group, the list
|
||||
* will contains all the objects of the group.<br> If \a objectName is the
|
||||
* "current" object in the context ( i.e: The object being used for launching
|
||||
* an action... ), none of the two rules below apply, and the list will only
|
||||
* contains the context "current" object name.
|
||||
*/
|
||||
std::vector<gd::String> ExpandObjectsName(
|
||||
const gd::String& objectName,
|
||||
const EventsCodeGenerationContext& context) const;
|
||||
|
||||
/**
|
||||
* \brief Get the maximum depth of custom conditions reached during code
|
||||
* generation.
|
||||
@@ -545,10 +566,6 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
return ".getChild(" + ConvertToStringExplicit(childName) + ")";
|
||||
};
|
||||
|
||||
virtual gd::String GenerateVariableValueAs(const gd::String& type) {
|
||||
return type == "string" ? ".getAsString()" : ".getAsNumber()";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate the code to get the child of a variable,
|
||||
* using generated the expression.
|
||||
@@ -577,15 +594,6 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
return "fakeObjectListOf_" + objectName;
|
||||
}
|
||||
|
||||
virtual gd::String GeneratePropertyGetter(const gd::PropertiesContainer& propertiesContainer,
|
||||
const gd::NamedPropertyDescriptor& property,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
virtual gd::String GenerateParameterGetter(const gd::ParameterMetadata& parameter,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
/**
|
||||
* \brief Generate the code to reference an object which is
|
||||
* in an empty/null state.
|
||||
@@ -769,7 +777,8 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
|
||||
const gd::Platform& platform; ///< The platform being used.
|
||||
|
||||
gd::ProjectScopedContainers projectScopedContainers;
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups;
|
||||
const gd::ObjectsContainer& objectsAndGroups;
|
||||
|
||||
bool hasProjectAndLayout; ///< true only if project and layout are valid
|
||||
///< references. If false, they should not be used.
|
||||
|
@@ -7,7 +7,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
|
||||
@@ -26,9 +25,6 @@
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/VariablesContainersList.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
|
||||
@@ -51,7 +47,8 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
}
|
||||
|
||||
gd::ExpressionValidator validator(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetProjectScopedContainers(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType);
|
||||
node->Visit(validator);
|
||||
if (!validator.GetFatalErrors().empty()) {
|
||||
@@ -103,94 +100,34 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
// This "translation" from the type to an enum could be avoided
|
||||
// if all types were moved to an enum.
|
||||
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType,
|
||||
node);
|
||||
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
// The node is a variable inside an expression waiting for a *variable* to be returned, not its value.
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: ((type == "scenevar")
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
rootObjectName,
|
||||
node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, scope, context, objectName);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
} else {
|
||||
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
|
||||
|
||||
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.name, [&](){
|
||||
// Generate the code to access the object variables.
|
||||
|
||||
// Defer generation of the access to the object and variable to the child,
|
||||
// once we know the name of the variable.
|
||||
objectNameToUseForVariableAccessor = node.name;
|
||||
if (node.child) node.child->Visit(*this);
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
if (!codeGenerator.HasProjectAndLayout()) {
|
||||
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
|
||||
output += GenerateDefaultValue(type);
|
||||
return;
|
||||
}
|
||||
|
||||
// This could be adapted in the future if more scopes are supported.
|
||||
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
|
||||
if (codeGenerator.GetProjectScopedContainers().GetVariablesContainersList().GetBottomMostVariablesContainer()->Has(node.name)) {
|
||||
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
|
||||
}
|
||||
|
||||
output += codeGenerator.GenerateGetVariable(node.name, scope, context, "");
|
||||
if (node.child) node.child->Visit(*this);
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
// Properties are not supported.
|
||||
output += GenerateDefaultValue(type);
|
||||
}, [&]() {
|
||||
// Parameters are not supported.
|
||||
output += GenerateDefaultValue(type);
|
||||
}, [&]() {
|
||||
// The identifier does not represents a variable (or a child variable), or not at least an existing
|
||||
// one, nor an object variable. It's invalid.
|
||||
output += GenerateDefaultValue(type);
|
||||
});
|
||||
}
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: ((type == "scenevar")
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootObjectName,
|
||||
node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, scope, context, objectName);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
|
||||
VariableAccessorNode& node) {
|
||||
if (!objectNameToUseForVariableAccessor.empty()) {
|
||||
// Use the name of the object passed by the parent, as we need both to access an object variable.
|
||||
output += codeGenerator.GenerateGetVariable(node.name,
|
||||
gd::EventsCodeGenerator::OBJECT_VARIABLE, context, objectNameToUseForVariableAccessor);
|
||||
|
||||
// We have accessed an object variable, from now we can continue accessing the child variables
|
||||
// (including using the bracket notation).
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
} else {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.name);
|
||||
}
|
||||
output += codeGenerator.GenerateVariableAccessor(node.name);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) {
|
||||
if (!objectNameToUseForVariableAccessor.empty()) {
|
||||
// Bracket notation can't be used to directly access a variable of an object (`MyObject["MyVariable"]`).
|
||||
// This would be rejected by the ExpressionValidator.
|
||||
output += codeGenerator.GenerateBadVariable();
|
||||
return;
|
||||
}
|
||||
|
||||
ExpressionCodeGenerator generator("string", "", codeGenerator, context);
|
||||
node.expression->Visit(generator);
|
||||
output +=
|
||||
@@ -200,10 +137,10 @@ void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType,
|
||||
node);
|
||||
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
output +=
|
||||
codeGenerator.GenerateObject(node.identifierName, type, context);
|
||||
@@ -216,7 +153,8 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootObjectName,
|
||||
node);
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
@@ -224,60 +162,30 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
} else {
|
||||
const auto& variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList();
|
||||
const auto& propertiesContainersList = codeGenerator.GetProjectScopedContainers().GetPropertiesContainersList();
|
||||
const auto& parametersVectorsList = codeGenerator.GetProjectScopedContainers().GetParametersVectorsList();
|
||||
|
||||
// The node represents a variable, property, parameter or an object.
|
||||
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.identifierName, [&]() {
|
||||
// Generate the code to access the object variable.
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE, context, node.identifierName);
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
if (!codeGenerator.HasProjectAndLayout()) {
|
||||
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
|
||||
output += GenerateDefaultValue(type);
|
||||
return;
|
||||
}
|
||||
|
||||
// This could be adapted in the future if more scopes are supported at runtime.
|
||||
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
|
||||
if (variablesContainersList.GetBottomMostVariablesContainer()->Has(node.identifierName)) {
|
||||
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
|
||||
}
|
||||
|
||||
output += codeGenerator.GenerateGetVariable(node.identifierName, scope, context, "");
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
const auto& propertiesContainerAndProperty = propertiesContainersList.Get(node.identifierName);
|
||||
|
||||
output += codeGenerator.GeneratePropertyGetter(
|
||||
propertiesContainerAndProperty.first, propertiesContainerAndProperty.second, type, context);
|
||||
}, [&]() {
|
||||
const auto& parameter = gd::ParameterMetadataTools::Get(parametersVectorsList, node.identifierName);
|
||||
output += codeGenerator.GenerateParameterGetter(parameter, type, context);
|
||||
}, [&]() {
|
||||
// The identifier does not represents a variable (or a child variable), or not at least an existing
|
||||
// one, nor an object variable. It's invalid.
|
||||
output += GenerateDefaultValue(type);
|
||||
});
|
||||
} else if (node.childIdentifierName.empty()) {
|
||||
output += "/* Error during generation, unrecognized identifier type: " +
|
||||
codeGenerator.ConvertToString(type) + " with value " +
|
||||
codeGenerator.ConvertToString(node.identifierName) + " */ " +
|
||||
codeGenerator.ConvertToStringExplicit(node.identifierName);
|
||||
}
|
||||
else {
|
||||
// This is for function names that are put in IdentifierNode
|
||||
// because the type is needed to tell them apart from variables.
|
||||
output += GenerateDefaultValue(type);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitFunctionCallNode(FunctionCallNode& node) {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType,
|
||||
node);
|
||||
|
||||
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
|
||||
codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
node);
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
@@ -328,6 +236,11 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
|
||||
const gd::String& objectName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata) {
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups =
|
||||
codeGenerator.GetGlobalObjectsAndGroups();
|
||||
const gd::ObjectsContainer& objectsAndGroups =
|
||||
codeGenerator.GetObjectsAndGroups();
|
||||
|
||||
codeGenerator.AddIncludeFiles(
|
||||
expressionMetadata.GetIncludeFiles());
|
||||
|
||||
@@ -348,14 +261,17 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
|
||||
|
||||
// Get object(s) concerned by function call
|
||||
std::vector<gd::String> realObjects =
|
||||
codeGenerator.GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
codeGenerator.ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
gd::String objectType = codeGenerator.GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
globalObjectsAndGroups, objectsAndGroups, realObjects[i]);
|
||||
const ObjectMetadata& objInfo = MetadataProvider::GetObjectMetadata(
|
||||
codeGenerator.GetPlatform(), objectType);
|
||||
|
||||
if (objInfo.IsSupportedBaseObjectCapability(
|
||||
expressionMetadata.GetRequiredBaseObjectCapability())) {
|
||||
codeGenerator.AddIncludeFiles(objInfo.includeFiles);
|
||||
functionOutput = codeGenerator.GenerateObjectFunctionCall(
|
||||
realObjects[i],
|
||||
@@ -364,6 +280,10 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
|
||||
parametersCode,
|
||||
functionOutput,
|
||||
context);
|
||||
} else {
|
||||
// Do nothing, skipping objects not supporting the capability required by
|
||||
// this expression.
|
||||
}
|
||||
}
|
||||
|
||||
return functionOutput;
|
||||
@@ -374,6 +294,11 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
|
||||
const gd::String& behaviorName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata) {
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups =
|
||||
codeGenerator.GetGlobalObjectsAndGroups();
|
||||
const gd::ObjectsContainer& objectsAndGroups =
|
||||
codeGenerator.GetObjectsAndGroups();
|
||||
|
||||
codeGenerator.AddIncludeFiles(
|
||||
expressionMetadata.GetIncludeFiles());
|
||||
|
||||
@@ -392,11 +317,12 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
|
||||
|
||||
// Get object(s) concerned by function call
|
||||
std::vector<gd::String> realObjects =
|
||||
codeGenerator.GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
codeGenerator.ExpandObjectsName(objectName, context);
|
||||
|
||||
gd::String functionOutput = GenerateDefaultValue(type);
|
||||
|
||||
gd::String behaviorType = codeGenerator.GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
||||
gd::String behaviorType = gd::GetTypeOfBehavior(
|
||||
globalObjectsAndGroups, objectsAndGroups, behaviorName);
|
||||
const BehaviorMetadata& autoInfo = MetadataProvider::GetBehaviorMetadata(
|
||||
codeGenerator.GetPlatform(), behaviorType);
|
||||
|
||||
@@ -432,7 +358,8 @@ gd::String ExpressionCodeGenerator::GenerateParametersCodes(
|
||||
if (!parameterMetadata.IsCodeOnly()) {
|
||||
if (nonCodeOnlyParameterIndex < parameters.size()) {
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootObjectName,
|
||||
*parameters[nonCodeOnlyParameterIndex].get());
|
||||
ExpressionCodeGenerator generator(parameterMetadata.GetType(), objectName, codeGenerator, context);
|
||||
@@ -502,7 +429,8 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType,
|
||||
node);
|
||||
output += GenerateDefaultValue(type);
|
||||
@@ -511,7 +439,8 @@ void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
|
||||
void ExpressionCodeGenerator::OnVisitObjectFunctionNameNode(
|
||||
ObjectFunctionNameNode& node) {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
rootType,
|
||||
node);
|
||||
output += GenerateDefaultValue(type);
|
||||
|
@@ -102,7 +102,6 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters);
|
||||
|
||||
gd::String output;
|
||||
gd::String objectNameToUseForVariableAccessor;
|
||||
EventsCodeGenerator& codeGenerator;
|
||||
EventsCodeGenerationContext& context;
|
||||
const gd::String rootType;
|
||||
|
@@ -240,7 +240,7 @@ class GD_CORE_API BaseEvent {
|
||||
*/
|
||||
virtual void UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element){};
|
||||
|
||||
|
||||
virtual bool AcceptVisitor(gd::EventVisitor& eventVisitor);
|
||||
virtual void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const;
|
||||
///@}
|
||||
@@ -281,6 +281,15 @@ class GD_CORE_API BaseEvent {
|
||||
* \brief True if the event should be folded in the events editor.
|
||||
*/
|
||||
bool IsFolded() const { return folded; }
|
||||
|
||||
/**
|
||||
* \brief Return a list of all objects linked to the event.
|
||||
*/
|
||||
virtual std::vector<gd::Expression*> GetAllObjectExpressions() {
|
||||
std::vector<gd::Expression*> allObjectExpressions;
|
||||
return allObjectExpressions;
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
std::weak_ptr<gd::BaseEvent>
|
||||
|
@@ -19,10 +19,8 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
#include "GrammarTerminals.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace gd::GrammarTerminals;
|
||||
|
||||
namespace gd {
|
||||
|
||||
|
@@ -18,7 +18,6 @@
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
#include "GrammarTerminals.h"
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
@@ -29,8 +28,6 @@ class ExpressionMetadata;
|
||||
|
||||
namespace gd {
|
||||
|
||||
using namespace gd::GrammarTerminals;
|
||||
|
||||
/** \brief Parse an expression, returning a tree of node corresponding
|
||||
* to the parsed expression.
|
||||
*
|
||||
@@ -47,9 +44,14 @@ class GD_CORE_API ExpressionParser2 {
|
||||
virtual ~ExpressionParser2(){};
|
||||
|
||||
/**
|
||||
* Parse the given expression into a tree of nodes.
|
||||
* Parse the given expression with the specified type.
|
||||
*
|
||||
* \param expression The expression to parse.
|
||||
* \param type Type of the expression: "string", "number",
|
||||
* type supported by gd::ParameterMetadata::IsObject, types supported by
|
||||
* gd::ParameterMetadata::IsExpression or "unknown".
|
||||
* \param expression The expression to parse
|
||||
* \param objectName Specify the object name, only for the
|
||||
* case of "objectvar" type.
|
||||
*
|
||||
* \return The node representing the expression as a parsed tree.
|
||||
*/
|
||||
@@ -209,7 +211,7 @@ class GD_CORE_API ExpressionParser2 {
|
||||
}
|
||||
SkipIfChar(IsClosingParenthesis);
|
||||
return factor;
|
||||
} else if (CheckIfChar(IsAllowedInIdentifier)) {
|
||||
} else if (IsIdentifierAllowedChar()) {
|
||||
return Identifier();
|
||||
}
|
||||
|
||||
@@ -262,11 +264,12 @@ class GD_CORE_API ExpressionParser2 {
|
||||
} else if (CheckIfChar(IsDot)) {
|
||||
ExpressionParserLocation dotLocation = SkipChar();
|
||||
SkipAllWhitespaces();
|
||||
return ObjectFunctionOrBehaviorFunctionOrVariable(
|
||||
return ObjectFunctionOrBehaviorFunction(
|
||||
name, nameLocation, dotLocation);
|
||||
} else if (CheckIfChar(IsOpeningSquareBracket)) {
|
||||
return Variable(name, nameLocation);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
auto identifier = gd::make_unique<IdentifierNode>(name);
|
||||
identifier->location = ExpressionParserLocation(
|
||||
nameLocation.GetStartPosition(), GetCurrentPosition());
|
||||
@@ -312,7 +315,7 @@ class GD_CORE_API ExpressionParser2 {
|
||||
auto dotLocation = SkipChar();
|
||||
SkipAllWhitespaces();
|
||||
|
||||
auto identifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false);
|
||||
auto identifierAndLocation = ReadIdentifierName();
|
||||
auto child =
|
||||
gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
|
||||
child->child = VariableAccessorOrVariableBracketAccessor();
|
||||
@@ -352,11 +355,11 @@ class GD_CORE_API ExpressionParser2 {
|
||||
}
|
||||
|
||||
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
|
||||
ObjectFunctionOrBehaviorFunctionOrVariable(
|
||||
ObjectFunctionOrBehaviorFunction(
|
||||
const gd::String &parentIdentifier,
|
||||
const ExpressionParserLocation &parentIdentifierLocation,
|
||||
const ExpressionParserLocation &parentIdentifierDotLocation) {
|
||||
auto childIdentifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false);
|
||||
auto childIdentifierAndLocation = ReadIdentifierName();
|
||||
const gd::String &childIdentifierName = childIdentifierAndLocation.name;
|
||||
const auto &childIdentifierNameLocation =
|
||||
childIdentifierAndLocation.location;
|
||||
@@ -414,6 +417,12 @@ class GD_CORE_API ExpressionParser2 {
|
||||
|
||||
auto node = gd::make_unique<IdentifierNode>(
|
||||
parentIdentifier, childIdentifierName);
|
||||
if (!CheckIfChar(IsParameterSeparator) && !CheckIfChar(IsClosingParenthesis) && !IsEndReached()) {
|
||||
node->diagnostic = RaiseSyntaxError(
|
||||
_("An opening parenthesis (for an object expression), a double colon "
|
||||
"(:: for a behavior expression), a dot or an opening bracket (for "
|
||||
"a child variable) where expected."));
|
||||
}
|
||||
node->location = ExpressionParserLocation(
|
||||
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
|
||||
node->identifierNameLocation = parentIdentifierLocation;
|
||||
@@ -597,6 +606,95 @@ class GD_CORE_API ExpressionParser2 {
|
||||
return predicate(character);
|
||||
}
|
||||
|
||||
bool IsIdentifierAllowedChar() {
|
||||
if (currentPosition >= expression.size()) return false;
|
||||
gd::String::value_type character = expression[currentPosition];
|
||||
|
||||
// Quickly compare if the character is a number or ASCII character.
|
||||
if ((character >= '0' && character <= '9') ||
|
||||
(character >= 'A' && character <= 'Z') ||
|
||||
(character >= 'a' && character <= 'z'))
|
||||
return true;
|
||||
|
||||
// Otherwise do the full check against separators forbidden in identifiers.
|
||||
if (!IsParameterSeparator(character) && !IsDot(character) &&
|
||||
!IsQuote(character) && !IsBracket(character) &&
|
||||
!IsExpressionOperator(character) && !IsTermOperator(character)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsWhitespace(gd::String::value_type character) {
|
||||
return character == ' ' || character == '\n' || character == '\r';
|
||||
}
|
||||
|
||||
static bool IsParameterSeparator(gd::String::value_type character) {
|
||||
return character == ',';
|
||||
}
|
||||
|
||||
static bool IsDot(gd::String::value_type character) {
|
||||
return character == '.';
|
||||
}
|
||||
|
||||
static bool IsQuote(gd::String::value_type character) {
|
||||
return character == '"';
|
||||
}
|
||||
|
||||
static bool IsBracket(gd::String::value_type character) {
|
||||
return character == '(' || character == ')' || character == '[' ||
|
||||
character == ']' || character == '{' || character == '}';
|
||||
}
|
||||
|
||||
static bool IsOpeningParenthesis(gd::String::value_type character) {
|
||||
return character == '(';
|
||||
}
|
||||
|
||||
static bool IsClosingParenthesis(gd::String::value_type character) {
|
||||
return character == ')';
|
||||
}
|
||||
|
||||
static bool IsOpeningSquareBracket(gd::String::value_type character) {
|
||||
return character == '[';
|
||||
}
|
||||
|
||||
static bool IsClosingSquareBracket(gd::String::value_type character) {
|
||||
return character == ']';
|
||||
}
|
||||
|
||||
static bool IsExpressionEndingChar(gd::String::value_type character) {
|
||||
return character == ',' || IsClosingParenthesis(character) ||
|
||||
IsClosingSquareBracket(character);
|
||||
}
|
||||
|
||||
static bool IsExpressionOperator(gd::String::value_type character) {
|
||||
return character == '+' || character == '-' || character == '<' ||
|
||||
character == '>' || character == '?' || character == '^' ||
|
||||
character == '=' || character == '\\' || character == ':' ||
|
||||
character == '!';
|
||||
}
|
||||
|
||||
static bool IsUnaryOperator(gd::String::value_type character) {
|
||||
return character == '+' || character == '-';
|
||||
}
|
||||
|
||||
static bool IsTermOperator(gd::String::value_type character) {
|
||||
return character == '/' || character == '*';
|
||||
}
|
||||
|
||||
static bool IsNumberFirstChar(gd::String::value_type character) {
|
||||
return character == '.' || (character >= '0' && character <= '9');
|
||||
}
|
||||
|
||||
static bool IsNonZeroDigit(gd::String::value_type character) {
|
||||
return (character >= '1' && character <= '9');
|
||||
}
|
||||
|
||||
static bool IsZeroDigit(gd::String::value_type character) {
|
||||
return character == '0';
|
||||
}
|
||||
|
||||
bool IsNamespaceSeparator() {
|
||||
// Namespace separator is a special kind of delimiter as it is 2 characters
|
||||
// long
|
||||
@@ -613,13 +711,13 @@ class GD_CORE_API ExpressionParser2 {
|
||||
ExpressionParserLocation location;
|
||||
};
|
||||
|
||||
IdentifierAndLocation ReadIdentifierName(bool allowDeprecatedSpacesInName = true) {
|
||||
IdentifierAndLocation ReadIdentifierName() {
|
||||
gd::String name;
|
||||
size_t startPosition = currentPosition;
|
||||
while (currentPosition < expression.size() &&
|
||||
(CheckIfChar(IsAllowedInIdentifier)
|
||||
(IsIdentifierAllowedChar()
|
||||
// Allow whitespace in identifier name for compatibility
|
||||
|| (allowDeprecatedSpacesInName && expression[currentPosition] == ' '))) {
|
||||
|| expression[currentPosition] == ' ')) {
|
||||
name += expression[currentPosition];
|
||||
currentPosition++;
|
||||
}
|
||||
|
@@ -189,7 +189,7 @@ struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
|
||||
*
|
||||
* The name of a function to call on an object or the behavior,
|
||||
* for example: "MyObject.Function" or "MyObject.Physics".
|
||||
*
|
||||
*
|
||||
* A variable, potentially with accessor to its child,
|
||||
* for example: MyVariable or MyVariable.MyChild
|
||||
*/
|
||||
@@ -239,14 +239,13 @@ struct GD_CORE_API VariableAccessorOrVariableBracketAccessorNode : public Expres
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A variable, or object variable, with bracket accessor or at least 2 "dot" accessors.
|
||||
*
|
||||
* Example: `MyVariable["MyChildren"]` or `MyVariable.MyChildren.MyGrandChildren`.
|
||||
* Example: `MyObject["MyVariable"]` or `MyObject.MyVariable.MyChildren`.
|
||||
* \brief A variable with bracket accessor or at least 2 "dot" accessors.
|
||||
*
|
||||
* Example: MyVariable[MyChildren] or MyVariable.MyChildren.MyGranChildren.
|
||||
*
|
||||
* Other cases like "MyVariable" or "MyVariable.MyChildren" are IdentifierNode
|
||||
* to allow handling ambiguities.
|
||||
*
|
||||
*
|
||||
* \see gd::IdentifierNode
|
||||
* \see gd::VariableAccessorNode
|
||||
* \see gd::VariableBracketAccessorNode
|
||||
@@ -268,7 +267,7 @@ struct GD_CORE_API VariableNode : public FunctionCallOrObjectFunctionNameOrEmpty
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A direct accessor to a child variable. Example: MyChild
|
||||
* \brief A bracket accessor of a variable. Example: MyChild
|
||||
* in MyVariable.MyChild
|
||||
*/
|
||||
struct GD_CORE_API VariableAccessorNode
|
||||
@@ -286,7 +285,7 @@ struct GD_CORE_API VariableAccessorNode
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A bracket accessor to a child variable. Example: ["MyChild"]
|
||||
* \brief A bracket accessor of a variable. Example: ["MyChild"]
|
||||
* (in MyVariable["MyChild"]).
|
||||
*/
|
||||
struct GD_CORE_API VariableBracketAccessorNode
|
||||
@@ -304,10 +303,10 @@ struct GD_CORE_API VariableBracketAccessorNode
|
||||
/**
|
||||
* \brief The name of a function to call on an object or the behavior
|
||||
* For example: "MyObject.Physics::LinearVelocity".
|
||||
*
|
||||
*
|
||||
* Other cases like "MyObject.Function" or "MyObject.Physics" are IdentifierNode
|
||||
* to allow handling ambiguities.
|
||||
*
|
||||
*
|
||||
* \see gd::IdentifierNode
|
||||
*/
|
||||
struct GD_CORE_API ObjectFunctionNameNode
|
||||
|
@@ -1,118 +0,0 @@
|
||||
#pragma once
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* Contains functions to handle the grammar of the expressions accepted by GDevelop.
|
||||
*/
|
||||
namespace GrammarTerminals {
|
||||
|
||||
inline bool IsWhitespace(gd::String::value_type character) {
|
||||
return character == ' ' || character == '\n' || character == '\r';
|
||||
}
|
||||
|
||||
inline bool IsParameterSeparator(gd::String::value_type character) {
|
||||
return character == ',';
|
||||
}
|
||||
|
||||
inline bool IsDot(gd::String::value_type character) { return character == '.'; }
|
||||
|
||||
inline bool IsQuote(gd::String::value_type character) {
|
||||
return character == '"';
|
||||
}
|
||||
|
||||
inline bool IsBracket(gd::String::value_type character) {
|
||||
return character == '(' || character == ')' || character == '[' ||
|
||||
character == ']' || character == '{' || character == '}';
|
||||
}
|
||||
|
||||
inline bool IsOpeningParenthesis(gd::String::value_type character) {
|
||||
return character == '(';
|
||||
}
|
||||
|
||||
inline bool IsClosingParenthesis(gd::String::value_type character) {
|
||||
return character == ')';
|
||||
}
|
||||
|
||||
inline bool IsOpeningSquareBracket(gd::String::value_type character) {
|
||||
return character == '[';
|
||||
}
|
||||
|
||||
inline bool IsClosingSquareBracket(gd::String::value_type character) {
|
||||
return character == ']';
|
||||
}
|
||||
|
||||
inline bool IsExpressionEndingChar(gd::String::value_type character) {
|
||||
return character == ',' || IsClosingParenthesis(character) ||
|
||||
IsClosingSquareBracket(character);
|
||||
}
|
||||
|
||||
inline bool IsExpressionOperator(gd::String::value_type character) {
|
||||
return character == '+' || character == '-' || character == '<' ||
|
||||
character == '>' || character == '?' || character == '^' ||
|
||||
character == '=' || character == '\\' || character == ':' ||
|
||||
character == '!';
|
||||
}
|
||||
|
||||
inline bool IsUnaryOperator(gd::String::value_type character) {
|
||||
return character == '+' || character == '-';
|
||||
}
|
||||
|
||||
inline bool IsTermOperator(gd::String::value_type character) {
|
||||
return character == '/' || character == '*';
|
||||
}
|
||||
|
||||
inline bool IsNumberFirstChar(gd::String::value_type character) {
|
||||
return character == '.' || (character >= '0' && character <= '9');
|
||||
}
|
||||
|
||||
inline bool IsNonZeroDigit(gd::String::value_type character) {
|
||||
return (character >= '1' && character <= '9');
|
||||
}
|
||||
|
||||
inline bool IsZeroDigit(gd::String::value_type character) {
|
||||
return character == '0';
|
||||
}
|
||||
|
||||
inline bool IsAdditionalReservedCharacter(gd::String::value_type character) {
|
||||
// These characters are not part of the grammar - but are often used in programming language
|
||||
// and could become operators or part of the grammar one day.
|
||||
return character == '~' || character == '\'' || character == '%' ||
|
||||
character == '#' || character == '@' || character == '|' ||
|
||||
character == '&' || character == '`' || character == '$' ||
|
||||
character == ';';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given character can be used in an identifier. This is
|
||||
* any unicode character, except for:
|
||||
* `, . " () [] {} + - < > ? ^ = \ : ! / * ~ ' % # @ | & $ ;`
|
||||
* and backtick and whitespaces (space, line break, carriage return).
|
||||
*
|
||||
* This is loosely based on what is allowed in languages like JavaScript
|
||||
* (see https://mathiasbynens.be/notes/javascript-properties), without support
|
||||
* for unicode escape syntax, and allowing all unicode ranges. The only
|
||||
* disallowed characters are the one used for the grammar.
|
||||
*/
|
||||
inline bool IsAllowedInIdentifier(gd::String::value_type character) {
|
||||
// Quickly compare if the character is a number or ASCII character.
|
||||
if ((character >= '0' && character <= '9') ||
|
||||
(character >= 'A' && character <= 'Z') ||
|
||||
(character >= 'a' && character <= 'z'))
|
||||
return true;
|
||||
|
||||
// Otherwise do the full check against separators forbidden in identifiers.
|
||||
if (!IsParameterSeparator(character) && !IsDot(character) &&
|
||||
!IsQuote(character) && !IsBracket(character) &&
|
||||
!IsExpressionOperator(character) && !IsTermOperator(character) &&
|
||||
!IsWhitespace(character) && !IsAdditionalReservedCharacter(character)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace GrammarTerminals
|
||||
} // namespace gd
|
@@ -43,12 +43,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
|
||||
static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsWindowExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsResizableExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsScalableExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsFlippableExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsAnimatableExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsEffectExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsOpacityExtension(gd::PlatformExtension& extension);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -39,6 +39,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetIcon("res/actions/direction24_black.png");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
|
||||
.SetIcon("res/actions/scale24_black.png");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Scale"))
|
||||
.SetIcon("res/actions/scale24_black.png");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
|
||||
.SetIcon("res/conditions/animation24.png");
|
||||
|
||||
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
|
||||
"", _("Base object"), _("Base object"), "res/objeticon24.png");
|
||||
@@ -1261,7 +1265,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression", _("Target X position"))
|
||||
.AddParameter("expression", _("Target Y position"));
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("EnableEffect",
|
||||
_("Enable an object effect"),
|
||||
_("Enable an effect on the object"),
|
||||
@@ -1273,13 +1276,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("yesorno", _("Enable?"))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.SetRequiredBaseObjectCapability("effect");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("SetEffectDoubleParameter",
|
||||
_("Effect property (number)"),
|
||||
_("Change the value of a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("Effect parameter (number)"),
|
||||
_("Change the value of a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
@@ -1287,17 +1289,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("objectEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("expression", _("New value"))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.SetRequiredBaseObjectCapability("effect");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("SetEffectStringParameter",
|
||||
_("Effect property (string)"),
|
||||
_("Change the value (string) of a property of an effect.") +
|
||||
_("Effect parameter (string)"),
|
||||
_("Change the value (string) of a parameter of an effect.") +
|
||||
"\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
@@ -1305,16 +1306,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("objectEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("string", _("New value"))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.SetRequiredBaseObjectCapability("effect");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("SetEffectBooleanParameter",
|
||||
_("Effect property (enable or disable)"),
|
||||
_("Enable or disable a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("Effect parameter (enable or disable)"),
|
||||
_("Enable or disable a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Enable _PARAM2_ for effect _PARAM1_ of _PARAM0_: _PARAM3_"),
|
||||
_("Effects"),
|
||||
@@ -1322,12 +1322,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("yesorno", _("Enable this property"))
|
||||
.AddParameter("objectEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("yesorno", _("Enable?"))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.SetRequiredBaseObjectCapability("effect");
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("IsEffectEnabled",
|
||||
_("Effect is enabled"),
|
||||
_("Check if the effect on an object is enabled."),
|
||||
@@ -1338,7 +1337,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.SetRequiredBaseObjectCapability("effect");
|
||||
|
||||
obj.AddAction("SetIncludedInParentCollisionMask",
|
||||
_("Include in parent collision mask"),
|
||||
@@ -1683,6 +1682,297 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"",
|
||||
"res/actions/layer.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
// Instruction for Resizable capability.
|
||||
{
|
||||
obj.AddAction("SetWidth",
|
||||
_("Width"),
|
||||
_("Change the width of the object."),
|
||||
_("the width"),
|
||||
_("Size"),
|
||||
"res/actions/scaleWidth24_black.png",
|
||||
"res/actions/scaleWidth_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("resizable")
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRequiredBaseObjectCapability("resizable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Width",
|
||||
_("Width"),
|
||||
_("Compare the width of the object."),
|
||||
_("the width"),
|
||||
_("Size"),
|
||||
"res/conditions/scaleWidth24_black.png",
|
||||
"res/conditions/scaleWidth_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("resizable")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRequiredBaseObjectCapability("resizable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("SetHeight",
|
||||
_("Height"),
|
||||
_("Change the height of the object."),
|
||||
_("the height"),
|
||||
_("Size"),
|
||||
"res/actions/scaleHeight24_black.png",
|
||||
"res/actions/scaleHeight_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("resizable")
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRequiredBaseObjectCapability("resizable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Height",
|
||||
_("Height"),
|
||||
_("Compare the height of the object."),
|
||||
_("the height"),
|
||||
_("Size"),
|
||||
"res/conditions/scaleHeight24_black.png",
|
||||
"res/conditions/scaleHeight_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("resizable")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRequiredBaseObjectCapability("resizable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("SetSize",
|
||||
_("Size"),
|
||||
_("Change the size of an object."),
|
||||
_("Change the size of _PARAM0_: set to _PARAM1_ x _PARAM2_"),
|
||||
_("Size"),
|
||||
"res/actions/scale24_black.png",
|
||||
"res/actions/scale_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("resizable")
|
||||
.AddParameter("expression", _("Width"))
|
||||
.AddParameter("expression", _("Height"))
|
||||
.SetRequiredBaseObjectCapability("resizable")
|
||||
.MarkAsAdvanced();
|
||||
}
|
||||
// Instruction for Scalable capability.
|
||||
{
|
||||
obj.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"Scale",
|
||||
_("Scale"),
|
||||
_("the scale of the object (default scale is 1)"),
|
||||
_("the scale"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("scalable")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetRequiredBaseObjectCapability("scalable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"ScaleX",
|
||||
_("Scale on X axis"),
|
||||
_("the scale on X axis of the object (default scale is 1)"),
|
||||
_("the scale on X axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("scalable")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetRequiredBaseObjectCapability("scalable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"ScaleY",
|
||||
_("Scale on Y axis"),
|
||||
_("the scale on Y axis of the object (default scale is 1)"),
|
||||
_("the scale on Y axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("scalable")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.SetRequiredBaseObjectCapability("scalable")
|
||||
.MarkAsAdvanced();
|
||||
}
|
||||
// Instruction for Flippable capability.
|
||||
{
|
||||
obj.AddAction("FlipX",
|
||||
_("Flip the object horizontally"),
|
||||
_("Flip the object horizontally"),
|
||||
_("Flip horizontally _PARAM0_: _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/actions/flipX24.png",
|
||||
"res/actions/flipX.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("flippable")
|
||||
.AddParameter("yesorno", _("Activate flipping"))
|
||||
.SetRequiredBaseObjectCapability("flippable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("FlipY",
|
||||
_("Flip the object vertically"),
|
||||
_("Flip the object vertically"),
|
||||
_("Flip vertically _PARAM0_: _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/actions/flipY24.png",
|
||||
"res/actions/flipY.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("flippable")
|
||||
.AddParameter("yesorno", _("Activate flipping"))
|
||||
.SetRequiredBaseObjectCapability("flippable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("FlippedX",
|
||||
_("Horizontally flipped"),
|
||||
_("Check if the object is horizontally flipped"),
|
||||
_("_PARAM0_ is horizontally flipped"),
|
||||
_("Effects"),
|
||||
"res/actions/flipX24.png",
|
||||
"res/actions/flipX.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("flippable")
|
||||
.SetRequiredBaseObjectCapability("flippable");
|
||||
|
||||
obj.AddCondition("FlippedY",
|
||||
_("Vertically flipped"),
|
||||
_("Check if the object is vertically flipped"),
|
||||
_("_PARAM0_ is vertically flipped"),
|
||||
_("Effects"),
|
||||
"res/actions/flipY24.png",
|
||||
"res/actions/flipY.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("flippable")
|
||||
.SetRequiredBaseObjectCapability("flippable");
|
||||
}
|
||||
// Instruction for Animable capability.
|
||||
{
|
||||
obj.AddExpressionAndConditionAndAction(
|
||||
"number", "AnimationIndex",
|
||||
_("Animation (by number)"),
|
||||
_("the number of the animation played by the object (the number from "
|
||||
"the animations list)"),
|
||||
_("the number of the animation"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("SetAnimationName",
|
||||
_("Animation (by name)"),
|
||||
_("Change the animation played by the object, using the name of the "
|
||||
"animation."),
|
||||
_("Change the animation of _PARAM0_ to _PARAM1_"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png",
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("AnimationName",
|
||||
_("Animation (by name)"),
|
||||
_("Check the animation played by the object."),
|
||||
_("The animation of _PARAM0_ is _PARAM1_"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddExpression("AnimationName",
|
||||
_("Animation (by name)"),
|
||||
_("the name of animation played by the object"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.SetRequiredBaseObjectCapability("animable");
|
||||
|
||||
obj.AddAction("PauseAnimation", _("Pause the animation"),
|
||||
_("Pause the animation of the object"),
|
||||
_("Pause the animation of _PARAM0_"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png",
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("PlayAnimation", _("Resume the animation"),
|
||||
_("Resume the animation of the object"),
|
||||
_("Resume the animation of _PARAM0_"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png",
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddExpressionAndConditionAndAction(
|
||||
"number", "AnimationSpeedScale",
|
||||
_("Animation speed scale"),
|
||||
_("the animation speed scale (1 = the default speed, >1 = faster and "
|
||||
"<1 = slower)"),
|
||||
_("the animation speed scale"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.UseStandardParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Speed scale")))
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("IsAnimationPaused",
|
||||
_("Animation paused"),
|
||||
_("Check if the animation of an object is paused."),
|
||||
_("The animation of _PARAM0_ is paused"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("HasAnimationEnded",
|
||||
_("Animation finished"),
|
||||
_("Check if the animation being played by the Sprite object "
|
||||
"is finished."),
|
||||
_("The animation of _PARAM0_ is finished"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddRequiredObjectCapabilityOnLastParameter("animable")
|
||||
.SetRequiredBaseObjectCapability("animable")
|
||||
.MarkAsSimple();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -444,9 +444,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"SetLayerEffectParameter",
|
||||
_("Effect property (number)"),
|
||||
_("Change the value of a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("Effect parameter (number)"),
|
||||
_("Change the value of a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
|
||||
_("Effects"),
|
||||
@@ -456,16 +456,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
.AddParameter("layer", _("Layer"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("layerEffectName", _("Effect name"))
|
||||
.AddParameter("layerEffectParameterName", _("Property name"))
|
||||
.AddParameter("layerEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("expression", _("New value"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"SetLayerEffectStringParameter",
|
||||
_("Effect property (string)"),
|
||||
_("Change the value (string) of a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("Effect parameter (string)"),
|
||||
_("Change the value (string) of a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
|
||||
_("Effects"),
|
||||
@@ -475,16 +475,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
.AddParameter("layer", _("Layer"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("layerEffectName", _("Effect name"))
|
||||
.AddParameter("layerEffectParameterName", _("Property name"))
|
||||
.AddParameter("layerEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("string", _("New value"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"SetLayerEffectBooleanParameter",
|
||||
_("Effect property (enable or disable)"),
|
||||
_("Enable or disable a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
_("Effect parameter (enable or disable)"),
|
||||
_("Enable or disable a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"),
|
||||
_("Effects"),
|
||||
@@ -494,8 +494,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
.AddParameter("layer", _("Layer"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("layerEffectName", _("Effect name"))
|
||||
.AddParameter("layerEffectParameterName", _("Property name"))
|
||||
.AddParameter("yesorno", _("Enable this property"))
|
||||
.AddParameter("layerEffectParameterName", _("Parameter name"))
|
||||
.AddParameter("yesorno", _("Enable this parameter"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
|
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAnimatableExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("AnimatableCapability",
|
||||
_("Animatable capability"),
|
||||
_("Animate objects."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
|
||||
.SetIcon("res/actions/animation24.png");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
"AnimatableBehavior",
|
||||
_("Animatable capability"),
|
||||
"Animation",
|
||||
_("Animate objects."),
|
||||
"",
|
||||
"res/actions/animation24.png",
|
||||
"AnimatableBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"Index",
|
||||
_("Animation (by number)"),
|
||||
_("the number of the animation played by the object (the number from "
|
||||
"the animations list)"),
|
||||
_("the number of the animation"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.UseStandardParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Animation index")))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"string",
|
||||
"Name",
|
||||
_("Animation (by name)"),
|
||||
_("the animation played by the object using the name of the "
|
||||
"animation"),
|
||||
_("the animation"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.UseStandardParameters(
|
||||
"objectAnimationName", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Animation name")))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("PauseAnimation",
|
||||
_("Pause the animation"),
|
||||
_("Pause the animation of the object."),
|
||||
_("Pause the animation of _PARAM0_"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png",
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("PlayAnimation",
|
||||
_("Resume the animation"),
|
||||
_("Resume the animation of the object."),
|
||||
_("Resume the animation of _PARAM0_"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png",
|
||||
"res/actions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"SpeedScale",
|
||||
_("Animation speed scale"),
|
||||
_("the animation speed scale (1 = the default speed, >1 = faster and "
|
||||
"<1 = slower)"),
|
||||
_("the animation speed scale"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.UseStandardParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Speed scale")))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedCondition("IsAnimationPaused",
|
||||
_("Animation paused"),
|
||||
_("Check if the animation of an object is paused."),
|
||||
_("The animation of _PARAM0_ is paused"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedCondition("HasAnimationEnded",
|
||||
_("Animation finished"),
|
||||
_("Check if the animation being played by the Sprite object "
|
||||
"is finished."),
|
||||
_("The animation of _PARAM0_ is finished"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/animation24.png",
|
||||
"res/conditions/animation.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
|
||||
.MarkAsSimple();
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("EffectCapability",
|
||||
_("Effect capability"),
|
||||
_("Apply visual effects to objects."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
|
||||
.SetIcon("res/actions/effect24.png");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
"EffectBehavior",
|
||||
_("Effect capability"),
|
||||
"Effect",
|
||||
_("Apply visual effects to objects."),
|
||||
"",
|
||||
"res/actions/effect24.png",
|
||||
"EffectBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddScopedAction("EnableEffect",
|
||||
_("Enable an object effect"),
|
||||
_("Enable an effect on the object"),
|
||||
_("Enable effect _PARAM2_ on _PARAM0_: _PARAM3_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("yesorno", _("Enable?"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("SetEffectDoubleParameter",
|
||||
_("Effect property (number)"),
|
||||
_("Change the value of a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("expression", _("New value"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("SetEffectStringParameter",
|
||||
_("Effect property (string)"),
|
||||
_("Change the value (string) of a property of an effect.") +
|
||||
"\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("string", _("New value"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("SetEffectBooleanParameter",
|
||||
_("Effect property (enable or disable)"),
|
||||
_("Enable or disable a property of an effect.") + "\n" +
|
||||
_("You can find the property names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Enable _PARAM3_ for effect _PARAM2_ of _PARAM0_: _PARAM4_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.AddParameter("objectEffectParameterName", _("Property name"))
|
||||
.AddParameter("yesorno", _("Enable this property"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedCondition("IsEffectEnabled",
|
||||
_("Effect is enabled"),
|
||||
_("Check if the effect on an object is enabled."),
|
||||
_("Effect _PARAM2_ of _PARAM0_ is enabled"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
|
||||
.AddParameter("objectEffectName", _("Effect name"))
|
||||
.MarkAsSimple();
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("FlippableCapability",
|
||||
_("Flippable capability"),
|
||||
_("Flip objects."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
|
||||
.SetIcon("res/actions/effect24.png");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
"FlippableBehavior",
|
||||
_("Flippable capability"),
|
||||
"Flippable",
|
||||
_("Flip objects."),
|
||||
"",
|
||||
"res/actions/flipX24.png",
|
||||
"FlippableBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddScopedAction("FlipX",
|
||||
_("Flip the object horizontally"),
|
||||
_("Flip the object horizontally"),
|
||||
_("Flip horizontally _PARAM0_: _PARAM2_"),
|
||||
_("Effects"),
|
||||
"res/actions/flipX24.png",
|
||||
"res/actions/flipX.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "FlippableBehavior")
|
||||
.AddParameter("yesorno", _("Activate flipping"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedAction("FlipY",
|
||||
_("Flip the object vertically"),
|
||||
_("Flip the object vertically"),
|
||||
_("Flip vertically _PARAM0_: _PARAM2_"),
|
||||
_("Effects"),
|
||||
"res/actions/flipY24.png",
|
||||
"res/actions/flipY.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "FlippableBehavior")
|
||||
.AddParameter("yesorno", _("Activate flipping"))
|
||||
.MarkAsSimple();
|
||||
|
||||
aut.AddScopedCondition("FlippedX",
|
||||
_("Horizontally flipped"),
|
||||
_("Check if the object is horizontally flipped"),
|
||||
_("_PARAM0_ is horizontally flipped"),
|
||||
_("Effects"),
|
||||
"res/actions/flipX24.png",
|
||||
"res/actions/flipX.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "FlippableBehavior");
|
||||
|
||||
aut.AddScopedCondition("FlippedY",
|
||||
_("Vertically flipped"),
|
||||
_("Check if the object is vertically flipped"),
|
||||
_("_PARAM0_ is vertically flipped"),
|
||||
_("Effects"),
|
||||
"res/actions/flipY24.png",
|
||||
"res/actions/flipY.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "FlippableBehavior");
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("OpacityCapability",
|
||||
_("Opacity capability"),
|
||||
_("Change the object opacity."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
|
||||
.SetIcon("res/actions/opacity24.png");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
"OpacityBehavior",
|
||||
_("Opacity capability"),
|
||||
"Opacity",
|
||||
_("Change the object opacity."),
|
||||
"",
|
||||
"res/actions/opacity24.png",
|
||||
"OpacityBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"Value",
|
||||
_("Opacity"),
|
||||
_("the opacity of an object, between 0 (fully transparent) to 255 "
|
||||
"(opaque)"),
|
||||
_("the opacity"),
|
||||
_("Visibility"),
|
||||
"res/actions/opacity24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "OpacityBehavior")
|
||||
.UseStandardParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity (0-255)")))
|
||||
.SetFunctionName("setOpacity")
|
||||
.SetGetter("getOpacity");
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
|
||||
gd::PlatformExtension &extension) {
|
||||
extension
|
||||
.SetExtensionInformation("ResizableCapability",
|
||||
_("Resizable capability"),
|
||||
_("Change the object dimensions."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
|
||||
"res/actions/scale24_black.png");
|
||||
|
||||
gd::BehaviorMetadata &aut =
|
||||
extension
|
||||
.AddBehavior("ResizableBehavior",
|
||||
_("Resizable capability"),
|
||||
"Resizable",
|
||||
_("Change the object dimensions."),
|
||||
"",
|
||||
"res/actions/scale24_black.png",
|
||||
"ResizableBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddScopedAction("SetWidth",
|
||||
_("Width"),
|
||||
_("Change the width of the object."),
|
||||
_("the width"),
|
||||
_("Size"),
|
||||
"res/actions/scaleWidth24_black.png",
|
||||
"res/actions/scaleWidth_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(_("Width")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddScopedCondition("Width",
|
||||
_("Width"),
|
||||
_("Compare the width of the object."),
|
||||
_("the width"),
|
||||
_("Size"),
|
||||
"res/conditions/scaleWidth24_black.png",
|
||||
"res/conditions/scaleWidth_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(_("Width")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddScopedAction("SetHeight",
|
||||
_("Height"),
|
||||
_("Change the height of the object."),
|
||||
_("the height"),
|
||||
_("Size"),
|
||||
"res/actions/scaleHeight24_black.png",
|
||||
"res/actions/scaleHeight_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
|
||||
.UseStandardOperatorParameters(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(_("Height")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddScopedCondition("Height",
|
||||
_("Height"),
|
||||
_("Compare the height of the object."),
|
||||
_("the height"),
|
||||
_("Size"),
|
||||
"res/conditions/scaleHeight24_black.png",
|
||||
"res/conditions/scaleHeight_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(_("Height")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddScopedAction(
|
||||
"SetSize",
|
||||
_("Size"),
|
||||
_("Change the size of an object."),
|
||||
_("Change the size of _PARAM0_: set to _PARAM2_ x _PARAM3_"),
|
||||
_("Size"),
|
||||
"res/actions/scale24_black.png",
|
||||
"res/actions/scale_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
|
||||
.AddParameter("expression", _("Width"))
|
||||
.AddParameter("expression", _("Height"))
|
||||
.MarkAsAdvanced();
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorsSharedData.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsScalableExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("ScalableCapability",
|
||||
_("Scalable capability"),
|
||||
_("Change the object scale."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/objects");
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
|
||||
.SetIcon("res/actions/scale24_black.png");
|
||||
|
||||
gd::BehaviorMetadata& aut = extension.AddBehavior(
|
||||
"ScalableBehavior",
|
||||
_("Scalable capability"),
|
||||
"Scale",
|
||||
_("Change the object scale."),
|
||||
"",
|
||||
"res/actions/scale24_black.png",
|
||||
"ResizableBehavior",
|
||||
std::make_shared<gd::Behavior>(),
|
||||
std::make_shared<gd::BehaviorsSharedData>())
|
||||
.SetHidden();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"Value",
|
||||
_("Scale"),
|
||||
_("the scale of the object (default scale is 1)"),
|
||||
_("the scale"),
|
||||
_("Scale"),
|
||||
"res/actions/scale24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"X",
|
||||
_("Scale on X axis"),
|
||||
_("the scale on X axis of the object (default scale is 1)"),
|
||||
_("the scale on X axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleWidth24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
aut.AddExpressionAndConditionAndAction(
|
||||
"number",
|
||||
"Y",
|
||||
_("Scale on Y axis"),
|
||||
_("the scale on Y axis of the object (default scale is 1)"),
|
||||
_("the scale on Y axis"),
|
||||
_("Scale"),
|
||||
"res/actions/scaleHeight24_black.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
|
||||
.UseStandardParameters(
|
||||
"number",
|
||||
gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Scale (1 by default)")))
|
||||
.MarkAsAdvanced();
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -2,7 +2,7 @@
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the GNU Lesser General Public
|
||||
* License.
|
||||
* LicenFse.
|
||||
*/
|
||||
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
|
||||
@@ -33,14 +33,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"most elements of a game"),
|
||||
"CppPlatform/Extensions/spriteicon.png")
|
||||
.SetCategoryFullName(_("General"))
|
||||
.AddDefaultBehavior("EffectCapability::EffectBehavior")
|
||||
.AddDefaultBehavior("ResizableCapability::ResizableBehavior")
|
||||
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
|
||||
.AddDefaultBehavior("FlippableCapability::FlippableBehavior")
|
||||
.AddDefaultBehavior("OpacityCapability::OpacityBehavior")
|
||||
.AddDefaultBehavior("AnimatableCapability::AnimatableBehavior");
|
||||
.MarkBaseObjectCapabilityAsSupported("resizable")
|
||||
.MarkBaseObjectCapabilityAsSupported("scalable")
|
||||
.MarkBaseObjectCapabilityAsSupported("flippable")
|
||||
.MarkBaseObjectCapabilityAsSupported("animable");
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("Opacity",
|
||||
_("Sprite opacity"),
|
||||
_("Change the opacity of a Sprite. 0 is fully transparent, 255 "
|
||||
@@ -55,8 +52,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity (0-255)")))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.MarkAsSimple();
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction("ChangeAnimation",
|
||||
@@ -438,7 +434,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
_("Scale (1 by default)")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
// Deprecated
|
||||
obj.AddCondition("Opacity",
|
||||
_("Opacity"),
|
||||
_("Compare the opacity of a Sprite, between 0 (fully "
|
||||
@@ -453,8 +448,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"number",
|
||||
ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Opacity to compare to (0-255)")))
|
||||
.MarkAsSimple()
|
||||
.SetHidden();
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition(
|
||||
"BlendMode",
|
||||
@@ -617,24 +611,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("Animation",
|
||||
_("Animation"),
|
||||
_("Animation of the object"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
// Deprecated
|
||||
obj.AddStrExpression("AnimationName",
|
||||
_("Animation name"),
|
||||
_("Name of the animation of the object"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
obj.AddExpression("Sprite",
|
||||
_("Image"),
|
||||
_("Current frame of the animation of the object"),
|
||||
@@ -649,39 +625,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/sprite.png")
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("AnimationSpeedScale",
|
||||
_("Animation speed scale"),
|
||||
_("Animation speed scale"),
|
||||
_("Animations and images"),
|
||||
"res/actions/animation.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
obj.AddExpression("ScaleX",
|
||||
_("Scale of the width of an object"),
|
||||
_("Scale of the width of an object"),
|
||||
_("Size"),
|
||||
"res/actions/scaleWidth_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
obj.AddExpression("ScaleY",
|
||||
_("Scale of the height of an object"),
|
||||
_("Scale of the height of an object"),
|
||||
_("Size"),
|
||||
"res/actions/scaleHeight_black.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
// Deprecated
|
||||
obj.AddExpression("Opacity",
|
||||
_("Opacity"),
|
||||
_("Opacity"),
|
||||
_("Opacity"),
|
||||
"res/actions/opacity.png")
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.SetHidden();
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
extension
|
||||
.AddCondition("Collision",
|
||||
|
@@ -13,8 +13,6 @@
|
||||
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "ParameterMetadata.h"
|
||||
#include "ParameterOptions.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
@@ -22,6 +20,7 @@ class Layout;
|
||||
class EventsCodeGenerator;
|
||||
class EventsCodeGenerationContext;
|
||||
class SerializerElement;
|
||||
class ObjectType;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -63,7 +62,13 @@ public:
|
||||
* \see gd::InstructionMetadata::SetParameterExtraInfo
|
||||
*/
|
||||
virtual AbstractFunctionMetadata &
|
||||
SetParameterExtraInfo(const gd::String &defaultValue) = 0;
|
||||
SetParameterExtraInfo(const gd::String &extraInfo) = 0;
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterObjectType
|
||||
*/
|
||||
virtual AbstractFunctionMetadata &
|
||||
SetParameterObjectType(const gd::ObjectType &objectType) = 0;
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterLongDescription
|
||||
|
@@ -34,7 +34,8 @@ BehaviorMetadata::BehaviorMetadata(
|
||||
className(className_),
|
||||
iconFilename(icon24x24),
|
||||
instance(instance_),
|
||||
sharedDatasInstance(sharedDatasInstance_) {
|
||||
sharedDatasInstance(sharedDatasInstance_),
|
||||
isEventBased(false) {
|
||||
SetFullName(gd::String(fullname_));
|
||||
SetDescription(gd::String(description_));
|
||||
SetDefaultName(gd::String(defaultName_));
|
||||
@@ -51,6 +52,29 @@ BehaviorMetadata::BehaviorMetadata(
|
||||
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(nameWithNamespace);
|
||||
}
|
||||
|
||||
BehaviorMetadata::BehaviorMetadata(
|
||||
const gd::String& extensionNamespace,
|
||||
const gd::String& nameWithNamespace,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& defaultName_,
|
||||
const gd::String& description_,
|
||||
const gd::String& group_,
|
||||
const gd::String& icon24x24_): BehaviorMetadata(
|
||||
extensionNamespace,
|
||||
nameWithNamespace,
|
||||
fullname_,
|
||||
defaultName_,
|
||||
description_,
|
||||
group_,
|
||||
icon24x24_,
|
||||
// Class name is the name, actually unused
|
||||
defaultName_,
|
||||
// It is only used to get the name for GetName.
|
||||
gd::make_unique<gd::Behavior>("", nameWithNamespace),
|
||||
nullptr){
|
||||
isEventBased = true;
|
||||
};
|
||||
|
||||
gd::InstructionMetadata& BehaviorMetadata::AddCondition(
|
||||
const gd::String& name,
|
||||
const gd::String& fullname,
|
||||
@@ -396,6 +420,10 @@ const gd::String& BehaviorMetadata::GetName() const {
|
||||
}
|
||||
|
||||
gd::Behavior& BehaviorMetadata::Get() const {
|
||||
if (isEventBased) {
|
||||
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
|
||||
"This method should not never be called.");
|
||||
}
|
||||
if (!instance) {
|
||||
gd::LogFatalError(
|
||||
"Trying to get a behavior from a BehaviorMetadata that has no "
|
||||
@@ -406,20 +434,11 @@ gd::Behavior& BehaviorMetadata::Get() const {
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
|
||||
if (isEventBased) {
|
||||
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
|
||||
"This method should not never be called.");
|
||||
}
|
||||
return sharedDatasInstance.get();
|
||||
}
|
||||
|
||||
const std::vector<gd::String>& BehaviorMetadata::GetRequiredBehaviorTypes() const {
|
||||
requiredBehaviors.clear();
|
||||
for (auto& property : Get().GetProperties()) {
|
||||
const String& propertyName = property.first;
|
||||
const gd::PropertyDescriptor& propertyDescriptor = property.second;
|
||||
|
||||
if (propertyDescriptor.GetType() == "Behavior") {
|
||||
requiredBehaviors.push_back(propertyDescriptor.GetExtraInfo()[0]);
|
||||
}
|
||||
}
|
||||
return requiredBehaviors;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -11,7 +11,9 @@
|
||||
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Project/ObjectType.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Behavior;
|
||||
class BehaviorsSharedData;
|
||||
@@ -247,7 +249,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
/**
|
||||
* \brief Set the type of the object that this behavior can be used on.
|
||||
*/
|
||||
BehaviorMetadata& SetObjectType(const gd::String& objectType_) {
|
||||
BehaviorMetadata& SetObjectType(const gd::ObjectType& objectType_) {
|
||||
objectType = objectType_;
|
||||
return *this;
|
||||
}
|
||||
@@ -257,12 +259,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
*
|
||||
* \note An empty string means the base object, so any object.
|
||||
*/
|
||||
const gd::String& GetObjectType() const { return objectType; }
|
||||
|
||||
/**
|
||||
* \brief Get the types of the behaviors that are required by this behavior.
|
||||
*/
|
||||
const std::vector<gd::String>& GetRequiredBehaviorTypes() const;
|
||||
const gd::ObjectType& GetObjectType() const { return objectType; }
|
||||
|
||||
/**
|
||||
* Check if the behavior is private - it can't be used outside of its
|
||||
@@ -279,21 +276,6 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the behavior is hidden - it can be used but not attached to
|
||||
* objects by users.
|
||||
*/
|
||||
bool IsHidden() const { return isHidden; }
|
||||
|
||||
/**
|
||||
* Set that the behavior is hidden - it can be used but not attached to
|
||||
* objects by users.
|
||||
*/
|
||||
BehaviorMetadata &SetHidden() {
|
||||
isHidden = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the associated gd::Behavior, handling behavior contents.
|
||||
*
|
||||
@@ -349,14 +331,13 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
gd::String description;
|
||||
gd::String group;
|
||||
gd::String iconFilename;
|
||||
gd::String objectType;
|
||||
mutable std::vector<gd::String> requiredBehaviors;
|
||||
gd::ObjectType objectType;
|
||||
bool isPrivate = false;
|
||||
bool isHidden = false;
|
||||
|
||||
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
|
||||
std::shared_ptr<gd::Behavior> instance;
|
||||
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance;
|
||||
bool isEventBased;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -42,21 +42,25 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
info.description = description;
|
||||
info.codeOnly = false;
|
||||
info.SetOptional(parameterIsOptional);
|
||||
info.SetExtraInfo(
|
||||
|
||||
gd::String fixedSupplementaryInformation =
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
((gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
// Prefix with the namespace if it's not already there.
|
||||
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
|
||||
? (supplementaryInformation.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
supplementaryInformation //... so prefix it with the extension
|
||||
// namespace.
|
||||
)
|
||||
: supplementaryInformation); // Otherwise don't change anything
|
||||
|
||||
//... so prefix it with the extension namespace.
|
||||
: extensionNamespace + supplementaryInformation)
|
||||
// Otherwise don't change anything
|
||||
: supplementaryInformation;
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
info.GetValueTypeMetadata().GetObjectType().SetName(fixedSupplementaryInformation);
|
||||
} else {
|
||||
info.SetExtraInfo(fixedSupplementaryInformation);
|
||||
}
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
@@ -75,8 +79,7 @@ gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
gd::ExpressionMetadata& ExpressionMetadata::SetRequiresBaseObjectCapability(
|
||||
gd::ExpressionMetadata& ExpressionMetadata::SetRequiredBaseObjectCapability(
|
||||
const gd::String& capability) {
|
||||
requiredBaseObjectCapability = capability;
|
||||
return *this;
|
||||
|
@@ -224,13 +224,41 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the type of object accepted by the last parameter (only apply
|
||||
* for object parameter).
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
ExpressionMetadata &
|
||||
SetParameterObjectType(const gd::ObjectType &objectType) override {
|
||||
if (!parameters.empty()) {
|
||||
parameters.back().GetValueTypeMetadata().SetObjectType(objectType);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the capabilities of the objects accepted by the last parameter
|
||||
* (only apply for object parameter).
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
ExpressionMetadata &
|
||||
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
|
||||
if (!parameters.empty()) {
|
||||
parameters.back().GetValueTypeMetadata().GetObjectType().AddCapability(capability);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark this (object) expression as requiring the specified capability,
|
||||
* offered by the base object.
|
||||
* This is useful for some objects that don't support this capability, so that
|
||||
* the editor can hide the expression as it does not apply to them.
|
||||
*/
|
||||
ExpressionMetadata& SetRequiresBaseObjectCapability(
|
||||
ExpressionMetadata& SetRequiredBaseObjectCapability(
|
||||
const gd::String& capability);
|
||||
|
||||
/**
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "ParameterMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
InstructionMetadata::InstructionMetadata()
|
||||
@@ -60,22 +60,25 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
info.description = description;
|
||||
info.codeOnly = false;
|
||||
info.SetOptional(parameterIsOptional);
|
||||
info.SetExtraInfo(
|
||||
|
||||
gd::String fixedSupplementaryInformation =
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
((gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
// Prefix with the namespace if it's not already there.
|
||||
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
|
||||
? (supplementaryInformation.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
supplementaryInformation //... so prefix it with the
|
||||
// extension
|
||||
// namespace.
|
||||
)
|
||||
: supplementaryInformation); // Otherwise don't change anything
|
||||
|
||||
//... so prefix it with the extension namespace.
|
||||
: extensionNamespace + supplementaryInformation)
|
||||
// Otherwise don't change anything
|
||||
: supplementaryInformation;
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
info.GetValueTypeMetadata().GetObjectType().SetName(fixedSupplementaryInformation);
|
||||
} else {
|
||||
info.SetExtraInfo(fixedSupplementaryInformation);
|
||||
}
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
@@ -212,7 +215,7 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
|
||||
return *this;
|
||||
}
|
||||
|
||||
InstructionMetadata& InstructionMetadata::SetRequiresBaseObjectCapability(
|
||||
InstructionMetadata& InstructionMetadata::SetRequiredBaseObjectCapability(
|
||||
const gd::String& capability) {
|
||||
if (!IsObjectInstruction() && !IsBehaviorInstruction()) {
|
||||
gd::LogError("Tried to add capability \"" + capability +
|
||||
|
@@ -24,7 +24,7 @@ class Layout;
|
||||
class EventsCodeGenerator;
|
||||
class EventsCodeGenerationContext;
|
||||
class SerializerElement;
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -36,17 +36,14 @@ namespace gd {
|
||||
* \ingroup Events
|
||||
*/
|
||||
class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
public:
|
||||
public:
|
||||
/**
|
||||
* Construct a new instruction metadata.
|
||||
*/
|
||||
InstructionMetadata(const gd::String &extensionNamespace,
|
||||
const gd::String &name,
|
||||
const gd::String &fullname,
|
||||
const gd::String &description,
|
||||
const gd::String &sentence,
|
||||
const gd::String &group,
|
||||
const gd::String &icon,
|
||||
const gd::String &name, const gd::String &fullname,
|
||||
const gd::String &description, const gd::String &sentence,
|
||||
const gd::String &group, const gd::String &icon,
|
||||
const gd::String &smallIcon);
|
||||
|
||||
/**
|
||||
@@ -229,11 +226,10 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*
|
||||
* \see EventsCodeGenerator::GenerateParametersCodes
|
||||
*/
|
||||
InstructionMetadata &AddParameter(
|
||||
const gd::String &type,
|
||||
const gd::String &label,
|
||||
const gd::String &supplementaryInformation = "",
|
||||
bool parameterIsOptional = false) override;
|
||||
InstructionMetadata &
|
||||
AddParameter(const gd::String &type, const gd::String &label,
|
||||
const gd::String &supplementaryInformation = "",
|
||||
bool parameterIsOptional = false) override;
|
||||
|
||||
/**
|
||||
* \brief Add a parameter not displayed in editor.
|
||||
@@ -246,8 +242,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*
|
||||
* \see EventsCodeGenerator::GenerateParametersCodes
|
||||
*/
|
||||
InstructionMetadata &AddCodeOnlyParameter(
|
||||
const gd::String &type, const gd::String &supplementaryInformation) override;
|
||||
InstructionMetadata &
|
||||
AddCodeOnlyParameter(const gd::String &type,
|
||||
const gd::String &supplementaryInformation) override;
|
||||
|
||||
/**
|
||||
* \brief Set the default value used in editor (or if an optional parameter is
|
||||
@@ -255,8 +252,10 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) override {
|
||||
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
|
||||
InstructionMetadata &
|
||||
SetDefaultValue(const gd::String &defaultValue_) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetDefaultValue(defaultValue_);
|
||||
return *this;
|
||||
};
|
||||
|
||||
@@ -266,8 +265,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterLongDescription(
|
||||
const gd::String &longDescription) override {
|
||||
InstructionMetadata &
|
||||
SetParameterLongDescription(const gd::String &longDescription) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetLongDescription(longDescription);
|
||||
return *this;
|
||||
@@ -280,8 +279,38 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) override {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
InstructionMetadata &
|
||||
SetParameterExtraInfo(const gd::String &extraInfo) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetExtraInfo(extraInfo);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the type of object accepted by the last parameter (only apply
|
||||
* for object parameter).
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &
|
||||
SetParameterObjectType(const gd::ObjectType &objectType) override {
|
||||
if (!parameters.empty()) {
|
||||
parameters.back().GetValueTypeMetadata().SetObjectType(objectType);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the capabilities of the objects accepted by the last parameter
|
||||
* (only apply for object parameter).
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &
|
||||
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
|
||||
if (!parameters.empty()) {
|
||||
parameters.back().GetValueTypeMetadata().GetObjectType().AddCapability(capability);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -292,8 +321,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \note The type "string" can be declined in several subtypes.
|
||||
* \see ParameterMetadata
|
||||
*/
|
||||
InstructionMetadata &UseStandardOperatorParameters(
|
||||
const gd::String &type, const ParameterOptions &options);
|
||||
InstructionMetadata &
|
||||
UseStandardOperatorParameters(const gd::String &type,
|
||||
const ParameterOptions &options);
|
||||
|
||||
/**
|
||||
* \brief Add the default parameters for an instruction comparing the
|
||||
@@ -302,8 +332,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \note The type "string" can be declined in several subtypes.
|
||||
* \see ParameterMetadata
|
||||
*/
|
||||
InstructionMetadata &UseStandardRelationalOperatorParameters(
|
||||
const gd::String &type, const ParameterOptions &options);
|
||||
InstructionMetadata &
|
||||
UseStandardRelationalOperatorParameters(const gd::String &type,
|
||||
const ParameterOptions &options);
|
||||
|
||||
/**
|
||||
* \brief Mark the instruction as an object instruction. Automatically called
|
||||
@@ -339,8 +370,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* that don't support this capability, so that the editor can hide the
|
||||
* instruction as it does not apply to them.
|
||||
*/
|
||||
InstructionMetadata &SetRequiresBaseObjectCapability(
|
||||
const gd::String &capability);
|
||||
InstructionMetadata &
|
||||
SetRequiredBaseObjectCapability(const gd::String &capability);
|
||||
|
||||
/**
|
||||
* \brief Get the required specified capability for this (object) instruction,
|
||||
@@ -384,8 +415,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
/**
|
||||
* \brief Defines information about how generate the code for an instruction
|
||||
*/
|
||||
class ExtraInformation {
|
||||
public:
|
||||
class ExtraInformation {
|
||||
public:
|
||||
enum AccessType { Reference, MutatorAndOrAccessor, Mutators };
|
||||
ExtraInformation() : accessType(Reference), hasCustomCodeGenerator(false){};
|
||||
virtual ~ExtraInformation(){};
|
||||
@@ -399,19 +430,20 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
std::map<gd::String, gd::String> optionalMutators;
|
||||
bool hasCustomCodeGenerator;
|
||||
std::function<gd::String(Instruction &instruction,
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context)>
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context)>
|
||||
customCodeGenerator;
|
||||
std::vector<gd::String> includeFiles;
|
||||
};
|
||||
ExtraInformation codeExtraInformation; ///< Information about how generate
|
||||
///< code for the instruction
|
||||
ExtraInformation codeExtraInformation; ///< Information about how generate
|
||||
///< code for the instruction
|
||||
|
||||
/**
|
||||
* Set the name of the function which will be called in the generated code.
|
||||
* \param functionName the name of the function to call.
|
||||
*/
|
||||
InstructionMetadata &SetFunctionName(const gd::String &functionName_) override {
|
||||
InstructionMetadata &
|
||||
SetFunctionName(const gd::String &functionName_) override {
|
||||
codeExtraInformation.functionCallName = functionName_;
|
||||
return *this;
|
||||
}
|
||||
@@ -445,12 +477,12 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
return codeExtraInformation.asyncFunctionCallName;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Declare if the instruction being declared is somewhat manipulating
|
||||
* in a standard way.
|
||||
*
|
||||
* \param type "number" or "string"
|
||||
*/
|
||||
/**
|
||||
* \brief Declare if the instruction being declared is somewhat manipulating
|
||||
* in a standard way.
|
||||
*
|
||||
* \param type "number" or "string"
|
||||
*/
|
||||
InstructionMetadata &SetManipulatedType(const gd::String &type_) {
|
||||
codeExtraInformation.type = type_;
|
||||
return *this;
|
||||
@@ -485,8 +517,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
InstructionMetadata &SetMutators(
|
||||
const std::map<gd::String, gd::String> &mutators) {
|
||||
InstructionMetadata &
|
||||
SetMutators(const std::map<gd::String, gd::String> &mutators) {
|
||||
codeExtraInformation.optionalMutators = mutators;
|
||||
codeExtraInformation.accessType = codeExtraInformation.Mutators;
|
||||
return *this;
|
||||
@@ -505,8 +537,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \brief Add a file to the already existing include files.
|
||||
*/
|
||||
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
|
||||
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
|
||||
codeExtraInformation.includeFiles.end())
|
||||
if (std::find(codeExtraInformation.includeFiles.begin(),
|
||||
codeExtraInformation.includeFiles.end(),
|
||||
includeFile) == codeExtraInformation.includeFiles.end())
|
||||
codeExtraInformation.includeFiles.push_back(includeFile);
|
||||
|
||||
return *this;
|
||||
@@ -521,8 +554,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
|
||||
InstructionMetadata &SetCustomCodeGenerator(
|
||||
std::function<gd::String(Instruction &instruction,
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context)>
|
||||
gd::EventsCodeGenerator &codeGenerator,
|
||||
gd::EventsCodeGenerationContext &context)>
|
||||
codeGenerator) {
|
||||
codeExtraInformation.hasCustomCodeGenerator = true;
|
||||
codeExtraInformation.customCodeGenerator = codeGenerator;
|
||||
@@ -532,26 +565,28 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
InstructionMetadata &RemoveCustomCodeGenerator() {
|
||||
codeExtraInformation.hasCustomCodeGenerator = false;
|
||||
std::function<gd::String(Instruction & instruction,
|
||||
gd::EventsCodeGenerator & codeGenerator,
|
||||
gd::EventsCodeGenerationContext & context)>
|
||||
gd::EventsCodeGenerator & codeGenerator,
|
||||
gd::EventsCodeGenerationContext & context)>
|
||||
emptyFunction;
|
||||
codeExtraInformation.customCodeGenerator = emptyFunction;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
|
||||
bool HasCustomCodeGenerator() const {
|
||||
return codeExtraInformation.hasCustomCodeGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the structure containing the information about code
|
||||
* generation for the instruction.
|
||||
*
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
InstructionMetadata &GetCodeExtraInformation() { return *this; }
|
||||
|
||||
std::vector<ParameterMetadata> parameters;
|
||||
|
||||
private:
|
||||
private:
|
||||
gd::String fullname;
|
||||
gd::String description;
|
||||
gd::String helpPath;
|
||||
@@ -562,8 +597,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
bool canHaveSubInstructions;
|
||||
gd::String extensionNamespace;
|
||||
bool hidden;
|
||||
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
|
||||
///< use) to 10 (complex to understand)
|
||||
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
|
||||
///< use) to 10 (complex to understand)
|
||||
bool isPrivate;
|
||||
bool isObjectInstruction;
|
||||
bool isBehaviorInstruction;
|
||||
@@ -571,4 +606,4 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
gd::String relevantContext;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
} // namespace gd
|
||||
|
@@ -14,7 +14,6 @@
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
|
||||
@@ -392,19 +391,20 @@ MetadataProvider::GetBehaviorAnyExpressionMetadata(const gd::Platform& platform,
|
||||
}
|
||||
|
||||
const gd::ExpressionMetadata& MetadataProvider::GetFunctionCallMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& node) {
|
||||
|
||||
if (!node.behaviorName.empty()) {
|
||||
gd::String behaviorType =
|
||||
objectsContainersList.GetTypeOfBehavior(node.behaviorName);
|
||||
gd::String behaviorType =
|
||||
GetTypeOfBehavior(globalObjectsContainer, objectsContainer, node.behaviorName);
|
||||
return MetadataProvider::GetBehaviorAnyExpressionMetadata(
|
||||
platform, behaviorType, node.functionName);
|
||||
}
|
||||
else if (!node.objectName.empty()) {
|
||||
gd::String objectType =
|
||||
objectsContainersList.GetTypeOfObject(node.objectName);
|
||||
gd::String objectType =
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, node.objectName);
|
||||
return MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform, objectType, node.functionName);
|
||||
}
|
||||
@@ -412,9 +412,10 @@ const gd::ExpressionMetadata& MetadataProvider::GetFunctionCallMetadata(
|
||||
return MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
|
||||
}
|
||||
|
||||
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& functionCall,
|
||||
ExpressionNode& parameter) {
|
||||
int parameterIndex = -1;
|
||||
@@ -428,15 +429,17 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
return nullptr;
|
||||
}
|
||||
return MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
platform,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
functionCall,
|
||||
parameterIndex);
|
||||
}
|
||||
|
||||
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& functionCall,
|
||||
int parameterIndex) {
|
||||
// Search the parameter metadata index skipping invisible ones.
|
||||
@@ -445,7 +448,7 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
ExpressionParser2::WrittenParametersFirstIndex(
|
||||
functionCall.objectName, functionCall.behaviorName);
|
||||
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
|
||||
platform, objectsContainersList, functionCall);
|
||||
platform, globalObjectsContainer, objectsContainer, functionCall);
|
||||
|
||||
if (IsBadExpressionMetadata(metadata)) {
|
||||
return nullptr;
|
||||
|
@@ -15,7 +15,6 @@ class ExpressionMetadata;
|
||||
class ExpressionMetadata;
|
||||
class Platform;
|
||||
class PlatformExtension;
|
||||
class ObjectsContainersList;
|
||||
struct FunctionCallNode;
|
||||
struct ExpressionNode;
|
||||
} // namespace gd
|
||||
@@ -238,19 +237,22 @@ class GD_CORE_API MetadataProvider {
|
||||
const gd::Platform& platform, gd::String objectType, gd::String exprType);
|
||||
|
||||
static const gd::ExpressionMetadata& GetFunctionCallMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& node);
|
||||
|
||||
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& functionCall,
|
||||
ExpressionNode& parameter);
|
||||
|
||||
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::Platform& platform,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
FunctionCallNode& functionCall,
|
||||
int parameterIndex);
|
||||
|
||||
@@ -273,10 +275,6 @@ class GD_CORE_API MetadataProvider {
|
||||
return &metadata == &badBehaviorMetadata;
|
||||
}
|
||||
|
||||
static bool IsBadObjectMetadata(const gd::ObjectMetadata& metadata) {
|
||||
return &metadata == &badObjectInfo;
|
||||
}
|
||||
|
||||
virtual ~MetadataProvider();
|
||||
|
||||
private:
|
||||
|
@@ -85,13 +85,47 @@ class GD_CORE_API MultipleInstructionMetadata : public AbstractFunctionMetadata
|
||||
* \see gd::InstructionMetadata::SetParameterExtraInfo
|
||||
*/
|
||||
MultipleInstructionMetadata &SetParameterExtraInfo(
|
||||
const gd::String &defaultValue) override {
|
||||
if (expression) expression->SetParameterExtraInfo(defaultValue);
|
||||
if (condition) condition->SetParameterExtraInfo(defaultValue);
|
||||
if (action) action->SetParameterExtraInfo(defaultValue);
|
||||
const gd::String &extraInfo) override {
|
||||
if (expression) expression->SetParameterExtraInfo(extraInfo);
|
||||
if (condition) condition->SetParameterExtraInfo(extraInfo);
|
||||
if (action) action->SetParameterExtraInfo(extraInfo);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterObjectType
|
||||
*/
|
||||
MultipleInstructionMetadata &
|
||||
SetParameterObjectType(const gd::ObjectType &objectType) override {
|
||||
if (expression) {
|
||||
expression->SetParameterObjectType(objectType);
|
||||
}
|
||||
if (condition) {
|
||||
condition->SetParameterObjectType(objectType);
|
||||
}
|
||||
if (action) {
|
||||
action->SetParameterObjectType(objectType);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::AddRequiredObjectCapabilityOnLastParameter
|
||||
*/
|
||||
MultipleInstructionMetadata &
|
||||
AddRequiredObjectCapabilityOnLastParameter(const gd::String &capability) {
|
||||
if (expression) {
|
||||
expression->AddRequiredObjectCapabilityOnLastParameter(capability);
|
||||
}
|
||||
if (condition) {
|
||||
condition->AddRequiredObjectCapabilityOnLastParameter(capability);
|
||||
}
|
||||
if (action) {
|
||||
action->AddRequiredObjectCapabilityOnLastParameter(capability);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetParameterLongDescription
|
||||
*/
|
||||
@@ -114,13 +148,13 @@ class GD_CORE_API MultipleInstructionMetadata : public AbstractFunctionMetadata
|
||||
};
|
||||
|
||||
/**
|
||||
* \see gd::InstructionMetadata::SetRequiresBaseObjectCapability
|
||||
* \see gd::InstructionMetadata::SetRequiredBaseObjectCapability
|
||||
*/
|
||||
MultipleInstructionMetadata &SetRequiresBaseObjectCapability(
|
||||
MultipleInstructionMetadata &SetRequiredBaseObjectCapability(
|
||||
const gd::String &capability) {
|
||||
if (expression) expression->SetRequiresBaseObjectCapability(capability);
|
||||
if (condition) condition->SetRequiresBaseObjectCapability(capability);
|
||||
if (action) action->SetRequiresBaseObjectCapability(capability);
|
||||
if (expression) expression->SetRequiredBaseObjectCapability(capability);
|
||||
if (condition) condition->SetRequiredBaseObjectCapability(capability);
|
||||
if (action) action->SetRequiredBaseObjectCapability(capability);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@@ -39,6 +39,7 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
return blueprintObject_->Clone();
|
||||
}) {
|
||||
blueprintObject = blueprintObject_;
|
||||
supportedBaseObjectCapabilities.insert("effect");
|
||||
}
|
||||
|
||||
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
@@ -56,7 +57,9 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
"Error: Event-based objects don't have blueprint. "
|
||||
"This method should not never be called.");
|
||||
return nullptr;
|
||||
}) {}
|
||||
}) {
|
||||
supportedBaseObjectCapabilities.insert("effect");
|
||||
}
|
||||
|
||||
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
const gd::String& name_,
|
||||
@@ -70,6 +73,7 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
|
||||
extensionNamespace(extensionNamespace_) {
|
||||
SetFullName(gd::String(fullname_));
|
||||
SetDescription(gd::String(description_));
|
||||
supportedBaseObjectCapabilities.insert("effect");
|
||||
}
|
||||
|
||||
gd::InstructionMetadata& ObjectMetadata::AddCondition(
|
||||
|
@@ -224,28 +224,44 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief The "capabilities" that are offered by through behaviors.
|
||||
* \brief The "capabilities" that are offered by the base object that are
|
||||
* supported by this object, and should *not* be hidden in the editor
|
||||
* interface.
|
||||
*/
|
||||
const std::set<gd::String>& GetDefaultBehaviors() const {
|
||||
return defaultBehaviorTypes;
|
||||
const std::set<gd::String>& GetSupportedBaseObjectCapabilities() const {
|
||||
return supportedBaseObjectCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if object has a default behavior of the given type.
|
||||
* \brief Add a "capability" that is offered by the base object that is
|
||||
* supported by this object, and should *not* be hidden in the editor interface.
|
||||
*/
|
||||
bool HasDefaultBehavior(const gd::String& behaviorType) const {
|
||||
return defaultBehaviorTypes.find(behaviorType) != defaultBehaviorTypes.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add a "capability" that is offered by through a behavior.
|
||||
*/
|
||||
ObjectMetadata& AddDefaultBehavior(
|
||||
const gd::String& behaviorType) {
|
||||
defaultBehaviorTypes.insert(behaviorType);
|
||||
ObjectMetadata& MarkBaseObjectCapabilityAsSupported(
|
||||
const gd::String& capability) {
|
||||
supportedBaseObjectCapabilities.insert(capability);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Remove a "capability" that is offered by the base object that is *not*
|
||||
* supported by this object, and should be hidden in the editor interface.
|
||||
*/
|
||||
ObjectMetadata& MarkBaseObjectCapabilityAsUnsupported(
|
||||
const gd::String& capability) {
|
||||
supportedBaseObjectCapabilities.erase(capability);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if a "capability" that is offered by the base object is
|
||||
* supported by this object, and should *not* be hidden in the editor interface.
|
||||
*/
|
||||
bool IsSupportedBaseObjectCapability(const gd::String& capability) const {
|
||||
return capability.empty() ||
|
||||
supportedBaseObjectCapabilities.find(capability) !=
|
||||
supportedBaseObjectCapabilities.end();
|
||||
}
|
||||
|
||||
const gd::String& GetName() const override { return name; }
|
||||
const gd::String& GetFullName() const override { return fullname; }
|
||||
const gd::String& GetCategoryFullName() const { return categoryFullName; }
|
||||
@@ -327,7 +343,7 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
gd::String description;
|
||||
gd::String iconFilename;
|
||||
gd::String categoryFullName;
|
||||
std::set<gd::String> defaultBehaviorTypes;
|
||||
std::set<gd::String> supportedBaseObjectCapabilities;
|
||||
bool hidden = false;
|
||||
|
||||
std::shared_ptr<gd::ObjectConfiguration>
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
|
||||
#include "GDCore/Project/ObjectType.h"
|
||||
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "InstructionMetadata.h"
|
||||
@@ -16,8 +15,6 @@
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
|
||||
namespace gd {
|
||||
const ParameterMetadata ParameterMetadataTools::badParameterMetadata;
|
||||
|
||||
void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
@@ -30,9 +27,10 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
if (parameter.GetName().empty()) continue;
|
||||
|
||||
if (gd::ParameterMetadata::IsObject(parameter.GetType())) {
|
||||
// TODO Declare object capabilities
|
||||
outputObjectsContainer.InsertNewObject(
|
||||
project,
|
||||
parameter.GetExtraInfo(),
|
||||
parameter.GetValueTypeMetadata().GetObjectType().GetName(),
|
||||
parameter.GetName(),
|
||||
outputObjectsContainer.GetObjectsCount());
|
||||
|
||||
@@ -60,55 +58,6 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterMetadataTools::ForEachParameterWithPrefix(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>&
|
||||
parametersVectorsList,
|
||||
const gd::String& prefix,
|
||||
std::function<void(const gd::ParameterMetadata&)> cb) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName().find(prefix) == 0) cb(parameterMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterMetadataTools::Has(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const gd::String& parameterName) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName() == parameterName) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const gd::ParameterMetadata& ParameterMetadataTools::Get(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>&
|
||||
parametersVectorsList,
|
||||
const gd::String& parameterName) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName() == parameterName) return parameterMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
return badParameterMetadata;
|
||||
}
|
||||
|
||||
void ParameterMetadataTools::IterateOverParameters(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
@@ -157,7 +106,8 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
|
||||
void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
const gd::Platform &platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList, FunctionCallNode &node,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer, FunctionCallNode &node,
|
||||
std::function<void(const gd::ParameterMetadata ¶meterMetadata,
|
||||
std::unique_ptr<gd::ExpressionNode> ¶meterNode,
|
||||
size_t parameterIndex, const gd::String &lastObjectName)>
|
||||
@@ -168,7 +118,8 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
const gd::ExpressionMetadata &metadata =
|
||||
isObjectFunction ? MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform,
|
||||
objectsContainersList.GetTypeOfObject(node.objectName),
|
||||
GetTypeOfObject(globalObjectsContainer,
|
||||
objectsContainer, node.objectName),
|
||||
node.functionName)
|
||||
: MetadataProvider::GetAnyExpressionMetadata(
|
||||
platform, node.functionName);
|
||||
|
@@ -3,8 +3,9 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef ParameterMetadataTools_H
|
||||
#define ParameterMetadataTools_H
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "GDCore/String.h"
|
||||
@@ -12,7 +13,6 @@ namespace gd {
|
||||
class Platform;
|
||||
class Project;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class ParameterMetadata;
|
||||
class Expression;
|
||||
struct FunctionCallNode;
|
||||
@@ -27,19 +27,6 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
||||
static void ForEachParameterWithPrefix(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const gd::String& prefix,
|
||||
std::function<void(const gd::ParameterMetadata&)> cb);
|
||||
|
||||
static bool Has(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const gd::String& parameterName);
|
||||
|
||||
static const gd::ParameterMetadata& Get(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const gd::String& parameterName);
|
||||
|
||||
/**
|
||||
* Iterate over a list of parameters and their values.
|
||||
* Callback function is called with the parameter metadata, its value
|
||||
@@ -72,7 +59,8 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
*/
|
||||
static void IterateOverParametersWithIndex(
|
||||
const gd::Platform &platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList, FunctionCallNode &node,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer, FunctionCallNode &node,
|
||||
std::function<void(const gd::ParameterMetadata ¶meterMetadata,
|
||||
std::unique_ptr<gd::ExpressionNode> ¶meterNode,
|
||||
size_t parameterIndex,
|
||||
@@ -86,8 +74,8 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
static size_t GetObjectParameterIndexFor(
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
size_t parameterIndex);
|
||||
|
||||
private:
|
||||
static const gd::ParameterMetadata badParameterMetadata;
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif // ParameterMetadataTools_H
|
||||
#endif
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -17,6 +18,9 @@ void ValueTypeMetadata::SerializeTo(SerializerElement& element) const {
|
||||
if (!supplementaryInformation.empty()) {
|
||||
element.SetAttribute("supplementaryInformation", supplementaryInformation);
|
||||
}
|
||||
if (gd::ParameterMetadata::IsObject(name)) {
|
||||
objectType.SerializeTo(element);
|
||||
}
|
||||
if (optional) {
|
||||
element.SetAttribute("optional", optional);
|
||||
}
|
||||
@@ -29,6 +33,16 @@ void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
|
||||
name = element.GetStringAttribute("type");
|
||||
supplementaryInformation =
|
||||
element.GetStringAttribute("supplementaryInformation");
|
||||
if (gd::ParameterMetadata::IsObject(name)) {
|
||||
objectType.UnserializeFrom(element);
|
||||
// Compatibility with GD <= 4.2.166
|
||||
if (!element.HasAttribute("objectType") && !supplementaryInformation.empty()) {
|
||||
objectType.SetName(supplementaryInformation);
|
||||
supplementaryInformation = "";
|
||||
}
|
||||
std::cout << "Unserialized object type: " << objectType.GetName() << std::endl;
|
||||
}
|
||||
// end of compatibility code
|
||||
optional = element.GetBoolAttribute("optional");
|
||||
defaultValue = element.GetStringAttribute("defaultValue");
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/Project/ObjectType.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
@@ -58,6 +59,23 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the object type.
|
||||
*/
|
||||
gd::ObjectType& GetObjectType() { return objectType; };
|
||||
|
||||
/**
|
||||
* \brief Get the type of the object.
|
||||
*/
|
||||
const gd::ObjectType& GetObjectType() const { return objectType; }
|
||||
|
||||
/**
|
||||
* \brief Set the type of the object.
|
||||
*/
|
||||
void SetObjectType(const gd::ObjectType& objectType_) {
|
||||
objectType = objectType_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the parameter is optional.
|
||||
*/
|
||||
@@ -121,13 +139,6 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("string", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a boolean.
|
||||
*/
|
||||
bool IsBoolean() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("boolean", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is a number.
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
@@ -138,24 +149,6 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("variable", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a variable but from a specific scope
|
||||
* (scene, project or object). In new code, prefer to use the more generic "variable"
|
||||
* parameter (which accepts any variable coming from an object or from containers in the scope).
|
||||
*/
|
||||
bool IsLegacyPreScopedVariable() const {
|
||||
return gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a variable but from a specific scope
|
||||
* (scene, project or object). In new code, prefer to use the more generic "variable"
|
||||
* parameter (which accepts any variable coming from an object or from containers in the scope).
|
||||
*/
|
||||
static bool IsTypeLegacyPreScopedVariable(const gd::String &type) {
|
||||
return type == "scenevar" || type == "globalvar" || type == "objectvar";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is representing one object
|
||||
* (or more, i.e: an object group).
|
||||
@@ -200,13 +193,8 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
parameterType == "externalLayoutName" ||
|
||||
parameterType == "leaderboardId" ||
|
||||
parameterType == "identifier";
|
||||
} else if (type == "boolean") {
|
||||
return parameterType == "yesorno" || parameterType == "trueorfalse";
|
||||
} else if (type == "variable") {
|
||||
return
|
||||
parameterType == "variable" || // Any variable.
|
||||
// Old, "pre-scoped" variables:
|
||||
parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
} else if (type == "resource") {
|
||||
return parameterType == "fontResource" ||
|
||||
@@ -226,7 +214,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
* \brief Return the expression type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
*
|
||||
*
|
||||
* \note It only maps string and number types.
|
||||
*/
|
||||
static const gd::String &GetExpressionPrimitiveValueType(const gd::String ¶meterType);
|
||||
@@ -235,7 +223,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
* \brief Return the primitive type from the parameter type.
|
||||
* Declinations of "number" and "string" types (like "forceMultiplier" or
|
||||
* "sceneName") are replaced by "number" and "string".
|
||||
*
|
||||
*
|
||||
* \note It also maps variable and boolean types.
|
||||
*/
|
||||
static const gd::String &GetPrimitiveValueType(const gd::String ¶meterType);
|
||||
@@ -267,6 +255,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
private:
|
||||
gd::String name; ///< Parameter type
|
||||
gd::String supplementaryInformation; ///< Used if needed
|
||||
gd::ObjectType objectType;
|
||||
bool optional; ///< True if the parameter is optional
|
||||
gd::String defaultValue; ///< Used as a default value in editor or if an
|
||||
///< optional parameter is empty.
|
||||
|
@@ -273,6 +273,25 @@ gd::BehaviorMetadata& PlatformExtension::AddBehavior(
|
||||
return behaviorsInfo[nameWithNamespace];
|
||||
}
|
||||
|
||||
gd::BehaviorMetadata& PlatformExtension::AddEventsBasedBehavior(
|
||||
const gd::String& name,
|
||||
const gd::String& fullname,
|
||||
const gd::String& description,
|
||||
const gd::String& group,
|
||||
const gd::String& icon24x24) {
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
behaviorsInfo[nameWithNamespace] = BehaviorMetadata(GetNameSpace(),
|
||||
nameWithNamespace,
|
||||
fullname,
|
||||
// Default name is the name
|
||||
name,
|
||||
description,
|
||||
group,
|
||||
icon24x24)
|
||||
.SetHelpPath(GetHelpPath());
|
||||
return behaviorsInfo[nameWithNamespace];
|
||||
}
|
||||
|
||||
gd::EffectMetadata& PlatformExtension::AddEffect(const gd::String& name) {
|
||||
gd::String nameWithNamespace = GetNameSpace() + name;
|
||||
effectsMetadata[nameWithNamespace] = EffectMetadata(nameWithNamespace);
|
||||
|
@@ -421,32 +421,6 @@ class GD_CORE_API PlatformExtension {
|
||||
*/
|
||||
const gd::String& GetIconUrl() const { return iconUrl; }
|
||||
|
||||
/**
|
||||
* \brief Return keywords that help search engines find this extension.
|
||||
*/
|
||||
const std::vector<gd::String>& GetTags() const { return tags; }
|
||||
|
||||
/**
|
||||
* \brief Set keywords that help search engines find this extension.
|
||||
*/
|
||||
PlatformExtension& SetTags(const gd::String& csvTags) {
|
||||
tags.clear();
|
||||
tags = csvTags.Split(',');
|
||||
for (size_t i = 0; i < tags.size(); i++)
|
||||
{
|
||||
tags[i] = tags[i].Trim().LowerCase();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add a keyword that help search engines find this extension.
|
||||
*/
|
||||
PlatformExtension& AddTag(const gd::String& tag) {
|
||||
tags.push_back(tag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the extension is flagged as being deprecated.
|
||||
*/
|
||||
@@ -687,7 +661,6 @@ private:
|
||||
gd::String helpPath; ///< The relative path to the help for this extension in
|
||||
///< the documentation.
|
||||
gd::String iconUrl; ///< The URL to the icon to be shown for this extension.
|
||||
std::vector<gd::String> tags;
|
||||
|
||||
std::map<gd::String, gd::ObjectMetadata> objectsInfos;
|
||||
std::map<gd::String, gd::BehaviorMetadata> behaviorsInfo;
|
||||
|
@@ -11,8 +11,6 @@
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -49,14 +47,7 @@ bool ArbitraryEventsWorker::VisitEvent(gd::BaseEvent& event) {
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j)
|
||||
VisitInstructionList(*actionsVectors[j], false);
|
||||
|
||||
auto allExpressionsWithMetadata = event.GetAllExpressionsWithMetadata();
|
||||
for (auto& expressionAndMetadata : allExpressionsWithMetadata) {
|
||||
shouldDelete |= VisitEventExpression(
|
||||
*expressionAndMetadata.first, expressionAndMetadata.second);
|
||||
}
|
||||
|
||||
|
||||
return shouldDelete;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitLinkEvent(gd::LinkEvent& linkEvent) {
|
||||
@@ -84,11 +75,6 @@ bool ArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
|
||||
return DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitEventExpression(gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
return DoVisitEventExpression(expression, metadata);
|
||||
}
|
||||
|
||||
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
|
||||
@@ -155,12 +141,6 @@ void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& inst
|
||||
DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEventExpression(const gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
DoVisitEventExpression(expression, metadata);
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::StopAnyEventIteration() {
|
||||
shouldStopIteration = true;
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include <vector>
|
||||
#include "GDCore/Events/InstructionsList.h"
|
||||
#include "GDCore/Events/EventVisitor.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
@@ -18,8 +17,6 @@ class BaseEvent;
|
||||
class LinkEvent;
|
||||
class EventsList;
|
||||
class ObjectsContainer;
|
||||
class Expression;
|
||||
class ParameterMetadata;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -50,7 +47,6 @@ class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
void VisitInstructionList(gd::InstructionsList& instructions,
|
||||
bool areConditions);
|
||||
bool VisitInstruction(gd::Instruction& instruction, bool isCondition);
|
||||
bool VisitEventExpression(gd::Expression& expression, const gd::ParameterMetadata& metadata);
|
||||
|
||||
/**
|
||||
* Called to do some work on an event list.
|
||||
@@ -66,9 +62,9 @@ class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
|
||||
/**
|
||||
* Called to do some work on a link event.
|
||||
*
|
||||
*
|
||||
* Note that DoVisitEvent is also called with this event.
|
||||
*
|
||||
*
|
||||
* \return true if the event must be deleted from the events list, false
|
||||
* otherwise (default).
|
||||
*/
|
||||
@@ -89,16 +85,6 @@ class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
bool isCondition) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called to do some work on an expression of an event.
|
||||
* \return true if the event must be deleted from the list, false
|
||||
* otherwise (default).
|
||||
*/
|
||||
virtual bool DoVisitEventExpression(gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -113,7 +99,8 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
: public ArbitraryEventsWorker {
|
||||
public:
|
||||
ArbitraryEventsWorkerWithContext()
|
||||
: projectScopedContainers(nullptr){};
|
||||
: currentGlobalObjectsContainer(nullptr),
|
||||
currentObjectsContainer(nullptr){};
|
||||
virtual ~ArbitraryEventsWorkerWithContext();
|
||||
|
||||
/**
|
||||
@@ -121,27 +108,30 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
* giving the objects container on which the events are applying to.
|
||||
*/
|
||||
void Launch(gd::EventsList& events,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_) {
|
||||
projectScopedContainers = &projectScopedContainers_;
|
||||
const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_) {
|
||||
currentGlobalObjectsContainer = &globalObjectsContainer_;
|
||||
currentObjectsContainer = &objectsContainer_;
|
||||
ArbitraryEventsWorker::Launch(events);
|
||||
};
|
||||
|
||||
void Launch(gd::EventsList& events) = delete;
|
||||
|
||||
protected:
|
||||
const gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||
const gd::ObjectsContainer& GetGlobalObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *projectScopedContainers;
|
||||
return *currentGlobalObjectsContainer;
|
||||
};
|
||||
const gd::ObjectsContainersList& GetObjectsContainersList() {
|
||||
const gd::ObjectsContainer& GetObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return projectScopedContainers->GetObjectsContainersList();
|
||||
return *currentObjectsContainer;
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::ProjectScopedContainers* projectScopedContainers;
|
||||
const gd::ObjectsContainer* currentGlobalObjectsContainer;
|
||||
const gd::ObjectsContainer* currentObjectsContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -172,7 +162,6 @@ protected:
|
||||
void VisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions);
|
||||
void VisitInstruction(const gd::Instruction& instruction, bool isCondition);
|
||||
void VisitEventExpression(const gd::Expression& expression, const gd::ParameterMetadata& metadata);
|
||||
|
||||
/**
|
||||
* Called to do some work on an event list.
|
||||
@@ -186,7 +175,7 @@ protected:
|
||||
|
||||
/**
|
||||
* Called to do some work on a link event.
|
||||
*
|
||||
*
|
||||
* Note that DoVisitEvent is also called with this event.
|
||||
*/
|
||||
virtual void DoVisitLinkEvent(const gd::LinkEvent& linkEvent) {};
|
||||
@@ -203,13 +192,6 @@ protected:
|
||||
virtual void DoVisitInstruction(const gd::Instruction& instruction,
|
||||
bool isCondition) {};
|
||||
|
||||
/**
|
||||
* Called to do some work on an expression of an event.
|
||||
*/
|
||||
virtual void DoVisitEventExpression(const gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
}
|
||||
|
||||
bool shouldStopIteration;
|
||||
};
|
||||
|
||||
@@ -225,7 +207,8 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
|
||||
: public ReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorkerWithContext()
|
||||
: projectScopedContainers(nullptr){};
|
||||
: currentGlobalObjectsContainer(nullptr),
|
||||
currentObjectsContainer(nullptr){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorkerWithContext();
|
||||
|
||||
/**
|
||||
@@ -233,22 +216,30 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
|
||||
* giving the objects container on which the events are applying to.
|
||||
*/
|
||||
void Launch(const gd::EventsList& events,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_) {
|
||||
projectScopedContainers = &projectScopedContainers_;
|
||||
const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_) {
|
||||
currentGlobalObjectsContainer = &globalObjectsContainer_;
|
||||
currentObjectsContainer = &objectsContainer_;
|
||||
ReadOnlyArbitraryEventsWorker::Launch(events);
|
||||
};
|
||||
|
||||
void Launch(gd::EventsList& events) = delete;
|
||||
|
||||
protected:
|
||||
const gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||
const gd::ObjectsContainer& GetGlobalObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *projectScopedContainers;
|
||||
return *currentGlobalObjectsContainer;
|
||||
};
|
||||
const gd::ObjectsContainer& GetObjectsContainer() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *currentObjectsContainer;
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::ProjectScopedContainers* projectScopedContainers;
|
||||
const gd::ObjectsContainer* currentGlobalObjectsContainer;
|
||||
const gd::ObjectsContainer* currentObjectsContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#include "BehaviorDefaultFlagClearer.h"
|
||||
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void BehaviorDefaultFlagClearer::DoVisitObject(gd::Object& object) {
|
||||
};
|
||||
|
||||
void BehaviorDefaultFlagClearer::DoVisitBehavior(gd::Behavior& behavior) {
|
||||
behavior.SetDefaultBehavior(false);
|
||||
};
|
||||
|
||||
BehaviorDefaultFlagClearer::~BehaviorDefaultFlagClearer() {}
|
||||
|
||||
} // namespace gd
|
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <set>
|
||||
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Object;
|
||||
class Behavior;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* @brief This is used for project exports to keep default behaviors in
|
||||
* serialized data used by Runtime.
|
||||
*/
|
||||
class GD_CORE_API BehaviorDefaultFlagClearer : public ArbitraryObjectsWorker {
|
||||
public:
|
||||
BehaviorDefaultFlagClearer() {};
|
||||
virtual ~BehaviorDefaultFlagClearer();
|
||||
|
||||
private:
|
||||
void DoVisitObject(gd::Object& object) override;
|
||||
void DoVisitBehavior(gd::Behavior& behavior) override;
|
||||
};
|
||||
|
||||
}; // namespace gd
|
@@ -4,6 +4,7 @@
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
@@ -31,10 +31,14 @@ namespace gd {
|
||||
class GD_CORE_API ExpressionBehaviorRenamer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionBehaviorRenamer(const gd::String& objectName_,
|
||||
ExpressionBehaviorRenamer(const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_,
|
||||
const gd::String& objectName_,
|
||||
const gd::String& oldBehaviorName_,
|
||||
const gd::String& newBehaviorName_)
|
||||
: hasDoneRenaming(false),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
objectName(objectName_),
|
||||
oldBehaviorName(oldBehaviorName_),
|
||||
newBehaviorName(newBehaviorName_){};
|
||||
@@ -93,6 +97,8 @@ class GD_CORE_API ExpressionBehaviorRenamer
|
||||
|
||||
private:
|
||||
bool hasDoneRenaming;
|
||||
const gd::ObjectsContainer& globalObjectsContainer;
|
||||
const gd::ObjectsContainer& objectsContainer;
|
||||
const gd::String& objectName; // The object name for which the behavior
|
||||
// must be replaced.
|
||||
const gd::String& oldBehaviorName;
|
||||
@@ -126,7 +132,9 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
} else {
|
||||
auto node = parameterValue.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionBehaviorRenamer renamer(objectName,
|
||||
ExpressionBehaviorRenamer renamer(GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
objectName,
|
||||
oldBehaviorName,
|
||||
newBehaviorName);
|
||||
node->Visit(renamer);
|
||||
|
@@ -19,8 +19,6 @@
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -35,11 +33,13 @@ class GD_CORE_API ExpressionObjectsAnalyzer
|
||||
public:
|
||||
ExpressionObjectsAnalyzer(
|
||||
const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &rootType_,
|
||||
EventsContext& context_) :
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
rootType(rootType_),
|
||||
context(context_){};
|
||||
virtual ~ExpressionObjectsAnalyzer(){};
|
||||
@@ -58,25 +58,6 @@ class GD_CORE_API ExpressionObjectsAnalyzer
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, projectScopedContainers.GetObjectsContainersList(), rootType, node);
|
||||
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.name, [&]() {
|
||||
// This is an object variable.
|
||||
context.AddObjectName(projectScopedContainers, node.name);
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
@@ -88,41 +69,26 @@ class GD_CORE_API ExpressionObjectsAnalyzer
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, projectScopedContainers.GetObjectsContainersList(), rootType, node);
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, globalObjectsContainer, objectsContainer, rootType, node);
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
context.AddObjectName(projectScopedContainers, node.identifierName);
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
// Nothing to do (identifier is a variable but not an object).
|
||||
} else {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.identifierName, [&]() {
|
||||
// This is an object variable.
|
||||
context.AddObjectName(projectScopedContainers, node.identifierName);
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
context.AddObjectName(node.identifierName);
|
||||
}
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
if (!node.objectName.empty()) {
|
||||
context.AddObjectName(projectScopedContainers, node.objectName);
|
||||
context.AddObjectName(node.objectName);
|
||||
|
||||
if (!node.behaviorFunctionName.empty()) {
|
||||
context.AddBehaviorName(projectScopedContainers, node.objectName, node.objectFunctionOrBehaviorName);
|
||||
context.AddBehaviorName(node.objectName, node.objectFunctionOrBehaviorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
if (!node.objectName.empty()) {
|
||||
context.AddObjectName(projectScopedContainers, node.objectName);
|
||||
context.AddObjectName(node.objectName);
|
||||
|
||||
if (!node.behaviorName.empty()) {
|
||||
context.AddBehaviorName(projectScopedContainers, node.objectName, node.behaviorName);
|
||||
context.AddBehaviorName(node.objectName, node.behaviorName);
|
||||
}
|
||||
}
|
||||
for (auto& parameter : node.parameters) {
|
||||
@@ -133,7 +99,8 @@ class GD_CORE_API ExpressionObjectsAnalyzer
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String rootType;
|
||||
|
||||
EventsContext& context;
|
||||
@@ -154,7 +121,8 @@ bool EventsContextAnalyzer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
const gd::Expression& parameterValue,
|
||||
const gd::String& lastObjectName) {
|
||||
AnalyzeParameter(platform,
|
||||
GetProjectScopedContainers(),
|
||||
project,
|
||||
layout,
|
||||
parameterMetadata,
|
||||
parameterValue,
|
||||
context,
|
||||
@@ -166,7 +134,8 @@ bool EventsContextAnalyzer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
|
||||
void EventsContextAnalyzer::AnalyzeParameter(
|
||||
const gd::Platform& platform,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
const gd::ParameterMetadata& metadata,
|
||||
const gd::Expression& parameter,
|
||||
EventsContext& context,
|
||||
@@ -174,39 +143,59 @@ void EventsContextAnalyzer::AnalyzeParameter(
|
||||
const auto& value = parameter.GetPlainString();
|
||||
const auto& type = metadata.GetType();
|
||||
if (ParameterMetadata::IsObject(type)) {
|
||||
context.AddObjectName(projectScopedContainers, value);
|
||||
context.AddObjectName(value);
|
||||
} else if (ParameterMetadata::IsExpression("number", type)) {
|
||||
auto node = parameter.GetRootNode();
|
||||
|
||||
ExpressionObjectsAnalyzer analyzer(platform, projectScopedContainers, "number", context);
|
||||
ExpressionObjectsAnalyzer analyzer(platform, project, layout, "number", context);
|
||||
node->Visit(analyzer);
|
||||
} else if (ParameterMetadata::IsExpression("string", type)) {
|
||||
auto node = parameter.GetRootNode();
|
||||
|
||||
ExpressionObjectsAnalyzer analyzer(platform, projectScopedContainers, "string", context);
|
||||
ExpressionObjectsAnalyzer analyzer(platform, project, layout, "string", context);
|
||||
node->Visit(analyzer);
|
||||
} else if (ParameterMetadata::IsBehavior(type)) {
|
||||
context.AddBehaviorName(projectScopedContainers, lastObjectName, value);
|
||||
context.AddBehaviorName(lastObjectName, value);
|
||||
}
|
||||
}
|
||||
|
||||
void EventsContext::AddObjectName(const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::String& objectOrGroupName) {
|
||||
auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
for (auto& realObjectName : objectsContainersList.ExpandObjectName(objectOrGroupName)) {
|
||||
void EventsContext::AddObjectName(const gd::String& objectOrGroupName) {
|
||||
for (auto& realObjectName : ExpandObjectsName(objectOrGroupName)) {
|
||||
objectNames.insert(realObjectName);
|
||||
}
|
||||
referencedObjectOrGroupNames.insert(objectOrGroupName);
|
||||
}
|
||||
|
||||
void EventsContext::AddBehaviorName(const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::String& objectOrGroupName,
|
||||
void EventsContext::AddBehaviorName(const gd::String& objectOrGroupName,
|
||||
const gd::String& behaviorName) {
|
||||
auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
for (auto& realObjectName : objectsContainersList.ExpandObjectName(objectOrGroupName)) {
|
||||
for (auto& realObjectName : ExpandObjectsName(objectOrGroupName)) {
|
||||
objectOrGroupBehaviorNames[realObjectName].insert(behaviorName);
|
||||
}
|
||||
objectOrGroupBehaviorNames[objectOrGroupName].insert(behaviorName);
|
||||
}
|
||||
|
||||
std::vector<gd::String> EventsContext::ExpandObjectsName(
|
||||
const gd::String& objectName) {
|
||||
// Note: this logic is duplicated in EventsCodeGenerator::ExpandObjectsName
|
||||
std::vector<gd::String> realObjects;
|
||||
if (project.GetObjectGroups().Has(objectName))
|
||||
realObjects =
|
||||
project.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
else if (layout.GetObjectGroups().Has(objectName))
|
||||
realObjects = layout.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
else
|
||||
realObjects.push_back(objectName);
|
||||
|
||||
// Ensure that all returned objects actually exists.
|
||||
for (std::size_t i = 0; i < realObjects.size();) {
|
||||
if (!layout.HasObjectNamed(realObjects[i]) &&
|
||||
!project.HasObjectNamed(realObjects[i]))
|
||||
realObjects.erase(realObjects.begin() + i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
return realObjects;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -15,7 +15,6 @@ namespace gd {
|
||||
class BaseEvent;
|
||||
class Platform;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class Project;
|
||||
class Layout;
|
||||
class EventsList;
|
||||
@@ -30,13 +29,12 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API EventsContext {
|
||||
public:
|
||||
EventsContext(){};
|
||||
EventsContext(gd::ObjectsContainer& project_, gd::ObjectsContainer& layout_)
|
||||
: project(project_), layout(layout_){};
|
||||
virtual ~EventsContext(){};
|
||||
|
||||
void AddObjectName(const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::String& objectOrGroupName);
|
||||
void AddBehaviorName(const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::String& objectOrGroupName,
|
||||
void AddObjectName(const gd::String& objectOrGroupName);
|
||||
void AddBehaviorName(const gd::String& objectOrGroupName,
|
||||
const gd::String& behaviorName);
|
||||
|
||||
/**
|
||||
@@ -61,9 +59,13 @@ class GD_CORE_API EventsContext {
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<gd::String> ExpandObjectsName(const gd::String& objectOrGroupName);
|
||||
|
||||
std::set<gd::String> referencedObjectOrGroupNames;
|
||||
std::set<gd::String> objectNames;
|
||||
std::map<gd::String, std::set<gd::String>> objectOrGroupBehaviorNames;
|
||||
gd::ObjectsContainer& project;
|
||||
gd::ObjectsContainer& layout;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -71,10 +73,15 @@ class GD_CORE_API EventsContext {
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsContextAnalyzer : public ArbitraryEventsWorkerWithContext {
|
||||
class GD_CORE_API EventsContextAnalyzer : public ArbitraryEventsWorker {
|
||||
public:
|
||||
EventsContextAnalyzer(const gd::Platform& platform_)
|
||||
: platform(platform_) {};
|
||||
EventsContextAnalyzer(const gd::Platform& platform_,
|
||||
gd::ObjectsContainer& project_,
|
||||
gd::ObjectsContainer& layout_)
|
||||
: platform(platform_),
|
||||
project(project_),
|
||||
layout(layout_),
|
||||
context(project, layout){};
|
||||
virtual ~EventsContextAnalyzer(){};
|
||||
|
||||
/**
|
||||
@@ -83,7 +90,8 @@ class GD_CORE_API EventsContextAnalyzer : public ArbitraryEventsWorkerWithContex
|
||||
const EventsContext& GetEventsContext() { return context; }
|
||||
|
||||
static void AnalyzeParameter(const gd::Platform& platform,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
const gd::ParameterMetadata& metadata,
|
||||
const gd::Expression& parameter,
|
||||
EventsContext& context,
|
||||
@@ -94,6 +102,8 @@ class GD_CORE_API EventsContextAnalyzer : public ArbitraryEventsWorkerWithContex
|
||||
bool isCondition);
|
||||
|
||||
const gd::Platform& platform;
|
||||
gd::ObjectsContainer& project;
|
||||
gd::ObjectsContainer& layout;
|
||||
EventsContext context;
|
||||
};
|
||||
|
||||
|
@@ -19,6 +19,8 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -34,12 +36,14 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
public:
|
||||
IdentifierFinderExpressionNodeWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String& identifierType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
identifierType(identifierType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~IdentifierFinderExpressionNodeWorker(){};
|
||||
@@ -77,14 +81,14 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
const gd::ExpressionMetadata &metadata = isObjectFunction ?
|
||||
MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform,
|
||||
projectScopedContainers.GetObjectsContainersList().GetTypeOfObject(objectName),
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
|
||||
node.functionName):
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
|
||||
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
|
||||
@@ -95,8 +99,9 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
auto& parameterNode = node.parameters[parameterIndex];
|
||||
++parameterIndex;
|
||||
|
||||
if (considerFunction && parameterMetadata.GetType() == "identifier"
|
||||
&& parameterMetadata.GetExtraInfo() == identifierType) {
|
||||
if (considerFunction &&
|
||||
parameterMetadata.GetType() == "identifier" &&
|
||||
parameterMetadata.GetExtraInfo() == identifierType) {
|
||||
// Store the value of the parameter
|
||||
results.insert(
|
||||
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
|
||||
@@ -109,7 +114,8 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
|
||||
std::set<gd::String>& results; ///< Reference to the std::set where argument
|
||||
///< values must be stored.
|
||||
@@ -146,8 +152,8 @@ class GD_CORE_API IdentifierFinderEventWorker
|
||||
platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].GetType() == "identifier"
|
||||
&& instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
|
||||
if (instrInfos.parameters[pNb].GetType() == "identifier" &&
|
||||
instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName) {
|
||||
results.insert(instruction.GetParameter(pNb).GetPlainString());
|
||||
@@ -155,22 +161,23 @@ class GD_CORE_API IdentifierFinderEventWorker
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
|
||||
IdentifierFinderExpressionNodeWorker searcher(
|
||||
results,
|
||||
platform,
|
||||
GetProjectScopedContainers(),
|
||||
GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
identifierType,
|
||||
objectName);
|
||||
node->Visit(searcher);
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
lastObjectParameter =
|
||||
instruction.GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
@@ -223,8 +230,7 @@ void EventsIdentifiersFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(layout.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout));
|
||||
eventWorker.Launch(layout.GetEvents(), project, layout);
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
@@ -235,8 +241,7 @@ void EventsIdentifiersFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(externalEvents.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout));
|
||||
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
@@ -245,8 +250,7 @@ void EventsIdentifiersFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
identifierType,
|
||||
objectName);
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, dependencyLayout));
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsPropertyReplacer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/PropertiesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Go through the nodes and rename properties,
|
||||
* or signal if the instruction must be renamed if a removed property is used.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionPropertyReplacer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionPropertyReplacer(
|
||||
const gd::Platform& platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
const gd::PropertiesContainer& targetPropertiesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewPropertyNames_,
|
||||
const std::unordered_set<gd::String>& removedPropertyNames_)
|
||||
: hasDoneRenaming(false),
|
||||
removedPropertyUsed(false),
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
targetPropertiesContainer(targetPropertiesContainer_),
|
||||
oldToNewPropertyNames(oldToNewPropertyNames_),
|
||||
removedPropertyNames(removedPropertyNames_){};
|
||||
virtual ~ExpressionPropertyReplacer(){};
|
||||
|
||||
bool HasDoneRenaming() const { return hasDoneRenaming; }
|
||||
bool IsRemovedPropertyUsed() const { return removedPropertyUsed; }
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
auto& propertiesContainersList =
|
||||
projectScopedContainers.GetPropertiesContainersList();
|
||||
|
||||
// The node represents a variable or an object name on which a variable
|
||||
// will be accessed, or a property with a child.
|
||||
|
||||
// Match the potential *new* name of the property, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.name),
|
||||
[&]() {
|
||||
// Do nothing, it's an object variable.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}, [&]() {
|
||||
// Do nothing, it's a variable.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}, [&]() {
|
||||
// This is a property, check if it's coming from the target container with
|
||||
// properties to replace.
|
||||
if (propertiesContainersList.HasPropertiesContainer(
|
||||
targetPropertiesContainer)) {
|
||||
// The node represents a property, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemovePropertyOfTargetPropertyContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}, [&]() {
|
||||
// Do nothing, it's a parameter.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}, [&]() {
|
||||
// This is something else - potentially a deleted property.
|
||||
// Check if it's coming from the target container with
|
||||
// properties to replace.
|
||||
if (propertiesContainersList.HasPropertiesContainer(
|
||||
targetPropertiesContainer)) {
|
||||
// The node represents a property, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemovePropertyOfTargetPropertyContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
});
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
auto& propertiesContainersList =
|
||||
projectScopedContainers.GetPropertiesContainersList();
|
||||
|
||||
// Match the potential *new* name of the property, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.identifierName),
|
||||
[&]() {
|
||||
// Do nothing, it's an object variable.
|
||||
}, [&]() {
|
||||
// Do nothing, it's a variable.
|
||||
}, [&]() {
|
||||
// This is a property, check if it's coming from the target container with
|
||||
// properties to replace.
|
||||
if (propertiesContainersList.HasPropertiesContainer(
|
||||
targetPropertiesContainer)) {
|
||||
// The node represents a property, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemovePropertyOfTargetPropertyContainer(node.identifierName);
|
||||
}
|
||||
}, [&]() {
|
||||
// Do nothing, it's a parameter.
|
||||
}, [&]() {
|
||||
// This is something else - potentially a deleted property.
|
||||
// Check if it's coming from the target container with
|
||||
// properties to replace.
|
||||
if (propertiesContainersList.HasPropertiesContainer(
|
||||
targetPropertiesContainer)) {
|
||||
// The node represents a property, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemovePropertyOfTargetPropertyContainer(node.identifierName);
|
||||
}
|
||||
});
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
for (auto& parameter : node.parameters) {
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
bool hasDoneRenaming;
|
||||
bool removedPropertyUsed;
|
||||
|
||||
const gd::String& GetPotentialNewName(const gd::String& oldName) {
|
||||
return oldToNewPropertyNames.count(oldName) >= 1
|
||||
? oldToNewPropertyNames.find(oldName)->second
|
||||
: oldName;
|
||||
}
|
||||
|
||||
bool RenameOrRemovePropertyOfTargetPropertyContainer(
|
||||
gd::String& propertyName) {
|
||||
if (oldToNewPropertyNames.count(propertyName) >= 1) {
|
||||
propertyName = oldToNewPropertyNames.find(propertyName)->second;
|
||||
hasDoneRenaming = true;
|
||||
return true;
|
||||
} else if (removedPropertyNames.count(propertyName) >= 1) {
|
||||
removedPropertyUsed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // Nothing was changed or done.
|
||||
}
|
||||
|
||||
// Scope:
|
||||
const gd::Platform& platform;
|
||||
const gd::ProjectScopedContainers& projectScopedContainers;
|
||||
|
||||
// Renaming or removing to do:
|
||||
const gd::PropertiesContainer& targetPropertiesContainer;
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewPropertyNames;
|
||||
const std::unordered_set<gd::String>& removedPropertyNames;
|
||||
|
||||
gd::String objectNameToUseForVariableAccessor;
|
||||
};
|
||||
|
||||
bool EventsPropertyReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
bool shouldDeleteInstruction = false;
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const gd::String& type = parameterMetadata.GetType();
|
||||
|
||||
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("number", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("string", type))
|
||||
return; // Not an expression that can contain properties.
|
||||
|
||||
auto node = parameterValue.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionPropertyReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
targetPropertiesContainer,
|
||||
oldToNewPropertyNames,
|
||||
removedPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.IsRemovedPropertyUsed()) {
|
||||
shouldDeleteInstruction = true;
|
||||
} else if (renamer.HasDoneRenaming()) {
|
||||
instruction.SetParameter(
|
||||
parameterIndex, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return shouldDeleteInstruction;
|
||||
}
|
||||
|
||||
bool EventsPropertyReplacer::DoVisitEventExpression(
|
||||
gd::Expression& expression, const gd::ParameterMetadata& metadata) {
|
||||
const gd::String& type = metadata.GetType();
|
||||
|
||||
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("number", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("string", type))
|
||||
return false; // Not an expression that can contain properties.
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionPropertyReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
targetPropertiesContainer,
|
||||
oldToNewPropertyNames,
|
||||
removedPropertyNames);
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.IsRemovedPropertyUsed()) {
|
||||
return true;
|
||||
} else if (renamer.HasDoneRenaming()) {
|
||||
expression = ExpressionParser2NodePrinter::PrintNode(*node);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsPropertyReplacer::~EventsPropertyReplacer() {}
|
||||
|
||||
} // namespace gd
|
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class PropertiesContainer;
|
||||
class EventsList;
|
||||
class Platform;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Replace in expressions and in parameters of actions or conditions,
|
||||
* references to the name of a property by another.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsPropertyReplacer
|
||||
: public ArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
EventsPropertyReplacer(
|
||||
const gd::Platform &platform_,
|
||||
const gd::PropertiesContainer &targetPropertiesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewPropertyNames_,
|
||||
const std::unordered_set<gd::String> &removedPropertyNames_)
|
||||
: platform(platform_),
|
||||
targetPropertiesContainer(targetPropertiesContainer_),
|
||||
oldToNewPropertyNames(oldToNewPropertyNames_),
|
||||
removedPropertyNames(removedPropertyNames_){};
|
||||
virtual ~EventsPropertyReplacer();
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
bool DoVisitEventExpression(gd::Expression &expression,
|
||||
const gd::ParameterMetadata &metadata) override;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::PropertiesContainer &targetPropertiesContainer;
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewPropertyNames;
|
||||
const std::unordered_set<gd::String> &removedPropertyNames;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -20,7 +20,6 @@
|
||||
#include "GDCore/IDE/Events/InstructionSentenceFormatter.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -37,12 +36,14 @@ const gd::String EventsRefactorer::searchIgnoredCharacters = ";:,#()";
|
||||
class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionObjectRenamer(const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &rootType_,
|
||||
const gd::String& objectName_,
|
||||
const gd::String& objectNewName_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
rootType(rootType_),
|
||||
hasDoneRenaming(false),
|
||||
objectName(objectName_),
|
||||
@@ -50,13 +51,14 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
virtual ~ExpressionObjectRenamer(){};
|
||||
|
||||
static bool Rename(const gd::Platform &platform,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
const gd::String &rootType,
|
||||
gd::ExpressionNode& node,
|
||||
const gd::String& objectName,
|
||||
const gd::String& objectNewName) {
|
||||
if (gd::ExpressionValidator::HasNoErrors(platform, projectScopedContainers, rootType, node)) {
|
||||
ExpressionObjectRenamer renamer(platform, projectScopedContainers, rootType, objectName, objectNewName);
|
||||
if (gd::ExpressionValidator::HasNoErrors(platform, globalObjectsContainer, objectsContainer, rootType, node)) {
|
||||
ExpressionObjectRenamer renamer(platform, globalObjectsContainer, objectsContainer, rootType, objectName, objectNewName);
|
||||
node.Visit(renamer);
|
||||
|
||||
return renamer.HasDoneRenaming();
|
||||
@@ -81,29 +83,6 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
const auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, objectsContainersList, rootType, node);
|
||||
|
||||
if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
if (node.name == objectName) {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.name, [&]() {
|
||||
// This is an object variable.
|
||||
hasDoneRenaming = true;
|
||||
node.name = objectNewName;
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
@@ -115,29 +94,11 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, projectScopedContainers.GetObjectsContainersList(), rootType, node);
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, globalObjectsContainer, objectsContainer, rootType, node);
|
||||
if (gd::ParameterMetadata::IsObject(type) &&
|
||||
node.identifierName == objectName) {
|
||||
hasDoneRenaming = true;
|
||||
node.identifierName = objectNewName;
|
||||
} else if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
if (node.identifierName == objectName) {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.identifierName, [&]() {
|
||||
// This is an object variable.
|
||||
hasDoneRenaming = true;
|
||||
node.identifierName = objectNewName;
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
@@ -163,7 +124,8 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
const gd::String& objectNewName;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String rootType;
|
||||
};
|
||||
|
||||
@@ -176,23 +138,26 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionObjectFinder(const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &rootType_,
|
||||
const gd::String& searchedObjectName_)
|
||||
const gd::String& objectName_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
rootType(rootType_),
|
||||
hasObject(false),
|
||||
searchedObjectName(searchedObjectName_){};
|
||||
objectName(objectName_){};
|
||||
virtual ~ExpressionObjectFinder(){};
|
||||
|
||||
static bool CheckIfHasObject(const gd::Platform &platform,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
const gd::String &rootType,
|
||||
gd::ExpressionNode& node,
|
||||
const gd::String& objectName) {
|
||||
if (gd::ExpressionValidator::HasNoErrors(platform, projectScopedContainers, rootType, node)) {
|
||||
ExpressionObjectFinder finder(platform, projectScopedContainers, rootType, objectName);
|
||||
if (gd::ExpressionValidator::HasNoErrors(platform, globalObjectsContainer, objectsContainer, rootType, node)) {
|
||||
ExpressionObjectFinder finder(platform, globalObjectsContainer, objectsContainer, rootType, objectName);
|
||||
node.Visit(finder);
|
||||
|
||||
return finder.HasFoundObject();
|
||||
@@ -217,28 +182,6 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
const auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, objectsContainersList, rootType, node);
|
||||
|
||||
if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
if (node.name == searchedObjectName) {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.name, [&]() {
|
||||
// This is an object variable.
|
||||
hasObject = true;
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
@@ -250,36 +193,19 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, projectScopedContainers.GetObjectsContainersList(), rootType, node);
|
||||
auto type = gd::ExpressionTypeFinder::GetType(platform, globalObjectsContainer, objectsContainer, rootType, node);
|
||||
if (gd::ParameterMetadata::IsObject(type) &&
|
||||
node.identifierName == searchedObjectName) {
|
||||
node.identifierName == objectName) {
|
||||
hasObject = true;
|
||||
} else if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
if (node.identifierName == searchedObjectName) {
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.identifierName, [&]() {
|
||||
// This is an object variable.
|
||||
hasObject = true;
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
if (node.objectName == searchedObjectName) {
|
||||
if (node.objectName == objectName) {
|
||||
hasObject = true;
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
if (node.objectName == searchedObjectName) {
|
||||
if (node.objectName == objectName) {
|
||||
hasObject = true;
|
||||
}
|
||||
for (auto& parameter : node.parameters) {
|
||||
@@ -290,15 +216,17 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
|
||||
private:
|
||||
bool hasObject;
|
||||
const gd::String& searchedObjectName;
|
||||
const gd::String& objectName;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String rootType;
|
||||
};
|
||||
|
||||
bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -317,7 +245,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
|
||||
actions[aId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
@@ -327,7 +255,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
|
||||
actions[aId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
@@ -337,7 +265,8 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
if (!actions[aId].GetSubInstructions().empty())
|
||||
somethingModified =
|
||||
RenameObjectInActions(platform,
|
||||
projectScopedContainers,
|
||||
project,
|
||||
layout,
|
||||
actions[aId].GetSubInstructions(),
|
||||
oldName,
|
||||
newName) ||
|
||||
@@ -349,7 +278,8 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RenameObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -369,7 +299,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
@@ -379,7 +309,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
@@ -389,7 +319,8 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
if (!conditions[cId].GetSubInstructions().empty())
|
||||
somethingModified =
|
||||
RenameObjectInConditions(platform,
|
||||
projectScopedContainers,
|
||||
project,
|
||||
layout,
|
||||
conditions[cId].GetSubInstructions(),
|
||||
oldName,
|
||||
newName) ||
|
||||
@@ -401,7 +332,8 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
|
||||
bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -416,7 +348,7 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
parameterMetadata.GetType())) {
|
||||
auto node = expression.GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
|
||||
expression = ExpressionParser2NodePrinter::PrintNode(*node);
|
||||
}
|
||||
}
|
||||
@@ -425,7 +357,7 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
parameterMetadata.GetType())) {
|
||||
auto node = expression.GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) {
|
||||
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
|
||||
expression = ExpressionParser2NodePrinter::PrintNode(*node);
|
||||
}
|
||||
}
|
||||
@@ -434,7 +366,8 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
}
|
||||
|
||||
void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -443,14 +376,14 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
events[i].GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
bool somethingModified = RenameObjectInConditions(
|
||||
platform, projectScopedContainers, *conditionsVectors[j], oldName, newName);
|
||||
platform, project, layout, *conditionsVectors[j], oldName, newName);
|
||||
}
|
||||
|
||||
vector<gd::InstructionsList*> actionsVectors =
|
||||
events[i].GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
bool somethingModified = RenameObjectInActions(
|
||||
platform, projectScopedContainers, *actionsVectors[j], oldName, newName);
|
||||
platform, project, layout, *actionsVectors[j], oldName, newName);
|
||||
}
|
||||
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata>>
|
||||
@@ -460,7 +393,8 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ParameterMetadata parameterMetadata =
|
||||
expressionsWithMetadata[j].second;
|
||||
bool somethingModified = RenameObjectInEventParameters(platform,
|
||||
projectScopedContainers,
|
||||
project,
|
||||
layout,
|
||||
*expression,
|
||||
parameterMetadata,
|
||||
oldName,
|
||||
@@ -469,7 +403,8 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
|
||||
if (events[i].CanHaveSubEvents())
|
||||
RenameObjectInEvents(platform,
|
||||
projectScopedContainers,
|
||||
project,
|
||||
layout,
|
||||
events[i].GetSubEvents(),
|
||||
oldName,
|
||||
newName);
|
||||
@@ -477,7 +412,8 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
}
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
@@ -499,7 +435,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "number", *node, name)) {
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
@@ -509,7 +445,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "string", *node, name)) {
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
@@ -523,7 +459,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
} else if (!actions[aId].GetSubInstructions().empty())
|
||||
somethingModified =
|
||||
RemoveObjectInActions(platform,
|
||||
projectScopedContainers,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
actions[aId].GetSubInstructions(),
|
||||
name) ||
|
||||
somethingModified;
|
||||
@@ -534,7 +471,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
@@ -557,7 +495,7 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "number", *node, name)) {
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
@@ -567,7 +505,7 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "string", *node, name)) {
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
@@ -581,7 +519,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
} else if (!conditions[cId].GetSubInstructions().empty())
|
||||
somethingModified =
|
||||
RemoveObjectInConditions(platform,
|
||||
projectScopedContainers,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
conditions[cId].GetSubInstructions(),
|
||||
name) ||
|
||||
somethingModified;
|
||||
@@ -591,7 +530,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
}
|
||||
|
||||
void EventsRefactorer::RemoveObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& globalObjectsContainer,
|
||||
gd::ObjectsContainer& objectsContainer,
|
||||
gd::EventsList& events,
|
||||
gd::String name) {
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
@@ -599,19 +539,19 @@ void EventsRefactorer::RemoveObjectInEvents(const gd::Platform& platform,
|
||||
events[i].GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
bool conditionsModified = RemoveObjectInConditions(
|
||||
platform, projectScopedContainers, *conditionsVectors[j], name);
|
||||
platform, globalObjectsContainer, objectsContainer, *conditionsVectors[j], name);
|
||||
}
|
||||
|
||||
vector<gd::InstructionsList*> actionsVectors =
|
||||
events[i].GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
bool actionsModified = RemoveObjectInActions(
|
||||
platform, projectScopedContainers, *actionsVectors[j], name);
|
||||
platform, globalObjectsContainer, objectsContainer, *actionsVectors[j], name);
|
||||
}
|
||||
|
||||
if (events[i].CanHaveSubEvents())
|
||||
RemoveObjectInEvents(
|
||||
platform, projectScopedContainers, events[i].GetSubEvents(), name);
|
||||
platform, globalObjectsContainer, objectsContainer, events[i].GetSubEvents(), name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,20 +587,20 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
bool eventModified = false;
|
||||
|
||||
auto allExpressionsWithMetadata = events[i].GetAllExpressionsWithMetadata();
|
||||
for (auto& expressionAndMetadata : allExpressionsWithMetadata) {
|
||||
gd::Expression* expression = expressionAndMetadata.first;
|
||||
|
||||
std::vector<gd::Expression*> allObjectExpressions =
|
||||
events[i].GetAllObjectExpressions();
|
||||
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
|
||||
gd::String newExpressionPlainString =
|
||||
matchCase ? expression->GetPlainString().FindAndReplace(
|
||||
matchCase ? allObjectExpressions[j]->GetPlainString().FindAndReplace(
|
||||
toReplace, newString, true)
|
||||
: ReplaceAllOccurrencesCaseInsensitive(
|
||||
expression->GetPlainString(),
|
||||
allObjectExpressions[j]->GetPlainString(),
|
||||
toReplace,
|
||||
newString);
|
||||
|
||||
if (newExpressionPlainString != expression->GetPlainString()) {
|
||||
*expression = gd::Expression(newExpressionPlainString);
|
||||
if (newExpressionPlainString !=
|
||||
allObjectExpressions[j]->GetPlainString()) {
|
||||
*allObjectExpressions[j] = gd::Expression(newExpressionPlainString);
|
||||
|
||||
if (!eventModified) {
|
||||
modifiedEvents.push_back(EventsSearchResult(
|
||||
@@ -875,14 +815,14 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
bool eventAddedInResults = false;
|
||||
|
||||
auto allExpressionsWithMetadata = events[i].GetAllExpressionsWithMetadata();
|
||||
for (auto& expressionAndMetadata : allExpressionsWithMetadata) {
|
||||
gd::Expression* expression = expressionAndMetadata.first;
|
||||
|
||||
std::vector<gd::Expression*> allObjectExpressions =
|
||||
events[i].GetAllObjectExpressions();
|
||||
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
|
||||
size_t foundPosition =
|
||||
matchCase
|
||||
? expression->GetPlainString().find(search)
|
||||
: expression->GetPlainString().FindCaseInsensitive(search);
|
||||
? allObjectExpressions[j]->GetPlainString().find(search)
|
||||
: allObjectExpressions[j]->GetPlainString().FindCaseInsensitive(
|
||||
search);
|
||||
|
||||
if (foundPosition != gd::String::npos && !eventAddedInResults) {
|
||||
results.push_back(EventsSearchResult(
|
||||
|
@@ -14,8 +14,6 @@
|
||||
namespace gd {
|
||||
class EventsList;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class ProjectScopedContainers;
|
||||
class Platform;
|
||||
class ExternalEvents;
|
||||
class BaseEvent;
|
||||
@@ -81,7 +79,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* events ).
|
||||
*/
|
||||
static void RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -90,7 +89,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* Remove all actions or conditions using an object
|
||||
*/
|
||||
static void RemoveObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::EventsList& events,
|
||||
gd::String name);
|
||||
|
||||
@@ -136,7 +136,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -148,7 +149,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -161,7 +163,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
*/
|
||||
static bool RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -173,7 +176,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
@@ -183,7 +187,8 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
|
@@ -1,404 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsVariableReplacer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Go through the nodes and rename variables,
|
||||
* or signal if the instruction must be renamed if a removed variable is used.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionVariableReplacer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionVariableReplacer(
|
||||
const gd::Platform& platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
const gd::VariablesContainer& targetVariablesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewVariableNames_,
|
||||
const std::unordered_set<gd::String>& removedVariableNames_)
|
||||
: hasDoneRenaming(false),
|
||||
removedVariableUsed(false),
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
forcedInitialVariablesContainer(nullptr),
|
||||
targetVariablesContainer(targetVariablesContainer_),
|
||||
oldToNewVariableNames(oldToNewVariableNames_),
|
||||
removedVariableNames(removedVariableNames_){};
|
||||
virtual ~ExpressionVariableReplacer(){};
|
||||
|
||||
void SetForcedInitialVariablesContainer(
|
||||
const gd::VariablesContainer* forcedInitialVariablesContainer_) {
|
||||
forcedInitialVariablesContainer = forcedInitialVariablesContainer_;
|
||||
}
|
||||
|
||||
bool HasDoneRenaming() const { return hasDoneRenaming; }
|
||||
bool IsRemovedVariableUsed() const { return removedVariableUsed; }
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
// The node represents a variable or an object name on which a variable
|
||||
// will be accessed.
|
||||
|
||||
if (forcedInitialVariablesContainer) {
|
||||
// A scope was forced. Honor it: it means this node represents a variable
|
||||
// of the forced variables container.
|
||||
if (forcedInitialVariablesContainer == &targetVariablesContainer) {
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Match the potential *new* name of the variable, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.name),
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
// Remember the object name.
|
||||
objectNameToUseForVariableAccessor = node.name;
|
||||
if (node.child) node.child->Visit(*this);
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
},
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
},
|
||||
[&]() {
|
||||
// This is a property.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
},
|
||||
[&]() {
|
||||
// This is a parameter.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
},
|
||||
[&]() {
|
||||
// This is something else - potentially a deleted variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
});
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
auto& objectsContainersList =
|
||||
projectScopedContainers.GetObjectsContainersList();
|
||||
if (!objectNameToUseForVariableAccessor.empty()) {
|
||||
if (objectsContainersList.HasVariablesContainer(
|
||||
objectNameToUseForVariableAccessor, targetVariablesContainer)) {
|
||||
// The node represents an object variable, and this object variables are
|
||||
// the target. Do the replacement or removals:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
}
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
auto& objectsContainersList =
|
||||
projectScopedContainers.GetObjectsContainersList();
|
||||
|
||||
// The node represents a variable or an object variable in an expression
|
||||
// (and if it's a variable reference or a value does not have any importance
|
||||
// here).
|
||||
|
||||
if (forcedInitialVariablesContainer) {
|
||||
// A scope was forced. Honor it: it means this node represents a variable
|
||||
// of the forced variables container.
|
||||
if (forcedInitialVariablesContainer == &targetVariablesContainer) {
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.identifierName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Match the potential *new* name of the variable, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.identifierName),
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
if (objectsContainersList.HasVariablesContainer(
|
||||
node.identifierName, targetVariablesContainer)) {
|
||||
// The node represents an object variable, and this object variables
|
||||
// are the target. Do the replacement or removals:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.childIdentifierName);
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.identifierName);
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// This is a property.
|
||||
},
|
||||
[&]() {
|
||||
// This is a parameter.
|
||||
},
|
||||
[&]() {
|
||||
// This is something else - potentially a deleted variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.identifierName);
|
||||
}
|
||||
});
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
const gd::ExpressionMetadata& metadata =
|
||||
MetadataProvider::GetFunctionCallMetadata(
|
||||
platform, projectScopedContainers.GetObjectsContainersList(), node);
|
||||
|
||||
for (size_t parameterIndex = 0; parameterIndex < node.parameters.size();
|
||||
++parameterIndex) {
|
||||
const gd::ParameterMetadata* parameterMetadata =
|
||||
MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
platform,
|
||||
projectScopedContainers.GetObjectsContainersList(),
|
||||
node,
|
||||
parameterIndex);
|
||||
|
||||
// Handle legacy pre-scoped variable parameters: in this case, we
|
||||
// force the "scope" at which starts the evalution of variables.
|
||||
if (parameterMetadata && parameterMetadata->GetValueTypeMetadata()
|
||||
.IsLegacyPreScopedVariable()) {
|
||||
const gd::VariablesContainer* oldForcedInitialVariablesContainer =
|
||||
forcedInitialVariablesContainer;
|
||||
|
||||
forcedInitialVariablesContainer = nullptr;
|
||||
if (parameterMetadata->GetType() == "globalvar") {
|
||||
forcedInitialVariablesContainer =
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetTopMostVariablesContainer();
|
||||
} else if (parameterMetadata->GetType() == "scenevar") {
|
||||
forcedInitialVariablesContainer =
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetBottomMostVariablesContainer();
|
||||
} else if (parameterMetadata->GetType() == "objectvar") {
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(
|
||||
platform,
|
||||
projectScopedContainers.GetObjectsContainersList(),
|
||||
node.objectName,
|
||||
*node.parameters[parameterIndex].get());
|
||||
forcedInitialVariablesContainer =
|
||||
projectScopedContainers.GetObjectsContainersList()
|
||||
.GetObjectOrGroupVariablesContainer(objectName);
|
||||
}
|
||||
|
||||
node.parameters[parameterIndex]->Visit(*this);
|
||||
forcedInitialVariablesContainer = oldForcedInitialVariablesContainer;
|
||||
} else {
|
||||
// For any other parameter, there is no special treatment being needed.
|
||||
node.parameters[parameterIndex]->Visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
bool hasDoneRenaming;
|
||||
bool removedVariableUsed;
|
||||
|
||||
const gd::String& GetPotentialNewName(const gd::String& oldName) {
|
||||
return oldToNewVariableNames.count(oldName) >= 1
|
||||
? oldToNewVariableNames.find(oldName)->second
|
||||
: oldName;
|
||||
}
|
||||
|
||||
bool RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
gd::String& variableName) {
|
||||
if (oldToNewVariableNames.count(variableName) >= 1) {
|
||||
variableName = oldToNewVariableNames.find(variableName)->second;
|
||||
hasDoneRenaming = true;
|
||||
return true;
|
||||
} else if (removedVariableNames.count(variableName) >= 1) {
|
||||
removedVariableUsed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // Nothing was changed or done.
|
||||
}
|
||||
|
||||
// Scope:
|
||||
const gd::Platform& platform;
|
||||
const gd::ProjectScopedContainers& projectScopedContainers;
|
||||
const gd::VariablesContainer* forcedInitialVariablesContainer;
|
||||
|
||||
// Renaming or removing to do:
|
||||
const gd::VariablesContainer& targetVariablesContainer;
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewVariableNames;
|
||||
const std::unordered_set<gd::String>& removedVariableNames;
|
||||
|
||||
gd::String objectNameToUseForVariableAccessor;
|
||||
};
|
||||
|
||||
const gd::VariablesContainer*
|
||||
EventsVariableReplacer::FindForcedVariablesContainerIfAny(
|
||||
const gd::String& type, const gd::String& lastObjectName) {
|
||||
// Handle legacy pre-scoped variable parameters: in this case, we
|
||||
// force the "scope" at which starts the evalution of variables.
|
||||
if (type == "objectvar") {
|
||||
return GetProjectScopedContainers()
|
||||
.GetObjectsContainersList()
|
||||
.GetObjectOrGroupVariablesContainer(lastObjectName);
|
||||
} else if (type == "globalvar") {
|
||||
return GetProjectScopedContainers()
|
||||
.GetVariablesContainersList()
|
||||
.GetTopMostVariablesContainer();
|
||||
} else if (type == "scenevar") {
|
||||
return GetProjectScopedContainers()
|
||||
.GetVariablesContainersList()
|
||||
.GetBottomMostVariablesContainer();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EventsVariableReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
bool shouldDeleteInstruction = false;
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const gd::String& type = parameterMetadata.GetType();
|
||||
|
||||
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("number", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("string", type))
|
||||
return; // Not an expression that can contain variables.
|
||||
|
||||
auto node = parameterValue.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionVariableReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
targetVariablesContainer,
|
||||
oldToNewVariableNames,
|
||||
removedVariableNames);
|
||||
renamer.SetForcedInitialVariablesContainer(
|
||||
FindForcedVariablesContainerIfAny(type, lastObjectName));
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.IsRemovedVariableUsed()) {
|
||||
shouldDeleteInstruction = true;
|
||||
} else if (renamer.HasDoneRenaming()) {
|
||||
instruction.SetParameter(
|
||||
parameterIndex, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return shouldDeleteInstruction;
|
||||
}
|
||||
|
||||
bool EventsVariableReplacer::DoVisitEventExpression(
|
||||
gd::Expression& expression, const gd::ParameterMetadata& metadata) {
|
||||
const gd::String& type = metadata.GetType();
|
||||
|
||||
if (!gd::ParameterMetadata::IsExpression("variable", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("number", type) &&
|
||||
!gd::ParameterMetadata::IsExpression("string", type))
|
||||
return false; // Not an expression that can contain variables.
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionVariableReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
targetVariablesContainer,
|
||||
oldToNewVariableNames,
|
||||
removedVariableNames);
|
||||
renamer.SetForcedInitialVariablesContainer(
|
||||
FindForcedVariablesContainerIfAny(type, ""));
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.IsRemovedVariableUsed()) {
|
||||
return true;
|
||||
} else if (renamer.HasDoneRenaming()) {
|
||||
expression = ExpressionParser2NodePrinter::PrintNode(*node);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsVariableReplacer::~EventsVariableReplacer() {}
|
||||
|
||||
} // namespace gd
|
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class VariablesContainer;
|
||||
class EventsList;
|
||||
class Platform;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Replace in expressions and in parameters of actions or conditions,
|
||||
* references to the name of a variable by another.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsVariableReplacer
|
||||
: public ArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
EventsVariableReplacer(
|
||||
const gd::Platform &platform_,
|
||||
const gd::VariablesContainer &targetVariablesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewVariableNames_,
|
||||
const std::unordered_set<gd::String> &removedVariableNames_)
|
||||
: platform(platform_),
|
||||
targetVariablesContainer(targetVariablesContainer_),
|
||||
oldToNewVariableNames(oldToNewVariableNames_),
|
||||
removedVariableNames(removedVariableNames_){};
|
||||
virtual ~EventsVariableReplacer();
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
bool DoVisitEventExpression(gd::Expression &expression,
|
||||
const gd::ParameterMetadata &metadata) override;
|
||||
|
||||
const gd::VariablesContainer *FindForcedVariablesContainerIfAny(
|
||||
const gd::String &type, const gd::String &lastObjectName);
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::VariablesContainer &targetVariablesContainer;
|
||||
gd::String objectName;
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewVariableNames;
|
||||
const std::unordered_set<gd::String> &removedVariableNames;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -17,7 +17,6 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
|
||||
@@ -35,12 +34,14 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
public:
|
||||
VariableFinderExpressionNodeWorker(std::set<gd::String>& results_,
|
||||
const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String& parameterType_,
|
||||
const gd::String& objectName_ = "")
|
||||
: results(results_),
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
parameterType(parameterType_),
|
||||
objectName(objectName_){};
|
||||
virtual ~VariableFinderExpressionNodeWorker(){};
|
||||
@@ -59,9 +60,6 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
// We don't check variables or object variables here, because object variables only work
|
||||
// if the variable is already declared.
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
@@ -72,10 +70,7 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
// We don't check object variables here, because object variables only work
|
||||
// if the variable is already declared.
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
bool considerFunction = objectName.empty() || node.objectName == objectName;
|
||||
@@ -84,7 +79,7 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
const gd::ExpressionMetadata &metadata = isObjectFunction ?
|
||||
MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform,
|
||||
projectScopedContainers.GetObjectsContainersList().GetTypeOfObject(objectName),
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
|
||||
node.functionName):
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
|
||||
|
||||
@@ -115,7 +110,8 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
|
||||
std::set<gd::String>& results; ///< Reference to the std::set where argument
|
||||
///< values must be stored.
|
||||
@@ -167,7 +163,8 @@ class GD_CORE_API VariableFinderEventWorker
|
||||
VariableFinderExpressionNodeWorker searcher(
|
||||
results,
|
||||
platform,
|
||||
GetProjectScopedContainers(),
|
||||
GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
parameterType,
|
||||
objectName);
|
||||
node->Visit(searcher);
|
||||
@@ -255,8 +252,7 @@ void EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(layout.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout));
|
||||
eventWorker.Launch(layout.GetEvents(), project, layout);
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
@@ -267,8 +263,7 @@ void EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(externalEvents.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout));
|
||||
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
@@ -277,8 +272,7 @@ void EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
parameterType,
|
||||
objectName);
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(),
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, dependencyLayout));
|
||||
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,15 +10,21 @@ namespace gd {
|
||||
const gd::ParameterMetadata
|
||||
ExpressionCompletionDescription::badParameterMetadata;
|
||||
|
||||
const gd::ObjectConfiguration
|
||||
ExpressionCompletionDescription::badObjectConfiguration;
|
||||
|
||||
/**
|
||||
* \brief Turn an ExpressionCompletionDescription to a string.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
ExpressionCompletionDescription const& value) {
|
||||
os << value.ToString();
|
||||
os << "{ " << value.GetCompletionKind() << ", " << value.GetType() << ", "
|
||||
<< value.GetPrefix() << ", " << value.GetObjectName() << ", "
|
||||
<< value.GetBehaviorName() << ", "
|
||||
<< (value.IsExact() ? "exact" : "non-exact") << ", "
|
||||
<< (value.IsLastParameter() ? "last parameter" : "not last parameter")
|
||||
<< ", "
|
||||
<< (value.HasParameterMetadata()
|
||||
? gd::String::From(&value.GetParameterMetadata())
|
||||
: "no parameter metadata")
|
||||
<< " }";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,6 @@
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
@@ -41,10 +40,11 @@ class GD_CORE_API ExpressionLeftSideTypeFinder : public ExpressionParser2NodeWor
|
||||
* operations.
|
||||
*/
|
||||
static const gd::String GetType(const gd::Platform &platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
gd::ExpressionNode& node) {
|
||||
gd::ExpressionLeftSideTypeFinder typeFinder(
|
||||
platform, objectsContainersList);
|
||||
platform, globalObjectsContainer, objectsContainer);
|
||||
node.Visit(typeFinder);
|
||||
return typeFinder.GetType();
|
||||
}
|
||||
@@ -53,9 +53,11 @@ class GD_CORE_API ExpressionLeftSideTypeFinder : public ExpressionParser2NodeWor
|
||||
|
||||
protected:
|
||||
ExpressionLeftSideTypeFinder(const gd::Platform &platform_,
|
||||
const gd::ObjectsContainersList &objectsContainersList_)
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_)
|
||||
: platform(platform_),
|
||||
objectsContainersList(objectsContainersList_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
type("unknown") {};
|
||||
|
||||
const gd::String &GetType() {
|
||||
@@ -83,7 +85,7 @@ class GD_CORE_API ExpressionLeftSideTypeFinder : public ExpressionParser2NodeWor
|
||||
}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
|
||||
platform, objectsContainersList, node);
|
||||
platform, globalObjectsContainer, objectsContainer, node);
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
type = "unknown";
|
||||
}
|
||||
@@ -111,7 +113,8 @@ class GD_CORE_API ExpressionLeftSideTypeFinder : public ExpressionParser2NodeWor
|
||||
gd::String type;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ObjectsContainersList &objectsContainersList;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String rootType;
|
||||
};
|
||||
|
||||
|
@@ -21,7 +21,6 @@
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
@@ -32,7 +31,7 @@ namespace gd {
|
||||
/**
|
||||
* \brief Find the type of the expression or sub-expression that a given node
|
||||
* represents.
|
||||
*
|
||||
*
|
||||
* The type returned by this worker is a mix of:
|
||||
* - an expected type looking up like a parameter declaration
|
||||
* - an actual type looking down, but only looking at the most left branch
|
||||
@@ -51,11 +50,12 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
* sub-expression that a given node represents.
|
||||
*/
|
||||
static const gd::String GetType(const gd::Platform &platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
const gd::String &rootType,
|
||||
gd::ExpressionNode& node) {
|
||||
gd::ExpressionTypeFinder typeFinder(
|
||||
platform, objectsContainersList, rootType);
|
||||
platform, globalObjectsContainer, objectsContainer, rootType);
|
||||
node.Visit(typeFinder);
|
||||
return typeFinder.GetType();
|
||||
}
|
||||
@@ -64,10 +64,12 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
|
||||
protected:
|
||||
ExpressionTypeFinder(const gd::Platform &platform_,
|
||||
const gd::ObjectsContainersList &objectsContainersList_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &rootType_)
|
||||
: platform(platform_),
|
||||
objectsContainersList(objectsContainersList_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
rootType(rootType_),
|
||||
type(ExpressionTypeFinder::unknownType),
|
||||
child(nullptr) {};
|
||||
@@ -112,8 +114,9 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
type = ExpressionTypeFinder::unknownType;
|
||||
}
|
||||
auto leftSideType = gd::ExpressionLeftSideTypeFinder::GetType(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
platform,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
node);
|
||||
if (leftSideType == ExpressionTypeFinder::numberType
|
||||
|| leftSideType == ExpressionTypeFinder::stringType) {
|
||||
@@ -126,7 +129,7 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
if (child == nullptr) {
|
||||
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
|
||||
platform, objectsContainersList, node);
|
||||
platform, globalObjectsContainer, objectsContainer, node);
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
VisitParent(node);
|
||||
}
|
||||
@@ -138,7 +141,8 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
const gd::ParameterMetadata* parameterMetadata =
|
||||
gd::MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
node,
|
||||
*child);
|
||||
if (parameterMetadata == nullptr || parameterMetadata->GetType().empty()) {
|
||||
@@ -158,8 +162,9 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
else if (rootType == ExpressionTypeFinder::numberOrStringType) {
|
||||
auto leftSideType = gd::ExpressionLeftSideTypeFinder::GetType(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
platform,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
node);
|
||||
if (leftSideType == ExpressionTypeFinder::numberType
|
||||
|| leftSideType == ExpressionTypeFinder::stringType) {
|
||||
@@ -183,7 +188,8 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
ExpressionNode *child;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ObjectsContainersList &objectsContainersList;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String rootType;
|
||||
};
|
||||
|
||||
|
@@ -11,20 +11,16 @@
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
#include "GDCore/Project/VariablesContainersList.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -63,167 +59,69 @@ size_t GetMaximumParametersNumber(
|
||||
|
||||
} // namespace
|
||||
|
||||
bool ExpressionValidator::ValidateObjectVariableOrVariableOrProperty(
|
||||
const gd::IdentifierNode& identifier) {
|
||||
auto validateVariableTypeForExpression =
|
||||
[this, &identifier](gd::Variable::Type type) {
|
||||
// Collections type can't be used directly in expressions, a child
|
||||
// must be accessed.
|
||||
if (type == Variable::Structure) {
|
||||
RaiseTypeError(_("You need to specify the name of the child variable "
|
||||
"to access. For example: `MyVariable.child`."),
|
||||
identifier.identifierNameLocation);
|
||||
} else if (type == Variable::Array) {
|
||||
RaiseTypeError(_("You need to specify the name of the child variable "
|
||||
"to access. For example: `MyVariable[0]`."),
|
||||
identifier.identifierNameLocation);
|
||||
ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::FunctionCallNode& function) {
|
||||
|
||||
} else {
|
||||
// Number, string or boolean variables can be used in expressions.
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const auto& variablesContainersList = projectScopedContainers.GetVariablesContainersList();
|
||||
const auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
const auto& propertiesContainersList = projectScopedContainers.GetPropertiesContainersList();
|
||||
const auto& parametersVectorsList = projectScopedContainers.GetParametersVectorsList();
|
||||
|
||||
return projectScopedContainers.MatchIdentifierWithName<bool>(identifier.identifierName,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
if (identifier.childIdentifierName.empty()) {
|
||||
RaiseTypeError(_("An object variable or expression should be entered."),
|
||||
identifier.identifierNameLocation);
|
||||
return true; // We should have found a variable.
|
||||
}
|
||||
|
||||
if (!objectsContainersList.HasObjectOrGroupWithVariableNamed(identifier.identifierName, identifier.childIdentifierName)) {
|
||||
RaiseTypeError(_("This variable does not exist on this object or group."),
|
||||
identifier.identifierNameLocation);
|
||||
return true; // We should have found a variable.
|
||||
}
|
||||
|
||||
return true; // We found a variable.
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
|
||||
// Try to identify a declared variable with the name (and maybe the child
|
||||
// variable).
|
||||
|
||||
const gd::Variable& variable =
|
||||
variablesContainersList.Get(identifier.identifierName);
|
||||
|
||||
if (identifier.childIdentifierName.empty()) {
|
||||
// Just the root variable is accessed, check it can be used in an
|
||||
// expression.
|
||||
validateVariableTypeForExpression(variable.GetType());
|
||||
|
||||
return true; // We found a variable.
|
||||
} else {
|
||||
// A child variable is accessed, check it can be used in an expression.
|
||||
if (!variable.HasChild(identifier.childIdentifierName)) {
|
||||
RaiseTypeError(_("No child variable with this name found."),
|
||||
identifier.childIdentifierNameLocation);
|
||||
|
||||
return true; // We should have found a variable.
|
||||
}
|
||||
|
||||
const gd::Variable& childVariable =
|
||||
variable.GetChild(identifier.childIdentifierName);
|
||||
return true; // We found a variable.
|
||||
}
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
if (!identifier.childIdentifierName.empty()) {
|
||||
RaiseTypeError(_("Accessing a child variable of a property is not possible - just write the property name."),
|
||||
identifier.childIdentifierNameLocation);
|
||||
return true; // We found a property, even if the child is not allowed.
|
||||
}
|
||||
|
||||
return true; // We found a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
if (!identifier.childIdentifierName.empty()) {
|
||||
RaiseTypeError(_("Accessing a child variable of a parameter is not possible - just write the parameter name."),
|
||||
identifier.childIdentifierNameLocation);
|
||||
return true; // We found a parameter, even if the child is not allowed.
|
||||
}
|
||||
|
||||
const auto& parameter = gd::ParameterMetadataTools::Get(parametersVectorsList, identifier.identifierName);
|
||||
const auto& valueTypeMetadata = parameter.GetValueTypeMetadata();
|
||||
if (!valueTypeMetadata.IsNumber() && !valueTypeMetadata.IsString() && !valueTypeMetadata.IsBoolean()) {
|
||||
RaiseTypeError(_("This parameter is not a string, number or boolean - it can't be used in an expression."),
|
||||
identifier.identifierNameLocation);
|
||||
return true; // We found a parameter, even though the type is incompatible.
|
||||
}
|
||||
|
||||
return true; // We found a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
const gd::FunctionCallNode& function) {
|
||||
ReportAnyError(function);
|
||||
|
||||
gd::String objectType = function.objectName.empty() ? "" :
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, function.objectName);
|
||||
|
||||
gd::String behaviorType = function.behaviorName.empty() ? "" :
|
||||
GetTypeOfBehavior(globalObjectsContainer, objectsContainer, function.behaviorName);
|
||||
|
||||
auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
|
||||
gd::String objectType =
|
||||
function.objectName.empty()
|
||||
? ""
|
||||
: objectsContainersList.GetTypeOfObject(function.objectName);
|
||||
|
||||
gd::String behaviorType = function.behaviorName.empty()
|
||||
? ""
|
||||
: objectsContainersList.GetTypeOfBehavior(function.behaviorName);
|
||||
|
||||
const gd::ExpressionMetadata& metadata =
|
||||
function.behaviorName.empty()
|
||||
? function.objectName.empty()
|
||||
? MetadataProvider::GetAnyExpressionMetadata(
|
||||
platform, function.functionName)
|
||||
: MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform, objectType, function.functionName)
|
||||
: MetadataProvider::GetBehaviorAnyExpressionMetadata(
|
||||
platform, behaviorType, function.functionName);
|
||||
const gd::ExpressionMetadata &metadata = function.behaviorName.empty() ?
|
||||
function.objectName.empty() ?
|
||||
MetadataProvider::GetAnyExpressionMetadata(platform, function.functionName) :
|
||||
MetadataProvider::GetObjectAnyExpressionMetadata(
|
||||
platform, objectType, function.functionName) :
|
||||
MetadataProvider::GetBehaviorAnyExpressionMetadata(
|
||||
platform, behaviorType, function.functionName);
|
||||
|
||||
Type returnType = StringToType(metadata.GetReturnType());
|
||||
|
||||
if (!function.objectName.empty() &&
|
||||
!objectsContainersList.HasObjectOrGroupNamed(function.objectName)) {
|
||||
!globalObjectsContainer.HasObjectNamed(function.objectName) &&
|
||||
!globalObjectsContainer.GetObjectGroups().Has(function.objectName) &&
|
||||
!objectsContainer.HasObjectNamed(function.objectName) &&
|
||||
!objectsContainer.GetObjectGroups().Has(function.objectName)) {
|
||||
RaiseTypeError(_("This object doesn't exist."),
|
||||
function.objectNameLocation,
|
||||
/*isFatal=*/false);
|
||||
function.objectNameLocation, /*isFatal=*/false);
|
||||
return returnType;
|
||||
}
|
||||
|
||||
if (!function.behaviorName.empty() &&
|
||||
!objectsContainersList.HasBehaviorInObjectOrGroup(function.objectName,
|
||||
function.behaviorName)) {
|
||||
!gd::HasBehaviorInObjectOrGroup(globalObjectsContainer, objectsContainer,
|
||||
function.objectName,
|
||||
function.behaviorName)) {
|
||||
RaiseTypeError(_("This behavior is not attached to this object."),
|
||||
function.behaviorNameLocation,
|
||||
/*isFatal=*/false);
|
||||
function.behaviorNameLocation, /*isFatal=*/false);
|
||||
return returnType;
|
||||
}
|
||||
|
||||
if (!function.objectName.empty() &&
|
||||
// If the function needs a capability on the object that may not be
|
||||
// covered by all objects, check it now.
|
||||
!metadata.GetRequiredBaseObjectCapability().empty()) {
|
||||
const gd::ObjectMetadata& objectMetadata =
|
||||
// If the function needs a capability on the object that may not be covered
|
||||
// by all objects, check it now.
|
||||
!metadata.GetRequiredBaseObjectCapability().empty()) {
|
||||
const gd::ObjectMetadata &objectMetadata =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
|
||||
if (!objectMetadata.IsSupportedBaseObjectCapability(
|
||||
metadata.GetRequiredBaseObjectCapability())) {
|
||||
RaiseTypeError(
|
||||
_("This expression exists, but it can't be used on this object."),
|
||||
function.objectNameLocation);
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
|
||||
RaiseError("invalid_function_name",
|
||||
_("Cannot find an expression with this name: ") +
|
||||
function.functionName + "\n" +
|
||||
_("Double check that you've not made any typo in the name."),
|
||||
function.location);
|
||||
return returnType;
|
||||
RaiseError(
|
||||
"invalid_function_name",
|
||||
_("Cannot find an expression with this name: ") +
|
||||
function.functionName + "\n" +
|
||||
_("Double check that you've not made any typo in the name."),
|
||||
function.location);
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// Validate the type of the function
|
||||
@@ -238,9 +136,9 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
} else if (parentType != Type::Number &&
|
||||
parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You tried to use an expression that returns a "
|
||||
"number, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
function.location);
|
||||
"number, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
function.location);
|
||||
return returnType;
|
||||
}
|
||||
} else if (returnType == Type::String) {
|
||||
@@ -254,16 +152,16 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
} else if (parentType != Type::String &&
|
||||
parentType != Type::NumberOrString) {
|
||||
RaiseTypeError(_("You tried to use an expression that returns a "
|
||||
"string, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
function.location);
|
||||
"string, but another type is expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
function.location);
|
||||
return returnType;
|
||||
}
|
||||
} else {
|
||||
if (parentType != returnType) {
|
||||
RaiseTypeError(
|
||||
_("You tried to use an expression with the wrong return type:") +
|
||||
" " + TypeToString(returnType),
|
||||
_("You tried to use an expression with the wrong return type:") + " " +
|
||||
TypeToString(returnType),
|
||||
function.location);
|
||||
return returnType;
|
||||
}
|
||||
@@ -272,12 +170,10 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
// Validate parameters count
|
||||
size_t minParametersCount = GetMinimumParametersNumber(
|
||||
metadata.parameters,
|
||||
ExpressionParser2::WrittenParametersFirstIndex(function.objectName,
|
||||
function.behaviorName));
|
||||
ExpressionParser2::WrittenParametersFirstIndex(function.objectName, function.behaviorName));
|
||||
size_t maxParametersCount = GetMaximumParametersNumber(
|
||||
metadata.parameters,
|
||||
ExpressionParser2::WrittenParametersFirstIndex(function.objectName,
|
||||
function.behaviorName));
|
||||
ExpressionParser2::WrittenParametersFirstIndex(function.objectName, function.behaviorName));
|
||||
if (function.parameters.size() < minParametersCount ||
|
||||
function.parameters.size() > maxParametersCount) {
|
||||
gd::String expectedCountMessage =
|
||||
@@ -291,29 +187,28 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
if (function.parameters.size() < minParametersCount) {
|
||||
RaiseError(
|
||||
"too_few_parameters",
|
||||
_("You have not entered enough parameters for the expression.") +
|
||||
" " + expectedCountMessage,
|
||||
_("You have not entered enough parameters for the expression.") + " " +
|
||||
expectedCountMessage,
|
||||
function.location);
|
||||
} else {
|
||||
RaiseError(
|
||||
"extra_parameter",
|
||||
_("This parameter was not expected by this expression. Remove it "
|
||||
"or verify that you've entered the proper expression name.") +
|
||||
" " + expectedCountMessage,
|
||||
ExpressionParserLocation(function.parameters[maxParametersCount]
|
||||
->location.GetStartPosition(),
|
||||
function.location.GetEndPosition() - 1));
|
||||
"or verify that you've entered the proper expression name.") + " " +
|
||||
expectedCountMessage,
|
||||
ExpressionParserLocation(
|
||||
function.parameters[maxParametersCount]->location.GetStartPosition(),
|
||||
function.location.GetEndPosition() - 1));
|
||||
}
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// TODO: reverse the order of diagnostic?
|
||||
size_t writtenParametersFirstIndex =
|
||||
ExpressionParser2::WrittenParametersFirstIndex(function.objectName,
|
||||
function.behaviorName);
|
||||
ExpressionParser2::WrittenParametersFirstIndex(
|
||||
function.objectName, function.behaviorName);
|
||||
int metadataIndex = writtenParametersFirstIndex;
|
||||
for (int parameterIndex = 0; parameterIndex < function.parameters.size();
|
||||
parameterIndex++) {
|
||||
for (int parameterIndex = 0; parameterIndex < function.parameters.size(); parameterIndex++) {
|
||||
auto& parameter = function.parameters[parameterIndex];
|
||||
while (metadata.GetParameters()[metadataIndex].IsCodeOnly()) {
|
||||
// The sizes are already checked above.
|
||||
@@ -321,45 +216,45 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
}
|
||||
auto& parameterMetadata = metadata.GetParameters()[metadataIndex];
|
||||
|
||||
if (!parameterMetadata.IsOptional() ||
|
||||
dynamic_cast<EmptyNode*>(parameter.get()) == nullptr) {
|
||||
if (!parameterMetadata.IsOptional() || dynamic_cast<EmptyNode*>(parameter.get()) == nullptr) {
|
||||
auto currentParentType = parentType;
|
||||
parentType = StringToType(parameterMetadata.GetType());
|
||||
parameter->Visit(*this);
|
||||
parentType = currentParentType;
|
||||
|
||||
const gd::String& expectedParameterType = parameterMetadata.GetType();
|
||||
|
||||
const gd::String &expectedParameterType = parameterMetadata.GetType();
|
||||
if (gd::ParameterMetadata::IsExpression(
|
||||
ExpressionValidator::variableTypeString, expectedParameterType)) {
|
||||
if (dynamic_cast<IdentifierNode*>(parameter.get()) == nullptr &&
|
||||
dynamic_cast<VariableNode*>(parameter.get()) == nullptr) {
|
||||
RaiseError("malformed_variable_parameter",
|
||||
_("A variable name was expected but something else was "
|
||||
"written. Enter just the name of the variable for this "
|
||||
"parameter."),
|
||||
parameter->location);
|
||||
ExpressionValidator::variableTypeString, expectedParameterType)) {
|
||||
if (dynamic_cast<IdentifierNode *>(parameter.get()) == nullptr
|
||||
&& dynamic_cast<VariableNode *>(parameter.get()) == nullptr) {
|
||||
RaiseError(
|
||||
"malformed_variable_parameter",
|
||||
_("A variable name was expected but something else was "
|
||||
"written. Enter just the name of the variable for this "
|
||||
"parameter."),
|
||||
parameter->location);
|
||||
}
|
||||
} else if (gd::ParameterMetadata::IsObject(expectedParameterType)) {
|
||||
if (dynamic_cast<IdentifierNode*>(parameter.get()) == nullptr) {
|
||||
RaiseError("malformed_object_parameter",
|
||||
_("An object name was expected but something else was "
|
||||
"written. Enter just the name of the object for this "
|
||||
"parameter."),
|
||||
parameter->location);
|
||||
if (dynamic_cast<IdentifierNode *>(parameter.get()) == nullptr) {
|
||||
RaiseError(
|
||||
"malformed_object_parameter",
|
||||
_("An object name was expected but something else was "
|
||||
"written. Enter just the name of the object for this "
|
||||
"parameter."),
|
||||
parameter->location);
|
||||
}
|
||||
}
|
||||
// String and number are already checked in children.
|
||||
else if (!gd::ParameterMetadata::IsExpression(
|
||||
ExpressionValidator::numberTypeString,
|
||||
expectedParameterType) &&
|
||||
!gd::ParameterMetadata::IsExpression(
|
||||
ExpressionValidator::stringTypeString,
|
||||
expectedParameterType)) {
|
||||
RaiseError("unknown_parameter_type",
|
||||
_("This function is improperly set up. Reach out to the "
|
||||
"extension developer or a GDevelop maintainer to fix "
|
||||
"this issue"),
|
||||
parameter->location);
|
||||
ExpressionValidator::numberTypeString, expectedParameterType)
|
||||
&& !gd::ParameterMetadata::IsExpression(
|
||||
ExpressionValidator::stringTypeString, expectedParameterType)) {
|
||||
RaiseError(
|
||||
"unknown_parameter_type",
|
||||
_("This function is improperly set up. Reach out to the "
|
||||
"extension developer or a GDevelop maintainer to fix "
|
||||
"this issue"),
|
||||
parameter->location);
|
||||
}
|
||||
}
|
||||
metadataIndex++;
|
||||
@@ -367,60 +262,55 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// TODO factorize in a file with an enum and helpers?
|
||||
const gd::String ExpressionValidator::unknownTypeString = "unknown";
|
||||
const gd::String ExpressionValidator::numberTypeString = "number";
|
||||
const gd::String ExpressionValidator::stringTypeString = "string";
|
||||
const gd::String ExpressionValidator::numberOrStringTypeString =
|
||||
"number|string";
|
||||
const gd::String ExpressionValidator::variableTypeString = "variable";
|
||||
const gd::String ExpressionValidator::objectTypeString = "object";
|
||||
const gd::String ExpressionValidator::emptyTypeString = "empty";
|
||||
// TODO factorize in a file with an enum and helpers?
|
||||
const gd::String ExpressionValidator::unknownTypeString = "unknown";
|
||||
const gd::String ExpressionValidator::numberTypeString = "number";
|
||||
const gd::String ExpressionValidator::stringTypeString = "string";
|
||||
const gd::String ExpressionValidator::numberOrStringTypeString = "number|string";
|
||||
const gd::String ExpressionValidator::variableTypeString = "variable";
|
||||
const gd::String ExpressionValidator::objectTypeString = "object";
|
||||
const gd::String ExpressionValidator::emptyTypeString = "empty";
|
||||
|
||||
const gd::String& ExpressionValidator::TypeToString(Type type) {
|
||||
switch (type) {
|
||||
case Type::Unknown:
|
||||
const gd::String &ExpressionValidator::TypeToString(Type type) {
|
||||
switch (type) {
|
||||
case Type::Unknown:
|
||||
return unknownTypeString;
|
||||
case Type::Number:
|
||||
case Type::Number:
|
||||
return numberTypeString;
|
||||
case Type::String:
|
||||
case Type::String:
|
||||
return stringTypeString;
|
||||
case Type::NumberOrString:
|
||||
case Type::NumberOrString:
|
||||
return numberOrStringTypeString;
|
||||
case Type::Variable:
|
||||
case Type::Variable:
|
||||
return variableTypeString;
|
||||
case Type::Object:
|
||||
case Type::Object:
|
||||
return objectTypeString;
|
||||
case Type::Empty:
|
||||
case Type::Empty:
|
||||
return emptyTypeString;
|
||||
}
|
||||
return unknownTypeString;
|
||||
}
|
||||
return unknownTypeString;
|
||||
}
|
||||
|
||||
ExpressionValidator::Type ExpressionValidator::StringToType(
|
||||
const gd::String& type) {
|
||||
if (type == ExpressionValidator::numberTypeString ||
|
||||
gd::ParameterMetadata::IsExpression(ExpressionValidator::numberTypeString,
|
||||
type)) {
|
||||
return Type::Number;
|
||||
ExpressionValidator::Type ExpressionValidator::StringToType(const gd::String &type) {
|
||||
if (type == ExpressionValidator::numberTypeString
|
||||
|| gd::ParameterMetadata::IsExpression(ExpressionValidator::numberTypeString, type)) {
|
||||
return Type::Number;
|
||||
}
|
||||
if (type == ExpressionValidator::stringTypeString
|
||||
|| gd::ParameterMetadata::IsExpression(ExpressionValidator::stringTypeString, type)) {
|
||||
return Type::String;
|
||||
}
|
||||
if (type == ExpressionValidator::numberOrStringTypeString) {
|
||||
return Type::NumberOrString;
|
||||
}
|
||||
if (type == ExpressionValidator::variableTypeString
|
||||
|| gd::ParameterMetadata::IsExpression(ExpressionValidator::variableTypeString, type)) {
|
||||
return Type::Variable;
|
||||
}
|
||||
if (type == ExpressionValidator::objectTypeString
|
||||
|| gd::ParameterMetadata::IsObject(type)) {
|
||||
return Type::Object;
|
||||
}
|
||||
return Type::Unknown;
|
||||
}
|
||||
if (type == ExpressionValidator::stringTypeString ||
|
||||
gd::ParameterMetadata::IsExpression(ExpressionValidator::stringTypeString,
|
||||
type)) {
|
||||
return Type::String;
|
||||
}
|
||||
if (type == ExpressionValidator::numberOrStringTypeString) {
|
||||
return Type::NumberOrString;
|
||||
}
|
||||
if (type == ExpressionValidator::variableTypeString ||
|
||||
gd::ParameterMetadata::IsExpression(
|
||||
ExpressionValidator::variableTypeString, type)) {
|
||||
return Type::Variable;
|
||||
}
|
||||
if (type == ExpressionValidator::objectTypeString ||
|
||||
gd::ParameterMetadata::IsObject(type)) {
|
||||
return Type::Object;
|
||||
}
|
||||
return Type::Unknown;
|
||||
}
|
||||
} // namespace gd
|
||||
|
@@ -13,18 +13,13 @@
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/VariablesContainersList.h"
|
||||
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class VariablesContainer;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
class VariablesContainersList;
|
||||
class ProjectScopedContainers;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -38,13 +33,14 @@ namespace gd {
|
||||
class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionValidator(const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers & projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &rootType_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
parentType(StringToType(gd::ParameterMetadata::GetExpressionValueType(rootType_))),
|
||||
childType(Type::Unknown),
|
||||
forbidsUsageOfBracketsBecauseParentIsObject(false) {};
|
||||
childType(Type::Unknown) {};
|
||||
virtual ~ExpressionValidator(){};
|
||||
|
||||
/**
|
||||
@@ -52,10 +48,11 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
* any error including non-fatal ones.
|
||||
*/
|
||||
static bool HasNoErrors(const gd::Platform &platform,
|
||||
const gd::ProjectScopedContainers & projectScopedContainers,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
const gd::String &rootType,
|
||||
gd::ExpressionNode& node) {
|
||||
gd::ExpressionValidator validator(platform, projectScopedContainers, rootType);
|
||||
gd::ExpressionValidator validator(platform, globalObjectsContainer, objectsContainer, rootType);
|
||||
node.Visit(validator);
|
||||
return validator.GetAllErrors().empty();
|
||||
}
|
||||
@@ -85,7 +82,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
|
||||
node.leftHandSide->Visit(*this);
|
||||
const Type leftType = childType;
|
||||
|
||||
@@ -188,69 +185,28 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
if (parentType == Type::Variable) {
|
||||
childType = Type::Variable;
|
||||
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
} else if (parentType == Type::String || parentType == Type::Number || parentType == Type::NumberOrString) {
|
||||
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
|
||||
childType = parentType;
|
||||
|
||||
const auto& variablesContainersList = projectScopedContainers.GetVariablesContainersList();
|
||||
const auto& objectsContainersList = projectScopedContainers.GetObjectsContainersList();
|
||||
const auto& propertiesContainerList = projectScopedContainers.GetPropertiesContainersList();
|
||||
|
||||
forbidsUsageOfBracketsBecauseParentIsObject = false;
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(node.name,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
|
||||
// While understood by the parser, it's forbidden to use the bracket notation just after
|
||||
// an object name (`MyObject["MyVariable"]`).
|
||||
forbidsUsageOfBracketsBecauseParentIsObject = true;
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
// Being in this node implies that there is at least a child - which is not supported for properties.
|
||||
RaiseTypeError(_("Accessing a child variable of a property is not possible - just write the property name."),
|
||||
node.location);
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
// Being in this node implies that there is at least a child - which is not supported for parameters.
|
||||
RaiseTypeError(_("Accessing a child variable of a parameter is not possible - just write the parameter name."),
|
||||
node.location);
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
RaiseTypeError(_("No object, variable or property with this name found."),
|
||||
node.location);
|
||||
});
|
||||
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
|
||||
forbidsUsageOfBracketsBecauseParentIsObject = false;
|
||||
} else {
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
childType = Type::Variable;
|
||||
if (parentType == Type::String) {
|
||||
RaiseTypeError(_("Variables must be surrounded by VariableString()."),
|
||||
node.location);
|
||||
} else if (parentType == Type::Number) {
|
||||
RaiseTypeError(_("Variables must be surrounded by Variable()."),
|
||||
node.location);
|
||||
} else if (parentType == Type::NumberOrString) {
|
||||
RaiseTypeError(
|
||||
_("Variables must be surrounded by Variable() or VariableString()."),
|
||||
node.location);
|
||||
} else if (parentType != Type::Variable) {
|
||||
RaiseTypeError(_("You entered a variable, but this type was expected:") +
|
||||
" " + TypeToString(parentType),
|
||||
node.location);
|
||||
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
// In the case we accessed an object variable (`MyObject.MyVariable`),
|
||||
// brackets can now be used (`MyObject.MyVariable["MyChildVariable"]` is now valid).
|
||||
forbidsUsageOfBracketsBecauseParentIsObject = false;
|
||||
|
||||
if (node.child) {
|
||||
node.child->Visit(*this);
|
||||
}
|
||||
@@ -259,15 +215,6 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
VariableBracketAccessorNode& node) override {
|
||||
ReportAnyError(node);
|
||||
|
||||
if (forbidsUsageOfBracketsBecauseParentIsObject) {
|
||||
RaiseError("brackets_not_allowed_for_objects",
|
||||
_("You can't use the brackets to access an object variable. "
|
||||
"Use a dot followed by the variable name, like this: "
|
||||
"`MyObject.MyVariable`."),
|
||||
node.location);
|
||||
}
|
||||
forbidsUsageOfBracketsBecauseParentIsObject = false;
|
||||
|
||||
Type currentParentType = parentType;
|
||||
parentType = Type::NumberOrString;
|
||||
node.expression->Visit(*this);
|
||||
@@ -280,29 +227,19 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
ReportAnyError(node);
|
||||
if (parentType == Type::String) {
|
||||
if (!ValidateObjectVariableOrVariableOrProperty(node)) {
|
||||
// The identifier is not a variable, so either the variable is not properly declared
|
||||
// or it's a text without quotes.
|
||||
RaiseTypeError(_("You must wrap your text inside double quotes "
|
||||
"(example: \"Hello world\")."),
|
||||
node.location);
|
||||
}
|
||||
RaiseTypeError(_("You must wrap your text inside double quotes "
|
||||
"(example: \"Hello world\")."),
|
||||
node.location);
|
||||
}
|
||||
else if (parentType == Type::Number) {
|
||||
if (!ValidateObjectVariableOrVariableOrProperty(node)) {
|
||||
// The identifier is not a variable, so the variable is not properly declared.
|
||||
RaiseTypeError(
|
||||
_("You must enter a number."), node.location);
|
||||
}
|
||||
RaiseTypeError(
|
||||
_("You must enter a number."), node.location);
|
||||
}
|
||||
else if (parentType == Type::NumberOrString) {
|
||||
if (!ValidateObjectVariableOrVariableOrProperty(node)) {
|
||||
// The identifier is not a variable, so either the variable is not properly declared
|
||||
// or it's a text without quotes.
|
||||
RaiseTypeError(
|
||||
_("You must enter a number or a text, wrapped inside double quotes (example: \"Hello world\"), or a variable name."),
|
||||
node.location);
|
||||
}
|
||||
RaiseTypeError(
|
||||
_("You must enter a number or a text, wrapped inside double quotes "
|
||||
"(example: \"Hello world\")."),
|
||||
node.location);
|
||||
}
|
||||
else if (parentType != Type::Object && parentType != Type::Variable) {
|
||||
// It can't happen.
|
||||
@@ -341,7 +278,6 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
private:
|
||||
enum Type {Unknown = 0, Number, String, NumberOrString, Variable, Object, Empty};
|
||||
Type ValidateFunction(const gd::FunctionCallNode& function);
|
||||
bool ValidateObjectVariableOrVariableOrProperty(const gd::IdentifierNode& identifier);
|
||||
|
||||
void ReportAnyError(const ExpressionNode& node, bool isFatal = true) {
|
||||
if (node.diagnostic && node.diagnostic->IsError()) {
|
||||
@@ -355,7 +291,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
}
|
||||
}
|
||||
|
||||
void RaiseError(const gd::String &type,
|
||||
void RaiseError(const gd::String &type,
|
||||
const gd::String &message, const ExpressionParserLocation &location, bool isFatal = true) {
|
||||
auto diagnostic = gd::make_unique<ExpressionParserError>(
|
||||
type, message, location);
|
||||
@@ -393,11 +329,11 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
|
||||
std::vector<ExpressionParserDiagnostic*> fatalErrors;
|
||||
std::vector<ExpressionParserDiagnostic*> allErrors;
|
||||
std::vector<std::unique_ptr<ExpressionParserDiagnostic>> supplementalErrors;
|
||||
Type childType; ///< The type "discovered" down the tree and passed up.
|
||||
Type parentType; ///< The type "required" by the top of the tree.
|
||||
bool forbidsUsageOfBracketsBecauseParentIsObject;
|
||||
Type childType;
|
||||
Type parentType;
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -32,10 +31,6 @@ namespace gd {
|
||||
* \brief Find the object name that should be used as a context of the
|
||||
* expression or sub-expression that a given node represents.
|
||||
*
|
||||
* This is needed because of the legacy convention where a "objectvar"
|
||||
* parameter represents a variable of the object represented by the previous "object"
|
||||
* parameter.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWorker {
|
||||
@@ -46,11 +41,12 @@ class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWo
|
||||
* context of the expression or sub-expression that a given node represents.
|
||||
*/
|
||||
static const gd::String GetObjectName(const gd::Platform &platform,
|
||||
const gd::ObjectsContainersList &objectsContainersList,
|
||||
const gd::ObjectsContainer &globalObjectsContainer,
|
||||
const gd::ObjectsContainer &objectsContainer,
|
||||
const gd::String& rootObjectName,
|
||||
gd::ExpressionNode& node) {
|
||||
gd::ExpressionVariableOwnerFinder typeFinder(
|
||||
platform, objectsContainersList, rootObjectName);
|
||||
platform, globalObjectsContainer, objectsContainer, rootObjectName);
|
||||
node.Visit(typeFinder);
|
||||
return typeFinder.GetObjectName();
|
||||
}
|
||||
@@ -59,10 +55,12 @@ class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWo
|
||||
|
||||
protected:
|
||||
ExpressionVariableOwnerFinder(const gd::Platform &platform_,
|
||||
const gd::ObjectsContainersList &objectsContainersList_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String& rootObjectName_)
|
||||
: platform(platform_),
|
||||
objectsContainersList(objectsContainersList_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
rootObjectName(rootObjectName_),
|
||||
objectName(""),
|
||||
variableNode(nullptr) {};
|
||||
@@ -128,8 +126,9 @@ class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWo
|
||||
}
|
||||
const gd::ParameterMetadata* parameterMetadata =
|
||||
MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
platform,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
functionCall,
|
||||
parameterIndex);
|
||||
if (parameterMetadata == nullptr
|
||||
@@ -143,8 +142,9 @@ class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWo
|
||||
for (int previousIndex = parameterIndex - 1; previousIndex >= 0; previousIndex--) {
|
||||
const gd::ParameterMetadata* previousParameterMetadata =
|
||||
MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
platform,
|
||||
objectsContainersList,
|
||||
platform,
|
||||
globalObjectsContainer,
|
||||
objectsContainer,
|
||||
functionCall,
|
||||
previousIndex);
|
||||
if (previousParameterMetadata != nullptr
|
||||
@@ -162,7 +162,8 @@ class GD_CORE_API ExpressionVariableOwnerFinder : public ExpressionParser2NodeWo
|
||||
gd::ExpressionNode *variableNode;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ObjectsContainersList &objectsContainersList;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
const gd::String &rootObjectName;
|
||||
};
|
||||
|
||||
|
@@ -31,14 +31,16 @@ namespace gd {
|
||||
class GD_CORE_API ExpressionParameterMover
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionParameterMover(const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
ExpressionParameterMover(const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_,
|
||||
const gd::String& behaviorType_,
|
||||
const gd::String& objectType_,
|
||||
const gd::String& functionName_,
|
||||
std::size_t oldIndex_,
|
||||
std::size_t newIndex_)
|
||||
: hasDoneMoving(false),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
behaviorType(behaviorType_),
|
||||
objectType(objectType_),
|
||||
functionName(functionName_),
|
||||
@@ -96,16 +98,16 @@ class GD_CORE_API ExpressionParameterMover
|
||||
// This refactor only applies on events object functions
|
||||
// and events object functions doesn't exist yet.
|
||||
// This is a dead code.
|
||||
const gd::String& thisObjectType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfObject(node.objectName);
|
||||
const gd::String& thisObjectType = gd::GetTypeOfObject(
|
||||
globalObjectsContainer, objectsContainer, node.objectName);
|
||||
if (thisObjectType == objectType) {
|
||||
moveParameter(node.parameters, 1);
|
||||
hasDoneMoving = true;
|
||||
}
|
||||
} else if (!behaviorType.empty() && !node.behaviorName.empty()) {
|
||||
// Move parameter of a behavior function
|
||||
const gd::String& thisBehaviorType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfBehavior(node.behaviorName);
|
||||
const gd::String& thisBehaviorType = gd::GetTypeOfBehavior(
|
||||
globalObjectsContainer, objectsContainer, node.behaviorName);
|
||||
if (thisBehaviorType == behaviorType) {
|
||||
moveParameter(node.parameters, 2);
|
||||
hasDoneMoving = true;
|
||||
@@ -124,7 +126,8 @@ class GD_CORE_API ExpressionParameterMover
|
||||
|
||||
private:
|
||||
bool hasDoneMoving;
|
||||
const gd::ProjectScopedContainers& projectScopedContainers;
|
||||
const gd::ObjectsContainer& globalObjectsContainer;
|
||||
const gd::ObjectsContainer& objectsContainer;
|
||||
const gd::String& behaviorType; // The behavior type of the function which
|
||||
// must have a parameter moved (optional).
|
||||
const gd::String& objectType; // The object type of the function which
|
||||
@@ -152,7 +155,8 @@ bool ExpressionsParameterMover::DoVisitInstruction(gd::Instruction& instruction,
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionParameterMover mover(GetProjectScopedContainers(),
|
||||
ExpressionParameterMover mover(GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
behaviorType,
|
||||
objectType,
|
||||
functionName,
|
||||
|
@@ -23,20 +23,22 @@
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Go through the nodes and change the given function name to a new name.
|
||||
* \brief Go through the nodes and change the given object name to a new one.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionFunctionRenamer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionFunctionRenamer(const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
ExpressionFunctionRenamer(const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_,
|
||||
const gd::String& behaviorType_,
|
||||
const gd::String& objectType_,
|
||||
const gd::String& oldFunctionName_,
|
||||
const gd::String& newFunctionName_)
|
||||
: hasDoneRenaming(false),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
behaviorType(behaviorType_),
|
||||
objectType(objectType_),
|
||||
oldFunctionName(oldFunctionName_),
|
||||
@@ -69,18 +71,16 @@ class GD_CORE_API ExpressionFunctionRenamer
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
// Nothing to do as this is either a variable, an object variable a property or something else
|
||||
// but not an expression.
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
if (!node.behaviorFunctionName.empty()) {
|
||||
// Behavior function name
|
||||
if (!behaviorType.empty() &&
|
||||
node.behaviorFunctionName == oldFunctionName) {
|
||||
const gd::String& thisBehaviorType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfBehavior(
|
||||
node.objectFunctionOrBehaviorName);
|
||||
const gd::String& thisBehaviorType =
|
||||
gd::GetTypeOfBehavior(globalObjectsContainer,
|
||||
objectsContainer,
|
||||
node.objectFunctionOrBehaviorName);
|
||||
if (thisBehaviorType == behaviorType) {
|
||||
node.behaviorFunctionName = newFunctionName;
|
||||
hasDoneRenaming = true;
|
||||
@@ -90,8 +90,8 @@ class GD_CORE_API ExpressionFunctionRenamer
|
||||
// Object function name
|
||||
if (behaviorType.empty() && !objectType.empty() &&
|
||||
node.objectFunctionOrBehaviorName == oldFunctionName) {
|
||||
const gd::String& thisObjectType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfObject(node.objectName);
|
||||
const gd::String& thisObjectType = gd::GetTypeOfObject(
|
||||
globalObjectsContainer, objectsContainer, node.objectName);
|
||||
if (thisObjectType == objectType) {
|
||||
node.objectFunctionOrBehaviorName = newFunctionName;
|
||||
hasDoneRenaming = true;
|
||||
@@ -104,16 +104,16 @@ class GD_CORE_API ExpressionFunctionRenamer
|
||||
if (behaviorType.empty() && !objectType.empty() &&
|
||||
!node.objectName.empty()) {
|
||||
// Replace an object function
|
||||
const gd::String& thisObjectType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfObject(node.objectName);
|
||||
const gd::String& thisObjectType = gd::GetTypeOfObject(
|
||||
globalObjectsContainer, objectsContainer, node.objectName);
|
||||
if (thisObjectType == objectType) {
|
||||
node.functionName = newFunctionName;
|
||||
hasDoneRenaming = true;
|
||||
}
|
||||
} else if (!behaviorType.empty() && !node.behaviorName.empty()) {
|
||||
// Replace a behavior function
|
||||
const gd::String& thisBehaviorType = projectScopedContainers
|
||||
.GetObjectsContainersList().GetTypeOfBehavior(node.behaviorName);
|
||||
const gd::String& thisBehaviorType = gd::GetTypeOfBehavior(
|
||||
globalObjectsContainer, objectsContainer, node.behaviorName);
|
||||
if (thisBehaviorType == behaviorType) {
|
||||
node.functionName = newFunctionName;
|
||||
hasDoneRenaming = true;
|
||||
@@ -132,7 +132,8 @@ class GD_CORE_API ExpressionFunctionRenamer
|
||||
|
||||
private:
|
||||
bool hasDoneRenaming;
|
||||
const gd::ProjectScopedContainers& projectScopedContainers;
|
||||
const gd::ObjectsContainer& globalObjectsContainer;
|
||||
const gd::ObjectsContainer& objectsContainer;
|
||||
const gd::String& behaviorType; // The behavior type for which the expression
|
||||
// must be replaced (optional).
|
||||
const gd::String& objectType; // The object type for which the expression
|
||||
@@ -158,7 +159,8 @@ bool ExpressionsRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionFunctionRenamer renamer(GetProjectScopedContainers(),
|
||||
ExpressionFunctionRenamer renamer(GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
behaviorType,
|
||||
objectType,
|
||||
oldFunctionName,
|
||||
|
@@ -34,12 +34,13 @@ class GD_CORE_API ExpressionIdentifierStringFinder
|
||||
public:
|
||||
ExpressionIdentifierStringFinder(
|
||||
const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_,
|
||||
const gd::String &expressionPlainString_,
|
||||
const gd::String ¶meterType_, const gd::String &objectName_,
|
||||
const gd::String &layerName_, const gd::String &oldName_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
: platform(platform_), globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
expressionPlainString(expressionPlainString_),
|
||||
parameterType(parameterType_), objectName(objectName_),
|
||||
layerName(layerName_), oldName(oldName_){};
|
||||
@@ -81,27 +82,16 @@ protected:
|
||||
void OnVisitFunctionCallNode(FunctionCallNode &node) override {
|
||||
gd::String lastLayerName;
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
platform, projectScopedContainers.GetObjectsContainersList(), node,
|
||||
platform, globalObjectsContainer, objectsContainer, node,
|
||||
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||
std::unique_ptr<gd::ExpressionNode> ¶meterNode,
|
||||
size_t parameterIndex, const gd::String &lastObjectName) {
|
||||
if (parameterMetadata.GetType() == "layer") {
|
||||
if (parameterNode->location.GetEndPosition() -
|
||||
parameterNode->location.GetStartPosition() <
|
||||
2) {
|
||||
// This is either the base layer or an invalid layer name.
|
||||
// Keep it as is.
|
||||
lastLayerName = expressionPlainString.substr(
|
||||
parameterNode->location.GetStartPosition(),
|
||||
parameterNode->location.GetEndPosition() -
|
||||
parameterNode->location.GetStartPosition());
|
||||
} else {
|
||||
// Remove quotes, so it can be compared to the layer name.
|
||||
lastLayerName = expressionPlainString.substr(
|
||||
parameterNode->location.GetStartPosition() + 1,
|
||||
parameterNode->location.GetEndPosition() -
|
||||
parameterNode->location.GetStartPosition() - 2);
|
||||
}
|
||||
// Remove quotes, it won't match if it's not a literal anyway.
|
||||
lastLayerName = expressionPlainString.substr(
|
||||
parameterNode->location.GetStartPosition() + 1,
|
||||
parameterNode->location.GetEndPosition() -
|
||||
parameterNode->location.GetStartPosition() - 2);
|
||||
}
|
||||
if (parameterMetadata.GetType() == parameterType) {
|
||||
auto parameterExpressionPlainString = expressionPlainString.substr(
|
||||
@@ -122,7 +112,8 @@ protected:
|
||||
|
||||
private:
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
/// It's used to extract parameter content.
|
||||
const gd::String &expressionPlainString;
|
||||
const gd::String &oldName;
|
||||
@@ -152,15 +143,9 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
|
||||
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||
const gd::String &lastObjectName) {
|
||||
if (parameterMetadata.GetType() == "layer") {
|
||||
if (parameterValue.GetPlainString().length() < 2) {
|
||||
// This is either the base layer or an invalid layer name.
|
||||
// Keep it as is.
|
||||
lastLayerName = parameterValue.GetPlainString();
|
||||
} else {
|
||||
// Remove quotes, so it can be compared to the layer name.
|
||||
lastLayerName = parameterValue.GetPlainString().substr(
|
||||
1, parameterValue.GetPlainString().length() - 2);
|
||||
}
|
||||
// Remove quotes, it won't match if it's not a literal anyway.
|
||||
lastLayerName = parameterValue.GetPlainString().substr(
|
||||
1, parameterValue.GetPlainString().length() - 2);
|
||||
}
|
||||
|
||||
if (parameterMetadata.GetType() == parameterType &&
|
||||
@@ -174,12 +159,13 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
|
||||
auto node = parameterValue.GetRootNode();
|
||||
if (node) {
|
||||
ExpressionIdentifierStringFinder finder(
|
||||
platform, GetProjectScopedContainers(),
|
||||
platform, GetGlobalObjectsContainer(), GetObjectsContainer(),
|
||||
parameterValue.GetPlainString(), parameterType, objectName,
|
||||
layerName, oldName);
|
||||
node->Visit(finder);
|
||||
|
||||
if (finder.GetOccurrences().size() > 0) {
|
||||
|
||||
gd::String newNameWithQuotes = "\"" + newName + "\"";
|
||||
gd::String oldParameterValue = parameterValue.GetPlainString();
|
||||
gd::String newParameterValue;
|
||||
|
@@ -108,33 +108,6 @@ void UsedExtensionsFinder::OnVisitUnaryOperatorNode(UnaryOperatorNode& node) {
|
||||
// Add variable extension and visit sub-expressions on variable nodes
|
||||
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||
result.GetUsedExtensions().insert("BuiltinVariables");
|
||||
|
||||
auto type = gd::ExpressionTypeFinder::GetType(
|
||||
project.GetCurrentPlatform(), GetObjectsContainersList(), rootType, node);
|
||||
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
// Nothing to do (this can't reference an object)
|
||||
} else {
|
||||
GetProjectScopedContainers().MatchIdentifierWithName<void>(node.name,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), node.name);
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
|
||||
result.GetUsedIncludeFiles().insert(includeFile);
|
||||
}
|
||||
}, [&]() {
|
||||
// This is a variable.
|
||||
}, [&]() {
|
||||
// This is a property.
|
||||
}, [&]() {
|
||||
// This is a parameter.
|
||||
}, [&]() {
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
|
||||
@@ -154,10 +127,9 @@ void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
|
||||
// Add extensions bound to Objects/Behaviors/Functions
|
||||
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode &node) {
|
||||
auto type = gd::ExpressionTypeFinder::GetType(
|
||||
project.GetCurrentPlatform(), GetObjectsContainersList(), rootType, node);
|
||||
if (gd::ParameterMetadata::IsObject(type) ||
|
||||
GetObjectsContainersList().HasObjectOrGroupNamed(node.identifierName)) {
|
||||
// An object or object variable is used.
|
||||
project.GetCurrentPlatform(), GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(), rootType, node);
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), node.identifierName);
|
||||
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
|
||||
|
@@ -17,11 +17,9 @@
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ResourcesManager.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/IDE/ResourceExposer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -133,9 +131,29 @@ void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
|
||||
std::cout << targetResourceName << std::endl;
|
||||
gd::Resource& targetResource =
|
||||
resourcesManager->GetResource(targetResourceName);
|
||||
const gd::String& targetResourceKind = targetResource.GetKind();
|
||||
|
||||
gd::String potentiallyUpdatedTargetResourceName = targetResourceName;
|
||||
ExposeResourceWithType(targetResource.GetKind(), potentiallyUpdatedTargetResourceName);
|
||||
|
||||
if (targetResourceKind == "audio") {
|
||||
ExposeAudio(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "bitmapFont") {
|
||||
ExposeBitmapFont(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "font") {
|
||||
ExposeFont(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "image") {
|
||||
ExposeImage(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "json") {
|
||||
ExposeJson(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "tilemap") {
|
||||
ExposeTilemap(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "tileset") {
|
||||
ExposeTileset(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "video") {
|
||||
ExposeVideo(potentiallyUpdatedTargetResourceName);
|
||||
} else if (targetResourceKind == "model3D") {
|
||||
ExposeModel3D(potentiallyUpdatedTargetResourceName);
|
||||
}
|
||||
|
||||
if (potentiallyUpdatedTargetResourceName != targetResourceName) {
|
||||
// The resource name was renamed. Also update the mapping.
|
||||
@@ -152,48 +170,6 @@ void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
|
||||
}
|
||||
}
|
||||
|
||||
void ArbitraryResourceWorker::ExposeResourceWithType(
|
||||
const gd::String &resourceType, gd::String &resourceName) {
|
||||
if (resourceType == "image") {
|
||||
ExposeImage(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "model3D") {
|
||||
ExposeModel3D(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "audio") {
|
||||
ExposeAudio(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "font") {
|
||||
ExposeFont(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "bitmapFont") {
|
||||
ExposeBitmapFont(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "tilemap") {
|
||||
ExposeTilemap(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "tileset") {
|
||||
ExposeTileset(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "json") {
|
||||
ExposeJson(resourceName);
|
||||
return;
|
||||
}
|
||||
if (resourceType == "video") {
|
||||
ExposeVideo(resourceName);
|
||||
return;
|
||||
}
|
||||
gd::LogError("Unexpected resource type: " + resourceType + " for: " + resourceName);
|
||||
return;
|
||||
}
|
||||
|
||||
void ArbitraryResourceWorker::ExposeResource(gd::Resource& resource) {
|
||||
if (!resource.UseFile()) return;
|
||||
|
||||
@@ -204,98 +180,86 @@ void ArbitraryResourceWorker::ExposeResource(gd::Resource& resource) {
|
||||
|
||||
ArbitraryResourceWorker::~ArbitraryResourceWorker() {}
|
||||
|
||||
bool ResourceWorkerInEventsWorker::DoVisitInstruction(gd::Instruction& instruction, bool isCondition) {
|
||||
const auto& platform = project.GetCurrentPlatform();
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
/**
|
||||
* Launch the specified resource worker on every resource referenced in the
|
||||
* events.
|
||||
*/
|
||||
class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
|
||||
public:
|
||||
ResourceWorkerInEventsWorker(const gd::Project& project_,
|
||||
gd::ArbitraryResourceWorker& worker_)
|
||||
: project(project_), worker(worker_){};
|
||||
virtual ~ResourceWorkerInEventsWorker(){};
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[this, &instruction](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterExpression,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const String& parameterValue = parameterExpression.GetPlainString();
|
||||
if (parameterMetadata.GetType() ==
|
||||
"police" || // Should be renamed fontResource
|
||||
parameterMetadata.GetType() == "fontResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeFont(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "soundfile" ||
|
||||
parameterMetadata.GetType() ==
|
||||
"musicfile") { // Should be renamed audioResource
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeAudio(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "bitmapFontResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeBitmapFont(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "imageResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeImage(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "jsonResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeJson(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "tilemapResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeTilemap(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "tilesetResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeTileset(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "model3DResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeModel3D(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
}
|
||||
});
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction& instruction, bool isCondition) {
|
||||
const auto& platform = project.GetCurrentPlatform();
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
return false;
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[this, &instruction](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterExpression,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const String& parameterValue = parameterExpression.GetPlainString();
|
||||
if (parameterMetadata.GetType() ==
|
||||
"police" || // Should be renamed fontResource
|
||||
parameterMetadata.GetType() == "fontResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeFont(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "soundfile" ||
|
||||
parameterMetadata.GetType() ==
|
||||
"musicfile") { // Should be renamed audioResource
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeAudio(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "bitmapFontResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeBitmapFont(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "imageResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeImage(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "jsonResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeJson(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "tilemapResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeTilemap(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "tilesetResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeTileset(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
} else if (parameterMetadata.GetType() == "model3DResource") {
|
||||
gd::String updatedParameterValue = parameterValue;
|
||||
worker.ExposeModel3D(updatedParameterValue);
|
||||
instruction.SetParameter(parameterIndex, updatedParameterValue);
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const gd::Project& project;
|
||||
gd::ArbitraryResourceWorker& worker;
|
||||
};
|
||||
|
||||
void LaunchResourceWorkerOnEvents(const gd::Project& project,
|
||||
gd::EventsList& events,
|
||||
gd::ArbitraryResourceWorker& worker) {
|
||||
gd::ResourceWorkerInEventsWorker eventsWorker(project, worker);
|
||||
ResourceWorkerInEventsWorker eventsWorker(project, worker);
|
||||
eventsWorker.Launch(events);
|
||||
}
|
||||
|
||||
gd::ResourceWorkerInEventsWorker
|
||||
GetResourceWorkerOnEvents(const gd::Project &project,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
gd::ResourceWorkerInEventsWorker eventsWorker(project, worker);
|
||||
return eventsWorker;
|
||||
}
|
||||
|
||||
void ResourceWorkerInObjectsWorker::DoVisitObject(gd::Object &object) {
|
||||
object.GetConfiguration().ExposeResources(worker);
|
||||
auto& effects = object.GetEffects();
|
||||
for (size_t effectIndex = 0; effectIndex < effects.GetEffectsCount(); effectIndex++)
|
||||
{
|
||||
auto& effect = effects.GetEffect(effectIndex);
|
||||
gd::ResourceExposer::ExposeEffectResources(project.GetCurrentPlatform(), effect, worker);
|
||||
}
|
||||
};
|
||||
|
||||
void ResourceWorkerInObjectsWorker::DoVisitBehavior(gd::Behavior &behavior){
|
||||
// TODO Allow behaviors to expose resources
|
||||
};
|
||||
|
||||
gd::ResourceWorkerInObjectsWorker
|
||||
GetResourceWorkerOnObjects(const gd::Project &project,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
gd::ResourceWorkerInObjectsWorker eventsWorker(project, worker);
|
||||
return eventsWorker;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
#endif
|
||||
|
@@ -4,14 +4,13 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef ARBITRARYRESOURCEWORKER_H
|
||||
#define ARBITRARYRESOURCEWORKER_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
}
|
||||
@@ -54,11 +53,6 @@ class GD_CORE_API ArbitraryResourceWorker {
|
||||
*/
|
||||
void ExposeResources(gd::ResourcesManager *resourcesManager);
|
||||
|
||||
/**
|
||||
* \brief Expose a resource from a given type.
|
||||
*/
|
||||
void ExposeResourceWithType(const gd::String& resourceType, gd::String& resourceName);
|
||||
|
||||
/**
|
||||
* \brief Expose an image, which is always a reference to a "image" resource.
|
||||
*/
|
||||
@@ -138,47 +132,18 @@ class GD_CORE_API ArbitraryResourceWorker {
|
||||
};
|
||||
|
||||
/**
|
||||
* Launch the specified resource worker on every resource referenced in the
|
||||
* events.
|
||||
* Tool function iterating over each event and calling
|
||||
* Expose(Actions/Conditions)Resources for each actions and conditions with the
|
||||
* ArbitraryResourceWorker passed as argument.
|
||||
*
|
||||
* \see gd::ArbitraryResourceWorker
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class ResourceWorkerInEventsWorker : public gd::ArbitraryEventsWorker {
|
||||
public:
|
||||
ResourceWorkerInEventsWorker(const gd::Project &project_,
|
||||
gd::ArbitraryResourceWorker &worker_)
|
||||
: project(project_), worker(worker_){};
|
||||
virtual ~ResourceWorkerInEventsWorker(){};
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
|
||||
const gd::Project &project;
|
||||
gd::ArbitraryResourceWorker &worker;
|
||||
};
|
||||
|
||||
ResourceWorkerInEventsWorker GD_CORE_API GetResourceWorkerOnEvents(
|
||||
const gd::Project &project, gd::ArbitraryResourceWorker &worker);
|
||||
|
||||
/**
|
||||
* Launch the specified resource worker on every resource referenced in the
|
||||
* objects.
|
||||
*/
|
||||
class GD_CORE_API ResourceWorkerInObjectsWorker
|
||||
: public gd::ArbitraryObjectsWorker {
|
||||
public:
|
||||
ResourceWorkerInObjectsWorker(const gd::Project &project_, gd::ArbitraryResourceWorker &worker_)
|
||||
: project(project_), worker(worker_){};
|
||||
~ResourceWorkerInObjectsWorker() {}
|
||||
|
||||
private:
|
||||
void DoVisitObject(gd::Object &object) override;
|
||||
void DoVisitBehavior(gd::Behavior &behavior) override;
|
||||
|
||||
const gd::Project &project;
|
||||
gd::ArbitraryResourceWorker &worker;
|
||||
};
|
||||
|
||||
gd::ResourceWorkerInObjectsWorker GD_CORE_API
|
||||
GetResourceWorkerOnObjects(const gd::Project &project, gd::ArbitraryResourceWorker &worker);
|
||||
void GD_CORE_API
|
||||
LaunchResourceWorkerOnEvents(const gd::Project &project,
|
||||
gd::EventsList &events,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // ARBITRARYRESOURCEWORKER_H
|
||||
|
@@ -15,8 +15,8 @@ namespace gd {
|
||||
|
||||
void BehaviorObjectTypeRenamer::DoVisitEventBasedBehavior(
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior) {
|
||||
if (eventsBasedBehavior.GetObjectType() == oldObjectType) {
|
||||
eventsBasedBehavior.SetObjectType(newObjectType);
|
||||
if (eventsBasedBehavior.GetObjectType().GetName() == oldObjectType) {
|
||||
eventsBasedBehavior.GetObjectType().SetName(newObjectType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,15 +10,17 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void FunctionParameterObjectTypeRenamer::DoVisitEventsFunction(
|
||||
gd::EventsFunction &eventsFunction) {
|
||||
for (auto &¶meter : eventsFunction.GetParameters()) {
|
||||
auto &objectType = parameter.GetValueTypeMetadata().GetObjectType();
|
||||
if (gd::ParameterMetadata::IsObject(parameter.GetType()) &&
|
||||
parameter.GetExtraInfo() == oldObjectType) {
|
||||
parameter.SetExtraInfo(newObjectType);
|
||||
objectType.GetName() == oldObjectType) {
|
||||
objectType.SetName(newObjectType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/IDE/ResourceExposer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -20,7 +19,7 @@ std::vector<gd::String> ProjectResourcesAdder::GetAllUseless(
|
||||
std::vector<gd::String> unusedResources;
|
||||
// Search for resources used in the project
|
||||
gd::ResourcesInUseHelper resourcesInUse;
|
||||
gd::ResourceExposer::ExposeWholeProjectResources(project, resourcesInUse);
|
||||
project.ExposeResources(resourcesInUse);
|
||||
std::set<gd::String>& usedResources = resourcesInUse.GetAll(resourceType);
|
||||
|
||||
// Search all resources not used
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/IDE/ResourceExposer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -27,7 +26,7 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
|
||||
bool preserveDirectoryStructure) {
|
||||
// Check if there are some resources with absolute filenames
|
||||
gd::ResourcesAbsolutePathChecker absolutePathChecker(fs);
|
||||
gd::ResourceExposer::ExposeWholeProjectResources(originalProject, absolutePathChecker);
|
||||
originalProject.ExposeResources(absolutePathChecker);
|
||||
|
||||
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
|
||||
std::cout << "Copying all resources from " << projectDirectory << " to "
|
||||
@@ -42,10 +41,10 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
|
||||
preserveAbsoluteFilenames);
|
||||
|
||||
if (updateOriginalProject) {
|
||||
gd::ResourceExposer::ExposeWholeProjectResources(originalProject, resourcesMergingHelper);
|
||||
originalProject.ExposeResources(resourcesMergingHelper);
|
||||
} else {
|
||||
std::shared_ptr<gd::Project> project(new gd::Project(originalProject));
|
||||
gd::ResourceExposer::ExposeWholeProjectResources(*project, resourcesMergingHelper);
|
||||
project->ExposeResources(resourcesMergingHelper);
|
||||
}
|
||||
|
||||
// Copy resources
|
||||
|
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/IDE/ResourceExposer.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -24,7 +23,7 @@ namespace gd {
|
||||
* Usage example:
|
||||
\code
|
||||
gd::ResourcesInUseHelper resourcesInUse;
|
||||
gd::ResourceExposer::ExposeWholeProjectResources(project, resourcesInUse);
|
||||
project.ExposeResources(resourcesInUse);
|
||||
|
||||
//Get a set with the name of all images in the project:
|
||||
std::set<gd::String> & usedImages = resourcesInUse.GetAllImages();
|
||||
|
@@ -16,9 +16,7 @@
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/PropertiesContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -88,17 +86,15 @@ void ProjectBrowserHelper::ExposeLayoutEvents(
|
||||
void ProjectBrowserHelper::ExposeLayoutEvents(
|
||||
gd::Project &project, gd::Layout &layout,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) {
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
||||
|
||||
// Add layouts events
|
||||
worker.Launch(layout.GetEvents(), projectScopedContainers);
|
||||
worker.Launch(layout.GetEvents(), project, layout);
|
||||
|
||||
// Add external events events
|
||||
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
||||
auto &externalEvents = project.GetExternalEvents(s);
|
||||
if (externalEvents.GetAssociatedLayout() == layout.GetName()) {
|
||||
worker.Launch(externalEvents.GetEvents(), projectScopedContainers);
|
||||
worker.Launch(externalEvents.GetEvents(), project, layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,19 +108,15 @@ void ProjectBrowserHelper::ExposeProjectEvents(
|
||||
// Add layouts events
|
||||
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
|
||||
auto &layout = project.GetLayout(s);
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
||||
worker.Launch(layout.GetEvents(), projectScopedContainers);
|
||||
worker.Launch(layout.GetEvents(), project, layout);
|
||||
}
|
||||
// Add external events events
|
||||
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
|
||||
const auto &externalEvents = project.GetExternalEvents(s);
|
||||
const gd::String &associatedLayout = externalEvents.GetAssociatedLayout();
|
||||
if (project.HasLayoutNamed(associatedLayout)) {
|
||||
auto &layout = project.GetLayout(associatedLayout);
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project, layout);
|
||||
worker.Launch(project.GetExternalEvents(s).GetEvents(), projectScopedContainers);
|
||||
worker.Launch(project.GetExternalEvents(s).GetEvents(), project,
|
||||
project.GetLayout(associatedLayout));
|
||||
}
|
||||
}
|
||||
// Add events based extensions
|
||||
@@ -138,11 +130,9 @@ void ProjectBrowserHelper::ExposeProjectEvents(
|
||||
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
project, eventsFunctionsExtension, *eventsFunction,
|
||||
globalObjectsAndGroups, objectsAndGroups);
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersFor(globalObjectsAndGroups, objectsAndGroups);
|
||||
projectScopedContainers.AddParameters(eventsFunction->GetParameters());
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
}
|
||||
|
||||
// Add (behavior) events functions
|
||||
@@ -179,13 +169,9 @@ void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
gd::EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
|
||||
project, eventsBasedBehavior, *eventsFunction, globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersFor(globalObjectsAndGroups, objectsAndGroups);
|
||||
projectScopedContainers.AddPropertiesContainer(eventsBasedBehavior.GetSharedPropertyDescriptors());
|
||||
projectScopedContainers.AddPropertiesContainer(eventsBasedBehavior.GetPropertyDescriptors());
|
||||
projectScopedContainers.AddParameters(eventsFunction->GetParameters());
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,12 +185,9 @@ void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
gd::EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
|
||||
project, eventsBasedObject, *eventsFunction, globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
auto projectScopedContainers =
|
||||
gd::ProjectScopedContainers::MakeNewProjectScopedContainersFor(globalObjectsAndGroups, objectsAndGroups);
|
||||
projectScopedContainers.AddPropertiesContainer(eventsBasedObject.GetPropertyDescriptors());
|
||||
projectScopedContainers.AddParameters(eventsFunction->GetParameters());
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(), projectScopedContainers);
|
||||
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +197,7 @@ void ProjectBrowserHelper::ExposeProjectObjects(
|
||||
// Global objects
|
||||
worker.Launch(project);
|
||||
|
||||
// Layout objects
|
||||
// Layers objects
|
||||
for (size_t i = 0; i < project.GetLayoutsCount(); i++) {
|
||||
worker.Launch(project.GetLayout(i));
|
||||
}
|
||||
|
@@ -11,8 +11,6 @@
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/IDE/WholeProjectBrowser.h"
|
||||
#include "GDCore/IDE/Events/BehaviorDefaultFlagClearer.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -21,10 +19,6 @@ void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
|
||||
while (project.GetExternalEventsCount() > 0)
|
||||
project.RemoveExternalEvents(project.GetExternalEvents(0).GetName());
|
||||
|
||||
gd::BehaviorDefaultFlagClearer behaviorDefaultFlagClearer;
|
||||
gd::WholeProjectBrowser wholeProjectBrowser;
|
||||
wholeProjectBrowser.ExposeObjects(project, behaviorDefaultFlagClearer);
|
||||
|
||||
for (unsigned int i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
project.GetLayout(i).GetObjectGroups().Clear();
|
||||
project.GetLayout(i).GetEvents().Clear();
|
||||
|
@@ -13,6 +13,7 @@
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/EventsFunction.h"
|
||||
#include "GDCore/Project/ObjectType.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/String.h"
|
||||
@@ -32,14 +33,16 @@ void PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::EventsBasedObject &eventsBasedObject,
|
||||
const gd::NamedPropertyDescriptor &property) {
|
||||
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, "",
|
||||
gd::ObjectType objectType;
|
||||
objectType.SetName(gd::PlatformExtension::GetObjectFullType(extension.GetName(), eventsBasedObject.GetName()));
|
||||
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, objectType,
|
||||
false, false);
|
||||
}
|
||||
|
||||
void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
gd::Project &project, gd::EventsFunctionsExtension &extension,
|
||||
gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
|
||||
const gd::NamedPropertyDescriptor &property, const gd::ObjectType &objectType,
|
||||
bool isBehavior, bool isSharedProperties) {
|
||||
auto &propertyName = property.GetName();
|
||||
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
|
||||
@@ -151,7 +154,8 @@ void PropertyFunctionGenerator::GenerateGetterAndSetter(
|
||||
objectParameter.SetType("object")
|
||||
.SetName("Object")
|
||||
.SetDescription("Object")
|
||||
.SetExtraInfo(objectType);
|
||||
.GetValueTypeMetadata()
|
||||
.SetObjectType(objectType);
|
||||
if (!isBehavior) {
|
||||
gd::String objectFullType = gd::PlatformExtension::GetObjectFullType(
|
||||
extension.GetName(), eventsBasedEntity.GetName());
|
||||
|
@@ -16,6 +16,7 @@ class EventsBasedObject;
|
||||
class AbstractEventsBasedEntity;
|
||||
class PropertyDescriptor;
|
||||
class NamedPropertyDescriptor;
|
||||
class ObjectType;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -60,7 +61,7 @@ class GD_CORE_API PropertyFunctionGenerator {
|
||||
gd::EventsFunctionsExtension &extension,
|
||||
gd::AbstractEventsBasedEntity &eventsBasedEntity,
|
||||
const gd::NamedPropertyDescriptor &property,
|
||||
const gd::String &objectType,
|
||||
const gd::ObjectType &objectType,
|
||||
bool isBehavior,
|
||||
bool isSharedProperties);
|
||||
|
||||
|
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ResourceExposer.h"
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/EventsFunctionTools.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void ResourceExposer::ExposeWholeProjectResources(gd::Project& project, gd::ArbitraryResourceWorker& worker) {
|
||||
// See also gd::ProjectBrowserHelper::ExposeProjectEvents for a method that
|
||||
// traverse the whole project (this time for events) and ExposeProjectEffects
|
||||
// (this time for effects).
|
||||
|
||||
gd::ResourcesManager* resourcesManager = &(project.GetResourcesManager());
|
||||
|
||||
// Expose any project resources as files.
|
||||
worker.ExposeResources(resourcesManager);
|
||||
project.GetPlatformSpecificAssets().ExposeResources(worker);
|
||||
|
||||
// Expose event resources
|
||||
auto eventWorker = gd::GetResourceWorkerOnEvents(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectEvents(
|
||||
project, eventWorker);
|
||||
|
||||
// Expose object configuration resources
|
||||
auto objectWorker = gd::GetResourceWorkerOnObjects(project, worker);
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(
|
||||
project, objectWorker);
|
||||
|
||||
// Expose layer effect resources
|
||||
for (std::size_t layoutIndex = 0; layoutIndex < project.GetLayoutsCount();
|
||||
layoutIndex++) {
|
||||
auto &layout = project.GetLayout(layoutIndex);
|
||||
|
||||
for (std::size_t layerIndex = 0; layerIndex < layout.GetLayersCount();
|
||||
layerIndex++) {
|
||||
auto &layer = layout.GetLayer(layerIndex);
|
||||
|
||||
auto &effects = layer.GetEffects();
|
||||
for (size_t effectIndex = 0; effectIndex < effects.GetEffectsCount();
|
||||
effectIndex++) {
|
||||
auto &effect = effects.GetEffect(effectIndex);
|
||||
gd::ResourceExposer::ExposeEffectResources(project.GetCurrentPlatform(),
|
||||
effect, worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose loading screen background image if present
|
||||
auto& loadingScreen = project.GetLoadingScreen();
|
||||
if (loadingScreen.GetBackgroundImageResourceName() != "")
|
||||
worker.ExposeImage(loadingScreen.GetBackgroundImageResourceName());
|
||||
}
|
||||
|
||||
void ResourceExposer::ExposeEffectResources(
|
||||
gd::Platform &platform, gd::Effect &effect,
|
||||
gd::ArbitraryResourceWorker &worker) {
|
||||
auto &effectMetadata =
|
||||
MetadataProvider::GetEffectMetadata(platform, effect.GetEffectType());
|
||||
|
||||
for (auto &propertyPair : effectMetadata.GetProperties()) {
|
||||
auto &propertyName = propertyPair.first;
|
||||
auto &propertyDescriptor = propertyPair.second;
|
||||
|
||||
if (propertyDescriptor.GetType() == "resource" &&
|
||||
propertyDescriptor.GetExtraInfo().size() > 0) {
|
||||
auto &resourceType = propertyDescriptor.GetExtraInfo()[0];
|
||||
|
||||
const gd::String &resourceName = effect.GetStringParameter(propertyName);
|
||||
gd::String potentiallyUpdatedResourceName = resourceName;
|
||||
worker.ExposeResourceWithType(resourceType,
|
||||
potentiallyUpdatedResourceName);
|
||||
if (potentiallyUpdatedResourceName != resourceName) {
|
||||
effect.SetStringParameter(propertyName, potentiallyUpdatedResourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace gd {
|
||||
class Platform;
|
||||
class Project;
|
||||
class ArbitraryResourceWorker;
|
||||
class Effect;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
class GD_CORE_API ResourceExposer {
|
||||
public:
|
||||
/**
|
||||
* \brief Called ( e.g. during compilation ) so as to inventory internal
|
||||
* resources, sometimes update their filename or any other work or resources.
|
||||
*
|
||||
* See WholeProjectRefactorer for the same thing for events.
|
||||
*
|
||||
* \see WholeProjectRefactorer
|
||||
* \see ArbitraryResourceWorker
|
||||
*/
|
||||
static void ExposeWholeProjectResources(gd::Project &project,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
|
||||
static void ExposeEffectResources(gd::Platform &platform, gd::Effect &effect,
|
||||
gd::ArbitraryResourceWorker &worker);
|
||||
};
|
||||
|
||||
} // namespace gd
|
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,7 @@
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Platform;
|
||||
class Project;
|
||||
@@ -20,7 +18,6 @@ class String;
|
||||
class EventsFunctionsExtension;
|
||||
class EventsFunction;
|
||||
class ObjectsContainer;
|
||||
class VariablesContainer;
|
||||
class EventsBasedBehavior;
|
||||
class EventsBasedObject;
|
||||
class ArbitraryEventsWorker;
|
||||
@@ -33,20 +30,10 @@ class Behavior;
|
||||
class BehaviorMetadata;
|
||||
class UnfilledRequiredBehaviorPropertyProblem;
|
||||
class ProjectBrowser;
|
||||
class SerializerElement;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
struct VariablesChangeset {
|
||||
std::unordered_set<gd::String> removedVariableNames;
|
||||
std::unordered_map<gd::String, gd::String> oldToNewVariableNames;
|
||||
|
||||
bool HasRemovedVariables() { return !removedVariableNames.empty(); }
|
||||
|
||||
VariablesChangeset& ClearRemovedVariables() { removedVariableNames.clear(); return *this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Tool functions to do refactoring on the whole project after
|
||||
* changes like deletion or renaming of an object.
|
||||
@@ -58,23 +45,6 @@ struct VariablesChangeset {
|
||||
class GD_CORE_API WholeProjectRefactorer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* \brief Compute the changes made on the variables of a variable container.
|
||||
*/
|
||||
static VariablesChangeset ComputeChangesetForVariablesContainer(
|
||||
gd::Project &project,
|
||||
const gd::SerializerElement &oldSerializedVariablesContainer,
|
||||
const gd::VariablesContainer &newVariablesContainer);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project according to the changes (renaming or deletion)
|
||||
* made to variables.
|
||||
*/
|
||||
static void ApplyRefactoringForVariablesContainer(
|
||||
gd::Project &project,
|
||||
const gd::VariablesContainer &newVariablesContainer,
|
||||
const gd::VariablesChangeset& changeset);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** an events function extension is
|
||||
* renamed.
|
||||
@@ -486,26 +456,6 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedObject& eventsBasedObject);
|
||||
|
||||
/**
|
||||
* \brief Remove all the instances from one layer.
|
||||
*/
|
||||
static void RemoveLayer(gd::Project &project, gd::Layout &layout,
|
||||
const gd::String &layerName);
|
||||
|
||||
/**
|
||||
* \brief Move all the instances from one layer into another.
|
||||
*/
|
||||
static void MergeLayers(gd::Project &project, gd::Layout &layout,
|
||||
const gd::String &originLayerName,
|
||||
const gd::String &targetLayerName);
|
||||
|
||||
/**
|
||||
* \brief Return the number of instances on the layer named \a layerName and
|
||||
* all its associated layouts.
|
||||
*/
|
||||
static size_t GetLayoutAndExternalLayoutLayerInstancesCount(
|
||||
gd::Project &project, gd::Layout &layout, const gd::String &layerName);
|
||||
|
||||
virtual ~WholeProjectRefactorer(){};
|
||||
|
||||
private:
|
||||
|
@@ -4,7 +4,6 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "AbstractEventsBasedEntity.h"
|
||||
|
||||
#include "EventsFunctionsContainer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
@@ -14,10 +13,7 @@ namespace gd {
|
||||
AbstractEventsBasedEntity::AbstractEventsBasedEntity(
|
||||
const gd::String& _name,
|
||||
gd::EventsFunctionsContainer::FunctionOwner functionContainerSource)
|
||||
: name(_name),
|
||||
fullName(""),
|
||||
eventsFunctionsContainer(functionContainerSource),
|
||||
propertyDescriptors(functionContainerSource) {}
|
||||
: name(_name), fullName(""), eventsFunctionsContainer(functionContainerSource) {}
|
||||
|
||||
void AbstractEventsBasedEntity::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("description", description);
|
||||
@@ -31,8 +27,8 @@ void AbstractEventsBasedEntity::SerializeTo(SerializerElement& element) const {
|
||||
"propertyDescriptor", element.AddChild("propertyDescriptors"));
|
||||
}
|
||||
|
||||
void AbstractEventsBasedEntity::UnserializeFrom(
|
||||
gd::Project& project, const SerializerElement& element) {
|
||||
void AbstractEventsBasedEntity::UnserializeFrom(gd::Project& project,
|
||||
const SerializerElement& element) {
|
||||
description = element.GetStringAttribute("description");
|
||||
name = element.GetStringAttribute("name");
|
||||
fullName = element.GetStringAttribute("fullName");
|
||||
|
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/Project/NamedPropertyDescriptor.h"
|
||||
#include "GDCore/Project/PropertiesContainer.h"
|
||||
#include "GDCore/Tools/SerializableWithNameList.h"
|
||||
#include "GDCore/Project/EventsFunctionsContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
@@ -98,14 +98,15 @@ class GD_CORE_API AbstractEventsBasedEntity {
|
||||
/**
|
||||
* \brief Return a reference to the list of the properties.
|
||||
*/
|
||||
gd::PropertiesContainer& GetPropertyDescriptors() {
|
||||
SerializableWithNameList<NamedPropertyDescriptor>& GetPropertyDescriptors() {
|
||||
return propertyDescriptors;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return a const reference to the list of the properties.
|
||||
*/
|
||||
const gd::PropertiesContainer& GetPropertyDescriptors() const {
|
||||
const SerializableWithNameList<NamedPropertyDescriptor>& GetPropertyDescriptors()
|
||||
const {
|
||||
return propertyDescriptors;
|
||||
}
|
||||
|
||||
@@ -149,7 +150,7 @@ class GD_CORE_API AbstractEventsBasedEntity {
|
||||
gd::String fullName;
|
||||
gd::String description;
|
||||
gd::EventsFunctionsContainer eventsFunctionsContainer;
|
||||
gd::PropertiesContainer propertyDescriptors;
|
||||
SerializableWithNameList<NamedPropertyDescriptor> propertyDescriptors;
|
||||
gd::String extensionName;
|
||||
};
|
||||
|
||||
|
@@ -23,23 +23,11 @@ namespace gd {
|
||||
class GD_CORE_API Behavior: public BehaviorConfigurationContainer {
|
||||
public:
|
||||
|
||||
Behavior(): BehaviorConfigurationContainer(), isDefaultBehavior(false) {};
|
||||
Behavior(): BehaviorConfigurationContainer() {};
|
||||
Behavior(const gd::String& name_, const gd::String& type_)
|
||||
: BehaviorConfigurationContainer(name_, type_),
|
||||
isDefaultBehavior(false) {};
|
||||
: BehaviorConfigurationContainer(name_, type_) {};
|
||||
virtual ~Behavior();
|
||||
virtual Behavior* Clone() const override { return new Behavior(*this); }
|
||||
|
||||
bool IsDefaultBehavior() const {
|
||||
return isDefaultBehavior;
|
||||
}
|
||||
|
||||
void SetDefaultBehavior(bool isDefaultBehavior_) {
|
||||
isDefaultBehavior = isDefaultBehavior_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool isDefaultBehavior;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -31,10 +31,10 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API BehaviorConfigurationContainer {
|
||||
public:
|
||||
BehaviorConfigurationContainer() : folded(false){};
|
||||
BehaviorConfigurationContainer(const gd::String& name_,
|
||||
const gd::String& type_)
|
||||
: name(name_), type(type_), folded(false){};
|
||||
|
||||
BehaviorConfigurationContainer(){};
|
||||
BehaviorConfigurationContainer(const gd::String& name_, const gd::String& type_)
|
||||
: name(name_), type(type_){};
|
||||
virtual ~BehaviorConfigurationContainer();
|
||||
virtual BehaviorConfigurationContainer* Clone() const { return new BehaviorConfigurationContainer(*this); }
|
||||
|
||||
@@ -61,7 +61,7 @@ class GD_CORE_API BehaviorConfigurationContainer {
|
||||
/**
|
||||
* \brief Called when the IDE wants to know about the custom properties of the
|
||||
* behavior.
|
||||
*
|
||||
*
|
||||
* \return a std::map with properties names as key.
|
||||
* \see gd::PropertyDescriptor
|
||||
*/
|
||||
@@ -104,17 +104,6 @@ class GD_CORE_API BehaviorConfigurationContainer {
|
||||
const gd::SerializerElement& GetContent() const { return content; };
|
||||
gd::SerializerElement& GetContent() { return content; };
|
||||
|
||||
/**
|
||||
* \brief Set if the behavior configuration panel should be folded in the UI.
|
||||
*/
|
||||
void SetFolded(bool fold = true) { folded = fold; }
|
||||
|
||||
/**
|
||||
* \brief True if the behavior configuration panel should be folded in the UI.
|
||||
*/
|
||||
bool IsFolded() const { return folded; }
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Called when the IDE wants to know about the custom properties of the
|
||||
@@ -159,7 +148,6 @@ protected:
|
||||
///< in the form "ExtensionName::BehaviorTypeName"
|
||||
|
||||
gd::SerializerElement content; // Storage for the behavior properties
|
||||
bool folded;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertiesContainer.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
@@ -18,7 +17,7 @@
|
||||
using namespace gd;
|
||||
|
||||
void CustomConfigurationHelper::InitializeContent(
|
||||
const gd::PropertiesContainer &properties,
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
gd::SerializerElement &configurationContent) {
|
||||
for (auto &&property : properties.GetInternalVector()) {
|
||||
auto &element = configurationContent.AddChild(property->GetName());
|
||||
@@ -36,7 +35,7 @@ void CustomConfigurationHelper::InitializeContent(
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetProperties(
|
||||
const gd::PropertiesContainer &properties,
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
const gd::SerializerElement &configurationContent) {
|
||||
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
|
||||
|
||||
@@ -72,7 +71,7 @@ std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetPrope
|
||||
}
|
||||
|
||||
bool CustomConfigurationHelper::UpdateProperty(
|
||||
const gd::PropertiesContainer &properties,
|
||||
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
|
||||
gd::SerializerElement &configurationContent,
|
||||
const gd::String &propertyName,
|
||||
const gd::String &newValue) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user