mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
180 Commits
v5.0.0-bet
...
v5.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
![]() |
13b62a06eb | ||
![]() |
d27119d8ea | ||
![]() |
dd3ff554d5 | ||
![]() |
287a17b634 | ||
![]() |
7dc477e29e | ||
![]() |
8174bca3b1 | ||
![]() |
7f6388c6f5 | ||
![]() |
da3a099ff2 | ||
![]() |
7b2c7b4a00 | ||
![]() |
f750a356c3 | ||
![]() |
611a72aee1 | ||
![]() |
1b965b65a4 | ||
![]() |
c077628eb4 | ||
![]() |
f1a6da0cb2 | ||
![]() |
df4a780311 | ||
![]() |
8c955cf77a | ||
![]() |
17efae037c | ||
![]() |
f1120238ec | ||
![]() |
5d6a2bb3a0 | ||
![]() |
f3a49ad2cf | ||
![]() |
aac3379f59 | ||
![]() |
49949189cf | ||
![]() |
977daa50fa | ||
![]() |
fd8a7df868 | ||
![]() |
303110ade5 | ||
![]() |
cb15111d03 | ||
![]() |
9db4d603a0 | ||
![]() |
6c7db9a948 | ||
![]() |
6b9a8f14e3 | ||
![]() |
2f3a18046a | ||
![]() |
812ff43905 | ||
![]() |
1a113004be | ||
![]() |
0dd10a7955 | ||
![]() |
00b25461ed | ||
![]() |
9e28068e4f | ||
![]() |
6b231f3eb6 | ||
![]() |
2dd2c85f12 | ||
![]() |
c61faa7e05 | ||
![]() |
1840f6f45a | ||
![]() |
b11eccfa22 | ||
![]() |
9236608502 | ||
![]() |
12a6bc23c3 | ||
![]() |
23c2b84707 | ||
![]() |
adb4f2a6cf | ||
![]() |
aa3ed78eda | ||
![]() |
efb8668077 | ||
![]() |
8d763d4600 | ||
![]() |
0cc1e57450 | ||
![]() |
24c13e1022 | ||
![]() |
965f7aab32 | ||
![]() |
23c1f2423d | ||
![]() |
1d5eb8e529 | ||
![]() |
8968ef34e2 | ||
![]() |
736ba023ff | ||
![]() |
ade075f076 | ||
![]() |
049c36b081 | ||
![]() |
3977e2b6f2 | ||
![]() |
f08f38bc3b | ||
![]() |
127a881416 | ||
![]() |
606143ff36 | ||
![]() |
05a68cb17f | ||
![]() |
280377cc98 | ||
![]() |
3c88c150d5 | ||
![]() |
13471ad40a | ||
![]() |
0d7d574f1b | ||
![]() |
19a10d7dab | ||
![]() |
84e096f85d | ||
![]() |
40f5eb3e23 | ||
![]() |
4948e16dd5 | ||
![]() |
2b38325d96 | ||
![]() |
9a10caeeac | ||
![]() |
a4be56a24b | ||
![]() |
fc8b724e3c | ||
![]() |
7e61419a36 | ||
![]() |
473661b8a2 | ||
![]() |
350fea08bf | ||
![]() |
4f9154549b | ||
![]() |
d9172ded36 | ||
![]() |
aef8271a4e | ||
![]() |
83db8ce272 | ||
![]() |
e26c1470c1 | ||
![]() |
4b382cb191 | ||
![]() |
6c631410f2 | ||
![]() |
516b1d978c | ||
![]() |
822146e5f1 | ||
![]() |
7b3987bae4 | ||
![]() |
506c029690 | ||
![]() |
b28e4e1230 | ||
![]() |
c1edcbfa19 | ||
![]() |
3125956dfc | ||
![]() |
633c7bbd9d | ||
![]() |
df92ea1ac9 | ||
![]() |
3eb571a03a | ||
![]() |
98303f7f50 | ||
![]() |
34dfbbc294 | ||
![]() |
afbb316bd2 | ||
![]() |
b75945869c | ||
![]() |
efb3f55885 | ||
![]() |
82d2a4b5e4 | ||
![]() |
7748f3c48e | ||
![]() |
80ddc9c1b7 | ||
![]() |
5d50c31e55 | ||
![]() |
61a969fdb1 | ||
![]() |
a14b8e8bcd | ||
![]() |
faa37a4fd2 | ||
![]() |
176efafe43 | ||
![]() |
c242e1747b | ||
![]() |
fe74ec0c49 | ||
![]() |
2b5a9b8254 | ||
![]() |
d352c28003 | ||
![]() |
1991cc634a | ||
![]() |
d653f846b6 | ||
![]() |
9a8ec971f2 | ||
![]() |
87c5007a25 | ||
![]() |
666a9c747a | ||
![]() |
cf59e6fb1e | ||
![]() |
ab04db387a | ||
![]() |
7a7a0d0eec | ||
![]() |
a27d1e97bc | ||
![]() |
076732abd9 | ||
![]() |
9d09ad4dd9 | ||
![]() |
c16d155066 | ||
![]() |
cbdfd344e3 | ||
![]() |
8cce4ab9f2 | ||
![]() |
3266559cb6 | ||
![]() |
990b04d629 | ||
![]() |
c295456231 | ||
![]() |
79e033d57b | ||
![]() |
f0fc709a84 | ||
![]() |
b80ed7e6f5 | ||
![]() |
f23936a6c4 | ||
![]() |
1dff166df0 | ||
![]() |
50278b1ab2 | ||
![]() |
5f4fde7a56 | ||
![]() |
5384225a9b | ||
![]() |
5ecdfa1c7f | ||
![]() |
df6910e062 | ||
![]() |
5a42d6b94c | ||
![]() |
afa9b2a2ae | ||
![]() |
1dae099be9 | ||
![]() |
6f64fd3d1c | ||
![]() |
6c0bd92b24 | ||
![]() |
0bcaa835e6 | ||
![]() |
32ca97650c | ||
![]() |
e19d63ce96 | ||
![]() |
352e5daf1e | ||
![]() |
003f56e9bc | ||
![]() |
4b3fa9fc39 | ||
![]() |
e3fa31c4a4 | ||
![]() |
1ad0ab9881 | ||
![]() |
355c53cb12 | ||
![]() |
2a9b27b503 | ||
![]() |
2fa2824ca2 | ||
![]() |
85e3ed42fa | ||
![]() |
8a178a85fb | ||
![]() |
54ef7482cf | ||
![]() |
c846a7a068 | ||
![]() |
86eff4e408 | ||
![]() |
916938b4a8 | ||
![]() |
49827984ac | ||
![]() |
02eac6ba5e | ||
![]() |
479167638b | ||
![]() |
fada85d41d | ||
![]() |
3017798283 | ||
![]() |
515308ed9d | ||
![]() |
7369e05e01 | ||
![]() |
55da9eb2ef | ||
![]() |
01a45a10df | ||
![]() |
32d313f538 | ||
![]() |
1640ca49d7 | ||
![]() |
654b8d0bc1 | ||
![]() |
2a47d2f630 | ||
![]() |
e1423e0b90 | ||
![]() |
458430bbfb | ||
![]() |
2a5c18474e | ||
![]() |
827c53e9d5 | ||
![]() |
019920009a | ||
![]() |
aaed10a598 | ||
![]() |
193ce8bcf8 | ||
![]() |
fd020fd2a3 |
6
.devcontainer/Dockerfile
Normal file
6
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
||||
# This is the Dockerfile to create a "devcontainer".
|
||||
# This is a way to quickly create a development environment,
|
||||
# that can be used with GitHub workspaces.
|
||||
|
||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux/.devcontainer/base.Dockerfile
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/universal:1-focal
|
16
.devcontainer/README.md
Normal file
16
.devcontainer/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Devcontainer (development environment in the cloud) for GDevelop (beta)
|
||||
|
||||
A devcontainer is the configuration to run a cloud development environment, available remotely.
|
||||
This is notably used to run a **[GitHub Codespace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces)**. The advantage is that you can quickly experiment and do changes without installing anything on your computer.
|
||||
|
||||
> ⚠️ This development environment is in beta, and not everything is supported. This is useful for playing a bit with GDevelop codebase or to make quick changes. **In particular, it's not possible to test your changes on GDJS** because only the web-app can be launched.
|
||||
|
||||
It's recommended that you follow the usual [README](../newIDE/README.md) to get started, with development tools installed on your computer.
|
||||
|
||||
## Start a GitHub workspace to work on GDevelop (beta)
|
||||
|
||||
- Subscribe to the [beta edition of GitHub workspace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces#joining-the-beta).
|
||||
- In the repository GitHub page, click **Code** and then choose **Open with Codespaces**.
|
||||
- Wait for the Codespace to load and Visual Studio Code to open.
|
||||
- When it's ready, open a terminal in Visual Studio Code.
|
||||
- Follow the usual [README in `newIDE`](../newIDE/README.md) to get started, like you would do on your own computer.
|
51
.devcontainer/devcontainer.json
Normal file
51
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,51 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux
|
||||
{
|
||||
"name": "GitHub Codespaces for GDevelop",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/zsh",
|
||||
"go.toolsManagement.checkForUpdates": "off",
|
||||
"go.useLanguageServer": true,
|
||||
"go.gopath": "/go",
|
||||
"go.goroot": "/usr/local/go",
|
||||
"python.pythonPath": "/opt/python/latest/bin/python",
|
||||
"python.linting.enabled": true,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
|
||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
|
||||
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
|
||||
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
|
||||
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
|
||||
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
|
||||
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
|
||||
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
|
||||
"lldb.executable": "/usr/bin/lldb",
|
||||
"files.watcherExclude": {
|
||||
"**/target/**": true
|
||||
}
|
||||
},
|
||||
"remoteUser": "codespace",
|
||||
"overrideCommand": false,
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/codespace/workspace,type=bind,consistency=cached",
|
||||
"workspaceFolder": "/home/codespace/workspace",
|
||||
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--privileged", "--init" ],
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"GitHub.vscode-pull-request-github",
|
||||
"esbenp.prettier-vscode",
|
||||
"ms-vscode.cpptools",
|
||||
"xaver.clang-format",
|
||||
"flowtype.flow-for-vscode"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// "oryx build" will automatically install your dependencies and attempt to build your project
|
||||
"postCreateCommand": "oryx build -p virtualenv_name=.venv || echo 'Could not auto-build. Skipping.'"
|
||||
}
|
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: GDevelop Discord
|
||||
url: https://discord.gg/rjdYHvj
|
||||
about: Discuss on the forum or on the Discord to get help creating a game or identifying a bug.
|
||||
- name: GDevelop Forums
|
||||
url: https://forum.gdevelop-app.com
|
||||
about: You can also discuss game creation, new feature requests and bugs on the forum.
|
||||
- name: GDevelop Roadmap
|
||||
url: https://trello.com/b/qf0lM7k8/gdevelop-roadmap
|
||||
about: Look at the roadmap and vote on features that you want to see in GDevelop.
|
||||
- name: Submit a new game example that you created
|
||||
url: https://github.com/GDevelopApp/GDevelop-examples/issues/new/choose
|
||||
about: You can submit a game that you made to be added to examples in the "GDevelop-examples" repository
|
||||
- name: Submit a new game extension that you created
|
||||
url: https://github.com/4ian/GDevelop-extensions/issues/new/choose
|
||||
about: You can submit an extension that you made in the "GDevelop-extensions" repository
|
14
.github/workflows/issues.yml
vendored
14
.github/workflows/issues.yml
vendored
@@ -4,13 +4,6 @@ jobs:
|
||||
autoclose:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Autoclose issues about adding a new example without providing anything
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*INSERT the link to your game here, or add it as an attachment.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any example.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](http://wiki.compilgames.net/doku.php/gdevelop5/start) to learn more about GDevelop. Thanks!"
|
||||
- name: Autoclose issues about adding a bug without changing the bug report template
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
@@ -18,3 +11,10 @@ jobs:
|
||||
type: "body"
|
||||
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](http://wiki.compilgames.net/doku.php/gdevelop5/start) to learn more about GDevelop. Thanks!"
|
||||
- name: Autoclose known beta 105 web-app update bug
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*_instance.getRawFloatProperty is not a function.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
|
||||
|
@@ -1,7 +1,6 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
# Cache .npm folder for faster npm install
|
||||
|
129
.vscode/GDevelopExtensions.code-snippets
vendored
Normal file
129
.vscode/GDevelopExtensions.code-snippets
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"Define extension": {
|
||||
"scope": "javascript",
|
||||
"description": "Adds the boilerplate code of a GDevelop extension definition.",
|
||||
"prefix": "gdext",
|
||||
"body": [
|
||||
"// @flow",
|
||||
"/**",
|
||||
" * This is a declaration of an extension for GDevelop 5.",
|
||||
" *",
|
||||
" * ℹ️ Changes in this file are watched and automatically imported if the editor",
|
||||
" * is running. You can also manually run `node import-GDJS-Runtime.js` (in newIDE/app/scripts).",
|
||||
" *",
|
||||
" * The file must be named \"JsExtension.js\", otherwise GDevelop won't load it.",
|
||||
" * ⚠️ If you make a change and the extension is not loaded, open the developer console",
|
||||
" * and search for any errors.",
|
||||
" *",
|
||||
" * More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md",
|
||||
" */",
|
||||
"",
|
||||
"/*::",
|
||||
"// Import types to allow Flow to do static type checking on this file.",
|
||||
"// Extensions declaration are typed using Flow (like the editor), but the files",
|
||||
"// for the game engine are checked with TypeScript annotations.",
|
||||
"import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'",
|
||||
"*/",
|
||||
"",
|
||||
"module.exports = {",
|
||||
"\tcreateExtension: function (",
|
||||
"\t\t/*: (string) => string */,",
|
||||
"\t\tgd /*: libGDevelop */",
|
||||
"\t) {",
|
||||
"\t\tconst extension = new gd.PlatformExtension();",
|
||||
"\t\textension",
|
||||
"\t\t\t.setExtensionInformation(",
|
||||
"\t\t\t\t'${1:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}}',",
|
||||
"\t\t\t\t_('${2:Extension Name}'),",
|
||||
"\t\t\t\t_(",
|
||||
"\t\t\t\t\t'${3:Extension description}'",
|
||||
"\t\t\t\t),",
|
||||
"\t\t\t\t'${4:Extension author}',",
|
||||
"\t\t\t\t'MIT'",
|
||||
"\t\t\t);",
|
||||
"",
|
||||
"\t\t$0",
|
||||
"",
|
||||
"\t\treturn extension;",
|
||||
"\t},",
|
||||
"\trunExtensionSanityTests: function (",
|
||||
"\t\tgd /*: libGDevelop */,",
|
||||
"\t\textension /*: gdPlatformExtension*/",
|
||||
"\t) {",
|
||||
"\t\treturn [];",
|
||||
"\t},",
|
||||
"};",
|
||||
""
|
||||
]
|
||||
},
|
||||
"Define instruction": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an instruction in a GDevelop extension definition.",
|
||||
"prefix": "gdinstr",
|
||||
"body": [
|
||||
"extension",
|
||||
"\t.add${1|Condition,Action|}(",
|
||||
"\t\t'${2:InstructionInternalName}',",
|
||||
"\t\t_('${3:Instruction full name}'),",
|
||||
"\t\t_(",
|
||||
"\t\t\t'${4:Instruction description}'",
|
||||
"\t\t),",
|
||||
"\t\t_('${5:Event sheet sentence}'),",
|
||||
"\t\t_('${6:Events group}'),",
|
||||
"\t\t'JsPlatform/Extensions/${8:icon}.png',",
|
||||
"\t\t'JsPlatform/Extensions/${8:icon}.png'",
|
||||
"\t)",
|
||||
"\t.getCodeExtraInformation()",
|
||||
"\t.setIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${9:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}tools}.js')",
|
||||
"\t.setFunctionName('gdjs.evtTools.${7:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}.}');",
|
||||
"",
|
||||
"$0"
|
||||
]
|
||||
},
|
||||
"Define expression": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an expression in a GDevelop extension definition.",
|
||||
"prefix": "gdexp",
|
||||
"body": [
|
||||
"extension",
|
||||
"\t.add${1|Expression,StrExpression|}(",
|
||||
"\t\t'${2:ExpressionsInternalName}',",
|
||||
"\t\t_('${3:Expression full name}'),",
|
||||
"\t\t_(",
|
||||
"\t\t\t'${4:Expression description}'",
|
||||
"\t\t),",
|
||||
"\t\t_('${5:Events group}'),",
|
||||
"\t\t'JsPlatform/Extensions/${7:icon}.png'",
|
||||
"\t)",
|
||||
"\t.getCodeExtraInformation()",
|
||||
"\t.setIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${8:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}tools}.js')",
|
||||
"\t.setFunctionName('gdjs.evtTools.${6:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}.}');",
|
||||
"",
|
||||
"$0"
|
||||
]
|
||||
},
|
||||
"Add parameter": {
|
||||
"scope": "javascript",
|
||||
"description": "Define a parameter in a GDevelop extension definition.",
|
||||
"prefix": "gdparam",
|
||||
"body": [
|
||||
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,police,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
|
||||
]
|
||||
},
|
||||
"Add code only parameter": {
|
||||
"scope": "javascript",
|
||||
"description": "Define a parameter in a GDevelop extension definition.",
|
||||
"prefix": "gdcoparam",
|
||||
"body": [
|
||||
".addCodeOnlyParameter('${1|inlineCode,currentScene,objectsContext,eventsFunctionContext,conditionInverted|}', '${2:Inline code (for inlineCode parameter)}')"
|
||||
]
|
||||
},
|
||||
"Add include": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an include file in a GDevelop extension definition.",
|
||||
"prefix": "gdincl",
|
||||
"body": [
|
||||
".addIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${1:include}.js')"
|
||||
]
|
||||
}
|
||||
}
|
202
.vscode/c_cpp_properties.json
vendored
202
.vscode/c_cpp_properties.json
vendored
@@ -1,108 +1,98 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Mac",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
|
||||
"/usr/local/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
|
||||
"/usr/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"browse": {
|
||||
"path": [
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
|
||||
"/usr/local/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
|
||||
"/usr/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
},
|
||||
"macFrameworkPath": [
|
||||
"/System/Library/Frameworks",
|
||||
"/Library/Frameworks"
|
||||
],
|
||||
"compilerPath": "/usr/bin/clang",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/IDE",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"/usr/include",
|
||||
"/usr/local/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"browse": {
|
||||
"path": [
|
||||
"/usr/include",
|
||||
"/usr/local/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/IDE",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
"UNICODE",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "msvc-x64",
|
||||
"browse": {
|
||||
"path": [
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Mac",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
|
||||
"/usr/local/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
|
||||
"/usr/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"browse": {
|
||||
"path": [
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
|
||||
"/usr/local/include",
|
||||
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
|
||||
"/usr/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
},
|
||||
"macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"],
|
||||
"compilerPath": "/usr/bin/clang",
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"/usr/include",
|
||||
"/usr/local/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"browse": {
|
||||
"path": ["/usr/include", "/usr/local/include", "${workspaceRoot}"],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
"UNICODE",
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
|
||||
],
|
||||
"intelliSenseMode": "msvc-x64",
|
||||
"browse": {
|
||||
"path": ["${workspaceRoot}"],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
"databaseFilename": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
|
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"xaver.clang-format",
|
||||
"ms-vscode.cpptools",
|
||||
"flowtype.flow-for-vscode"
|
||||
]
|
||||
}
|
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"preLaunchTask": "Start development server"
|
||||
}
|
||||
]
|
||||
}
|
21
.vscode/settings.json
vendored
21
.vscode/settings.json
vendored
@@ -90,12 +90,31 @@
|
||||
"__node_handle": "cpp",
|
||||
"bit": "cpp",
|
||||
"optional": "cpp",
|
||||
"filesystem": "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"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
"Binaries/Output": true,
|
||||
"ExtLibs/SFML": true,
|
||||
"GDJS/Runtime-dist": true,
|
||||
"docs": true,
|
||||
"newIDE/electron-app/dist": true,
|
||||
"newIDE/app/build": true,
|
||||
|
158
.vscode/tasks.json
vendored
158
.vscode/tasks.json
vendored
@@ -1,66 +1,100 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"path": "GDevelop.js/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Build GDevelop.js",
|
||||
"detail": "Builds GDCore for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "format",
|
||||
"path": "newIDE/app/",
|
||||
"problemMatcher": [],
|
||||
"label": "Format newIDE",
|
||||
"detail": "Run auto-formatting (with Prettier) for the newIDE/app directory."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Run newIDE tests",
|
||||
"detail": "Run tests for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "typescript",
|
||||
"tsconfig": "GDJS/tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
],
|
||||
"group": "test",
|
||||
"label": "GDJS TS Check",
|
||||
"detail": "Runs a types check on the GDJS Runtime."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "GDJS/",
|
||||
"group": "test",
|
||||
"problemMatcher": [],
|
||||
"label": "Run GDJS tests",
|
||||
"detail": "Run tests for GDJS."
|
||||
}
|
||||
]
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/app/",
|
||||
"group": "build",
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server.",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "cra",
|
||||
"fileLocation": ["relative", "${workspaceFolder}/newIDE/app"],
|
||||
"source": "create-react-app",
|
||||
"applyTo": "allDocuments",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([^\\s].*?)$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "^ Line\\s+(\\d+):\\s+(.*)\\s\\s+(.*)$",
|
||||
"line": 1,
|
||||
"message": 2,
|
||||
"code": 3,
|
||||
"loop": true
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^(?:Compiled with warnings\\.|Compiled successfully!)$",
|
||||
"endsPattern": "^(?:Search for the keywords to learn more about each warning\\.|Note that the development build is not optimized\\.)$"
|
||||
}
|
||||
}
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"isBackground": true,
|
||||
"runOptions": { "instanceLimit": 1, "runOn": "folderOpen" }
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/electron-app/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Start electron app",
|
||||
"detail": "Starts the development local version of GDevelop."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"path": "GDevelop.js/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Build GDevelop.js",
|
||||
"detail": "Builds GDCore for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "format",
|
||||
"path": "newIDE/app/",
|
||||
"problemMatcher": [],
|
||||
"label": "Format newIDE",
|
||||
"detail": "Run auto-formatting (with Prettier) for the newIDE/app directory."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Run newIDE tests",
|
||||
"detail": "Run tests for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "typescript",
|
||||
"tsconfig": "GDJS/tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": ["$tsc-watch"],
|
||||
"group": "test",
|
||||
"label": "GDJS TS Check",
|
||||
"detail": "Runs a types check on the GDJS Runtime."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "GDJS/",
|
||||
"group": "test",
|
||||
"problemMatcher": [],
|
||||
"label": "Run GDJS tests",
|
||||
"detail": "Run tests for GDJS."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -1 +1,3 @@
|
||||
This is the directory where native/WebAssembly binaries from GDCore, GDCpp and GDJS are produced.
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore, GDCpp and GDJS are produced.
|
||||
|
||||
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
|
@@ -9,6 +9,7 @@
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Project/Layer.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
@@ -26,10 +27,9 @@ void ExposeProjectEffects(
|
||||
auto& layout = project.GetLayout(s);
|
||||
|
||||
for (std::size_t l = 0; l < layout.GetLayersCount(); ++l) {
|
||||
auto& layer = layout.GetLayer(l);
|
||||
|
||||
for (std::size_t e = 0; e < layer.GetEffectsCount(); ++e) {
|
||||
auto& effect = layer.GetEffect(e);
|
||||
auto& effects = layout.GetLayer(l).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
|
@@ -360,8 +360,11 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
return codeGenerator.GenerateBadObject();
|
||||
}
|
||||
if (gd::ParameterMetadata::IsExpression("string", type)) {
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
return (type == "string") ? "\"\"" : "0";
|
||||
return "0";
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
|
||||
|
@@ -66,6 +66,22 @@ class GD_CORE_API ExpressionParser2 {
|
||||
return Start(type, objectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object name (or empty if none) and a behavior name (or empty if none),
|
||||
* return the index of the first parameter that is inside the parenthesis:
|
||||
* 0, 1 or 2.
|
||||
*
|
||||
* For example, in an expression like `Object.MyBehavior::Method("hello")`, the
|
||||
* parameter "hello" is the second parameter (the first being by convention Object,
|
||||
* and the second MyBehavior, also by convention).
|
||||
*/
|
||||
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
|
||||
const gd::String &behaviorName) {
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
return !behaviorName.empty() ? 2 : (!objectName.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
/** \name Grammar
|
||||
* Each method is a part of the grammar.
|
||||
@@ -999,13 +1015,6 @@ class GD_CORE_API ExpressionParser2 {
|
||||
}
|
||||
///@}
|
||||
|
||||
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
|
||||
const gd::String &behaviorName) {
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
return !behaviorName.empty() ? 2 : (!objectName.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
gd::String expression;
|
||||
std::size_t currentPosition;
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "AllBuiltinExtensions.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
@@ -26,7 +27,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
obj.AddCondition("PosX",
|
||||
_("Compare X position of an object"),
|
||||
_("X position"),
|
||||
_("Compare the X position of the object."),
|
||||
_("the X position"),
|
||||
_("Position"),
|
||||
@@ -38,7 +39,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("MettreX",
|
||||
_("X position of an object"),
|
||||
_("X position"),
|
||||
_("Change the X position of an object."),
|
||||
_("the X position"),
|
||||
_("Position"),
|
||||
@@ -50,7 +51,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("PosY",
|
||||
_("Compare Y position of an object"),
|
||||
_("Y position"),
|
||||
_("Compare the Y position of an object."),
|
||||
_("the Y position"),
|
||||
_("Position"),
|
||||
@@ -62,7 +63,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("MettreY",
|
||||
_("Y position of an object"),
|
||||
_("Y position"),
|
||||
_("Change the Y position of an object."),
|
||||
_("the Y position"),
|
||||
_("Position"),
|
||||
@@ -74,7 +75,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("MettreXY",
|
||||
_("Position of an object"),
|
||||
_("Position"),
|
||||
_("Change the position of an object."),
|
||||
_("Change the position of _PARAM0_: _PARAM1_ _PARAM2_ (x "
|
||||
"axis), _PARAM3_ _PARAM4_ (y axis)"),
|
||||
@@ -89,8 +90,41 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression", _("Y position"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("SetCenter",
|
||||
_("Center position"),
|
||||
_("Change the position of an object, using its center."),
|
||||
_("Change the position of the center of _PARAM0_: _PARAM1_ _PARAM2_ (x "
|
||||
"axis), _PARAM3_ _PARAM4_ (y axis)"),
|
||||
_("Position/Center"),
|
||||
"res/actions/position24.png",
|
||||
"res/actions/position.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("operator", _("Modification's sign"))
|
||||
.AddParameter("expression", _("X position"))
|
||||
.AddParameter("operator", _("Modification's sign"))
|
||||
.AddParameter("expression", _("Y position"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddExpressionAndConditionAndAction("number", "CenterX",
|
||||
_("Center X position"),
|
||||
_("the X position of the center"),
|
||||
_("the X position of the center"),
|
||||
_("Position/Center"),
|
||||
"res/actions/position24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.UseStandardParameters("number");
|
||||
|
||||
obj.AddExpressionAndConditionAndAction("number", "CenterY",
|
||||
_("Center Y position"),
|
||||
_("the Y position of the center"),
|
||||
_("the Y position of the center"),
|
||||
_("Position/Center"),
|
||||
"res/actions/position24.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.UseStandardParameters("number");
|
||||
|
||||
obj.AddAction("MettreAutourPos",
|
||||
_("Put an object around a position"),
|
||||
_("Put around a position"),
|
||||
_("Position the center of the given object around a position, "
|
||||
"using the specified angle "
|
||||
"and distance."),
|
||||
@@ -172,7 +206,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"all of the forces it has."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force of _PARAM1_ p/s on X axis and "
|
||||
"_PARAM2_ p/s on Y axis"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -188,7 +222,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"using the specified angle and length."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force, angle: _PARAM1_ degrees and "
|
||||
"length: _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -202,9 +236,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"AddForceVersPos",
|
||||
_("Add a force to move toward a position"),
|
||||
_("Add a force to an object to make it move toward a position."),
|
||||
_("Move _PARAM0_ to _PARAM1_;_PARAM2_ with _PARAM4_ force of _PARAM3_ "
|
||||
_("Move _PARAM0_ toward _PARAM1_;_PARAM2_ with _PARAM4_ force of _PARAM3_ "
|
||||
"pixels"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -217,30 +251,30 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddAction(
|
||||
"AddForceTournePos",
|
||||
_("Add a force to move around a position"),
|
||||
_("Add a force to an object to make it rotate around a "
|
||||
"Add a force to move around a position",
|
||||
"Add a force to an object to make it rotate around a "
|
||||
"position.\nNote that the movement is not precise, especially if "
|
||||
"the speed is high.\nTo position an object around a position more "
|
||||
"precisely, use the actions in the category \"Position\"."),
|
||||
_("Rotate _PARAM0_ around _PARAM1_;_PARAM2_ at _PARAM3_ deg/sec and "
|
||||
"_PARAM4_ pixels away"),
|
||||
_("Movement"),
|
||||
"precisely, use the actions in the category \"Position\".",
|
||||
"Rotate _PARAM0_ around _PARAM1_;_PARAM2_ at _PARAM3_ deg/sec and "
|
||||
"_PARAM4_ pixels away",
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceTourne24.png",
|
||||
"res/actions/forceTourne.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("X position of the center"))
|
||||
.AddParameter("expression", _("Y position of the center"))
|
||||
.AddParameter("expression", _("Speed (in Degrees per seconds)"))
|
||||
.AddParameter("expression", _("Distance (in pixels)"))
|
||||
.AddParameter("forceMultiplier", _("Force multiplier"))
|
||||
.AddParameter("expression", "X position of the center")
|
||||
.AddParameter("expression", "Y position of the center")
|
||||
.AddParameter("expression", "Speed (in Degrees per seconds)")
|
||||
.AddParameter("expression", "Distance (in pixels)")
|
||||
.AddParameter("forceMultiplier", "Force multiplier")
|
||||
.SetHidden();
|
||||
|
||||
obj.AddAction("Arreter",
|
||||
_("Stop the object"),
|
||||
_("Stop the object by deleting all of its forces."),
|
||||
_("Stop _PARAM0_ (remove all forces)"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/arreter24.png",
|
||||
"res/actions/arreter.png")
|
||||
|
||||
@@ -248,7 +282,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("Delete",
|
||||
_("Delete an object"),
|
||||
_("Delete the object"),
|
||||
_("Delete the specified object."),
|
||||
_("Delete _PARAM0_"),
|
||||
_("Objects"),
|
||||
@@ -383,7 +417,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddAction("Montre",
|
||||
_("Show"),
|
||||
_("Show the specified object"),
|
||||
_("Show the specified object."),
|
||||
_("Show _PARAM0_"),
|
||||
_("Visibility"),
|
||||
"res/actions/visibilite24.png",
|
||||
@@ -406,10 +440,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Plan",
|
||||
_("Compare Z order"),
|
||||
_("Z-order"),
|
||||
_("Compare the Z-order of the specified object."),
|
||||
_("the z Order"),
|
||||
_("Z order"),
|
||||
_("the Z-order"),
|
||||
_("Z-order"),
|
||||
"res/conditions/planicon24.png",
|
||||
"res/conditions/planicon.png")
|
||||
|
||||
@@ -418,7 +452,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Layer",
|
||||
_("Compare layer"),
|
||||
_("Current layer"),
|
||||
_("Check if the object is on the specified layer."),
|
||||
_("_PARAM0_ is on layer _PARAM1_"),
|
||||
_("Layer"),
|
||||
@@ -430,7 +464,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Visible",
|
||||
_("Visibility of an object"),
|
||||
_("Visibility"),
|
||||
_("Check if an object is visible."),
|
||||
_("_PARAM0_ is visible (not marked as hidden)"),
|
||||
_("Visibility"),
|
||||
@@ -441,9 +475,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("Invisible",
|
||||
_("Invisibility of an object"),
|
||||
_("Check if an object is hidden."),
|
||||
_("_PARAM0_ is hidden"),
|
||||
"Invisibility of an object",
|
||||
"Check if an object is hidden.",
|
||||
"_PARAM0_ is hidden",
|
||||
_("Visibility"),
|
||||
"res/conditions/visibilite24.png",
|
||||
"res/conditions/visibilite.png")
|
||||
@@ -452,10 +486,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetHidden(); // Inverted "Visible" condition does the same thing.
|
||||
|
||||
obj.AddCondition("Arret",
|
||||
_("Object is stopped"),
|
||||
_("Object is stopped (no forces applied on it)"),
|
||||
_("Check if an object is not moving"),
|
||||
_("_PARAM0_ is stopped"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/arret24.png",
|
||||
"res/conditions/arret.png")
|
||||
|
||||
@@ -463,10 +497,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Vitesse",
|
||||
_("Speed"),
|
||||
_("Speed (from forces)"),
|
||||
_("Compare the overall speed of an object"),
|
||||
_("the overall speed"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/vitesse24.png",
|
||||
"res/conditions/vitesse.png")
|
||||
|
||||
@@ -475,17 +509,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("AngleOfDisplacement",
|
||||
_("Angle of movement"),
|
||||
_("Compare the angle of displacement of an object"),
|
||||
_("Angle of displacement of _PARAM0_ is _PARAM1_ (tolerance "
|
||||
_("Angle of movement (using forces)"),
|
||||
_("Compare the angle of movement of an object according to the forces applied on it."),
|
||||
_("Angle of movement of _PARAM0_ is _PARAM1_ (tolerance"
|
||||
": _PARAM2_ degrees)"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/vitesse24.png",
|
||||
"res/conditions/vitesse.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Tolerance"))
|
||||
.AddParameter("expression", _("Tolerance, in degrees"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("VarObjet",
|
||||
@@ -526,9 +560,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetDefaultValue("true");
|
||||
|
||||
obj.AddCondition("VarObjetDef",
|
||||
_("Variable defined"),
|
||||
_("Check if the variable is defined."),
|
||||
_("Variable _PARAM1 of _PARAM0_ is defined"),
|
||||
"Variable defined",
|
||||
"Check if the variable is defined.",
|
||||
"Variable _PARAM1 of _PARAM0_ is defined",
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -598,7 +632,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Removes a variable at the specified index of an object array "
|
||||
"variable."),
|
||||
_("Remove variable at index _PARAM2_ from array variable _PARAM1_ of "
|
||||
"object _PARAM0_"),
|
||||
"_PARAM0_"),
|
||||
_("Variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
@@ -636,8 +670,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"AddForceVers",
|
||||
_("Add a force to move toward an object"),
|
||||
_("Add a force to an object to make it move toward another."),
|
||||
_("Move _PARAM0_ to _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
_("Move _PARAM0_ toward _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceVers24.png",
|
||||
"res/actions/forceVers.png")
|
||||
|
||||
@@ -656,7 +690,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"the actions in category \"Position\"."),
|
||||
_("Rotate _PARAM0_ around _PARAM1_ at _PARAM2_ deg/sec and _PARAM3_ "
|
||||
"pixels away"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceTourne24.png",
|
||||
"res/actions/forceTourne.png")
|
||||
|
||||
@@ -668,7 +702,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("MettreAutour",
|
||||
_("Put an object around another"),
|
||||
_("Put the object around another"),
|
||||
_("Position an object around another, with the specified angle "
|
||||
"and distance. The center of the objects are used for "
|
||||
"positioning them."),
|
||||
@@ -686,32 +720,32 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
// Deprecated action
|
||||
obj.AddAction("Rebondir",
|
||||
_("Move an object away from another"),
|
||||
_("Move an object away from another, using forces."),
|
||||
_("Move _PARAM0_ away from _PARAM1_ (only _PARAM0_ will move)"),
|
||||
_("Movement"),
|
||||
"Move an object away from another",
|
||||
"Move an object away from another, using forces.",
|
||||
"Move _PARAM0_ away from _PARAM1_ (only _PARAM0_ will move)",
|
||||
_("Movement using forces"),
|
||||
"res/actions/ecarter24.png",
|
||||
"res/actions/ecarter.png")
|
||||
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2 (won't move)"));
|
||||
.AddParameter("objectList", "Object 2 (won't move)");
|
||||
|
||||
// Deprecated action
|
||||
obj.AddAction("Ecarter",
|
||||
_("Move an object away from another"),
|
||||
_("Move an object away from another without using forces."),
|
||||
_("Move _PARAM0_ away from _PARAM2_ (only _PARAM0_ will move)"),
|
||||
"Move an object away from another",
|
||||
"Move an object away from another without using forces.",
|
||||
"Move _PARAM0_ away from _PARAM2_ (only _PARAM0_ will move)",
|
||||
_("Position"),
|
||||
"res/actions/ecarter24.png",
|
||||
"res/actions/ecarter.png")
|
||||
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2 (won't move)"));
|
||||
.AddParameter("objectList", "Object 2 (won't move)");
|
||||
|
||||
obj.AddAction("SeparateFromObjects",
|
||||
_("Separate two objects"),
|
||||
_("Separate objects"),
|
||||
_("Move an object away from another using their collision "
|
||||
"masks.\nBe sure to call this action on a reasonable number "
|
||||
"of objects\nto avoid slowing down the game."),
|
||||
@@ -848,37 +882,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceX",
|
||||
_("Average X coordinates of forces"),
|
||||
_("Average X coordinates of forces"),
|
||||
_("Movement"),
|
||||
_("X coordinate of the sum of forces"),
|
||||
_("X coordinate of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceY",
|
||||
_("Average Y coordinates of forces"),
|
||||
_("Average Y coordinates of forces"),
|
||||
_("Movement"),
|
||||
_("Y coordinate of the sum of forces"),
|
||||
_("Y coordinate of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceAngle",
|
||||
_("Average angle of the forces"),
|
||||
_("Average angle of the forces"),
|
||||
_("Movement"),
|
||||
_("Angle of the sum of forces"),
|
||||
_("Angle of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceLength",
|
||||
_("Average length of the forces"),
|
||||
_("Average length of the forces"),
|
||||
_("Movement"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("Longueur",
|
||||
_("Average length of the forces"),
|
||||
_("Average length of the forces"),
|
||||
_("Movement"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.SetHidden();
|
||||
@@ -914,15 +948,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetHidden();
|
||||
|
||||
obj.AddExpression("ZOrder",
|
||||
_("Z order"),
|
||||
_("Z order of an object"),
|
||||
_("Z-order"),
|
||||
_("Z-order of an object"),
|
||||
_("Visibility"),
|
||||
"res/actions/planicon.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("Plan",
|
||||
_("Z order"),
|
||||
_("Z order of an object"),
|
||||
_("Z-order"),
|
||||
_("Z-order of an object"),
|
||||
_("Visibility"),
|
||||
"res/actions/planicon.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
@@ -998,17 +1032,41 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Angle between two objects"),
|
||||
_("Compute the angle between two objects. If you need the "
|
||||
"angle to an arbitrary position, use AngleToPosition."),
|
||||
_("Position"),
|
||||
_("Angle"),
|
||||
"res/actions/position.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectPtr", _("Object"));
|
||||
|
||||
obj.AddExpression("XFromAngleAndDistance",
|
||||
_("X position from angle and distance"),
|
||||
_("Compute the X position when given an angle and distance "
|
||||
"relative to the starting object. This is also known as "
|
||||
"getting the cartesian coordinates of a 2D vector, using "
|
||||
"its polar coordinates."),
|
||||
_("Position"),
|
||||
"res/actions/position.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Distance"));
|
||||
|
||||
obj.AddExpression("YFromAngleAndDistance",
|
||||
_("Y position from angle and distance"),
|
||||
_("Compute the Y position when given an angle and distance "
|
||||
"relative to the starting object. This is also known as "
|
||||
"getting the cartesian coordinates of a 2D vector, using "
|
||||
"its polar coordinates."),
|
||||
_("Position"),
|
||||
"res/actions/position.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Distance"));
|
||||
|
||||
obj.AddExpression("AngleToPosition",
|
||||
_("Angle between an object and a position"),
|
||||
_("Compute the angle between the object center and a "
|
||||
"\"target\" position. If you need the angle between two "
|
||||
"objects, use AngleToObject."),
|
||||
_("Position"),
|
||||
_("Angle"),
|
||||
"res/actions/position.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Target X position"))
|
||||
@@ -1091,7 +1149,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Moves all objects according to the forces they have. GDevelop "
|
||||
"calls this action at the end of the events by default."),
|
||||
_("Apply movement to all objects"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/doMove24.png",
|
||||
"res/actions/doMove.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
@@ -1099,16 +1157,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("SeDirige",
|
||||
_("An object is moving toward another"),
|
||||
_("An object is moving toward another (using forces)"),
|
||||
_("Check if an object moves toward another.\nThe first "
|
||||
"object must move."),
|
||||
_("_PARAM0_ is moving toward _PARAM1_"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/sedirige24.png",
|
||||
"res/conditions/sedirige.png")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2"))
|
||||
.AddParameter("expression", _("Angle of tolerance"))
|
||||
.AddParameter("expression", _("Tolerance, in degrees"))
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
|
@@ -379,6 +379,30 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
|
||||
.AddParameter("expression", _("b (in a+(b-a)*x)"))
|
||||
.AddParameter("expression", _("x (in a+(b-a)*x)"));
|
||||
|
||||
extension
|
||||
.AddExpression("XFromAngleAndDistance",
|
||||
_("X position from angle and distance"),
|
||||
_("Compute the X position when given an angle and distance "
|
||||
"relative to the origin (0;0). This is also known as "
|
||||
"getting the cartesian coordinates of a 2D vector, using "
|
||||
"its polar coordinates."),
|
||||
_("Mathematical tools"),
|
||||
"res/mathfunction.png")
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Distance"));
|
||||
|
||||
extension
|
||||
.AddExpression("YFromAngleAndDistance",
|
||||
_("Y position from angle and distance"),
|
||||
_("Compute the Y position when given an angle and distance "
|
||||
"relative to the origin (0;0). This is also known as "
|
||||
"getting the cartesian coordinates of a 2D vector, using "
|
||||
"its polar coordinates."),
|
||||
_("Mathematical tools"),
|
||||
"res/mathfunction.png")
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Distance"));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
.SetExtensionInformation(
|
||||
"BuiltinNetwork",
|
||||
_("Basic internet features"),
|
||||
_("Features to send web requests, communicate with external \"APIs\" and other network related tasks."),
|
||||
_("Features to send web requests, communicate with external \"APIs\" "
|
||||
"and other network related tasks."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/all-features/network");
|
||||
@@ -24,33 +25,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"SendRequest",
|
||||
_("Send a request to a web page"),
|
||||
_("Send a request to the specified web page.\n\nPlease note that for "
|
||||
"the web games, the game must be hosted on the same host "
|
||||
"as specified below, except if the server is configured to answer "
|
||||
"to all requests (cross-domain requests)."),
|
||||
_("Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_"),
|
||||
"Send a request to a web page",
|
||||
"Send a request to the specified web page.\n\nPlease note that for "
|
||||
"the web games, the game must be hosted on the same host "
|
||||
"as specified below, except if the server is configured to answer "
|
||||
"to all requests (cross-domain requests).",
|
||||
"Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_",
|
||||
_("Network"),
|
||||
"res/actions/net24.png",
|
||||
"res/actions/net.png")
|
||||
.AddParameter("string", _("Host, with protocol"))
|
||||
.SetParameterLongDescription(_("Example: \"http://example.com/\"."))
|
||||
.AddParameter("string", _("Path"))
|
||||
.AddParameter("string", "Host, with protocol")
|
||||
.SetParameterLongDescription("Example: \"http://example.com/\".")
|
||||
.AddParameter("string", "Path")
|
||||
.SetParameterLongDescription(
|
||||
_("Example: \"/user/123\" or \"/some-page.php\"."))
|
||||
.AddParameter("string", _("Request body content"))
|
||||
.AddParameter("string", _("Method: \"POST\" or \"GET\""), "", true)
|
||||
.SetParameterLongDescription(_("If empty, \"GET\" will be used."))
|
||||
"Example: \"/user/123\" or \"/some-page.php\".")
|
||||
.AddParameter("string", "Request body content")
|
||||
.AddParameter("string", "Method: \"POST\" or \"GET\"", "", true)
|
||||
.SetParameterLongDescription("If empty, \"GET\" will be used.")
|
||||
.SetDefaultValue("\"GET\"")
|
||||
.AddParameter("string", _("Content type"), "", true)
|
||||
.AddParameter("string", "Content type", "", true)
|
||||
.SetParameterLongDescription(
|
||||
_("If empty, \"application/x-www-form-urlencoded\" will be used."))
|
||||
.AddParameter("scenevar", _("Reponse scene variable"), "", true)
|
||||
"If empty, \"application/x-www-form-urlencoded\" will be used.")
|
||||
.AddParameter("scenevar", "Reponse scene variable", "", true)
|
||||
.SetParameterLongDescription(
|
||||
_("The response of the server will be stored, as a string, in this "
|
||||
"variable. If the server returns *JSON*, you may want to use the "
|
||||
"action \"Convert JSON to a scene variable\" afterwards, to "
|
||||
"explore the results with a *structure variable*."))
|
||||
"The response of the server will be stored, as a string, in this "
|
||||
"variable. If the server returns *JSON*, you may want to use the "
|
||||
"action \"Convert JSON to a scene variable\" afterwards, to "
|
||||
"explore the results with a *structure variable*.")
|
||||
.MarkAsComplex()
|
||||
.SetHidden();
|
||||
|
||||
@@ -74,7 +75,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
"highly recommended."))
|
||||
.AddParameter("string", _("Request body content"))
|
||||
.AddParameter("stringWithSelector",
|
||||
_("Resize mode"),
|
||||
_("Request method"),
|
||||
"[\"GET\", \"POST\", \"PUT\", \"HEAD\", \"DELETE\", "
|
||||
"\"PATCH\", \"OPTIONS\"]",
|
||||
false)
|
||||
|
@@ -66,7 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Animation name"))
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction(
|
||||
@@ -133,9 +133,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("TourneVersPos",
|
||||
_("Rotate an object toward a position"),
|
||||
_("Rotate an object towards a position."),
|
||||
_("Rotate _PARAM0_ towards _PARAM1_;_PARAM2_"),
|
||||
"Rotate an object toward a position",
|
||||
"Rotate an object towards a position.",
|
||||
"Rotate _PARAM0_ towards _PARAM1_;_PARAM2_",
|
||||
_("Direction"),
|
||||
"res/actions/direction24.png",
|
||||
"res/actions/direction.png")
|
||||
@@ -230,7 +230,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/conditions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Animation name"))
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition(
|
||||
@@ -249,7 +249,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
|
||||
obj.AddCondition("Sprite",
|
||||
_("Current frame"),
|
||||
_("Compare the index of the current frame in the animation displayed by the specified object. The first frame in an animation starts at index 0."),
|
||||
_("Compare the index of the current frame in the animation "
|
||||
"displayed by the specified object. The first frame in an "
|
||||
"animation starts at index 0."),
|
||||
_("the animation frame"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/sprite24.png",
|
||||
@@ -365,14 +367,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("color", _("Color to make transparent"));
|
||||
|
||||
obj.AddAction(
|
||||
"ChangeColor",
|
||||
_("Tint color"),
|
||||
_("Change the tint of an object. The default color is white."),
|
||||
_("Change tint of _PARAM0_ to _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/actions/color24.png",
|
||||
"res/actions/color.png")
|
||||
obj.AddAction("ChangeColor",
|
||||
_("Tint color"),
|
||||
_("Change the tint of an object. The default color is white."),
|
||||
_("Change tint of _PARAM0_ to _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/actions/color24.png",
|
||||
"res/actions/color.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("color", _("Tint"));
|
||||
@@ -436,15 +437,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
obj.AddAction("TourneVers",
|
||||
_("Rotate an object toward another"),
|
||||
_("Rotate an object towards another."),
|
||||
_("Rotate _PARAM0_ towards _PARAM1_"),
|
||||
"Rotate an object toward another",
|
||||
"Rotate an object towards another.",
|
||||
"Rotate _PARAM0_ towards _PARAM1_",
|
||||
_("Direction"),
|
||||
"res/actions/direction24.png",
|
||||
"res/actions/direction.png")
|
||||
|
||||
.AddParameter("object", _("Object to be rotated"), "Sprite")
|
||||
.AddParameter("objectPtr", _("Rotate toward this object"))
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("objectPtr", "Rotate toward this object")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.SetHidden(); // Deprecated
|
||||
|
||||
@@ -455,7 +456,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
.AddParameter("objectPointName", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("Y",
|
||||
_("Y position of a point"),
|
||||
@@ -464,7 +465,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
.AddParameter("objectPointName", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("PointX",
|
||||
_("X position of a point"),
|
||||
@@ -473,7 +474,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
.AddParameter("objectPointName", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("PointY",
|
||||
_("Y position of a point"),
|
||||
@@ -482,7 +483,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
.AddParameter("objectPointName", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("Direc",
|
||||
_("Direction"),
|
||||
|
@@ -112,9 +112,9 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
|
||||
extension
|
||||
.AddExpression("StrRFind",
|
||||
_("Search in a text from the end"),
|
||||
_("Search in a text from the end (return the position of "
|
||||
"the result or -1 if not found)"),
|
||||
"Search in a text from the end",
|
||||
"Search in a text from the end (return the position of "
|
||||
"the result or -1 if not found)",
|
||||
_("Manipulation of text"),
|
||||
"res/conditions/toujours24.png")
|
||||
|
||||
@@ -152,17 +152,17 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
extension
|
||||
.AddExpression(
|
||||
"StrRFindFrom",
|
||||
_("Search in a text from the end, starting from a position"),
|
||||
_("Search in a text from the end, starting from a position (return "
|
||||
"the position of the result or -1 if not found)"),
|
||||
"Search in a text from the end, starting from a position",
|
||||
"Search in a text from the end, starting from a position (return "
|
||||
"the position of the result or -1 if not found)",
|
||||
_("Manipulation of text"),
|
||||
"res/conditions/toujours24.png")
|
||||
|
||||
.AddParameter("string", _("Text"))
|
||||
.AddParameter("string", _("Text to search for"))
|
||||
.AddParameter("expression",
|
||||
_("Position of the last character in the string to be "
|
||||
"considered in the search"))
|
||||
"Position of the last character in the string to be "
|
||||
"considered in the search")
|
||||
.SetHidden(); // Deprecated, see StrFindLastFrom instead.
|
||||
|
||||
extension
|
||||
|
@@ -87,9 +87,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("VarSceneDef",
|
||||
_("Test if a scene variable is defined"),
|
||||
_("Test if the scene variable exists."),
|
||||
_("Scene variable _PARAM0_ is defined"),
|
||||
"Test if a scene variable is defined",
|
||||
"Test if the scene variable exists.",
|
||||
"Scene variable _PARAM0_ is defined",
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -136,9 +136,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("VarGlobalDef",
|
||||
_("Test if a global variable is defined"),
|
||||
_("Test if a global variable exists"),
|
||||
_("Global variable _PARAM0_ is defined"),
|
||||
"Test if a global variable is defined",
|
||||
"Test if a global variable exists",
|
||||
"Global variable _PARAM0_ is defined",
|
||||
_("Variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -341,7 +341,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"SceneVariableRemoveAt",
|
||||
_("Remove variable from a scene array (by index)"),
|
||||
_("Removes a variable at the specified index of a scene array variable."),
|
||||
_("Remove variable at index _PARAM1_ from array variable _PARAM0_"),
|
||||
_("Remove variable at index _PARAM1_ from scene array variable _PARAM0_"),
|
||||
_("Variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
@@ -367,7 +367,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"GlobalVariableRemoveAt",
|
||||
_("Remove variable from a global array (by index)"),
|
||||
_("Removes a variable at the specified index of a global array variable."),
|
||||
_("Remove variable at index _PARAM1_ from array variable _PARAM0_"),
|
||||
_("Remove variable at index _PARAM1_ from global array variable _PARAM0_"),
|
||||
_("Variables/Global variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
|
@@ -19,7 +19,7 @@ using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::BehaviorMetadata MetadataProvider::badBehaviorInfo;
|
||||
gd::BehaviorMetadata MetadataProvider::badBehaviorMetadata;
|
||||
gd::ObjectMetadata MetadataProvider::badObjectInfo;
|
||||
gd::EffectMetadata MetadataProvider::badEffectMetadata;
|
||||
gd::InstructionMetadata MetadataProvider::badInstructionMetadata;
|
||||
@@ -38,7 +38,7 @@ MetadataProvider::GetExtensionAndBehaviorMetadata(const gd::Platform& platform,
|
||||
}
|
||||
}
|
||||
|
||||
return ExtensionAndMetadata<BehaviorMetadata>(badExtension, badBehaviorInfo);
|
||||
return ExtensionAndMetadata<BehaviorMetadata>(badExtension, badBehaviorMetadata);
|
||||
}
|
||||
|
||||
const BehaviorMetadata& MetadataProvider::GetBehaviorMetadata(
|
||||
|
@@ -245,13 +245,17 @@ class GD_CORE_API MetadataProvider {
|
||||
return &metadata == &badExpressionMetadata;
|
||||
}
|
||||
|
||||
static bool IsBadBehaviorMetadata(const gd::BehaviorMetadata& metadata) {
|
||||
return &metadata == &badBehaviorMetadata;
|
||||
}
|
||||
|
||||
virtual ~MetadataProvider();
|
||||
|
||||
private:
|
||||
MetadataProvider();
|
||||
|
||||
static PlatformExtension badExtension;
|
||||
static BehaviorMetadata badBehaviorInfo;
|
||||
static BehaviorMetadata badBehaviorMetadata;
|
||||
static ObjectMetadata badObjectInfo;
|
||||
static EffectMetadata badEffectMetadata;
|
||||
static gd::InstructionMetadata badInstructionMetadata;
|
||||
|
@@ -123,7 +123,10 @@ gd::InstructionMetadata& ObjectMetadata::AddScopedCondition(
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace =
|
||||
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
|
||||
GetName().empty()
|
||||
? name // Don't insert a namespace separator for the base object.
|
||||
: GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
|
||||
|
||||
conditionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
|
||||
nameWithNamespace,
|
||||
fullname,
|
||||
@@ -148,7 +151,10 @@ gd::InstructionMetadata& ObjectMetadata::AddScopedAction(
|
||||
const gd::String& smallicon) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String nameWithNamespace =
|
||||
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
|
||||
GetName().empty()
|
||||
? name // Don't insert a namespace separator for the base object.
|
||||
: GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
|
||||
|
||||
actionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
|
||||
nameWithNamespace,
|
||||
fullname,
|
||||
|
@@ -175,7 +175,8 @@ class GD_CORE_API ParameterMetadata {
|
||||
* \brief Return true if the type of the parameter is an expression of the
|
||||
* given type.
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor) and in the EventsCodeGenerator.
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
*/
|
||||
static bool IsExpression(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
@@ -187,7 +188,9 @@ class GD_CORE_API ParameterMetadata {
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "joyaxis" ||
|
||||
parameterType == "stringWithSelector" ||
|
||||
parameterType == "sceneName";
|
||||
parameterType == "sceneName" ||
|
||||
parameterType == "objectPointName" ||
|
||||
parameterType == "objectAnimationName";
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
|
@@ -100,26 +100,6 @@ std::unique_ptr<gd::Object> Platform::CreateObject(
|
||||
return std::unique_ptr<gd::Object>(std::move(object));
|
||||
}
|
||||
|
||||
gd::Behavior* Platform::GetBehavior(const gd::String& behaviorType) const {
|
||||
for (std::size_t i = 0; i < extensionsLoaded.size(); ++i) {
|
||||
gd::Behavior* behavior = extensionsLoaded[i]->GetBehavior(behaviorType);
|
||||
if (behavior) return behavior;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* Platform::GetBehaviorSharedDatas(
|
||||
const gd::String& behaviorType) const {
|
||||
for (std::size_t i = 0; i < extensionsLoaded.size(); ++i) {
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
extensionsLoaded[i]->GetBehaviorSharedDatas(behaviorType);
|
||||
if (behaviorSharedData) return behaviorSharedData;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::shared_ptr<gd::BaseEvent> Platform::CreateEvent(
|
||||
const gd::String& eventType) const {
|
||||
|
@@ -126,7 +126,8 @@ class GD_CORE_API Platform {
|
||||
///@}
|
||||
|
||||
/** \name Factory method
|
||||
* Member functions used to create the platforms objects
|
||||
* Member functions used to create the platform objects.
|
||||
* TODO: This could be moved to gd::MetadataProvider.
|
||||
*/
|
||||
///@{
|
||||
|
||||
@@ -136,18 +137,6 @@ class GD_CORE_API Platform {
|
||||
std::unique_ptr<gd::Object> CreateObject(gd::String type,
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Get the class handling the behavior with the given type, or
|
||||
* `nullptr` if no behavior with the given type is found.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(const gd::String& type) const;
|
||||
|
||||
/**
|
||||
* \brief Get the class handling the behavior shared data with the given type,
|
||||
* or `nullptr` if no behavior with the given type is found.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(const gd::String& type) const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Create an event of given type
|
||||
@@ -165,11 +154,13 @@ class GD_CORE_API Platform {
|
||||
/**
|
||||
* \brief Called when the IDE is about to shut down: Take this opportunity for
|
||||
* erasing for example any temporary file.
|
||||
* @deprecated This should be removed.
|
||||
*/
|
||||
virtual void OnIDEClosed(){};
|
||||
|
||||
/**
|
||||
* \brief Called when the IDE is initialized and ready to be used.
|
||||
* @deprecated This should be removed.
|
||||
*/
|
||||
virtual void OnIDEInitialized(){};
|
||||
|
||||
|
@@ -512,7 +512,7 @@ PlatformExtension::GetAllStrExpressionsForBehavior(gd::String autoType) {
|
||||
return badExpressionsMetadata;
|
||||
}
|
||||
|
||||
gd::BaseEventSPtr PlatformExtension::CreateEvent(gd::String eventType) const {
|
||||
gd::BaseEventSPtr PlatformExtension::CreateEvent(const gd::String& eventType) const {
|
||||
if (eventsInfos.find(eventType) != eventsInfos.end()) {
|
||||
if (eventsInfos.find(eventType)->second.instance ==
|
||||
std::shared_ptr<BaseEvent>()) {
|
||||
@@ -531,14 +531,14 @@ gd::BaseEventSPtr PlatformExtension::CreateEvent(gd::String eventType) const {
|
||||
#endif
|
||||
|
||||
CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
|
||||
gd::String objectType) const {
|
||||
const gd::String& objectType) const {
|
||||
if (objectsInfos.find(objectType) != objectsInfos.end())
|
||||
return objectsInfos.find(objectType)->second.createFunPtr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gd::Behavior* PlatformExtension::GetBehavior(gd::String type) const {
|
||||
gd::Behavior* PlatformExtension::GetBehavior(const gd::String& type) const {
|
||||
if (behaviorsInfo.find(type) != behaviorsInfo.end())
|
||||
return &behaviorsInfo.find(type)->second.Get();
|
||||
|
||||
@@ -546,7 +546,7 @@ gd::Behavior* PlatformExtension::GetBehavior(gd::String type) const {
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* PlatformExtension::GetBehaviorSharedDatas(
|
||||
gd::String type) const {
|
||||
const gd::String& type) const {
|
||||
if (behaviorsInfo.find(type) != behaviorsInfo.end() &&
|
||||
behaviorsInfo.find(type)->second.GetSharedDataInstance())
|
||||
return behaviorsInfo.find(type)->second.GetSharedDataInstance();
|
||||
|
@@ -400,7 +400,7 @@ class GD_CORE_API PlatformExtension {
|
||||
* \brief Return a function to create the object if the type is handled by the
|
||||
* extension
|
||||
*/
|
||||
CreateFunPtr GetObjectCreationFunctionPtr(gd::String objectType) const;
|
||||
CreateFunPtr GetObjectCreationFunctionPtr(const gd::String& objectType) const;
|
||||
|
||||
/**
|
||||
* \brief Return a vector containing all the effect types provided by the
|
||||
@@ -413,13 +413,13 @@ class GD_CORE_API PlatformExtension {
|
||||
*
|
||||
* Return an empty pointer if \a eventType is not provided by the extension.
|
||||
*/
|
||||
std::shared_ptr<gd::BaseEvent> CreateEvent(gd::String eventType) const;
|
||||
std::shared_ptr<gd::BaseEvent> CreateEvent(const gd::String& eventType) const;
|
||||
/**
|
||||
* \brief Get the gd::Behavior handling the given behavior type.
|
||||
*
|
||||
* Return nullptr if \a behaviorType is not provided by the extension.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(gd::String behaviorType) const;
|
||||
gd::Behavior* GetBehavior(const gd::String& behaviorType) const;
|
||||
|
||||
/**
|
||||
* \brief Get the gd::BehaviorsSharedData handling the given behavior shared
|
||||
@@ -428,7 +428,7 @@ class GD_CORE_API PlatformExtension {
|
||||
* Return nullptr if \a behaviorType is not provided by the extension.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(
|
||||
gd::String behaviorType) const;
|
||||
const gd::String& behaviorType) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the ObjectMetadata object associated to \a
|
||||
|
@@ -15,25 +15,18 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::Layout& layout_)
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::Layout& layout_)
|
||||
: project(project_), layout(&layout_), externalEvents(NULL) {
|
||||
parentScenes.push_back(layout->GetName());
|
||||
}
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::ExternalEvents& externalEvents_)
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::ExternalEvents& externalEvents_)
|
||||
: project(project_), layout(NULL), externalEvents(&externalEvents_) {
|
||||
parentExternalEvents.push_back(externalEvents->GetName());
|
||||
}
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const DependenciesAnalyzer& parent)
|
||||
: parentScenes(parent.parentScenes),
|
||||
parentExternalEvents(parent.parentExternalEvents),
|
||||
project(parent.project),
|
||||
layout(NULL),
|
||||
externalEvents(NULL) {}
|
||||
|
||||
bool DependenciesAnalyzer::Analyze() {
|
||||
if (layout)
|
||||
return Analyze(layout->GetEvents(), true);
|
||||
@@ -47,9 +40,9 @@ bool DependenciesAnalyzer::Analyze() {
|
||||
|
||||
DependenciesAnalyzer::~DependenciesAnalyzer() {}
|
||||
|
||||
bool DependenciesAnalyzer::Analyze(gd::EventsList& events, bool isOnTopLevel) {
|
||||
bool DependenciesAnalyzer::Analyze(const gd::EventsList& events, bool isOnTopLevel) {
|
||||
for (unsigned int i = 0; i < events.size(); ++i) {
|
||||
gd::LinkEvent* linkEvent = dynamic_cast<gd::LinkEvent*>(&events[i]);
|
||||
const gd::LinkEvent* linkEvent = dynamic_cast<const gd::LinkEvent*>(&events[i]);
|
||||
if (linkEvent) {
|
||||
DependenciesAnalyzer analyzer(*this);
|
||||
|
||||
@@ -113,7 +106,7 @@ bool DependenciesAnalyzer::Analyze(gd::EventsList& events, bool isOnTopLevel) {
|
||||
sourceFilesDependencies.insert(dependencies.begin(), dependencies.end());
|
||||
|
||||
const gd::String& associatedSourceFile =
|
||||
events[i].GetAssociatedGDManagedSourceFile(project);
|
||||
events[i].GetAssociatedGDManagedSourceFile(const_cast<gd::Project&>(project));
|
||||
if (!associatedSourceFile.empty())
|
||||
sourceFilesDependencies.insert(associatedSourceFile);
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
/**
|
||||
* \brief Constructor for analyzing the dependencies of a layout
|
||||
*/
|
||||
DependenciesAnalyzer(gd::Project& project_, gd::Layout& layout_);
|
||||
DependenciesAnalyzer(const gd::Project& project_, const gd::Layout& layout_);
|
||||
|
||||
/**
|
||||
* \brief Constructor for analyzing the dependencies of external events.
|
||||
@@ -45,8 +45,8 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
* external events can be compiled separatly and called by a scene. \see
|
||||
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene
|
||||
*/
|
||||
DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::ExternalEvents& externalEvents);
|
||||
DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::ExternalEvents& externalEvents);
|
||||
|
||||
virtual ~DependenciesAnalyzer();
|
||||
|
||||
@@ -124,13 +124,7 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
* (they have no parents). \return false if a circular dependency exists, true
|
||||
* otherwise.
|
||||
*/
|
||||
bool Analyze(gd::EventsList& events, bool isOnTopLevel);
|
||||
|
||||
/**
|
||||
* \brief Internal constructor used when analyzing a linked layout/external
|
||||
* events.
|
||||
*/
|
||||
DependenciesAnalyzer(const DependenciesAnalyzer& parent);
|
||||
bool Analyze(const gd::EventsList& events, bool isOnTopLevel);
|
||||
|
||||
void AddParentScene(gd::String parentScene) {
|
||||
parentScenes.push_back(parentScene);
|
||||
@@ -161,9 +155,9 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
std::vector<gd::String>
|
||||
parentExternalEvents; ///< Used to check for circular dependencies.
|
||||
|
||||
gd::Project& project;
|
||||
gd::Layout* layout;
|
||||
gd::ExternalEvents* externalEvents;
|
||||
const gd::Project& project;
|
||||
const gd::Layout* layout;
|
||||
const gd::ExternalEvents* externalEvents;
|
||||
};
|
||||
|
||||
#endif // DEPENDENCIESANALYZER_H
|
||||
|
@@ -17,6 +17,7 @@ LayoutEditorCanvasOptions::LayoutEditorCanvasOptions()
|
||||
gridHeight(32),
|
||||
gridOffsetX(0),
|
||||
gridOffsetY(0),
|
||||
gridType("rectangular"),
|
||||
gridR(158),
|
||||
gridG(180),
|
||||
gridB(255),
|
||||
@@ -30,6 +31,7 @@ void LayoutEditorCanvasOptions::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("gridHeight", gridHeight);
|
||||
element.SetAttribute("gridOffsetX", gridOffsetX);
|
||||
element.SetAttribute("gridOffsetY", gridOffsetY);
|
||||
element.SetAttribute("gridType", gridType);
|
||||
element.SetAttribute("gridR", gridR);
|
||||
element.SetAttribute("gridG", gridG);
|
||||
element.SetAttribute("gridB", gridB);
|
||||
@@ -42,10 +44,11 @@ void LayoutEditorCanvasOptions::UnserializeFrom(
|
||||
grid = element.GetBoolAttribute("grid");
|
||||
snap = element.GetBoolAttribute("snap");
|
||||
windowMask = element.GetBoolAttribute("windowMask");
|
||||
gridWidth = element.GetIntAttribute("gridWidth", 32);
|
||||
gridHeight = element.GetIntAttribute("gridHeight", 32);
|
||||
gridOffsetX = element.GetIntAttribute("gridOffsetX", 0);
|
||||
gridOffsetY = element.GetIntAttribute("gridOffsetY", 0);
|
||||
gridWidth = element.GetDoubleAttribute("gridWidth", 32);
|
||||
gridHeight = element.GetDoubleAttribute("gridHeight", 32);
|
||||
gridOffsetX = element.GetDoubleAttribute("gridOffsetX", 0);
|
||||
gridOffsetY = element.GetDoubleAttribute("gridOffsetY", 0);
|
||||
gridType = element.GetStringAttribute("gridType", "rectangular");
|
||||
gridR = element.GetIntAttribute("gridR", 158);
|
||||
gridG = element.GetIntAttribute("gridG", 180);
|
||||
gridB = element.GetIntAttribute("gridB", 255);
|
||||
|
@@ -40,10 +40,11 @@ class GD_CORE_API LayoutEditorCanvasOptions {
|
||||
|
||||
bool grid; ///< True if grid activated in editor
|
||||
bool snap; ///< True if snap to grid activated in editor
|
||||
int gridWidth; ///< Grid width in editor
|
||||
int gridHeight; ///< Grid height in editor
|
||||
int gridOffsetX; ///< Grid X offset
|
||||
int gridOffsetY; ///< Grid Y offset
|
||||
double gridWidth; ///< Grid width in editor
|
||||
double gridHeight; ///< Grid height in editor
|
||||
double gridOffsetX; ///< Grid X offset
|
||||
double gridOffsetY; ///< Grid Y offset
|
||||
gd::String gridType; ///< Grid type: rectangular or isometric
|
||||
int gridR; ///< Grid red color in editor
|
||||
int gridG; ///< Grid green color in editor
|
||||
int gridB; ///< Grid blue color in editor
|
||||
|
@@ -17,6 +17,8 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -95,11 +97,11 @@ std::set<gd::String> EventsVariablesFinder::FindAllGlobalVariables(
|
||||
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInEvents(platform,
|
||||
project,
|
||||
project.GetLayout(i),
|
||||
project.GetLayout(i).GetEvents(),
|
||||
"globalvar");
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
project,
|
||||
project.GetLayout(i),
|
||||
"globalvar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
|
||||
@@ -112,8 +114,8 @@ std::set<gd::String> EventsVariablesFinder::FindAllLayoutVariables(
|
||||
const gd::Layout& layout) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(
|
||||
platform, project, layout, layout.GetEvents(), "scenevar");
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
platform, project, layout, "scenevar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
return results;
|
||||
@@ -126,12 +128,12 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
|
||||
const gd::Object& object) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(platform,
|
||||
project,
|
||||
layout,
|
||||
layout.GetEvents(),
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
return results;
|
||||
@@ -203,6 +205,38 @@ std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(
|
||||
platform, project, layout, layout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
|
||||
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, layout, externalEvents.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, dependencyLayout, dependencyLayout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEvents(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
|
@@ -24,11 +24,17 @@ namespace gd {
|
||||
* global or object variables.
|
||||
*
|
||||
* \todo Refactor this class using ArbitraryEventsWorker
|
||||
* \todo Rework this class to return the shapes (maybe even types?) of the
|
||||
* variables (in particular for structures and arrays), so we can use this
|
||||
* for better autocompletions in the variables dialogs in the IDE.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class EventsVariablesFinder {
|
||||
public:
|
||||
EventsVariablesFinder(){};
|
||||
virtual ~EventsVariablesFinder(){};
|
||||
|
||||
/**
|
||||
* Construct a list containing the name of all global variables used in the
|
||||
* project.
|
||||
@@ -94,10 +100,34 @@ class EventsVariablesFinder {
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType
|
||||
* parameterType. It searchs in events dependencies.
|
||||
*
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param project The layout used
|
||||
* \param layout The layout used
|
||||
* \param events The events to be analyzed
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
*
|
||||
* \return A std::set filled with the values used for all parameters of the
|
||||
* specified type
|
||||
*/
|
||||
static std::set<gd::String> FindArgumentsInEventsAndDependencies(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType. It doesn't search in events dependencies.
|
||||
*
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param layout The layout used
|
||||
* \param events The events to be analyzed
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
@@ -113,10 +143,7 @@ class EventsVariablesFinder {
|
||||
const gd::Layout& layout,
|
||||
const gd::EventsList& events,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
EventsVariablesFinder(){};
|
||||
virtual ~EventsVariablesFinder(){};
|
||||
const gd::String& objectName);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
31
Core/GDCore/IDE/Events/ExpressionCompletionFinder.cpp
Normal file
31
Core/GDCore/IDE/Events/ExpressionCompletionFinder.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ExpressionCompletionFinder.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
const gd::ParameterMetadata
|
||||
ExpressionCompletionDescription::badParameterMetadata;
|
||||
|
||||
/**
|
||||
* \brief Turn an ExpressionCompletionDescription to a string.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
ExpressionCompletionDescription const& value) {
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -8,10 +8,14 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/IDE/Events/ExpressionNodeLocationFinder.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
@@ -33,19 +37,21 @@ struct ExpressionCompletionDescription {
|
||||
/**
|
||||
* The different kind of completions that can be described.
|
||||
*/
|
||||
enum CompletionKind {
|
||||
Object,
|
||||
Behavior,
|
||||
Expression,
|
||||
Variable,
|
||||
};
|
||||
enum CompletionKind { Object, Behavior, Expression, Variable, Text };
|
||||
|
||||
/**
|
||||
* \brief Create a completion for an object with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForObject(const gd::String& type_,
|
||||
const gd::String& prefix_) {
|
||||
return ExpressionCompletionDescription(Object, type_, prefix_);
|
||||
static ExpressionCompletionDescription ForObject(
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_) {
|
||||
return ExpressionCompletionDescription(Object,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,17 +59,58 @@ struct ExpressionCompletionDescription {
|
||||
* the specified object
|
||||
*/
|
||||
static ExpressionCompletionDescription ForBehavior(
|
||||
const gd::String& prefix_, const gd::String& objectName_) {
|
||||
return ExpressionCompletionDescription(Behavior, "", prefix_, objectName_);
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_) {
|
||||
return ExpressionCompletionDescription(Behavior,
|
||||
"",
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for a variable with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForVariable(
|
||||
const gd::String& type_, const gd::String& prefix_) {
|
||||
return ExpressionCompletionDescription(Variable, type_, prefix_);
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "") {
|
||||
return ExpressionCompletionDescription(Variable,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for a text with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForText(
|
||||
const gd::String& type_,
|
||||
const gd::ParameterMetadata& parameterMetadata_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const bool isLastParameter_,
|
||||
const gd::String& objectName_ = "") {
|
||||
auto description =
|
||||
ExpressionCompletionDescription(Text,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
description.SetIsLastParameter(isLastParameter_);
|
||||
description.SetParameterMetadata(parameterMetadata_);
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for an expression (free, object or behavior
|
||||
* expression) with the given prefix
|
||||
@@ -71,10 +118,17 @@ struct ExpressionCompletionDescription {
|
||||
static ExpressionCompletionDescription ForExpression(
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "",
|
||||
const gd::String& behaviorName_ = "") {
|
||||
return ExpressionCompletionDescription(
|
||||
Expression, type_, prefix_, objectName_, behaviorName_);
|
||||
return ExpressionCompletionDescription(Expression,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_,
|
||||
behaviorName_);
|
||||
}
|
||||
|
||||
/** Check if two description of completions are equal */
|
||||
@@ -131,6 +185,56 @@ struct ExpressionCompletionDescription {
|
||||
*/
|
||||
bool IsExact() const { return isExact; }
|
||||
|
||||
/**
|
||||
* \brief Return the first character index of the autocompleted part.
|
||||
*/
|
||||
size_t GetReplacementStartPosition() const {
|
||||
return replacementStartPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the first character index after the autocompleted part.
|
||||
*/
|
||||
size_t GetReplacementEndPosition() const { return replacementEndPosition; }
|
||||
|
||||
/**
|
||||
* \brief Set if the expression is the last child of a function call.
|
||||
*/
|
||||
ExpressionCompletionDescription& SetIsLastParameter(bool isLastParameter_) {
|
||||
isLastParameter = isLastParameter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the expression is the last child of a function call.
|
||||
*/
|
||||
bool IsLastParameter() const { return isLastParameter; }
|
||||
|
||||
/**
|
||||
* \brief Set the parameter metadata, in the case the completion is about
|
||||
* a parameter of a function call.
|
||||
*/
|
||||
ExpressionCompletionDescription& SetParameterMetadata(
|
||||
const gd::ParameterMetadata& parameterMetadata_) {
|
||||
parameterMetadata = ¶meterMetadata_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the completion is about a parameter of a function call.
|
||||
*/
|
||||
bool HasParameterMetadata() const {
|
||||
return parameterMetadata != &badParameterMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the parameter metadata, if the completion is about a
|
||||
* parameter of a function call. Returns an empty metadata otherwise.
|
||||
*/
|
||||
const gd::ParameterMetadata& GetParameterMetadata() const {
|
||||
return *parameterMetadata;
|
||||
}
|
||||
|
||||
/** Default constructor, only to be used by Emscripten bindings. */
|
||||
ExpressionCompletionDescription() : completionKind(Object){};
|
||||
|
||||
@@ -138,34 +242,40 @@ struct ExpressionCompletionDescription {
|
||||
ExpressionCompletionDescription(CompletionKind completionKind_,
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "",
|
||||
const gd::String& behaviorName_ = "")
|
||||
: completionKind(completionKind_),
|
||||
type(type_),
|
||||
prefix(prefix_),
|
||||
replacementStartPosition(replacementStartPosition_),
|
||||
replacementEndPosition(replacementEndPosition_),
|
||||
objectName(objectName_),
|
||||
behaviorName(behaviorName_),
|
||||
isExact(false) {}
|
||||
isExact(false),
|
||||
isLastParameter(false),
|
||||
parameterMetadata(&badParameterMetadata) {}
|
||||
|
||||
CompletionKind completionKind;
|
||||
gd::String type;
|
||||
gd::String prefix;
|
||||
size_t replacementStartPosition;
|
||||
size_t replacementEndPosition;
|
||||
gd::String objectName;
|
||||
gd::String behaviorName;
|
||||
bool isExact;
|
||||
bool isLastParameter;
|
||||
const gd::ParameterMetadata* parameterMetadata;
|
||||
|
||||
static const gd::ParameterMetadata badParameterMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Turn an ExpressionCompletionDescription to a string.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
ExpressionCompletionDescription const& value) {
|
||||
os << "{ " << value.GetCompletionKind() << ", " << value.GetType() << ", "
|
||||
<< value.GetPrefix() << ", " << value.GetObjectName() << ", "
|
||||
<< value.GetBehaviorName() << ", "
|
||||
<< (value.IsExact() ? "exact" : "non-exact") << " }";
|
||||
return os;
|
||||
}
|
||||
ExpressionCompletionDescription const& value);
|
||||
|
||||
/**
|
||||
* \brief Returns the list of completion descriptions for an expression node.
|
||||
@@ -182,16 +292,18 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
static std::vector<ExpressionCompletionDescription>
|
||||
GetCompletionDescriptionsFor(gd::ExpressionNode& node,
|
||||
size_t searchedPosition) {
|
||||
gd::ExpressionNode* nodeAtLocation =
|
||||
gd::ExpressionNodeLocationFinder::GetNodeAtPosition(node,
|
||||
searchedPosition);
|
||||
gd::ExpressionNodeLocationFinder finder(searchedPosition);
|
||||
node.Visit(finder);
|
||||
gd::ExpressionNode* nodeAtLocation = finder.GetNode();
|
||||
|
||||
if (nodeAtLocation == nullptr) {
|
||||
std::vector<ExpressionCompletionDescription> emptyCompletions;
|
||||
return emptyCompletions;
|
||||
}
|
||||
|
||||
gd::ExpressionCompletionFinder autocompletionProvider(searchedPosition);
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation = finder.GetParentNode();
|
||||
gd::ExpressionCompletionFinder autocompletionProvider(
|
||||
searchedPosition, maybeParentNodeAtLocation);
|
||||
nodeAtLocation->Visit(autocompletionProvider);
|
||||
return autocompletionProvider.GetCompletionDescriptions();
|
||||
}
|
||||
@@ -208,32 +320,92 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {
|
||||
// No completions
|
||||
}
|
||||
|
||||
void OnVisitTextNode(TextNode& node) override {
|
||||
// No completions
|
||||
// Completions are searched in the case the text node is a parameter of a
|
||||
// function call.
|
||||
FunctionCallNode* functionCall =
|
||||
dynamic_cast<FunctionCallNode*>(maybeParentNodeAtLocation);
|
||||
if (functionCall != nullptr) {
|
||||
int parameterIndex = -1;
|
||||
for (int i = 0; i < functionCall->parameters.size(); i++) {
|
||||
if (functionCall->parameters.at(i).get() == &node) {
|
||||
parameterIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parameterIndex < 0) {
|
||||
return;
|
||||
}
|
||||
// Search the parameter metadata index skipping invisible ones.
|
||||
size_t visibleParameterIndex = 0;
|
||||
size_t metadataParameterIndex = ExpressionParser2::WrittenParametersFirstIndex(
|
||||
functionCall->objectName, functionCall->behaviorName);
|
||||
|
||||
const gd::ParameterMetadata* parameterMetadata = nullptr;
|
||||
while (metadataParameterIndex <
|
||||
functionCall->expressionMetadata.parameters.size()) {
|
||||
if (!functionCall->expressionMetadata.parameters[metadataParameterIndex]
|
||||
.IsCodeOnly()) {
|
||||
if (visibleParameterIndex == parameterIndex) {
|
||||
parameterMetadata = &functionCall->expressionMetadata
|
||||
.parameters[metadataParameterIndex];
|
||||
}
|
||||
visibleParameterIndex++;
|
||||
}
|
||||
metadataParameterIndex++;
|
||||
}
|
||||
const int visibleParameterCount = visibleParameterIndex;
|
||||
if (parameterMetadata == nullptr) {
|
||||
// There are too many parameters in the expression, this text node is
|
||||
// not actually linked to a parameter expected by the function call.
|
||||
return;
|
||||
}
|
||||
|
||||
const gd::String& type = parameterMetadata->GetType();
|
||||
if (type == "string") {
|
||||
// No completions for an arbitrary string.
|
||||
return;
|
||||
}
|
||||
|
||||
bool isLastParameter = parameterIndex == visibleParameterCount - 1;
|
||||
completions.push_back(ExpressionCompletionDescription::ForText(
|
||||
type,
|
||||
*parameterMetadata,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition(),
|
||||
isLastParameter,
|
||||
functionCall->objectName));
|
||||
}
|
||||
}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForVariable(node.type, node.name));
|
||||
completions.push_back(ExpressionCompletionDescription::ForVariable(
|
||||
node.type,
|
||||
node.name,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
// No completions
|
||||
@@ -246,13 +418,22 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
if (gd::ParameterMetadata::IsObject(node.type)) {
|
||||
// Only show completions of objects if an object is required
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
} else {
|
||||
// Show completions for expressions and objects otherwise.
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
}
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
@@ -262,16 +443,24 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// function name missing)
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
} else if (IsCaretOn(node.behaviorNameNamespaceSeparatorLocation) ||
|
||||
IsCaretOn(node.behaviorFunctionNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.behaviorFunctionName,
|
||||
node.behaviorFunctionNameLocation.GetStartPosition(),
|
||||
node.behaviorFunctionNameLocation.GetEndPosition(),
|
||||
node.objectName,
|
||||
node.objectFunctionOrBehaviorName));
|
||||
}
|
||||
@@ -279,13 +468,23 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// Object function or behavior name
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.type,
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,24 +496,35 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// Behavior function
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.behaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.behaviorName, node.objectName));
|
||||
node.behaviorName,
|
||||
node.behaviorNameLocation.GetStartPosition(),
|
||||
node.behaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
} else {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type,
|
||||
node.functionName,
|
||||
node.objectName,
|
||||
node.behaviorName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition(),
|
||||
node.objectName,
|
||||
node.behaviorName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
} else if (!node.objectName.empty()) {
|
||||
// Object function
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else {
|
||||
// Add completions for behaviors, because we could imagine that the user
|
||||
// wants to move from an object function to a behavior function, and so
|
||||
@@ -323,25 +533,41 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// function).
|
||||
if (!isCaretOnParenthesis) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.functionName, node.objectName));
|
||||
node.functionName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.functionName, node.objectName)
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition(),
|
||||
node.objectName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
} else {
|
||||
// Free function
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.functionName)
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition())
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, node.text));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, node.text));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -354,11 +580,14 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
(inclusive && searchedPosition <= location.GetEndPosition())));
|
||||
}
|
||||
|
||||
ExpressionCompletionFinder(size_t searchedPosition_)
|
||||
: searchedPosition(searchedPosition_){};
|
||||
ExpressionCompletionFinder(size_t searchedPosition_,
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation_)
|
||||
: searchedPosition(searchedPosition_),
|
||||
maybeParentNodeAtLocation(maybeParentNodeAtLocation_){};
|
||||
|
||||
std::vector<ExpressionCompletionDescription> completions;
|
||||
size_t searchedPosition;
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
namespace gd {
|
||||
@@ -46,11 +47,30 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
return finder.GetNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper function to find the parent of the deepest node at the search
|
||||
* position, if any.
|
||||
*
|
||||
* \warning Useful for tests. In other cases, prefer using `GetParentNode`.
|
||||
*/
|
||||
static ExpressionNode* GetParentNodeAtPosition(gd::ExpressionNode& node,
|
||||
size_t searchedPosition) {
|
||||
gd::ExpressionNodeLocationFinder finder(searchedPosition);
|
||||
node.Visit(finder);
|
||||
return finder.GetParentNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the deepest node found at the search position, if any.
|
||||
*/
|
||||
ExpressionNode* GetNode() { return foundNode; };
|
||||
|
||||
/**
|
||||
* \brief Return the parent of deepest node found at the search position, if
|
||||
* any.
|
||||
*/
|
||||
ExpressionNode* GetParentNode() { return parentNode; };
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
CheckSearchPositionInNode(node);
|
||||
@@ -110,6 +130,7 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
if (node.location.GetStartPosition() <= searchedPosition &&
|
||||
((!inclusive && searchedPosition < node.location.GetEndPosition()) ||
|
||||
(inclusive && searchedPosition <= node.location.GetEndPosition()))) {
|
||||
parentNode = foundNode;
|
||||
foundNode = &node;
|
||||
return true;
|
||||
}
|
||||
@@ -119,6 +140,7 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
|
||||
size_t searchedPosition;
|
||||
ExpressionNode* foundNode;
|
||||
ExpressionNode* parentNode;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -24,24 +24,6 @@ namespace gd {
|
||||
|
||||
InstructionSentenceFormatter *InstructionSentenceFormatter::_singleton = NULL;
|
||||
|
||||
gd::String InstructionSentenceFormatter::Translate(
|
||||
const gd::Instruction &instr, const gd::InstructionMetadata &metadata) {
|
||||
gd::String out = metadata.GetSentence();
|
||||
if (out.empty())
|
||||
out = " "; // Prevent empty sentences that could trigger graphical
|
||||
// glitches.
|
||||
|
||||
// Replace _PARAMx_ placeholders by their values
|
||||
for (std::size_t i = 0; i < metadata.parameters.size(); ++i) {
|
||||
gd::String placeholder = "_PARAM" + gd::String::From(i) + "_";
|
||||
gd::String parameter = instr.GetParameter(i).GetPlainString();
|
||||
out = out.FindAndReplace(placeholder, parameter);
|
||||
}
|
||||
|
||||
out = out.FindAndReplace("\n", " ");
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<std::pair<gd::String, gd::TextFormatting> >
|
||||
InstructionSentenceFormatter::GetAsFormattedText(
|
||||
const Instruction &instr, const gd::InstructionMetadata &metadata) {
|
||||
@@ -83,8 +65,7 @@ InstructionSentenceFormatter::GetAsFormattedText(
|
||||
}
|
||||
|
||||
// Add the parameter
|
||||
TextFormatting format =
|
||||
GetFormattingFromType(metadata.parameters[firstParamIndex].type);
|
||||
TextFormatting format;
|
||||
format.userData = firstParamIndex;
|
||||
|
||||
gd::String text = instr.GetParameter(firstParamIndex).GetPlainString();
|
||||
@@ -109,74 +90,6 @@ InstructionSentenceFormatter::GetAsFormattedText(
|
||||
return formattedStr;
|
||||
}
|
||||
|
||||
TextFormatting InstructionSentenceFormatter::GetFormattingFromType(
|
||||
const gd::String &type) {
|
||||
if (gd::ParameterMetadata::IsObject(type)) return typesFormatting["object"];
|
||||
|
||||
return typesFormatting[type];
|
||||
}
|
||||
|
||||
gd::String InstructionSentenceFormatter::LabelFromType(const gd::String &type) {
|
||||
if (type.empty())
|
||||
return "";
|
||||
else if (type == "expression")
|
||||
return _("Expression");
|
||||
else if (gd::ParameterMetadata::IsObject(type))
|
||||
return _("Object");
|
||||
else if (type == "behavior")
|
||||
return _("Behavior");
|
||||
else if (type == "operator")
|
||||
return _("Operator");
|
||||
else if (type == "relationalOperator")
|
||||
return _("Relational operator");
|
||||
else if (type == "file")
|
||||
return _("File");
|
||||
else if (type == "key")
|
||||
return _("Key");
|
||||
else if (type == "mouse")
|
||||
return _("Mouse button");
|
||||
else if (type == "yesorno")
|
||||
return _("Yes or No");
|
||||
else if (type == "police")
|
||||
return _("Font");
|
||||
else if (type == "color")
|
||||
return _("Color");
|
||||
else if (type == "trueorfalse")
|
||||
return _("True or False");
|
||||
else if (type == "string")
|
||||
return _("String");
|
||||
else if (type == "musicfile")
|
||||
return _("Music");
|
||||
else if (type == "soundfile")
|
||||
return _("Sound");
|
||||
else if (type == "password")
|
||||
return _("Password");
|
||||
else if (type == "layer")
|
||||
return _("Layer");
|
||||
else if (type == "joyaxis")
|
||||
return _("Joystick axis");
|
||||
else if (type == "objectvar")
|
||||
return _("Variable of the object");
|
||||
else if (type == "scenevar")
|
||||
return _("Scene variable");
|
||||
else if (type == "globalvar")
|
||||
return _("Global variable");
|
||||
|
||||
return _("Unknown");
|
||||
}
|
||||
|
||||
void InstructionSentenceFormatter::LoadTypesFormattingFromConfig() {
|
||||
// Load default configuration
|
||||
typesFormatting.clear();
|
||||
typesFormatting["expression"].SetColor(27, 143, 1).SetBold();
|
||||
typesFormatting["object"].SetColor(182, 97, 10).SetBold();
|
||||
typesFormatting["behavior"].SetColor(119, 119, 119).SetBold();
|
||||
typesFormatting["operator"].SetColor(55, 131, 211).SetBold();
|
||||
typesFormatting["objectvar"].SetColor(131, 55, 162).SetBold();
|
||||
typesFormatting["scenevar"].SetColor(131, 55, 162).SetBold();
|
||||
typesFormatting["globalvar"].SetColor(131, 55, 162).SetBold();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
|
@@ -25,39 +25,12 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API InstructionSentenceFormatter {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a sentence from an instruction and its metadata.
|
||||
*
|
||||
* Sentence is provided in the gd::InstructionMetadata passed as parameter.
|
||||
* Parameters placeholders ("_PARAMx_", x being the parameter index) are
|
||||
* replaced by their values stored in the isntruction passed as parameter.
|
||||
*/
|
||||
gd::String Translate(const gd::Instruction &instr,
|
||||
const gd::InstructionMetadata &metadata);
|
||||
|
||||
/**
|
||||
* \brief Create a formatted sentence from an instruction and its metadata.
|
||||
*/
|
||||
std::vector<std::pair<gd::String, gd::TextFormatting> > GetAsFormattedText(
|
||||
const gd::Instruction &instr, const gd::InstructionMetadata &metadata);
|
||||
|
||||
/**
|
||||
* \brief Return the TextFormatting object associated to the \a type.
|
||||
*/
|
||||
TextFormatting GetFormattingFromType(const gd::String &type);
|
||||
|
||||
/**
|
||||
* \brief Return the label of a parameter type
|
||||
*/
|
||||
gd::String LabelFromType(const gd::String &type);
|
||||
|
||||
/**
|
||||
* \brief Load the configuration from the default configuration.
|
||||
*/
|
||||
void LoadTypesFormattingFromConfig();
|
||||
|
||||
std::map<gd::String, gd::TextFormatting> typesFormatting;
|
||||
|
||||
static InstructionSentenceFormatter *Get() {
|
||||
if (NULL == _singleton) {
|
||||
_singleton = new InstructionSentenceFormatter;
|
||||
|
@@ -13,85 +13,20 @@ namespace gd {
|
||||
/**
|
||||
* \brief Represents the style of a text displayed in the events editor.
|
||||
*
|
||||
* Notably used by EventsRenderingHelper to render Instruction.
|
||||
*
|
||||
* \see EventsRenderingHelper
|
||||
* \ingroup IDEDialogsEventsEditor
|
||||
*/
|
||||
class GD_CORE_API TextFormatting {
|
||||
public:
|
||||
TextFormatting()
|
||||
: colorRed(0),
|
||||
colorGreen(0),
|
||||
colorBlue(0),
|
||||
bold(false),
|
||||
italic(false),
|
||||
userData(gd::String::npos) {}
|
||||
TextFormatting() : userData(gd::String::npos) {}
|
||||
~TextFormatting() {}
|
||||
|
||||
/**
|
||||
* \brief Return true if the bold style must be applied.
|
||||
*/
|
||||
bool IsBold() const { return bold; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the italic style must be applied.
|
||||
*/
|
||||
bool IsItalic() const { return italic; }
|
||||
|
||||
/**
|
||||
* \brief Return the red component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorRed() const { return colorRed; }
|
||||
/**
|
||||
* \brief Return the green component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorGreen() const { return colorGreen; }
|
||||
/**
|
||||
* \brief Return the blue component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorBlue() const { return colorBlue; }
|
||||
|
||||
/**
|
||||
* Change the color of the text.
|
||||
*/
|
||||
TextFormatting& SetColor(unsigned int r, unsigned int g, unsigned int b) {
|
||||
colorRed = r;
|
||||
colorGreen = g;
|
||||
colorBlue = b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set if the bold style must be applied.
|
||||
*/
|
||||
TextFormatting& SetBold(bool enable = true) {
|
||||
bold = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set if the italic style must be applied.
|
||||
*/
|
||||
TextFormatting& SetItalic(bool enable = true) {
|
||||
italic = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data (an integer) associated with the text formatting.
|
||||
* Used to store the parameter when rendering instructions.
|
||||
*/
|
||||
size_t GetUserData() const { return userData; }
|
||||
|
||||
unsigned int colorRed;
|
||||
unsigned int colorGreen;
|
||||
unsigned int colorBlue;
|
||||
bool bold;
|
||||
bool italic;
|
||||
size_t userData;
|
||||
};
|
||||
|
||||
|
144
Core/GDCore/IDE/Events/UsedExtensionsFinder.cpp
Normal file
144
Core/GDCore/IDE/Events/UsedExtensionsFinder.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "UsedExtensionsFinder.h"
|
||||
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/Project/BehaviorContent.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
std::set<gd::String> UsedExtensionsFinder::ScanProject(gd::Project& project) {
|
||||
UsedExtensionsFinder worker(project);
|
||||
gd::WholeProjectRefactorer::ExposeProjectObjects(project, worker);
|
||||
gd::WholeProjectRefactorer::ExposeProjectEvents(project, worker);
|
||||
return worker.usedExtensions;
|
||||
};
|
||||
|
||||
// Objects scanner
|
||||
|
||||
void UsedExtensionsFinder::DoVisitObject(gd::Object& object) {
|
||||
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), object.GetType())
|
||||
.GetExtension()
|
||||
.GetName());
|
||||
};
|
||||
|
||||
// Behaviors scanner
|
||||
|
||||
void UsedExtensionsFinder::DoVisitBehavior(gd::BehaviorContent& behavior) {
|
||||
usedExtensions.insert(
|
||||
gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
|
||||
project.GetCurrentPlatform(), behavior.GetTypeName())
|
||||
.GetExtension()
|
||||
.GetName());
|
||||
};
|
||||
|
||||
// Instructions scanner
|
||||
|
||||
bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
auto metadata =
|
||||
isCondition ? gd::MetadataProvider::GetExtensionAndConditionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType())
|
||||
: gd::MetadataProvider::GetExtensionAndActionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType());
|
||||
usedExtensions.insert(metadata.GetExtension().GetName());
|
||||
|
||||
size_t i = 0;
|
||||
for (auto expression : instruction.GetParameters()) {
|
||||
const gd::String& parameterType =
|
||||
metadata.GetMetadata().GetParameter(i).GetType();
|
||||
i++;
|
||||
|
||||
if (gd::ParameterMetadata::IsExpression("string", parameterType) ||
|
||||
gd::ParameterMetadata::IsExpression("number", parameterType)) {
|
||||
gd::ExpressionParser2 parser(project.GetCurrentPlatform(),
|
||||
GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer());
|
||||
parser.ParseExpression(parameterType, expression.GetPlainString())
|
||||
->Visit(*this);
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", parameterType))
|
||||
usedExtensions.insert("BuiltinVariables");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Expressions scanner
|
||||
|
||||
// Ignore litterals nodes
|
||||
void UsedExtensionsFinder::OnVisitNumberNode(NumberNode& node){};
|
||||
void UsedExtensionsFinder::OnVisitTextNode(TextNode& node){};
|
||||
|
||||
// Ignore nodes without valid extensions
|
||||
void UsedExtensionsFinder::OnVisitEmptyNode(EmptyNode& node){};
|
||||
void UsedExtensionsFinder::OnVisitObjectFunctionNameNode(
|
||||
ObjectFunctionNameNode& node){};
|
||||
|
||||
// Visit sub-expressions
|
||||
void UsedExtensionsFinder::OnVisitSubExpressionNode(SubExpressionNode& node) {
|
||||
node.expression->Visit(*this);
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitOperatorNode(OperatorNode& node) {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitUnaryOperatorNode(UnaryOperatorNode& node) {
|
||||
node.factor->Visit(*this);
|
||||
};
|
||||
|
||||
// Add variable extension and visit sub-expressions on variable nodes
|
||||
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
|
||||
usedExtensions.insert("BuiltinVariables");
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitVariableAccessorNode(
|
||||
VariableAccessorNode& node) {
|
||||
usedExtensions.insert("BuiltinVariables");
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) {
|
||||
usedExtensions.insert("BuiltinVariables");
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
};
|
||||
|
||||
// Add extensions bound to Objects/Behaviors/Functions
|
||||
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
if (gd::ParameterMetadata::IsObject(node.type)) {
|
||||
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
|
||||
project.GetCurrentPlatform(), node.identifierName)
|
||||
.GetExtension()
|
||||
.GetName());
|
||||
}
|
||||
};
|
||||
|
||||
void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
|
||||
// Extensions of non-free functions are already found when scanning objects.
|
||||
if (!(node.objectName.empty() && node.behaviorName.empty())) return;
|
||||
gd::ExtensionAndMetadata<gd::ExpressionMetadata> metadata;
|
||||
|
||||
// Try to find a free number expression
|
||||
metadata = gd::MetadataProvider::GetExtensionAndExpressionMetadata(
|
||||
project.GetCurrentPlatform(), node.functionName);
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata.GetMetadata())) {
|
||||
// Try to find a free str expression
|
||||
metadata = gd::MetadataProvider::GetExtensionAndStrExpressionMetadata(
|
||||
project.GetCurrentPlatform(), node.functionName);
|
||||
// No valid expression found, return.
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata.GetMetadata()))
|
||||
return;
|
||||
}
|
||||
|
||||
usedExtensions.insert(metadata.GetExtension().GetName());
|
||||
};
|
||||
|
||||
} // namespace gd
|
64
Core/GDCore/IDE/Events/UsedExtensionsFinder.h
Normal file
64
Core/GDCore/IDE/Events/UsedExtensionsFinder.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_USED_EXTENSIONS_FINDER_H
|
||||
#define GDCORE_USED_EXTENSIONS_FINDER_H
|
||||
#include <set>
|
||||
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class Object;
|
||||
class BehaviorContent;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
class GD_CORE_API UsedExtensionsFinder
|
||||
: public ArbitraryObjectsWorker,
|
||||
public ArbitraryEventsWorkerWithContext,
|
||||
public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
static std::set<gd::String> ScanProject(gd::Project& project);
|
||||
|
||||
private:
|
||||
UsedExtensionsFinder(gd::Project& project_) : project(project_){};
|
||||
gd::Project& project;
|
||||
std::set<gd::String> usedExtensions;
|
||||
|
||||
// Object Visitor
|
||||
void DoVisitObject(gd::Object& object) override;
|
||||
|
||||
// Behavior Visitor
|
||||
void DoVisitBehavior(gd::BehaviorContent& behavior) override;
|
||||
|
||||
// Instructions Visitor
|
||||
bool DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) override;
|
||||
|
||||
// Expression Visitor
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override;
|
||||
void OnVisitOperatorNode(OperatorNode& node) override;
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override;
|
||||
void OnVisitNumberNode(NumberNode& node) override;
|
||||
void OnVisitTextNode(TextNode& node) override;
|
||||
void OnVisitVariableNode(VariableNode& node) override;
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override;
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override;
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override;
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override;
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override;
|
||||
void OnVisitEmptyNode(EmptyNode& node) override;
|
||||
};
|
||||
|
||||
}; // namespace gd
|
||||
|
||||
#endif
|
@@ -14,16 +14,16 @@ namespace gd {
|
||||
* \note Both objects must be kept alive, as this is keeping a pointer to them.
|
||||
*/
|
||||
struct DependencyMetadataAndExtension {
|
||||
DependencyMetadataAndExtension(gd::DependencyMetadata& dependency_,
|
||||
gd::PlatformExtension& extension_)
|
||||
DependencyMetadataAndExtension(gd::DependencyMetadata &dependency_,
|
||||
gd::PlatformExtension &extension_)
|
||||
: dependency(&dependency_), extension(&extension_){};
|
||||
|
||||
gd::DependencyMetadata& GetDependency() const { return *dependency; };
|
||||
gd::PlatformExtension& GetExtension() const { return *extension; };
|
||||
gd::DependencyMetadata &GetDependency() const { return *dependency; };
|
||||
gd::PlatformExtension &GetExtension() const { return *extension; };
|
||||
|
||||
private:
|
||||
gd::DependencyMetadata* dependency;
|
||||
gd::PlatformExtension* extension;
|
||||
gd::DependencyMetadata *dependency;
|
||||
gd::PlatformExtension *extension;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -33,8 +33,8 @@ struct DependencyMetadataAndExtension {
|
||||
class ExportedDependencyResolver {
|
||||
public:
|
||||
/**
|
||||
* \brief Return the list of dependencies to be exported for the given project
|
||||
* and dependency type.
|
||||
* \brief Return the list of dependencies to be exported for the given
|
||||
* project, used extensions list and dependency type.
|
||||
*
|
||||
* Not all dependencies declared by extensions must be exported: some are only
|
||||
* exported when some settings are filled. Then, some others are only exported
|
||||
@@ -42,11 +42,13 @@ class ExportedDependencyResolver {
|
||||
* one level though).
|
||||
*/
|
||||
static std::vector<DependencyMetadataAndExtension> GetDependenciesFor(
|
||||
const gd::Project& project, const gd::String& dependencyType) {
|
||||
const gd::Project &project,
|
||||
std::set<gd::String> usedExtensions,
|
||||
const gd::String &dependencyType) {
|
||||
std::vector<DependencyMetadataAndExtension> dependenciesWithProperType;
|
||||
for (std::shared_ptr<gd::PlatformExtension> extension :
|
||||
project.GetCurrentPlatform().GetAllPlatformExtensions()) {
|
||||
for (gd::DependencyMetadata& dependency :
|
||||
for (const gd::String &extensionName : usedExtensions) {
|
||||
auto extension = project.GetCurrentPlatform().GetExtension(extensionName);
|
||||
for (gd::DependencyMetadata &dependency :
|
||||
extension->GetAllDependencies()) {
|
||||
if (dependency.GetDependencyType() == dependencyType) {
|
||||
DependencyMetadataAndExtension dependencyMetadataAndExtension(
|
||||
@@ -60,7 +62,7 @@ class ExportedDependencyResolver {
|
||||
// and those that don't require extra settings to be filled.
|
||||
std::vector<DependencyMetadataAndExtension> dependenciesWithFilledSettings;
|
||||
for (auto dependencyAndExtension : dependenciesWithProperType) {
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
auto extraSettingValues = GetExtensionDependencyExtraSettingValues(
|
||||
project, dependencyAndExtension);
|
||||
|
||||
@@ -73,15 +75,15 @@ class ExportedDependencyResolver {
|
||||
// exported (or dependencies that don't require another dependency).
|
||||
std::vector<DependencyMetadataAndExtension> exportedDependencies;
|
||||
for (auto dependencyAndExtension : dependenciesWithFilledSettings) {
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
auto& otherDependencyName =
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
auto &otherDependencyName =
|
||||
dependency.GetOtherDependencyThatMustBeExported();
|
||||
if (otherDependencyName.empty() ||
|
||||
std::find_if(
|
||||
dependenciesWithFilledSettings.begin(),
|
||||
dependenciesWithFilledSettings.end(),
|
||||
[&otherDependencyName](
|
||||
DependencyMetadataAndExtension& otherDependencyAndExtension) {
|
||||
DependencyMetadataAndExtension &otherDependencyAndExtension) {
|
||||
return otherDependencyAndExtension.GetDependency().GetName() ==
|
||||
otherDependencyName;
|
||||
}) != dependenciesWithFilledSettings.end()) {
|
||||
@@ -98,15 +100,15 @@ class ExportedDependencyResolver {
|
||||
*/
|
||||
static std::map<gd::String, gd::String>
|
||||
GetExtensionDependencyExtraSettingValues(
|
||||
const gd::Project& project,
|
||||
const gd::DependencyMetadataAndExtension& dependencyAndExtension) {
|
||||
const gd::Project &project,
|
||||
const gd::DependencyMetadataAndExtension &dependencyAndExtension) {
|
||||
std::map<gd::String, gd::String> values;
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
const gd::String& extensionName =
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
const gd::String &extensionName =
|
||||
dependencyAndExtension.GetExtension().GetName();
|
||||
|
||||
for (const auto& extraSetting : dependency.GetAllExtraSettings()) {
|
||||
const gd::String& type = extraSetting.second.GetType();
|
||||
for (const auto &extraSetting : dependency.GetAllExtraSettings()) {
|
||||
const gd::String &type = extraSetting.second.GetType();
|
||||
const gd::String extraSettingValue =
|
||||
type == "ExtensionProperty"
|
||||
? project.GetExtensionProperties().GetValue(
|
||||
|
43
Core/GDCore/IDE/Project/ArbitraryObjectsWorker.cpp
Normal file
43
Core/GDCore/IDE/Project/ArbitraryObjectsWorker.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ArbitraryObjectsWorker.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/BehaviorContent.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
ArbitraryObjectsWorker::~ArbitraryObjectsWorker() {}
|
||||
|
||||
void ArbitraryObjectsWorker::VisitObjectContainer(
|
||||
gd::ObjectsContainer& objects) {
|
||||
DoVisitObjectContainer(objects);
|
||||
|
||||
for (size_t i = 0; i < objects.GetObjectsCount(); i++)
|
||||
VisitObject(objects.GetObject(i));
|
||||
}
|
||||
|
||||
void ArbitraryObjectsWorker::VisitObject(gd::Object& object) {
|
||||
DoVisitObject(object);
|
||||
|
||||
for (auto behaviorName : object.GetAllBehaviorNames())
|
||||
VisitBehavior(object.GetBehavior(behaviorName));
|
||||
}
|
||||
|
||||
void ArbitraryObjectsWorker::VisitBehavior(gd::BehaviorContent& behavior) {
|
||||
DoVisitBehavior(behavior);
|
||||
}
|
||||
|
||||
} // namespace gd
|
63
Core/GDCore/IDE/Project/ArbitraryObjectsWorker.h
Normal file
63
Core/GDCore/IDE/Project/ArbitraryObjectsWorker.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef ARBITRARYOBJECTSWORKER_H
|
||||
#define ARBITRARYOBJECTSWORKER_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Object;
|
||||
class ObjectsContainer;
|
||||
class BehaviorContent;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief ArbitraryObjectsWorker is an abstract class used to browse objects
|
||||
* (and behaviors) and do some work on them. Can be used to implement
|
||||
* refactoring for example.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ArbitraryObjectsWorker {
|
||||
public:
|
||||
ArbitraryObjectsWorker(){};
|
||||
virtual ~ArbitraryObjectsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(gd::ObjectsContainer& objects) { VisitObjectContainer(objects); };
|
||||
|
||||
private:
|
||||
void VisitObjectContainer(gd::ObjectsContainer& objects);
|
||||
void VisitObject(gd::Object& object);
|
||||
void VisitBehavior(gd::BehaviorContent& instruction);
|
||||
|
||||
/**
|
||||
* Called to do some work on an object container.
|
||||
*/
|
||||
virtual void DoVisitObjectContainer(gd::ObjectsContainer& objects){};
|
||||
|
||||
/**
|
||||
* Called to do some work on an object.
|
||||
*/
|
||||
virtual void DoVisitObject(gd::Object& object){};
|
||||
|
||||
/**
|
||||
* Called to do some work on a behavior.
|
||||
*/
|
||||
virtual void DoVisitBehavior(gd::BehaviorContent& instruction){};
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // ARBITRARYOBJECTSWORKER_H
|
@@ -6,8 +6,10 @@
|
||||
#if defined(GD_IDE_ONLY)
|
||||
|
||||
#include "ArbitraryResourceWorker.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
@@ -55,6 +57,21 @@ void ArbitraryResourceWorker::ExposeFont(gd::String& fontName) {
|
||||
ExposeFile(fontName);
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeBitmapFont(gd::String& bitmapFontName) {
|
||||
for (auto resources : GetResources()) {
|
||||
if (!resources) continue;
|
||||
|
||||
if (resources->HasResource(bitmapFontName) &&
|
||||
resources->GetResource(bitmapFontName).GetKind() == "bitmapFont") {
|
||||
// Nothing to do, the font is a reference to a resource that
|
||||
// is already exposed.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ExposeFile(bitmapFontName);
|
||||
};
|
||||
|
||||
void ArbitraryResourceWorker::ExposeResources(
|
||||
gd::ResourcesManager* resourcesManager) {
|
||||
if (!resourcesManager) return;
|
||||
@@ -82,15 +99,8 @@ void LaunchResourceWorkerOnEvents(const gd::Project& project,
|
||||
gd::EventsList& events,
|
||||
gd::ArbitraryResourceWorker& worker) {
|
||||
// Get all extensions used
|
||||
std::vector<std::shared_ptr<gd::PlatformExtension> > allGameExtensions;
|
||||
std::vector<gd::String> usedExtensions = project.GetUsedExtensions();
|
||||
for (std::size_t i = 0; i < usedExtensions.size(); ++i) {
|
||||
std::shared_ptr<gd::PlatformExtension> extension =
|
||||
project.GetCurrentPlatform().GetExtension(usedExtensions[i]);
|
||||
|
||||
if (extension != std::shared_ptr<gd::PlatformExtension>())
|
||||
allGameExtensions.push_back(extension);
|
||||
}
|
||||
auto allGameExtensions =
|
||||
project.GetCurrentPlatform().GetAllPlatformExtensions();
|
||||
|
||||
for (std::size_t j = 0; j < events.size(); j++) {
|
||||
vector<gd::InstructionsList*> allActionsVectors =
|
||||
|
@@ -70,6 +70,12 @@ class GD_CORE_API ArbitraryResourceWorker {
|
||||
*/
|
||||
virtual void ExposeFont(gd::String &fontName);
|
||||
|
||||
/**
|
||||
* \brief Expose a bitmap font, which is either a reference to a "bitmapFont" resource,
|
||||
* or a filename if no resource with this name exists.
|
||||
*/
|
||||
virtual void ExposeBitmapFont(gd::String &bitmapFontName);
|
||||
|
||||
/**
|
||||
* \brief Expose a shader.
|
||||
* \warn Currently unsupported.
|
||||
|
@@ -38,12 +38,15 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
std::set<gd::String>& GetAllImages() { return GetAll("image"); };
|
||||
std::set<gd::String>& GetAllFonts() { return GetAll("font"); };
|
||||
std::set<gd::String>& GetAllAudios() { return GetAll("audio"); };
|
||||
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
|
||||
std::set<gd::String>& GetAll(const gd::String& resourceType) {
|
||||
return resourceType == "image"
|
||||
? allImages
|
||||
: (resourceType == "audio"
|
||||
? allAudios
|
||||
: (resourceType == "font") ? allFonts : emptyResources);
|
||||
: (resourceType == "font")
|
||||
? allFonts
|
||||
: (resourceType == "bitmapFont") ? allBitmapFonts : emptyResources);
|
||||
};
|
||||
|
||||
virtual void ExposeFile(gd::String& resource) override{
|
||||
@@ -58,11 +61,15 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
|
||||
virtual void ExposeFont(gd::String& fontResourceName) override {
|
||||
allFonts.insert(fontResourceName);
|
||||
};
|
||||
virtual void ExposeBitmapFont(gd::String& bitmapFontResourceName) override {
|
||||
allBitmapFonts.insert(bitmapFontResourceName);
|
||||
};
|
||||
|
||||
protected:
|
||||
std::set<gd::String> allImages;
|
||||
std::set<gd::String> allAudios;
|
||||
std::set<gd::String> allFonts;
|
||||
std::set<gd::String> allBitmapFonts;
|
||||
std::set<gd::String> emptyResources;
|
||||
};
|
||||
|
||||
|
@@ -4,15 +4,17 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "WholeProjectRefactorer.h"
|
||||
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Events/EventsRefactorer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionsParameterMover.h"
|
||||
#include "GDCore/IDE/Events/InstructionsTypeRenamer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
|
||||
#include "GDCore/IDE/Events/InstructionsParameterMover.h"
|
||||
#include "GDCore/IDE/Events/InstructionsTypeRenamer.h"
|
||||
#include "GDCore/IDE/EventsFunctionTools.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
@@ -141,6 +143,13 @@ void WholeProjectRefactorer::ExposeProjectEvents(
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ExposeProjectObjects(
|
||||
gd::Project& project, gd::ArbitraryObjectsWorker& worker) {
|
||||
worker.Launch(project);
|
||||
for (size_t i = 0; i < project.GetLayoutsCount(); i++)
|
||||
worker.Launch(project.GetLayout(i));
|
||||
};
|
||||
|
||||
std::set<gd::String>
|
||||
WholeProjectRefactorer::GetAllObjectTypesUsingEventsBasedBehavior(
|
||||
const gd::Project& project,
|
||||
|
@@ -16,6 +16,7 @@ class EventsFunction;
|
||||
class ObjectsContainer;
|
||||
class EventsBasedBehavior;
|
||||
class ArbitraryEventsWorker;
|
||||
class ArbitraryObjectsWorker;
|
||||
class ArbitraryEventsWorkerWithContext;
|
||||
} // namespace gd
|
||||
|
||||
@@ -50,10 +51,21 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
gd::ArbitraryEventsWorkerWithContext& worker);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** an events function extension is renamed.
|
||||
* \brief Call the specified worker on all ObjectContainers of the project (global,
|
||||
* layouts...)
|
||||
*
|
||||
* This should be the preferred way to traverse all the objects of a project.
|
||||
*/
|
||||
static void ExposeProjectObjects(
|
||||
gd::Project& project, gd::ArbitraryObjectsWorker& worker);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** an events function extension is
|
||||
* renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified extension after calling this.
|
||||
* This is because the extension is expected to have its old name for the refactoring.
|
||||
* This is because the extension is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameEventsFunctionsExtension(
|
||||
gd::Project& project,
|
||||
@@ -65,7 +77,8 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* \brief Refactor the project **before** an events function is renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified function after calling this.
|
||||
* This is because the function is expected to have its old name for the refactoring.
|
||||
* This is because the function is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameEventsFunction(
|
||||
gd::Project& project,
|
||||
@@ -78,7 +91,8 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified function after calling this.
|
||||
* This is because the function is expected to have its old name for the refactoring.
|
||||
* This is because the function is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameBehaviorEventsFunction(
|
||||
gd::Project& project,
|
||||
@@ -91,8 +105,9 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* \brief Refactor the project **before** an events function parameter
|
||||
* is moved.
|
||||
*
|
||||
* \warning Do the move of the specified function parameters after calling this.
|
||||
* This is because the function is expected to be in its old state for the refactoring.
|
||||
* \warning Do the move of the specified function parameters after calling
|
||||
* this. This is because the function is expected to be in its old state for
|
||||
* the refactoring.
|
||||
*/
|
||||
static void MoveEventsFunctionParameter(
|
||||
gd::Project& project,
|
||||
@@ -102,11 +117,12 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** the parameter of an events function of a
|
||||
* behavior is moved.
|
||||
* \brief Refactor the project **before** the parameter of an events function
|
||||
* of a behavior is moved.
|
||||
*
|
||||
* \warning Do the move of the specified function parameters after calling this.
|
||||
* This is because the function is expected to be in its old state for the refactoring.
|
||||
* \warning Do the move of the specified function parameters after calling
|
||||
* this. This is because the function is expected to be in its old state for
|
||||
* the refactoring.
|
||||
*/
|
||||
static void MoveBehaviorEventsFunctionParameter(
|
||||
gd::Project& project,
|
||||
@@ -121,7 +137,8 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified property after calling this.
|
||||
* This is because the property is expected to have its old name for the refactoring.
|
||||
* This is because the property is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameBehaviorProperty(
|
||||
gd::Project& project,
|
||||
@@ -134,7 +151,8 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* \brief Refactor the project **before** a behavior is renamed.
|
||||
*
|
||||
* \warning Do the renaming of the specified behavior after calling this.
|
||||
* This is because the behavior is expected to have its old name for the refactoring.
|
||||
* This is because the behavior is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameEventsBasedBehavior(
|
||||
gd::Project& project,
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void Effect::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", GetName());
|
||||
element.SetAttribute("effectType", GetEffectType());
|
||||
@@ -32,7 +31,6 @@ void Effect::SerializeTo(SerializerElement& element) const {
|
||||
booleanParametersElement.AddChild(parameter.first)
|
||||
.SetValue(parameter.second);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Effect::UnserializeFrom(const SerializerElement& element) {
|
||||
SetName(element.GetStringAttribute("name"));
|
||||
|
@@ -74,12 +74,10 @@ class GD_CORE_API Effect {
|
||||
booleanParameters.clear();
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Serialize layer.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layer.
|
||||
|
140
Core/GDCore/Project/EffectsContainer.cpp
Normal file
140
Core/GDCore/Project/EffectsContainer.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EffectsContainer.h"
|
||||
|
||||
#include "Effect.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
Effect EffectsContainer::badEffect;
|
||||
|
||||
EffectsContainer::EffectsContainer() {}
|
||||
|
||||
EffectsContainer::EffectsContainer(const EffectsContainer& other) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
EffectsContainer& EffectsContainer::operator=(const EffectsContainer& rhs) {
|
||||
if (this != &rhs) Init(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void EffectsContainer::Init(const EffectsContainer& other) {
|
||||
effects.clear();
|
||||
for (auto& it : other.effects) {
|
||||
effects.push_back(std::make_shared<Effect>(*it));
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectsContainer::HasEffectNamed(const gd::String& name) const {
|
||||
return (find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
}) != effects.end());
|
||||
}
|
||||
|
||||
gd::Effect& EffectsContainer::GetEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
|
||||
const gd::Effect& EffectsContainer::GetEffect(const gd::String& name) const {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
gd::Effect& EffectsContainer::GetEffect(std::size_t index) {
|
||||
return *effects[index];
|
||||
}
|
||||
const gd::Effect& EffectsContainer::GetEffect(std::size_t index) const {
|
||||
return *effects[index];
|
||||
}
|
||||
std::size_t EffectsContainer::GetEffectsCount() const { return effects.size(); }
|
||||
std::size_t EffectsContainer::GetEffectPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < effects.size(); ++i) {
|
||||
if (effects[i]->GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
}
|
||||
|
||||
gd::Effect& EffectsContainer::InsertNewEffect(const gd::String& name,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<Effect>();
|
||||
newEffect->SetName(name);
|
||||
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
|
||||
return *newEffect;
|
||||
}
|
||||
|
||||
void EffectsContainer::InsertEffect(const gd::Effect& effect,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<gd::Effect>(effect);
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
}
|
||||
|
||||
void EffectsContainer::RemoveEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
if (effect == effects.end()) return;
|
||||
|
||||
effects.erase(effect);
|
||||
}
|
||||
|
||||
void EffectsContainer::SwapEffects(std::size_t firstEffectIndex,
|
||||
std::size_t secondEffectIndex) {
|
||||
if (firstEffectIndex >= effects.size() || secondEffectIndex >= effects.size())
|
||||
return;
|
||||
|
||||
auto temp = effects[firstEffectIndex];
|
||||
effects[firstEffectIndex] = effects[secondEffectIndex];
|
||||
effects[secondEffectIndex] = temp;
|
||||
}
|
||||
|
||||
void EffectsContainer::SerializeTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {
|
||||
SerializerElement& effectElement = element.AddChild("effect");
|
||||
GetEffect(i).SerializeTo(effectElement);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsContainer::UnserializeFrom(const SerializerElement& element) {
|
||||
effects.clear();
|
||||
element.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& effectElement = element.GetChild(i);
|
||||
|
||||
auto effect = std::make_shared<Effect>();
|
||||
effect->UnserializeFrom(effectElement);
|
||||
effects.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
114
Core/GDCore/Project/EffectsContainer.h
Normal file
114
Core/GDCore/Project/EffectsContainer.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EFFECTS_CONTAINER_H
|
||||
#define GDCORE_EFFECTS_CONTAINER_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Effect;
|
||||
}
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Contains effects applied to an entity on screen (i.e: a Layer or an
|
||||
* Object).
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API EffectsContainer {
|
||||
public:
|
||||
EffectsContainer();
|
||||
EffectsContainer(const EffectsContainer& other);
|
||||
virtual ~EffectsContainer(){};
|
||||
|
||||
EffectsContainer& operator=(const EffectsContainer& rhs);
|
||||
/**
|
||||
* \brief Return true if the effect called "name" exists.
|
||||
*/
|
||||
bool HasEffectNamed(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
Effect& GetEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
const Effect& GetEffect(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
Effect& GetEffect(std::size_t index);
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
const Effect& GetEffect(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* Return the position of the effect called "name" in the effects list
|
||||
*/
|
||||
std::size_t GetEffectPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return the number of effecst.
|
||||
*/
|
||||
std::size_t GetEffectsCount() const;
|
||||
|
||||
/**
|
||||
* Add a new effect at the specified position in the effects list.
|
||||
*/
|
||||
gd::Effect& InsertNewEffect(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* \brief Add a copy of the specified effect in the effects list.
|
||||
*
|
||||
* \note No pointer or reference must be kept on the effect passed as
|
||||
* parameter.
|
||||
*
|
||||
* \param theEffect The effect that must be copied and inserted
|
||||
* into the effects list
|
||||
* \param position Insertion position.
|
||||
*/
|
||||
void InsertEffect(const Effect& theEffect, std::size_t position);
|
||||
|
||||
/**
|
||||
* Remove the specified effect.
|
||||
*/
|
||||
void RemoveEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of two effects.
|
||||
*/
|
||||
void SwapEffects(std::size_t firstEffectIndex, std::size_t secondEffectIndex);
|
||||
|
||||
/**
|
||||
* \brief Serialize the effects container.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the effects container.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<gd::Effect>> effects;
|
||||
static Effect badEffect;
|
||||
void Init(const EffectsContainer& other);
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
@@ -4,6 +4,7 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/Layer.h"
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
@@ -11,9 +12,9 @@
|
||||
namespace gd {
|
||||
|
||||
Camera Layer::badCamera;
|
||||
Effect Layer::badEffect;
|
||||
|
||||
Layer::Layer() : isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
|
||||
Layer::Layer()
|
||||
: isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
|
||||
|
||||
/**
|
||||
* Change cameras count, automatically adding/removing them.
|
||||
@@ -52,11 +53,7 @@ void Layer::SerializeTo(SerializerElement& element) const {
|
||||
}
|
||||
|
||||
SerializerElement& effectsElement = element.AddChild("effects");
|
||||
effectsElement.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {
|
||||
SerializerElement& effectElement = effectsElement.AddChild("effect");
|
||||
GetEffect(i).SerializeTo(effectElement);
|
||||
}
|
||||
effectsContainer.SerializeTo(effectsElement);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -67,155 +64,53 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
|
||||
SetName(element.GetStringAttribute("name", "", "Name"));
|
||||
SetVisibility(element.GetBoolAttribute("visibility", true, "Visibility"));
|
||||
SetLightingLayer(element.GetBoolAttribute("isLightingLayer", false));
|
||||
SetFollowBaseLayerCamera(element.GetBoolAttribute("followBaseLayerCamera", false));
|
||||
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
|
||||
SetFollowBaseLayerCamera(
|
||||
element.GetBoolAttribute("followBaseLayerCamera", false));
|
||||
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
|
||||
element.GetIntAttribute("ambientLightColorG", 200),
|
||||
element.GetIntAttribute("ambientLightColorB", 200));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (element.HasChild("Camera")) {
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount("Camera"); ++i) {
|
||||
const SerializerElement& cameraElement = element.GetChild("Camera", i);
|
||||
SetCameraCount(GetCameraCount() + 1);
|
||||
Camera& camera = GetCamera(GetCameraCount() - 1);
|
||||
cameras.clear();
|
||||
SerializerElement& camerasElement = element.GetChild("cameras");
|
||||
camerasElement.ConsiderAsArrayOf("camera");
|
||||
for (std::size_t i = 0; i < camerasElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& cameraElement = camerasElement.GetChild(i);
|
||||
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("DefaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("Width"),
|
||||
cameraElement.GetDoubleAttribute("Height"));
|
||||
Camera camera;
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("defaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("defaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"viewportBottom"));
|
||||
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("DefaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("ViewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("ViewportTop"),
|
||||
cameraElement.GetDoubleAttribute("ViewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"ViewportBottom")); // (sf::Rect used Right and Bottom instead of
|
||||
// Width and Height before)
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
SerializerElement& camerasElement = element.GetChild("cameras");
|
||||
camerasElement.ConsiderAsArrayOf("camera");
|
||||
for (std::size_t i = 0; i < camerasElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& cameraElement = camerasElement.GetChild(i);
|
||||
|
||||
SetCameraCount(GetCameraCount() + 1);
|
||||
Camera& camera = GetCamera(GetCameraCount() - 1);
|
||||
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("defaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("defaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"viewportBottom")); // (sf::Rect used Right and Bottom instead of
|
||||
// Width and Height before)
|
||||
}
|
||||
cameras.push_back(camera);
|
||||
}
|
||||
|
||||
effects.clear();
|
||||
SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsElement.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < effectsElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& effectElement = effectsElement.GetChild(i);
|
||||
|
||||
auto effect = std::make_shared<Effect>();
|
||||
effect->UnserializeFrom(effectElement);
|
||||
effects.push_back(effect);
|
||||
if (camerasElement.GetChildrenCount() > 50) {
|
||||
// Highly unlikely that we want as many cameras, as they were not even exposed in
|
||||
// the editor nor used in the game engine. Must be because of a bug in the editor that
|
||||
// duplicated cameras when cancelling changes on a layer.
|
||||
// Reset to one camera.
|
||||
SetCameraCount(1);
|
||||
}
|
||||
|
||||
const SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsContainer.UnserializeFrom(effectsElement);
|
||||
}
|
||||
|
||||
gd::Effect& Layer::GetEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
const gd::Effect& Layer::GetEffect(const gd::String& name) const {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
gd::Effect& Layer::GetEffect(std::size_t index) { return *effects[index]; }
|
||||
const gd::Effect& Layer::GetEffect(std::size_t index) const {
|
||||
return *effects[index];
|
||||
}
|
||||
std::size_t Layer::GetEffectsCount() const { return effects.size(); }
|
||||
|
||||
bool Layer::HasEffectNamed(const gd::String& name) const {
|
||||
return (find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
}) != effects.end());
|
||||
}
|
||||
std::size_t Layer::GetEffectPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < effects.size(); ++i) {
|
||||
if (effects[i]->GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
gd::EffectsContainer& Layer::GetEffects() {
|
||||
return effectsContainer;
|
||||
}
|
||||
|
||||
gd::Effect& Layer::InsertNewEffect(const gd::String& name,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<Effect>();
|
||||
newEffect->SetName(name);
|
||||
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
|
||||
return *newEffect;
|
||||
}
|
||||
|
||||
void Layer::InsertEffect(const gd::Effect& effect, std::size_t position) {
|
||||
auto newEffect = std::make_shared<gd::Effect>(effect);
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
}
|
||||
|
||||
void Layer::RemoveEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
if (effect == effects.end()) return;
|
||||
|
||||
effects.erase(effect);
|
||||
}
|
||||
|
||||
void Layer::SwapEffects(std::size_t firstEffectIndex,
|
||||
std::size_t secondEffectIndex) {
|
||||
if (firstEffectIndex >= effects.size() || secondEffectIndex >= effects.size())
|
||||
return;
|
||||
|
||||
auto temp = effects[firstEffectIndex];
|
||||
effects[firstEffectIndex] = effects[secondEffectIndex];
|
||||
effects[secondEffectIndex] = temp;
|
||||
const gd::EffectsContainer& Layer::GetEffects() const {
|
||||
return effectsContainer;
|
||||
}
|
||||
|
||||
Camera::Camera()
|
||||
|
@@ -7,7 +7,10 @@
|
||||
#define GDCORE_LAYER_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "EffectsContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Effect;
|
||||
}
|
||||
@@ -17,6 +20,9 @@ class Camera;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
namespace gd {
|
||||
class EffectsContainer;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -54,7 +60,9 @@ class GD_CORE_API Layer {
|
||||
/**
|
||||
* \brief Set if the layer is a lightining layer or not.
|
||||
*/
|
||||
void SetLightingLayer(bool isLightingLayer_) { isLightingLayer = isLightingLayer_; }
|
||||
void SetLightingLayer(bool isLightingLayer_) {
|
||||
isLightingLayer = isLightingLayer_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer is a lighting layer.
|
||||
@@ -64,7 +72,9 @@ class GD_CORE_API Layer {
|
||||
/**
|
||||
* \brief Set if the layer automatically follows the base layer or not.
|
||||
*/
|
||||
void SetFollowBaseLayerCamera(bool followBaseLayerCamera_) { followBaseLayerCamera = followBaseLayerCamera_; }
|
||||
void SetFollowBaseLayerCamera(bool followBaseLayerCamera_) {
|
||||
followBaseLayerCamera = followBaseLayerCamera_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer follows the base layer.
|
||||
@@ -144,66 +154,14 @@ class GD_CORE_API Layer {
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Return true if the effect called "name" exists.
|
||||
* \brief Return the effects container.
|
||||
*/
|
||||
bool HasEffectNamed(const gd::String& name) const;
|
||||
EffectsContainer& GetEffects();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
* \brief Return a const reference to the effects container.
|
||||
*/
|
||||
Effect& GetEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
const Effect& GetEffect(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
Effect& GetEffect(std::size_t index);
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
const Effect& GetEffect(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* Return the position of the effect called "name" in the effects list
|
||||
*/
|
||||
std::size_t GetEffectPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return the number of effecst.
|
||||
*/
|
||||
std::size_t GetEffectsCount() const;
|
||||
|
||||
/**
|
||||
* Add a new effect at the specified position in the effects list.
|
||||
*/
|
||||
gd::Effect& InsertNewEffect(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* \brief Add a copy of the specified effect in the effects list.
|
||||
*
|
||||
* \note No pointer or reference must be kept on the layer passed as
|
||||
* parameter.
|
||||
*
|
||||
* \param theEffect The effect that must be copied and inserted
|
||||
* into the effects list
|
||||
* \param position Insertion position.
|
||||
*/
|
||||
void InsertEffect(const Effect& theEffect, std::size_t position);
|
||||
|
||||
/**
|
||||
* Remove the specified effect.
|
||||
*/
|
||||
void RemoveEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of two effects.
|
||||
*/
|
||||
void SwapEffects(std::size_t firstEffectIndex, std::size_t secondEffectIndex);
|
||||
const EffectsContainer& GetEffects() const;
|
||||
///@}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
@@ -219,19 +177,19 @@ class GD_CORE_API Layer {
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
gd::String name; ///< The name of the layer
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLightingLayer; ///< True if the layer is used to display lights and renders an ambient light.
|
||||
bool followBaseLayerCamera; ///< True if the layer automatically follows the base layer
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
gd::String name; ///< The name of the layer
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLightingLayer; ///< True if the layer is used to display lights and
|
||||
///< renders an ambient light.
|
||||
bool followBaseLayerCamera; ///< True if the layer automatically follows the
|
||||
///< base layer
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
|
||||
std::vector<std::shared_ptr<gd::Effect>>
|
||||
effects; ///< The effects applied to the layer.
|
||||
gd::EffectsContainer effectsContainer; ///< The effects applied to the layer.
|
||||
|
||||
static gd::Camera badCamera;
|
||||
static gd::Effect badEffect;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -5,10 +5,14 @@
|
||||
*/
|
||||
|
||||
#include "Layout.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/SceneNameMangler.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
@@ -219,16 +223,21 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
|
||||
++i) {
|
||||
const gd::String& name = allBehaviorsNames[i];
|
||||
|
||||
if (behaviorsSharedData.find(name) == behaviorsSharedData.end()) {
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
project.GetBehaviorSharedDatas(allBehaviorsTypes[i]);
|
||||
if (behaviorSharedData) {
|
||||
auto behaviorContent =
|
||||
gd::make_unique<gd::BehaviorContent>(name, allBehaviorsTypes[i]);
|
||||
behaviorSharedData->InitializeContent(behaviorContent->GetContent());
|
||||
behaviorsSharedData[name] = std::move(behaviorContent);
|
||||
}
|
||||
}
|
||||
if (behaviorsSharedData.find(name) != behaviorsSharedData.end()) continue;
|
||||
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(project.GetCurrentPlatform(),
|
||||
allBehaviorsTypes[i]);
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) continue;
|
||||
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
behaviorMetadata.GetSharedDataInstance();
|
||||
if (!behaviorSharedData) continue;
|
||||
|
||||
auto behaviorContent =
|
||||
gd::make_unique<gd::BehaviorContent>(name, allBehaviorsTypes[i]);
|
||||
behaviorSharedData->InitializeContent(behaviorContent->GetContent());
|
||||
behaviorsSharedData[name] = std::move(behaviorContent);
|
||||
}
|
||||
|
||||
// Remove useless shared data:
|
||||
|
@@ -5,15 +5,63 @@
|
||||
*/
|
||||
|
||||
#include "LoadingScreen.h"
|
||||
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
LoadingScreen::LoadingScreen()
|
||||
: showGDevelopSplash(true),
|
||||
gdevelopLogoStyle("light"),
|
||||
backgroundImageResourceName(""),
|
||||
backgroundColor(0),
|
||||
backgroundFadeInDuration(0.2),
|
||||
minDuration(1.5),
|
||||
logoAndProgressFadeInDuration(0.2),
|
||||
logoAndProgressLogoFadeInDelay(0.2),
|
||||
showProgressBar(true),
|
||||
progressBarMinWidth(40),
|
||||
progressBarMaxWidth(200),
|
||||
progressBarWidthPercent(30),
|
||||
progressBarHeight(20),
|
||||
progressBarColor(0xFFFFFF){};
|
||||
|
||||
void LoadingScreen::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("showGDevelopSplash", showGDevelopSplash);
|
||||
element.SetAttribute("gdevelopLogoStyle",
|
||||
gdevelopLogoStyle);
|
||||
element.SetAttribute("backgroundImageResourceName",
|
||||
backgroundImageResourceName);
|
||||
element.SetAttribute("backgroundColor", backgroundColor);
|
||||
element.SetAttribute("backgroundFadeInDuration", backgroundFadeInDuration);
|
||||
element.SetAttribute("minDuration", minDuration);
|
||||
element.SetAttribute("logoAndProgressFadeInDuration", logoAndProgressFadeInDuration);
|
||||
element.SetAttribute("logoAndProgressLogoFadeInDelay", logoAndProgressLogoFadeInDelay);
|
||||
element.SetAttribute("showProgressBar", showProgressBar);
|
||||
element.SetAttribute("progressBarMinWidth", progressBarMinWidth);
|
||||
element.SetAttribute("progressBarMaxWidth", progressBarMaxWidth);
|
||||
element.SetAttribute("progressBarWidthPercent", progressBarWidthPercent);
|
||||
element.SetAttribute("progressBarHeight", progressBarHeight);
|
||||
element.SetAttribute("progressBarColor", progressBarColor);
|
||||
}
|
||||
|
||||
void LoadingScreen::UnserializeFrom(const SerializerElement& element) {
|
||||
showGDevelopSplash = element.GetBoolAttribute("showGDevelopSplash", true);
|
||||
gdevelopLogoStyle =
|
||||
element.GetStringAttribute("gdevelopLogoStyle", "light");
|
||||
backgroundImageResourceName =
|
||||
element.GetStringAttribute("backgroundImageResourceName");
|
||||
backgroundColor = element.GetIntAttribute("backgroundColor", 0);
|
||||
backgroundFadeInDuration =
|
||||
element.GetDoubleAttribute("backgroundFadeInDuration", 0.2);
|
||||
minDuration = element.GetDoubleAttribute("minDuration", 1.5);
|
||||
logoAndProgressFadeInDuration = element.GetDoubleAttribute("logoAndProgressFadeInDuration", 0.2);
|
||||
logoAndProgressLogoFadeInDelay = element.GetDoubleAttribute("logoAndProgressLogoFadeInDelay", 0.2);
|
||||
showProgressBar = element.GetBoolAttribute("showProgressBar", true);
|
||||
progressBarMinWidth = element.GetDoubleAttribute("progressBarMinWidth", 40);
|
||||
progressBarMaxWidth = element.GetDoubleAttribute("progressBarMaxWidth", 200);
|
||||
progressBarWidthPercent = element.GetDoubleAttribute("progressBarWidthPercent", 30);
|
||||
progressBarHeight = element.GetDoubleAttribute("progressBarHeight", 20);
|
||||
progressBarColor = element.GetIntAttribute("progressBarColor", 0xFFFFFF);
|
||||
}
|
||||
} // namespace gd
|
||||
|
@@ -22,36 +22,151 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API LoadingScreen {
|
||||
public:
|
||||
LoadingScreen(){};
|
||||
LoadingScreen();
|
||||
virtual ~LoadingScreen(){};
|
||||
|
||||
/**
|
||||
* \brief Set if the GDevelop splash should be shown while loading assets.
|
||||
*/
|
||||
void ShowGDevelopSplash(bool show) { showGDevelopSplash = show; };
|
||||
|
||||
/**
|
||||
* \brief Return true if the GDevelop splash should be shown while loading
|
||||
* \brief Return true if the GDevelop logo should be shown while loading
|
||||
* assets.
|
||||
*/
|
||||
bool IsGDevelopSplashShown() const { return showGDevelopSplash; };
|
||||
|
||||
/**
|
||||
* \brief Set if the GDevelop logo should be shown while loading assets.
|
||||
*/
|
||||
LoadingScreen& ShowGDevelopSplash(bool show) {
|
||||
showGDevelopSplash = show;
|
||||
return *this;
|
||||
};
|
||||
|
||||
const gd::String& GetGDevelopLogoStyle() const { return gdevelopLogoStyle; };
|
||||
|
||||
LoadingScreen& SetGDevelopLogoStyle(const gd::String& value) {
|
||||
gdevelopLogoStyle = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const gd::String& GetBackgroundImageResourceName() const {
|
||||
return backgroundImageResourceName;
|
||||
};
|
||||
|
||||
LoadingScreen& SetBackgroundImageResourceName(const gd::String& value) {
|
||||
backgroundImageResourceName = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int GetBackgroundColor() const { return backgroundColor; };
|
||||
|
||||
LoadingScreen& SetBackgroundColor(int value) {
|
||||
backgroundColor = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetBackgroundFadeInDuration() const {
|
||||
return backgroundFadeInDuration;
|
||||
};
|
||||
|
||||
LoadingScreen& SetBackgroundFadeInDuration(double value) {
|
||||
backgroundFadeInDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetMinDuration() const { return minDuration; };
|
||||
|
||||
LoadingScreen& SetMinDuration(double value) {
|
||||
minDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetLogoAndProgressFadeInDuration() const {
|
||||
return logoAndProgressFadeInDuration;
|
||||
}
|
||||
|
||||
LoadingScreen& SetLogoAndProgressFadeInDuration(double value) {
|
||||
logoAndProgressFadeInDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetLogoAndProgressLogoFadeInDelay() const {
|
||||
return logoAndProgressLogoFadeInDelay;
|
||||
}
|
||||
|
||||
LoadingScreen& SetLogoAndProgressLogoFadeInDelay(double value) {
|
||||
logoAndProgressLogoFadeInDelay = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool GetShowProgressBar() const { return showProgressBar; }
|
||||
|
||||
LoadingScreen& SetShowProgressBar(bool value) {
|
||||
showProgressBar = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarMinWidth() const { return progressBarMinWidth; }
|
||||
|
||||
LoadingScreen& SetProgressBarMinWidth(double value) {
|
||||
progressBarMinWidth = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarMaxWidth() const { return progressBarMaxWidth; }
|
||||
|
||||
LoadingScreen& SetProgressBarMaxWidth(double value) {
|
||||
progressBarMaxWidth = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarWidthPercent() const { return progressBarWidthPercent; }
|
||||
|
||||
LoadingScreen& SetProgressBarWidthPercent(double value) {
|
||||
progressBarWidthPercent = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarHeight() const { return progressBarHeight; }
|
||||
|
||||
LoadingScreen& SetProgressBarHeight(double value) {
|
||||
progressBarHeight = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int GetProgressBarColor() const { return progressBarColor; }
|
||||
|
||||
LoadingScreen& SetProgressBarColor(int value) {
|
||||
progressBarColor = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \name Saving and loading
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize objects groups container.
|
||||
* \brief Serialize the loading screen setup.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the objects groups container.
|
||||
* \brief Unserialize the loading screen setup.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
private:
|
||||
bool showGDevelopSplash;
|
||||
gd::String gdevelopLogoStyle;
|
||||
gd::String backgroundImageResourceName;
|
||||
int backgroundColor;
|
||||
double backgroundFadeInDuration; // In seconds.
|
||||
double minDuration; // In seconds.
|
||||
double logoAndProgressFadeInDuration; // In seconds.
|
||||
double logoAndProgressLogoFadeInDelay; // In seconds.
|
||||
bool showProgressBar;
|
||||
double progressBarMinWidth; // In pixels.
|
||||
double progressBarMaxWidth; // In pixels.
|
||||
double progressBarWidthPercent;
|
||||
double progressBarHeight; // In pixels.
|
||||
int progressBarColor;
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
|
@@ -4,6 +4,9 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
@@ -24,6 +27,7 @@ void Object::Init(const gd::Object& object) {
|
||||
type = object.type;
|
||||
objectVariables = object.objectVariables;
|
||||
tags = object.tags;
|
||||
effectsContainer = object.effectsContainer;
|
||||
|
||||
behaviors.clear();
|
||||
for (auto& it : object.behaviors) {
|
||||
@@ -85,16 +89,17 @@ std::map<gd::String, gd::PropertyDescriptor> Object::GetProperties() const {
|
||||
gd::BehaviorContent* Object::AddNewBehavior(gd::Project& project,
|
||||
const gd::String& type,
|
||||
const gd::String& name) {
|
||||
gd::Behavior* behavior = project.GetCurrentPlatform().GetBehavior(type);
|
||||
|
||||
if (behavior) {
|
||||
auto behaviorContent = gd::make_unique<gd::BehaviorContent>(name, type);
|
||||
behavior->InitializeContent(behaviorContent->GetContent());
|
||||
behaviors[name] = std::move(behaviorContent);
|
||||
return behaviors[name].get();
|
||||
} else {
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(project.GetCurrentPlatform(),
|
||||
type);
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto behaviorContent = gd::make_unique<gd::BehaviorContent>(name, type);
|
||||
behaviorMetadata.Get().InitializeContent(behaviorContent->GetContent());
|
||||
behaviors[name] = std::move(behaviorContent);
|
||||
return behaviors[name].get();
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
@@ -116,6 +121,11 @@ void Object::UnserializeFrom(gd::Project& project,
|
||||
element.GetChild("variables", 0, "Variables"));
|
||||
behaviors.clear();
|
||||
|
||||
if (element.HasChild("effects")) {
|
||||
const SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsContainer.UnserializeFrom(effectsElement);
|
||||
}
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (element.HasChild("Automatism")) {
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount("Automatism"); ++i) {
|
||||
@@ -180,6 +190,7 @@ void Object::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("type", GetType());
|
||||
element.SetAttribute("tags", GetTags());
|
||||
objectVariables.SerializeTo(element.AddChild("variables"));
|
||||
effectsContainer.SerializeTo(element.AddChild("effects"));
|
||||
|
||||
SerializerElement& behaviorsElement = element.AddChild("behaviors");
|
||||
behaviorsElement.ConsiderAsArrayOf("behavior");
|
||||
|
@@ -9,7 +9,9 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/BehaviorContent.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
@@ -20,6 +22,7 @@ class Layout;
|
||||
class ArbitraryResourceWorker;
|
||||
class InitialInstance;
|
||||
class SerializerElement;
|
||||
class EffectsContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -146,8 +149,7 @@ class GD_CORE_API Object {
|
||||
*
|
||||
* \return false if the new value cannot be set
|
||||
*/
|
||||
virtual bool UpdateProperty(const gd::String& name,
|
||||
const gd::String& value) {
|
||||
virtual bool UpdateProperty(const gd::String& name, const gd::String& value) {
|
||||
return false;
|
||||
};
|
||||
///@}
|
||||
@@ -198,12 +200,12 @@ class GD_CORE_API Object {
|
||||
std::vector<gd::String> GetAllBehaviorNames() const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the behavior called \a name.
|
||||
* \brief Return a reference to the content of the behavior called \a name.
|
||||
*/
|
||||
BehaviorContent& GetBehavior(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the behavior called \a name.
|
||||
* \brief Return a reference to the content of the behavior called \a name.
|
||||
*/
|
||||
const BehaviorContent& GetBehavior(const gd::String& name) const;
|
||||
|
||||
@@ -270,6 +272,24 @@ class GD_CORE_API Object {
|
||||
* object variables
|
||||
*/
|
||||
gd::VariablesContainer& GetVariables() { return objectVariables; }
|
||||
///@}
|
||||
|
||||
/**
|
||||
* \name Effects management
|
||||
* Member functions related to effects management.
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Provide access to the gd::EffectsContainer member containing the
|
||||
* effects.
|
||||
*/
|
||||
const gd::EffectsContainer& GetEffects() const { return effectsContainer; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the gd::EffectsContainer member containing the
|
||||
* effects.
|
||||
*/
|
||||
gd::EffectsContainer& GetEffects() { return effectsContainer; }
|
||||
///@}
|
||||
|
||||
/** \name Serialization
|
||||
@@ -301,7 +321,9 @@ class GD_CORE_API Object {
|
||||
///< object.
|
||||
gd::VariablesContainer
|
||||
objectVariables; ///< List of the variables of the object
|
||||
gd::String tags; ///< Comma-separated list of tags
|
||||
gd::String tags; ///< Comma-separated list of tags
|
||||
gd::EffectsContainer
|
||||
effectsContainer; ///< The effects container for the object.
|
||||
|
||||
/**
|
||||
* \brief Derived objects can redefine this method to load custom attributes.
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Events/UsedExtensionsFinder.h"
|
||||
#include "GDCore/IDE/PlatformManager.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
@@ -79,28 +80,6 @@ Project::Project()
|
||||
#endif
|
||||
{
|
||||
imageManager->SetResourcesManager(&resourcesManager);
|
||||
#if defined(GD_IDE_ONLY)
|
||||
// Game use builtin extensions by default
|
||||
extensionsUsed.push_back("BuiltinObject");
|
||||
extensionsUsed.push_back("BuiltinAudio");
|
||||
extensionsUsed.push_back("BuiltinVariables");
|
||||
extensionsUsed.push_back("BuiltinTime");
|
||||
extensionsUsed.push_back("BuiltinMouse");
|
||||
extensionsUsed.push_back("BuiltinKeyboard");
|
||||
extensionsUsed.push_back("BuiltinJoystick");
|
||||
extensionsUsed.push_back("BuiltinCamera");
|
||||
extensionsUsed.push_back("BuiltinWindow");
|
||||
extensionsUsed.push_back("BuiltinFile");
|
||||
extensionsUsed.push_back("BuiltinNetwork");
|
||||
extensionsUsed.push_back("BuiltinScene");
|
||||
extensionsUsed.push_back("BuiltinAdvanced");
|
||||
extensionsUsed.push_back("Sprite");
|
||||
extensionsUsed.push_back("BuiltinCommonInstructions");
|
||||
extensionsUsed.push_back("BuiltinCommonConversions");
|
||||
extensionsUsed.push_back("BuiltinStringInstructions");
|
||||
extensionsUsed.push_back("BuiltinMathematicalTools");
|
||||
extensionsUsed.push_back("BuiltinExternalLayouts");
|
||||
#endif
|
||||
|
||||
#if !defined(GD_IDE_ONLY)
|
||||
platforms.push_back(&CppPlatform::Get());
|
||||
@@ -130,33 +109,6 @@ std::unique_ptr<gd::Object> Project::CreateObject(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::Behavior* Project::GetBehavior(const gd::String& type,
|
||||
const gd::String& platformName) {
|
||||
for (std::size_t i = 0; i < platforms.size(); ++i) {
|
||||
if (!platformName.empty() && platforms[i]->GetName() != platformName)
|
||||
continue;
|
||||
|
||||
gd::Behavior* behavior = platforms[i]->GetBehavior(type);
|
||||
if (behavior) return behavior;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* Project::GetBehaviorSharedDatas(
|
||||
const gd::String& type, const gd::String& platformName) {
|
||||
for (std::size_t i = 0; i < platforms.size(); ++i) {
|
||||
if (!platformName.empty() && platforms[i]->GetName() != platformName)
|
||||
continue;
|
||||
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
platforms[i]->GetBehaviorSharedDatas(type);
|
||||
if (behaviorSharedData) return behaviorSharedData;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::shared_ptr<gd::BaseEvent> Project::CreateEvent(
|
||||
const gd::String& type, const gd::String& platformName) {
|
||||
@@ -536,8 +488,6 @@ void Project::ClearEventsFunctionsExtensions() {
|
||||
void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
// Checking version
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String updateText;
|
||||
|
||||
const SerializerElement& gdVersionElement =
|
||||
element.GetChild("gdVersion", 0, "GDVersion");
|
||||
gdMajorVersion =
|
||||
@@ -549,10 +499,10 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
|
||||
if (gdMajorVersion > gd::VersionWrapper::Major())
|
||||
gd::LogWarning(
|
||||
_("The version of GDevelop used to create this game seems to be a new "
|
||||
"version.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available."));
|
||||
"The version of GDevelop used to create this game seems to be a new "
|
||||
"version.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available.");
|
||||
else {
|
||||
if ((gdMajorVersion == gd::VersionWrapper::Major() &&
|
||||
gdMinorVersion > gd::VersionWrapper::Minor()) ||
|
||||
@@ -564,22 +514,12 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
gdBuildVersion == gd::VersionWrapper::Build() &&
|
||||
revision > gd::VersionWrapper::Revision())) {
|
||||
gd::LogWarning(
|
||||
_("The version of GDevelop used to create this game seems to be "
|
||||
"greater.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available."));
|
||||
"The version of GDevelop used to create this game seems to be "
|
||||
"greater.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available.");
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility code
|
||||
if (gdMajorVersion <= 1) {
|
||||
gd::LogError(_(
|
||||
"The game was saved with version of GDevelop which is too old. Please "
|
||||
"open and save the game with one of the first version of GDevelop 2. "
|
||||
"You will then be able to open your game with this GDevelop version."));
|
||||
return;
|
||||
}
|
||||
// End of Compatibility code
|
||||
#endif
|
||||
|
||||
const SerializerElement& propElement =
|
||||
@@ -651,18 +591,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
|
||||
#endif
|
||||
|
||||
const SerializerElement& extensionsElement =
|
||||
propElement.GetChild("extensions", 0, "Extensions");
|
||||
extensionsElement.ConsiderAsArrayOf("extension", "Extension");
|
||||
for (std::size_t i = 0; i < extensionsElement.GetChildrenCount(); ++i) {
|
||||
gd::String extensionName =
|
||||
extensionsElement.GetChild(i).GetStringAttribute("name");
|
||||
if (find(GetUsedExtensions().begin(),
|
||||
GetUsedExtensions().end(),
|
||||
extensionName) == GetUsedExtensions().end())
|
||||
GetUsedExtensions().push_back(extensionName);
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
currentPlatform = NULL;
|
||||
gd::String currentPlatformName =
|
||||
@@ -715,83 +643,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
currentPlatform = platforms.back();
|
||||
#endif
|
||||
|
||||
// Compatibility code
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (VersionWrapper::IsOlder(gdMajorVersion, 0, 0, 0, 3, 0, 0, 0)) {
|
||||
updateText +=
|
||||
_("Sprite scaling has changed since GD 2: The resizing is made so that "
|
||||
"the origin point of the object won't move whatever the scale of the "
|
||||
"object.\n");
|
||||
updateText +=
|
||||
_("You may have to slightly change the position of some objects if you "
|
||||
"have changed their size.\n\n");
|
||||
updateText += _("Thank you for your understanding.\n");
|
||||
}
|
||||
#endif
|
||||
// End of Compatibility code
|
||||
|
||||
// Compatibility code
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (VersionWrapper::IsOlderOrEqual(gdMajorVersion,
|
||||
gdMinorVersion,
|
||||
revision,
|
||||
gdBuildVersion,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
10822)) {
|
||||
if (std::find(GetUsedExtensions().begin(),
|
||||
GetUsedExtensions().end(),
|
||||
"BuiltinExternalLayouts") == GetUsedExtensions().end())
|
||||
GetUsedExtensions().push_back("BuiltinExternalLayouts");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compatibility code
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (VersionWrapper::IsOlderOrEqual(gdMajorVersion,
|
||||
gdMinorVersion,
|
||||
revision,
|
||||
gdBuildVersion,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
0)) {
|
||||
if (std::find(GetUsedExtensions().begin(),
|
||||
GetUsedExtensions().end(),
|
||||
"AStarBehavior") != GetUsedExtensions().end()) {
|
||||
GetUsedExtensions().erase(std::remove(GetUsedExtensions().begin(),
|
||||
GetUsedExtensions().end(),
|
||||
"AStarBehavior"),
|
||||
GetUsedExtensions().end());
|
||||
GetUsedExtensions().push_back("PathfindingBehavior");
|
||||
updateText +=
|
||||
_("The project is using the pathfinding behavior. This behavior has "
|
||||
"been replaced by a new one:\n");
|
||||
updateText +=
|
||||
_("You must add the new 'Pathfinding' behavior to the objects that "
|
||||
"need to be moved, and add the 'Pathfinding Obstacle' to the "
|
||||
"objects that must act as obstacles.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Compatibility code
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (VersionWrapper::IsOlderOrEqual(gdMajorVersion,
|
||||
gdMinorVersion,
|
||||
revision,
|
||||
gdBuildVersion,
|
||||
4,
|
||||
0,
|
||||
85,
|
||||
0)) {
|
||||
for (unsigned int i = 0; i < extensionsUsed.size(); ++i)
|
||||
extensionsUsed[i] =
|
||||
extensionsUsed[i].FindAndReplace("Automatism", "Behavior");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
GetObjectGroups().UnserializeFrom(
|
||||
element.GetChild("objectsGroups", 0, "ObjectGroups"));
|
||||
@@ -917,12 +768,6 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
extensionProperties.SerializeTo(propElement.AddChild("extensionProperties"));
|
||||
|
||||
SerializerElement& extensionsElement = propElement.AddChild("extensions");
|
||||
extensionsElement.ConsiderAsArrayOf("extension");
|
||||
for (std::size_t i = 0; i < GetUsedExtensions().size(); ++i)
|
||||
extensionsElement.AddChild("extension")
|
||||
.SetAttribute("name", GetUsedExtensions()[i]);
|
||||
|
||||
SerializerElement& platformsElement = propElement.AddChild("platforms");
|
||||
platformsElement.ConsiderAsArrayOf("platform");
|
||||
for (std::size_t i = 0; i < platforms.size(); ++i) {
|
||||
@@ -1121,7 +966,6 @@ void Project::Init(const gd::Project& game) {
|
||||
|
||||
currentPlatform = game.currentPlatform;
|
||||
#endif
|
||||
extensionsUsed = game.extensionsUsed;
|
||||
platforms = game.platforms;
|
||||
|
||||
resourcesManager = game.resourcesManager;
|
||||
|
@@ -313,20 +313,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
void ResetProjectUuid();
|
||||
|
||||
/**
|
||||
* Return a reference to the vector containing the names of extensions used by
|
||||
* the project.
|
||||
*/
|
||||
const std::vector<gd::String>& GetUsedExtensions() const {
|
||||
return extensionsUsed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a reference to the vector containing the names of extensions used by
|
||||
* the project.
|
||||
*/
|
||||
std::vector<gd::String>& GetUsedExtensions() { return extensionsUsed; };
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Get the properties set by extensions.
|
||||
@@ -404,37 +390,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
const gd::String& name,
|
||||
const gd::String& platformName = "");
|
||||
|
||||
/**
|
||||
* Get the behavior of the given type.
|
||||
*
|
||||
* \note A project can use more than one platform. In this case, the first
|
||||
* platform supporting the behavior is used, unless \a platformName argument
|
||||
* is not empty.
|
||||
* It is assumed that each platform provides an equivalent
|
||||
* behavior.
|
||||
*
|
||||
* \param type The type of the behavior
|
||||
* \param platformName The name of the platform to be used. If empty, the
|
||||
* first platform supporting the object is used.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(const gd::String& type,
|
||||
const gd::String& platformName = "");
|
||||
|
||||
/**
|
||||
* Get the behavior shared data of the given type.
|
||||
*
|
||||
* \note A project can use more than one platform. In this case, the first
|
||||
* platform supporting the behavior shared data is used, unless \a
|
||||
* platformName argument is not empty.
|
||||
* It is assumed that each platform provides equivalent behavior shared data.
|
||||
*
|
||||
* \param type The type of behavior
|
||||
* \param platformName The name of the platform to be used. If empty, the
|
||||
* first platform supporting the object is used.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(
|
||||
const gd::String& type, const gd::String& platformName = "");
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* Create an event of the given type.
|
||||
@@ -1002,7 +957,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
std::shared_ptr<gd::ImageManager>
|
||||
imageManager; ///< Image manager is accessed thanks to a (smart) ptr as
|
||||
///< it can be shared with GD C++ Platform projects.
|
||||
std::vector<gd::String> extensionsUsed; ///< List of extensions used
|
||||
std::vector<gd::Platform*>
|
||||
platforms; ///< Pointers to the platforms this project supports.
|
||||
gd::String firstLayout;
|
||||
|
@@ -80,6 +80,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
|
||||
return std::make_shared<VideoResource>();
|
||||
else if (kind == "json")
|
||||
return std::make_shared<JsonResource>();
|
||||
else if (kind == "bitmapFont")
|
||||
return std::make_shared<BitmapFontResource>();
|
||||
|
||||
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
|
||||
return std::make_shared<Resource>();
|
||||
@@ -654,6 +656,26 @@ bool JsonResource::UpdateProperty(const gd::String& name,
|
||||
|
||||
#endif
|
||||
|
||||
void BitmapFontResource::SetFile(const gd::String& newFile) {
|
||||
file = newFile;
|
||||
|
||||
// Convert all backslash to slashs.
|
||||
while (file.find('\\') != gd::String::npos)
|
||||
file.replace(file.find('\\'), 1, "/");
|
||||
}
|
||||
|
||||
void BitmapFontResource::UnserializeFrom(const SerializerElement& element) {
|
||||
SetUserAdded(element.GetBoolAttribute("userAdded"));
|
||||
SetFile(element.GetStringAttribute("file"));
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void BitmapFontResource::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("userAdded", IsUserAdded());
|
||||
element.SetAttribute("file", GetFile());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
ResourceFolder::ResourceFolder(const ResourceFolder& other) { Init(other); }
|
||||
|
||||
|
@@ -374,6 +374,34 @@ class GD_CORE_API JsonResource : public Resource {
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Describe a bitmap font file used by a project.
|
||||
*
|
||||
* \see Resource
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API BitmapFontResource : public Resource {
|
||||
public:
|
||||
BitmapFontResource() : Resource() { SetKind("bitmapFont"); };
|
||||
virtual ~BitmapFontResource(){};
|
||||
virtual BitmapFontResource* Clone() const override {
|
||||
return new BitmapFontResource(*this);
|
||||
}
|
||||
|
||||
virtual const gd::String& GetFile() const override { return file; };
|
||||
virtual void SetFile(const gd::String& newFile) override;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
virtual bool UseFile() override { return true; }
|
||||
void SerializeTo(SerializerElement& element) const override;
|
||||
#endif
|
||||
|
||||
void UnserializeFrom(const SerializerElement& element) override;
|
||||
|
||||
private:
|
||||
gd::String file;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Inventory all resources used by a project
|
||||
*
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include "GDCore/Project/Variable.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
@@ -91,7 +92,9 @@ double Variable::GetValue() const {
|
||||
if (type == Type::Number) {
|
||||
return value;
|
||||
} else if (type == Type::String) {
|
||||
return str.To<double>();
|
||||
double retVal = str.To<double>();
|
||||
if(std::isnan(retVal)) retVal = 0.0;
|
||||
return retVal;
|
||||
} else if (type == Type::Boolean) {
|
||||
return boolVal ? 1.0 : 0.0;
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "DummyPlatform.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
@@ -36,31 +37,38 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Identifier") {
|
||||
SECTION("Object or expression completions when type is string") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("string", "My"),
|
||||
gd::ExpressionCompletionDescription::ForExpression("string", "My")};
|
||||
gd::ExpressionCompletionDescription::ForObject("string", "My", 0, 2),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"string", "My", 0, 2)};
|
||||
REQUIRE(getCompletionsFor("string", "My", 0) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "My", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "My", 2) == expectedEmptyCompletions);
|
||||
}
|
||||
SECTION("Object or expression completions when type is number") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("number", "My"),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number", "My")};
|
||||
gd::ExpressionCompletionDescription::ForObject("number", "My", 0, 2),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"number", "My", 0, 2)};
|
||||
REQUIRE(getCompletionsFor("number", "My", 0) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number", "My", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number", "My", 2) == expectedEmptyCompletions);
|
||||
}
|
||||
SECTION("Object or expression completions when type is number|string") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("number|string", "My"),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number|string", "My")};
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 0) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 2) == expectedEmptyCompletions);
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"number|string", "My", 0, 2),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"number|string", "My", 0, 2)};
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 0) ==
|
||||
expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 1) ==
|
||||
expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number|string", "My", 2) ==
|
||||
expectedEmptyCompletions);
|
||||
}
|
||||
SECTION("Object when type is an object") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("object", "My")};
|
||||
gd::ExpressionCompletionDescription::ForObject("object", "My", 0, 2)};
|
||||
REQUIRE(getCompletionsFor("object", "My", 0) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("object", "My", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("object", "My", 2) == expectedEmptyCompletions);
|
||||
@@ -70,7 +78,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
// Also test alternate types also considered as objects (but that can
|
||||
// result in different code generation):
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("objectPtr", "My")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"objectPtr", "My", 0, 2)};
|
||||
REQUIRE(getCompletionsFor("objectPtr", "My", 0) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("objectPtr", "My", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("objectPtr", "My", 2) ==
|
||||
@@ -78,30 +87,42 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
}
|
||||
}
|
||||
SECTION("Operator (number)") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("number", ""),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number", "")};
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 1) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 2) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 3) == expectedCompletions);
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions1{
|
||||
gd::ExpressionCompletionDescription::ForObject("number", "", 1, 1),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number", "", 1, 1)};
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions2{
|
||||
gd::ExpressionCompletionDescription::ForObject("number", "", 2, 2),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number", "", 2, 2)};
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions3{
|
||||
gd::ExpressionCompletionDescription::ForObject("number", "", 3, 3),
|
||||
gd::ExpressionCompletionDescription::ForExpression("number", "", 3, 3)};
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 1) == expectedCompletions1);
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 2) == expectedCompletions2);
|
||||
REQUIRE(getCompletionsFor("number", "1 + ", 3) == expectedCompletions3);
|
||||
}
|
||||
SECTION("Operator (string)") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("string", ""),
|
||||
gd::ExpressionCompletionDescription::ForExpression("string", "")};
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 3) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 4) == expectedCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 5) == expectedCompletions);
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions3{
|
||||
gd::ExpressionCompletionDescription::ForObject("string", "", 3, 3),
|
||||
gd::ExpressionCompletionDescription::ForExpression("string", "", 3, 3)};
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions4{
|
||||
gd::ExpressionCompletionDescription::ForObject("string", "", 4, 4),
|
||||
gd::ExpressionCompletionDescription::ForExpression("string", "", 4, 4)};
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions5{
|
||||
gd::ExpressionCompletionDescription::ForObject("string", "", 5, 5),
|
||||
gd::ExpressionCompletionDescription::ForExpression("string", "", 5, 5)};
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 3) == expectedCompletions3);
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 4) == expectedCompletions4);
|
||||
REQUIRE(getCompletionsFor("string", "\"a\" + ", 5) == expectedCompletions5);
|
||||
}
|
||||
|
||||
SECTION("Free function") {
|
||||
SECTION("Test 1") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression("unknown",
|
||||
"Function")};
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Function", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedExactCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression("unknown",
|
||||
"Function")
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Function", 0, 8)
|
||||
.SetIsExact(true)};
|
||||
REQUIRE(getCompletionsFor("string", "Function(", 0) ==
|
||||
expectedCompletions);
|
||||
@@ -123,33 +144,48 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
expectedEmptyCompletions);
|
||||
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("unknown", "a"),
|
||||
gd::ExpressionCompletionDescription::ForExpression("unknown", "a")};
|
||||
gd::ExpressionCompletionDescription::ForObject("unknown", "a", 9, 10),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "a", 9, 10)};
|
||||
REQUIRE(getCompletionsFor("string", "Function(a", 9) ==
|
||||
expectedCompletions);
|
||||
}
|
||||
SECTION("Function with a Variable as argument") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForVariable("scenevar",
|
||||
"myVar")};
|
||||
gd::ExpressionCompletionDescription::ForVariable(
|
||||
"scenevar", "myVar", 33, 38)};
|
||||
REQUIRE(getCompletionsFor("number",
|
||||
"MyExtension::GetVariableAsNumber(myVar",
|
||||
33) == expectedCompletions);
|
||||
}
|
||||
SECTION("Function with a Layer as argument") {
|
||||
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
|
||||
gd::ExpressionCompletionDescription::ForText(
|
||||
"layer",
|
||||
gd::MetadataProvider::GetExpressionMetadata(platform,
|
||||
"MyExtension::MouseX")
|
||||
.GetParameter(0),
|
||||
"",
|
||||
20,
|
||||
21,
|
||||
false)};
|
||||
REQUIRE(getCompletionsFor("number", "MyExtension::MouseX(\"", 20) ==
|
||||
expectedCompletions);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Partial object or behavior function") {
|
||||
SECTION("Test with string type") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("string",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"string", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorOrFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("Func",
|
||||
"MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"Func", 9, 13, "MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"string", "Func", "MyObject")};
|
||||
"string", "Func", 9, 13, "MyObject")};
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.Func", 0) ==
|
||||
expectedObjectCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.Func", 7) ==
|
||||
@@ -166,14 +202,14 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Test with 'number|string' type") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("number|string",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"number|string", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorOrFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("Func",
|
||||
"MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"Func", 9, 13, "MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"number|string", "Func", "MyObject")};
|
||||
"number|string", "Func", 9, 13, "MyObject")};
|
||||
REQUIRE(getCompletionsFor("number|string", "MyObject.Func", 0) ==
|
||||
expectedObjectCompletions);
|
||||
REQUIRE(getCompletionsFor("number|string", "MyObject.Func", 7) ==
|
||||
@@ -193,18 +229,18 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Test 1") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("unknown",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"unknown", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorOrFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("Func",
|
||||
"MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"Func", 9, 13, "MyObject"),
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Func", "MyObject")};
|
||||
"unknown", "Func", 9, 13, "MyObject")};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedExactFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Func", "MyObject")
|
||||
"unknown", "Func", 9, 13, "MyObject")
|
||||
.SetIsExact(true)};
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 0) ==
|
||||
expectedObjectCompletions);
|
||||
@@ -229,16 +265,16 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Test 1") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("string",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"string", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"MyBehavior", 9, 19, "MyObject")};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"string", "Func", "MyObject", "MyBehavior")};
|
||||
"string", "Func", 21, 25, "MyObject", "MyBehavior")};
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func", 0) ==
|
||||
expectedObjectCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func", 7) ==
|
||||
@@ -261,16 +297,16 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Test 2") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("string",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"string", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"MyBehavior", 9, 19, "MyObject")};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"string", "", "MyObject", "MyBehavior")};
|
||||
"string", "", 21, 21, "MyObject", "MyBehavior")};
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::", 0) ==
|
||||
expectedObjectCompletions);
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::", 7) ==
|
||||
@@ -292,20 +328,20 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
|
||||
SECTION("Test 1") {
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedObjectCompletions{
|
||||
gd::ExpressionCompletionDescription::ForObject("unknown",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForObject(
|
||||
"unknown", "MyObject", 0, 8)};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedBehaviorCompletions{
|
||||
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
|
||||
"MyObject")};
|
||||
gd::ExpressionCompletionDescription::ForBehavior(
|
||||
"MyBehavior", 9, 19, "MyObject")};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Func", "MyObject", "MyBehavior")};
|
||||
"unknown", "Func", 21, 25, "MyObject", "MyBehavior")};
|
||||
std::vector<gd::ExpressionCompletionDescription>
|
||||
expectedExactFunctionCompletions{
|
||||
gd::ExpressionCompletionDescription::ForExpression(
|
||||
"unknown", "Func", "MyObject", "MyBehavior")
|
||||
"unknown", "Func", 21, 25, "MyObject", "MyBehavior")
|
||||
.SetIsExact(true)};
|
||||
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 0) ==
|
||||
expectedObjectCompletions);
|
||||
|
@@ -24,6 +24,18 @@ bool CheckNodeAtLocationIs(gd::ExpressionParser2& parser,
|
||||
*node, searchPosition)) != nullptr;
|
||||
}
|
||||
|
||||
template <class TNode>
|
||||
bool CheckParentNodeAtLocationIs(gd::ExpressionParser2& parser,
|
||||
const gd::String& type,
|
||||
const gd::String& expression,
|
||||
size_t searchPosition) {
|
||||
auto node = parser.ParseExpression(type, expression);
|
||||
REQUIRE(node != nullptr);
|
||||
return dynamic_cast<TNode*>(
|
||||
gd::ExpressionNodeLocationFinder::GetParentNodeAtPosition(
|
||||
*node, searchPosition)) != nullptr;
|
||||
}
|
||||
|
||||
bool CheckNoNodeAtLocation(gd::ExpressionParser2& parser,
|
||||
const gd::String& type,
|
||||
const gd::String& expression,
|
||||
@@ -34,6 +46,16 @@ bool CheckNoNodeAtLocation(gd::ExpressionParser2& parser,
|
||||
*node, searchPosition) == nullptr;
|
||||
}
|
||||
|
||||
bool CheckNoParentNodeAtLocation(gd::ExpressionParser2& parser,
|
||||
const gd::String& type,
|
||||
const gd::String& expression,
|
||||
size_t searchPosition) {
|
||||
auto node = parser.ParseExpression(type, expression);
|
||||
REQUIRE(node != nullptr);
|
||||
return gd::ExpressionNodeLocationFinder::GetParentNodeAtPosition(
|
||||
*node, searchPosition) == nullptr;
|
||||
}
|
||||
|
||||
TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
gd::Project project;
|
||||
gd::Platform platform;
|
||||
@@ -186,6 +208,13 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::TextNode>(parser, "number", "12+\"hello\"", 3) == true);
|
||||
}
|
||||
|
||||
SECTION("Numbers and texts mismatchs (parent node)") {
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(parser, "number", "12+\"hello\"", 0) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(parser, "number", "12+\"hello\"", 1) == true);
|
||||
REQUIRE(CheckNoParentNodeAtLocation(parser, "number", "12+\"hello\"", 2) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(parser, "number", "12+\"hello\"", 3) == true);
|
||||
}
|
||||
|
||||
SECTION("Valid objects") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::IdentifierNode>(
|
||||
parser, "object", "HelloWorld1", 0) == true);
|
||||
@@ -195,6 +224,10 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
parser, "object", "HelloWorld1", 10) == true);
|
||||
REQUIRE(CheckNoNodeAtLocation(parser, "object", "HelloWorld1", 11) == true);
|
||||
}
|
||||
SECTION("Valid objects (parent node)") {
|
||||
REQUIRE(CheckNoParentNodeAtLocation(
|
||||
parser, "object", "HelloWorld1", 0) == true);
|
||||
}
|
||||
SECTION("Invalid objects") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::IdentifierNode>(
|
||||
parser, "object", "a+b", 0) == true);
|
||||
@@ -296,6 +329,29 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
"MyExtension::GetNumberWith2Params(12, \"hello world\")",
|
||||
52) == true);
|
||||
}
|
||||
SECTION("Parent node") {
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(
|
||||
parser, "number", "12 + MyExtension::GetNumber()", 0) ==
|
||||
true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::OperatorNode>(
|
||||
parser, "number", "12 + MyExtension::GetNumber()", 6) ==
|
||||
true);
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::NumberNode>(
|
||||
parser,
|
||||
"number",
|
||||
"MyExtension::GetNumberWith2Params(12, \"hello world\")",
|
||||
35) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::FunctionCallNode>(
|
||||
parser,
|
||||
"number",
|
||||
"MyExtension::GetNumberWith2Params(12, \"hello world\")",
|
||||
35) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::FunctionCallNode>(
|
||||
parser,
|
||||
"number",
|
||||
"MyExtension::GetNumberWith2Params(12, \"hello world\")",
|
||||
39) == true);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid function calls") {
|
||||
@@ -316,6 +372,12 @@ TEST_CASE("ExpressionNodeLocationFinder", "[common][events]") {
|
||||
REQUIRE(CheckNoNodeAtLocation(parser, "number", "Idontexist(12)", 14) ==
|
||||
true);
|
||||
}
|
||||
SECTION("Invalid function calls (parent node)") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::NumberNode>(
|
||||
parser, "number", "Idontexist(12)", 12) == true);
|
||||
REQUIRE(CheckParentNodeAtLocationIs<gd::FunctionCallNode>(
|
||||
parser, "number", "Idontexist(12)", 12) == true);
|
||||
}
|
||||
|
||||
SECTION("Unterminated function calls") {
|
||||
REQUIRE(CheckNodeAtLocationIs<gd::FunctionCallNode>(
|
||||
|
@@ -348,7 +348,7 @@ module.exports = {
|
||||
type: 'stringWithSelector',
|
||||
paramLabel: _('Alignment'),
|
||||
options: ['left', 'right', 'center'],
|
||||
conditionDescription: _('Check the current text alignment'),
|
||||
conditionDescription: _('Check the current text alignment.'),
|
||||
conditionSentence: _('The text alignment of _PARAM0_ is _PARAM1_'),
|
||||
actionDescription: _('Change the alignment of the text.'),
|
||||
actionSentence: _('Set text alignment of _PARAM0_ to _PARAM1_'),
|
||||
@@ -360,7 +360,7 @@ module.exports = {
|
||||
iconPath: 'res/actions/scaleWidth24.png',
|
||||
type: 'boolean',
|
||||
paramLabel: _('Word wrap'),
|
||||
conditionDescription: _('Check if word wrap is enabled'),
|
||||
conditionDescription: _('Check if word wrap is enabled.'),
|
||||
conditionSentence: _('Word wrap is enabled'),
|
||||
actionDescription: _('Set word wrap'),
|
||||
actionSentence: _('Activate word wrap for _PARAM0_: _PARAM1_'),
|
||||
|
@@ -56,7 +56,7 @@ namespace gdjs {
|
||||
// @ts-ignore - parseFloat should not be required, but GDevelop 5.0 beta 92 and below were storing it as a string.
|
||||
this._opacity = parseFloat(objectData.content.opacity);
|
||||
this._text = objectData.content.text;
|
||||
this._color = BBTextRuntimeObject.hexToRGBColor(objectData.content.color);
|
||||
this._color = gdjs.hexToRGBColor(objectData.content.color);
|
||||
this._fontFamily = objectData.content.fontFamily;
|
||||
// @ts-ignore - parseFloat should not be required, but GDevelop 5.0 beta 92 and below were storing it as a string.
|
||||
this._fontSize = parseFloat(objectData.content.fontSize);
|
||||
@@ -69,11 +69,6 @@ namespace gdjs {
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
static hexToRGBColor(hex) {
|
||||
const hexNumber = parseInt(hex.replace('#', ''), 16);
|
||||
return [(hexNumber >> 16) & 255, (hexNumber >> 8) & 255, hexNumber & 255];
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
return this._renderer.getRendererObject();
|
||||
}
|
||||
@@ -93,9 +88,7 @@ namespace gdjs {
|
||||
this.setBBText(newObjectData.content.text);
|
||||
}
|
||||
if (oldObjectData.content.color !== newObjectData.content.color) {
|
||||
this._color = BBTextRuntimeObject.hexToRGBColor(
|
||||
newObjectData.content.color
|
||||
);
|
||||
this._color = gdjs.hexToRGBColor(newObjectData.content.color);
|
||||
this._renderer.updateColor();
|
||||
}
|
||||
if (
|
||||
@@ -226,6 +219,12 @@ namespace gdjs {
|
||||
* @param opacity The new opacity of the object (0-255).
|
||||
*/
|
||||
setOpacity(opacity: float): void {
|
||||
if (opacity < 0) {
|
||||
opacity = 0;
|
||||
}
|
||||
if (opacity > 255) {
|
||||
opacity = 255;
|
||||
}
|
||||
this._opacity = opacity;
|
||||
this._renderer.updateOpacity();
|
||||
}
|
||||
|
721
Extensions/BitmapText/JsExtension.js
Normal file
721
Extensions/BitmapText/JsExtension.js
Normal file
@@ -0,0 +1,721 @@
|
||||
// @flow
|
||||
/**
|
||||
* This is a declaration of an extension for GDevelop 5.
|
||||
*
|
||||
* ℹ️ Changes in this file are watched and automatically imported if the editor
|
||||
* is running. You can also manually run `node import-GDJS-Runtime.js` (in newIDE/app/scripts).
|
||||
*
|
||||
* The file must be named "JsExtension.js", otherwise GDevelop won't load it.
|
||||
* ⚠️ If you make a change and the extension is not loaded, open the developer console
|
||||
* and search for any errors.
|
||||
*
|
||||
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
|
||||
*/
|
||||
|
||||
/*::
|
||||
// Import types to allow Flow to do static type checking on this file.
|
||||
// Extensions declaration are typed using Flow (like the editor), but the files
|
||||
// for the game engine are checked with TypeScript annotations.
|
||||
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension
|
||||
.setExtensionInformation(
|
||||
'BitmapText',
|
||||
_('Bitmap Text'),
|
||||
_('Displays a text using a "Bitmap Font" (an image representing characters). This is more performant than a traditional Text object and it allows for complete control on the characters aesthetic.'),
|
||||
'Aurélien Vivet',
|
||||
'Open source (MIT License)'
|
||||
)
|
||||
.setExtensionHelpPath('/objects/bitmap_text');
|
||||
|
||||
const bitmapTextObject = new gd.ObjectJsImplementation();
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.updateProperty = function (
|
||||
objectContent,
|
||||
propertyName,
|
||||
newValue
|
||||
) {
|
||||
if (propertyName in objectContent) {
|
||||
if (typeof objectContent[propertyName] === 'boolean')
|
||||
objectContent[propertyName] = newValue === '1';
|
||||
else if (typeof objectContent[propertyName] === 'number')
|
||||
objectContent[propertyName] = parseFloat(newValue);
|
||||
else objectContent[propertyName] = newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.getProperties = function (objectContent) {
|
||||
const objectProperties = new gd.MapStringPropertyDescriptor();
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('text')
|
||||
.setValue(objectContent.text)
|
||||
.setType('textarea')
|
||||
.setLabel(_('Text'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('opacity')
|
||||
.setValue(objectContent.opacity.toString())
|
||||
.setType('number')
|
||||
.setLabel(_('Opacity (0-255)'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('align')
|
||||
.setValue(objectContent.align)
|
||||
.setType('choice')
|
||||
.addExtraInfo('left')
|
||||
.addExtraInfo('center')
|
||||
.addExtraInfo('right')
|
||||
.setLabel(_('Alignment, when multiple lines are displayed'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('bitmapFontResourceName')
|
||||
.setValue(objectContent.bitmapFontResourceName)
|
||||
.setType('resource')
|
||||
.addExtraInfo('bitmapFont') //fnt or xml files
|
||||
.setLabel(_('Bitmap Font'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('textureAtlasResourceName')
|
||||
.setValue(objectContent.textureAtlasResourceName)
|
||||
.setType('resource')
|
||||
.addExtraInfo('image')
|
||||
.setLabel(_('Bitmap atlas image'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('scale')
|
||||
.setValue(objectContent.scale.toString())
|
||||
.setType('number')
|
||||
.setLabel(_('Text scale'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('tint')
|
||||
.setValue(objectContent.tint)
|
||||
.setType('color')
|
||||
.setLabel(_('Font tint'));
|
||||
|
||||
objectProperties
|
||||
.getOrCreate('wordWrap')
|
||||
.setValue(objectContent.wordWrap ? 'true' : 'false')
|
||||
.setType('boolean')
|
||||
.setLabel(_('Word wrapping'));
|
||||
|
||||
return objectProperties;
|
||||
};
|
||||
bitmapTextObject.setRawJSONContent(
|
||||
JSON.stringify({
|
||||
text:
|
||||
'This text use the default bitmap font.\nUse a custom Bitmap Font to create your own texts.',
|
||||
opacity: 255,
|
||||
scale: 1,
|
||||
fontSize: 20,
|
||||
tint: '#ffffff',
|
||||
bitmapFontResourceName: '',
|
||||
textureAtlasResourceName: '',
|
||||
align: 'left',
|
||||
wordWrap: true,
|
||||
})
|
||||
);
|
||||
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.updateInitialInstanceProperty = function (
|
||||
objectContent,
|
||||
instance,
|
||||
propertyName,
|
||||
newValue,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
return false;
|
||||
};
|
||||
// $FlowExpectedError
|
||||
bitmapTextObject.getInitialInstanceProperties = function (
|
||||
content,
|
||||
instance,
|
||||
project,
|
||||
layout
|
||||
) {
|
||||
var instanceProperties = new gd.MapStringPropertyDescriptor();
|
||||
return instanceProperties;
|
||||
};
|
||||
|
||||
const object = extension
|
||||
.addObject(
|
||||
'BitmapTextObject',
|
||||
_('Bitmap Text'),
|
||||
_(
|
||||
'Displays a text using a "Bitmap Font" (an image representing characters). This is more performant than a traditional Text object and it allows for complete control on the characters aesthetic.'
|
||||
),
|
||||
'JsPlatform/Extensions/bitmapfont32.png',
|
||||
bitmapTextObject
|
||||
)
|
||||
.setIncludeFile('Extensions/BitmapText/bitmaptextruntimeobject.js')
|
||||
.addIncludeFile(
|
||||
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
|
||||
);
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
'string',
|
||||
'Text',
|
||||
_('Text'),
|
||||
_('the text'),
|
||||
_('the text'),
|
||||
'',
|
||||
'res/conditions/text24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('string')
|
||||
.setFunctionName('setText')
|
||||
.setGetter('getText');
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
'number',
|
||||
'Opacity',
|
||||
_('Opacity'),
|
||||
_('the opacity, between 0 (fully transparent) and 255 (opaque)'),
|
||||
_('the opacity'),
|
||||
'',
|
||||
'res/conditions/opacity24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('number')
|
||||
.setFunctionName('setOpacity')
|
||||
.setGetter('getOpacity');
|
||||
|
||||
object
|
||||
.addExpressionAndCondition(
|
||||
'number',
|
||||
'FontSize',
|
||||
_('Font size'),
|
||||
_('the font size, defined in the Bitmap Font'),
|
||||
_('the font size'),
|
||||
'',
|
||||
'res/conditions/characterSize24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('number')
|
||||
.setFunctionName('getFontSize');
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
'number',
|
||||
'Scale',
|
||||
_('Scale'),
|
||||
_('the scale (1 by default)'),
|
||||
_('the scale'),
|
||||
'',
|
||||
'res/actions/scale24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('number')
|
||||
.setFunctionName('setScale')
|
||||
.setGetter('getScale');
|
||||
|
||||
object
|
||||
.addExpressionAndCondition(
|
||||
'string',
|
||||
'FontName',
|
||||
_('Font name'),
|
||||
_('the font name (defined in the Bitmap font)'),
|
||||
_('the font name'),
|
||||
'',
|
||||
'res/conditions/font24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('string')
|
||||
.setFunctionName('getFontName');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetTint',
|
||||
_('Tint'),
|
||||
_('Set the tint of the Bitmap Text object.'),
|
||||
_('Set tint of _PARAM0_ to _PARAM1_'),
|
||||
'',
|
||||
'res/actions/color24.png',
|
||||
'res/actions/color.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter('color', _('Color'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setTint');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetBitmapFontAndTextureAtlasResourceName',
|
||||
_('Bitmap files resources'),
|
||||
_('Change the Bitmap Font and/or the atlas image used by the object.') +
|
||||
' ' +
|
||||
_(
|
||||
'The resource name can be found in: `Project Manager > Game settings > Resources`.'
|
||||
),
|
||||
_(
|
||||
'Set the bitmap font of _PARAM0_ to _PARAM1_ and the atlas to _PARAM2_'
|
||||
),
|
||||
'',
|
||||
'res/actions/font24.png',
|
||||
'res/actions/font.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter('bitmapFont', _('Bitmap font resource name'), '', false)
|
||||
.setParameterLongDescription(
|
||||
'The resource name of the font file, without quotes.'
|
||||
)
|
||||
.addParameter('string', _('Texture atlas resource name'), '', false)
|
||||
.setParameterLongDescription(
|
||||
'The resource name of the image exported with the font, with quotes.'
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setBitmapFontAndTextureAtlasResourceName');
|
||||
|
||||
object
|
||||
.addExpressionAndCondition(
|
||||
'string',
|
||||
'Alignment',
|
||||
_('Alignment'),
|
||||
_('the text alignment'),
|
||||
_('the text alignment'),
|
||||
'',
|
||||
'res/actions/textAlign24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('string')
|
||||
.setFunctionName('getAlignment');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetAlignment',
|
||||
_('Alignment'),
|
||||
_('Change the alignment of a Bitmap text object.'),
|
||||
_('Set the alignment of _PARAM0_ to _PARAM1_'),
|
||||
'',
|
||||
'res/actions/textAlign24.png',
|
||||
'res/actions/textAlign.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter(
|
||||
'stringWithSelector',
|
||||
_('Alignment'),
|
||||
'["left", "center", "right"]',
|
||||
false
|
||||
)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setAlignment');
|
||||
|
||||
object
|
||||
.addCondition(
|
||||
'WordWrap',
|
||||
_('Word wrap'),
|
||||
_('Check if word wrap is enabled.'),
|
||||
_('_PARAM0_ word wrap is enabled'),
|
||||
'',
|
||||
'res/conditions/wordWrap24.png',
|
||||
'res/conditions/wordWrap.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('getWordWrap');
|
||||
|
||||
object
|
||||
.addAction(
|
||||
'SetWordWrap',
|
||||
_('Word wrap'),
|
||||
_('De/activate word wrapping.'),
|
||||
_('Activate word wrap of _PARAM0_: _PARAM1_'),
|
||||
'',
|
||||
'res/actions/wordWrap24.png',
|
||||
'res/actions/wordWrap.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.addParameter('yesorno', _('Activate word wrap'), '', false)
|
||||
.getCodeExtraInformation()
|
||||
.setFunctionName('setWordWrap');
|
||||
|
||||
object
|
||||
.addExpressionAndConditionAndAction(
|
||||
'number',
|
||||
'WrappingWidth',
|
||||
_('Wrapping width'),
|
||||
_('the width, in pixels, after which the text is wrapped on next line'),
|
||||
_('the wrapping width'),
|
||||
'',
|
||||
'res/actions/scaleWidth24.png'
|
||||
)
|
||||
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
|
||||
.useStandardParameters('number')
|
||||
.setFunctionName('setWrappingWidth')
|
||||
.setGetter('getWrappingWidth');
|
||||
|
||||
return extension;
|
||||
},
|
||||
|
||||
/**
|
||||
* You can optionally add sanity tests that will check the basic working
|
||||
* of your extension behaviors/objects by instanciating behaviors/objects
|
||||
* and setting the property to a given value.
|
||||
*
|
||||
* If you don't have any tests, you can simply return an empty array.
|
||||
*
|
||||
* But it is recommended to create tests for the behaviors/objects properties you created
|
||||
* to avoid mistakes.
|
||||
*/
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
return [];
|
||||
},
|
||||
/**
|
||||
* Register editors for objects.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerEditorConfigurations: function (
|
||||
objectsEditorService /*: ObjectsEditorService */
|
||||
) {
|
||||
objectsEditorService.registerEditorConfiguration(
|
||||
'BitmapText::BitmapTextObject',
|
||||
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
|
||||
helpPagePath: '/objects/bitmaptext',
|
||||
})
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Register renderers for instance of objects on the scene editor.
|
||||
*
|
||||
* ℹ️ Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change.
|
||||
*/
|
||||
registerInstanceRenderers: function (
|
||||
objectsRenderingService /*: ObjectsRenderingService */
|
||||
) {
|
||||
const RenderedInstance = objectsRenderingService.RenderedInstance;
|
||||
const PIXI = objectsRenderingService.PIXI;
|
||||
|
||||
/** The bitmap font used in case another font can't be loaded. */
|
||||
let defaultBitmapFont = null;
|
||||
|
||||
const defaultBitmapFontInstallKey = 'GD-DEFAULT-BITMAP-FONT';
|
||||
|
||||
/**
|
||||
* Map counting the number of "reference" to a bitmap font. This is useful
|
||||
* to uninstall a bitmap font when not used anymore.
|
||||
*/
|
||||
const bitmapFontUsageCount = {};
|
||||
|
||||
/**
|
||||
* We patch the installed font to use a name that is unique for each font data and texture,
|
||||
* to avoid conflicts between different font files using the same font name (by default, the
|
||||
* font name used by Pixi is the one inside the font data, but this name is not necessarily unique.
|
||||
* For example, 2 resources can use the same font, or we can have multiple objects with the same
|
||||
* font data and different textures).
|
||||
*/
|
||||
const patchBitmapFont = (bitmapFont, bitmapFontInstallKey) => {
|
||||
const defaultName = bitmapFont.font;
|
||||
bitmapFont.font = bitmapFontInstallKey;
|
||||
PIXI.BitmapFont.available[bitmapFontInstallKey] = bitmapFont;
|
||||
|
||||
delete PIXI.BitmapFont.available[defaultName];
|
||||
return PIXI.BitmapFont.available[bitmapFontInstallKey];
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a default bitmap font to be used in case another font can't be loaded.
|
||||
*/
|
||||
const getDefaultBitmapFont = () => {
|
||||
if (defaultBitmapFont) return defaultBitmapFont;
|
||||
|
||||
const defaultBitmapFontStyle = new PIXI.TextStyle({
|
||||
fontFamily: 'Arial',
|
||||
fontSize: 20,
|
||||
padding: 5,
|
||||
align: 'left',
|
||||
fill: '#ffffff',
|
||||
wordWrap: true,
|
||||
lineHeight: 20,
|
||||
});
|
||||
|
||||
defaultBitmapFont = patchBitmapFont(
|
||||
PIXI.BitmapFont.from(
|
||||
defaultBitmapFontStyle.fontFamily,
|
||||
defaultBitmapFontStyle,
|
||||
{
|
||||
chars: [
|
||||
[' ', '~'], // All the printable ASCII characters
|
||||
],
|
||||
}
|
||||
),
|
||||
defaultBitmapFontInstallKey
|
||||
);
|
||||
return defaultBitmapFont;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a bitmap font resource name and a texture atlas resource name, returns the PIXI.BitmapFont
|
||||
* for it.
|
||||
* The font must be released with `releaseBitmapFont` when not used anymore - so that it can be removed
|
||||
* from memory when not used by any instance.
|
||||
*
|
||||
* @param pixiResourcesLoader
|
||||
* @param project
|
||||
* @param bitmapFontResourceName
|
||||
* @param textureAtlasResourceName
|
||||
*/
|
||||
const obtainBitmapFont = (
|
||||
pixiResourcesLoader,
|
||||
project,
|
||||
bitmapFontResourceName,
|
||||
textureAtlasResourceName
|
||||
) => {
|
||||
const bitmapFontInstallKey =
|
||||
bitmapFontResourceName + '@' + textureAtlasResourceName;
|
||||
|
||||
if (PIXI.BitmapFont.available[bitmapFontInstallKey]) {
|
||||
// Return the existing BitmapFont that is already in memory and already installed.
|
||||
bitmapFontUsageCount[bitmapFontInstallKey] =
|
||||
(bitmapFontUsageCount[bitmapFontInstallKey] || 0) + 1;
|
||||
return Promise.resolve(PIXI.BitmapFont.available[bitmapFontInstallKey]);
|
||||
}
|
||||
|
||||
// Get the atlas texture, the bitmap font data and install the font:
|
||||
const texture = pixiResourcesLoader.getPIXITexture(
|
||||
project,
|
||||
textureAtlasResourceName
|
||||
);
|
||||
|
||||
const loadBitmapFont = () =>
|
||||
pixiResourcesLoader
|
||||
.getBitmapFontData(project, bitmapFontResourceName)
|
||||
.then((fontData) => {
|
||||
if (!texture.valid)
|
||||
throw new Error(
|
||||
'Tried to install a BitmapFont with an invalid texture.'
|
||||
);
|
||||
|
||||
const bitmapFont = patchBitmapFont(
|
||||
PIXI.BitmapFont.install(fontData, texture),
|
||||
bitmapFontInstallKey
|
||||
);
|
||||
bitmapFontUsageCount[bitmapFontInstallKey] =
|
||||
(bitmapFontUsageCount[bitmapFontInstallKey] || 0) + 1;
|
||||
|
||||
return bitmapFont;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.warn('Unable to load font data:', err);
|
||||
console.info(
|
||||
'Is the texture atlas properly set for the Bitmap Text object? The default font will be used instead.'
|
||||
);
|
||||
|
||||
const bitmapFont = getDefaultBitmapFont();
|
||||
return bitmapFont;
|
||||
});
|
||||
|
||||
if (!texture.valid) {
|
||||
// Post pone texture update if texture is not loaded.
|
||||
// (otherwise, the bitmap font would not get updated when the
|
||||
// texture is loaded and udpated).
|
||||
return new Promise((resolve) => {
|
||||
texture.once('update', () => {
|
||||
resolve(loadBitmapFont());
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// We're ready to load the bitmap font now, as the texture
|
||||
// is already loaded.
|
||||
return loadBitmapFont();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* When a font is not used by an object anymore (object destroyed or font changed),
|
||||
* call this function to decrease the internal count of objects using the font.
|
||||
*
|
||||
* Fonts are unloaded when not used anymore.
|
||||
*/
|
||||
const releaseBitmapFont = (bitmapFontInstallKey) => {
|
||||
if (bitmapFontInstallKey === defaultBitmapFontInstallKey) {
|
||||
// Never uninstall the default bitmap font.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bitmapFontUsageCount[bitmapFontInstallKey]) {
|
||||
console.error(
|
||||
'BitmapFont with name ' +
|
||||
bitmapFontInstallKey +
|
||||
' was tried to be released but was never marked as used.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
bitmapFontUsageCount[bitmapFontInstallKey]--;
|
||||
|
||||
if (bitmapFontUsageCount[bitmapFontInstallKey] === 0) {
|
||||
PIXI.BitmapFont.uninstall(bitmapFontInstallKey);
|
||||
console.info(
|
||||
'Uninstalled BitmapFont "' + bitmapFontInstallKey + '" from memory.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Renderer for instances of BitmapText inside the IDE.
|
||||
*
|
||||
* @extends RenderedBitmapTextInstance
|
||||
* @class RenderedBitmapTextInstance
|
||||
* @constructor
|
||||
*/
|
||||
function RenderedBitmapTextInstance(
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObject,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
) {
|
||||
RenderedInstance.call(
|
||||
this,
|
||||
project,
|
||||
layout,
|
||||
instance,
|
||||
associatedObject,
|
||||
pixiContainer,
|
||||
pixiResourcesLoader
|
||||
);
|
||||
|
||||
// We'll track changes of the font to trigger the loading of the new font.
|
||||
this._currentBitmapFontResourceName = '';
|
||||
this._currentTextureAtlasResourceName = '';
|
||||
|
||||
this._pixiObject = new PIXI.BitmapText('', {
|
||||
// Use a default font. The proper font will be loaded in `update` method.
|
||||
fontName: getDefaultBitmapFont().font,
|
||||
});
|
||||
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
this._pixiContainer.addChild(this._pixiObject);
|
||||
this.update();
|
||||
}
|
||||
RenderedBitmapTextInstance.prototype = Object.create(
|
||||
RenderedInstance.prototype
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the path to the thumbnail of the specified object.
|
||||
*/
|
||||
RenderedBitmapTextInstance.getThumbnail = function (
|
||||
project,
|
||||
resourcesLoader,
|
||||
object
|
||||
) {
|
||||
return 'JsPlatform/Extensions/bitmapfont24.png';
|
||||
};
|
||||
|
||||
// This is called to update the PIXI object on the scene editor
|
||||
RenderedBitmapTextInstance.prototype.update = function () {
|
||||
const properties = this._associatedObject.getProperties();
|
||||
|
||||
// Update the rendered text properties (note: Pixi is only
|
||||
// applying changes if there were changed).
|
||||
const rawText = properties.get('text').getValue();
|
||||
this._pixiObject.text = rawText;
|
||||
|
||||
const opacity = properties.get('opacity').getValue();
|
||||
this._pixiObject.alpha = opacity / 255;
|
||||
|
||||
const align = properties.get('align').getValue();
|
||||
this._pixiObject.align = align;
|
||||
|
||||
const color = properties.get('tint').getValue();
|
||||
this._pixiObject.tint = parseInt(color.replace('#', '0x'), 16);
|
||||
|
||||
const scale = properties.get('scale').getValue() || 1;
|
||||
this._pixiObject.scale.set(scale);
|
||||
|
||||
// Track the changes in font to load the new requested font.
|
||||
const bitmapFontResourceName = properties
|
||||
.get('bitmapFontResourceName')
|
||||
.getValue();
|
||||
const textureAtlasResourceName = properties
|
||||
.get('textureAtlasResourceName')
|
||||
.getValue();
|
||||
|
||||
if (
|
||||
this._currentBitmapFontResourceName !== bitmapFontResourceName ||
|
||||
this._currentTextureAtlasResourceName !== textureAtlasResourceName
|
||||
) {
|
||||
// Release the old font (if it was installed).
|
||||
releaseBitmapFont(this._pixiObject.fontName);
|
||||
|
||||
this._currentBitmapFontResourceName = bitmapFontResourceName;
|
||||
this._currentTextureAtlasResourceName = textureAtlasResourceName;
|
||||
obtainBitmapFont(
|
||||
this._pixiResourcesLoader,
|
||||
this._project,
|
||||
this._currentBitmapFontResourceName,
|
||||
this._currentTextureAtlasResourceName
|
||||
).then((bitmapFont) => {
|
||||
this._pixiObject.fontName = bitmapFont.font;
|
||||
this._pixiObject.fontSize = bitmapFont.size;
|
||||
this._pixiObject.dirty = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Set up the wrapping width if enabled.
|
||||
const wordWrap = properties.get('wordWrap').getValue() === 'true';
|
||||
if (wordWrap && this._instance.hasCustomSize()) {
|
||||
this._pixiObject.maxWidth =
|
||||
this._instance.getCustomWidth() / this._pixiObject.scale.x;
|
||||
this._pixiObject.dirty = true;
|
||||
} else {
|
||||
this._pixiObject.maxWidth = 0;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
this._pixiObject.position.x =
|
||||
this._instance.getX() + (this._pixiObject.textWidth * scale) / 2;
|
||||
this._pixiObject.position.y =
|
||||
this._instance.getY() + (this._pixiObject.textHeight * scale) / 2;
|
||||
this._pixiObject.rotation = RenderedInstance.toRad(
|
||||
this._instance.getAngle()
|
||||
);
|
||||
};
|
||||
|
||||
RenderedBitmapTextInstance.prototype.onRemovedFromScene = function () {
|
||||
RenderedInstance.prototype.onRemovedFromScene.call(this);
|
||||
|
||||
releaseBitmapFont(this._pixiObject.fontName);
|
||||
this._pixiObject.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the width of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBitmapTextInstance.prototype.getDefaultWidth = function () {
|
||||
return this._pixiObject.width;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the height of the instance, when it's not resized.
|
||||
*/
|
||||
RenderedBitmapTextInstance.prototype.getDefaultHeight = function () {
|
||||
return this._pixiObject.height;
|
||||
};
|
||||
|
||||
objectsRenderingService.registerInstanceRenderer(
|
||||
'BitmapText::BitmapTextObject',
|
||||
RenderedBitmapTextInstance
|
||||
);
|
||||
},
|
||||
};
|
@@ -0,0 +1,33 @@
|
||||
namespace gdjs {
|
||||
/**
|
||||
* The Cocos2D-JS renderer for the BitmapTextRuntimeObject.
|
||||
*
|
||||
* The implementation is empty as the object is not supported in Cocos2D-JS for now.
|
||||
*/
|
||||
export class BitmapTextRuntimeObjectCocosRenderer {
|
||||
getRendererObject() {}
|
||||
onDestroy() {}
|
||||
getFontSize() {}
|
||||
updateFont() {}
|
||||
updateTint() {}
|
||||
getTint() {}
|
||||
updateScale() {}
|
||||
getScale() {}
|
||||
updateWrappingWidth() {}
|
||||
updateTextContent() {}
|
||||
updateAlignment() {}
|
||||
updatePosition() {}
|
||||
updateAngle() {}
|
||||
updateOpacity() {}
|
||||
|
||||
getWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
getHeight() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectCocosRenderer;
|
||||
}
|
173
Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.ts
Normal file
173
Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
|
||||
/**
|
||||
* The PIXI.js renderer for the Bitmap Text runtime object.
|
||||
*/
|
||||
export class BitmapTextRuntimeObjectPixiRenderer {
|
||||
_object: gdjs.BitmapTextRuntimeObject;
|
||||
_pixiObject: PIXI.BitmapText;
|
||||
|
||||
/**
|
||||
* @param runtimeObject The object to render
|
||||
* @param runtimeScene The gdjs.RuntimeScene in which the object is
|
||||
*/
|
||||
constructor(
|
||||
runtimeObject: gdjs.BitmapTextRuntimeObject,
|
||||
runtimeScene: gdjs.RuntimeScene
|
||||
) {
|
||||
this._object = runtimeObject;
|
||||
|
||||
// Obtain the bitmap font to use in the object.
|
||||
const bitmapFont = runtimeScene
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.obtainBitmapFont(
|
||||
runtimeObject._bitmapFontResourceName,
|
||||
runtimeObject._textureAtlasResourceName
|
||||
);
|
||||
this._pixiObject = new PIXI.BitmapText(runtimeObject._text, {
|
||||
fontName: bitmapFont.font,
|
||||
fontSize: bitmapFont.size,
|
||||
});
|
||||
|
||||
// Set the object on the scene
|
||||
runtimeScene
|
||||
.getLayer('')
|
||||
.getRenderer()
|
||||
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
|
||||
|
||||
// Set the anchor in the center, so that the object rotates around
|
||||
// its center.
|
||||
// @ts-ignore
|
||||
this._pixiObject.anchor.x = 0.5;
|
||||
// @ts-ignore
|
||||
this._pixiObject.anchor.y = 0.5;
|
||||
|
||||
this.updateAlignment();
|
||||
this.updateTextContent();
|
||||
this.updateAngle();
|
||||
this.updateOpacity();
|
||||
this.updateScale();
|
||||
this.updateWrappingWidth();
|
||||
this.updateTint();
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
return this._pixiObject;
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
// Mark the font from the object as not used anymore.
|
||||
this._object._runtimeScene
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.releaseBitmapFont(this._pixiObject.fontName);
|
||||
|
||||
this._pixiObject.destroy();
|
||||
}
|
||||
|
||||
getFontSize() {
|
||||
return this._pixiObject.fontSize;
|
||||
}
|
||||
|
||||
updateFont(): void {
|
||||
// Get the new bitmap font to use
|
||||
const bitmapFont = this._object._runtimeScene
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.obtainBitmapFont(
|
||||
this._object._bitmapFontResourceName,
|
||||
this._object._textureAtlasResourceName
|
||||
);
|
||||
|
||||
// Mark the old font as not used anymore
|
||||
this._object._runtimeScene
|
||||
.getGame()
|
||||
.getBitmapFontManager()
|
||||
.releaseBitmapFont(this._pixiObject.fontName);
|
||||
|
||||
// Update the font used by the object:
|
||||
this._pixiObject.fontName = bitmapFont.font;
|
||||
this._pixiObject.fontSize = bitmapFont.size;
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updateTint(): void {
|
||||
this._pixiObject.tint = gdjs.rgbToHexNumber(
|
||||
this._object._tint[0],
|
||||
this._object._tint[1],
|
||||
this._object._tint[2]
|
||||
);
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tint of the bitmap object as a "R;G;B" string.
|
||||
* @returns the tint of bitmap object in "R;G;B" format.
|
||||
*/
|
||||
getTint(): string {
|
||||
return (
|
||||
this._object._tint[0] +
|
||||
';' +
|
||||
this._object._tint[1] +
|
||||
';' +
|
||||
this._object._tint[2]
|
||||
);
|
||||
}
|
||||
|
||||
updateScale(): void {
|
||||
this._pixiObject.scale.set(Math.max(this._object._scale, 0));
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
getScale() {
|
||||
return Math.max(this._pixiObject.scale.x, this._pixiObject.scale.y);
|
||||
}
|
||||
|
||||
updateWrappingWidth(): void {
|
||||
if (this._object._wordWrap) {
|
||||
this._pixiObject.maxWidth =
|
||||
this._object._wrappingWidth / this._object._scale;
|
||||
this._pixiObject.dirty = true;
|
||||
} else {
|
||||
this._pixiObject.maxWidth = 0;
|
||||
this._pixiObject.dirty = true;
|
||||
}
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updateTextContent(): void {
|
||||
this._pixiObject.text = this._object._text;
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updateAlignment(): void {
|
||||
// @ts-ignore - assume align is always a valid value.
|
||||
this._pixiObject.align = this._object._align;
|
||||
this.updatePosition();
|
||||
}
|
||||
|
||||
updatePosition(): void {
|
||||
this._pixiObject.position.x = this._object.x + this.getWidth() / 2;
|
||||
this._pixiObject.position.y = this._object.y + this.getHeight() / 2;
|
||||
}
|
||||
|
||||
updateAngle(): void {
|
||||
this._pixiObject.rotation = gdjs.toRad(this._object.angle);
|
||||
}
|
||||
|
||||
updateOpacity(): void {
|
||||
this._pixiObject.alpha = this._object._opacity / 255;
|
||||
}
|
||||
|
||||
getWidth(): float {
|
||||
return this._pixiObject.textWidth * this.getScale();
|
||||
}
|
||||
|
||||
getHeight(): float {
|
||||
return this._pixiObject.textHeight * this.getScale();
|
||||
}
|
||||
}
|
||||
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectPixiRenderer;
|
||||
}
|
323
Extensions/BitmapText/bitmaptextruntimeobject.ts
Normal file
323
Extensions/BitmapText/bitmaptextruntimeobject.ts
Normal file
@@ -0,0 +1,323 @@
|
||||
namespace gdjs {
|
||||
/** Base parameters for {@link gdjs.BitmapTextRuntimeObject} */
|
||||
export type BitmapTextObjectDataType = {
|
||||
/** The base parameters of the Bitmap Text */
|
||||
content: {
|
||||
/** The opacity of the text. */
|
||||
opacity: float;
|
||||
/** Content of the text. */
|
||||
text: string;
|
||||
/** The tint of the text. */
|
||||
tint: string;
|
||||
/** The name of the resource containing the bitmap font for the text. */
|
||||
bitmapFontResourceName: string;
|
||||
/** The name of the resource containing the atlas image file for the text. */
|
||||
textureAtlasResourceName: string;
|
||||
/** The scale of the text. */
|
||||
scale: float;
|
||||
/** Activate word wrap if set to true. */
|
||||
wordWrap: boolean;
|
||||
/** Wrapping with from custom size properties. */
|
||||
wrappingWidth: float;
|
||||
/** Alignment of the text. */
|
||||
align: 'left' | 'center' | 'right';
|
||||
};
|
||||
};
|
||||
export type BitmapTextObjectData = ObjectData & BitmapTextObjectDataType;
|
||||
|
||||
/**
|
||||
* Displays a text using a "Bitmap Font", generated in a external editor like bmFont.
|
||||
* This is more efficient/faster to render than a traditional text (which needs
|
||||
* to have its whole texture re-rendered anytime it changes).
|
||||
*
|
||||
* Bitmap Font can be created with softwares like:
|
||||
* * BMFont (Windows, free): http://www.angelcode.com/products/bmfont/|http://www.angelcode.com/products/bmfont/
|
||||
* * Glyph Designer (OS X, commercial): http://www.71squared.com/en/glyphdesigner|http://www.71squared.com/en/glyphdesigner
|
||||
* * Littera (Web-based, free): http://kvazars.com/littera/|http://kvazars.com/littera/
|
||||
*/
|
||||
export class BitmapTextRuntimeObject extends gdjs.RuntimeObject {
|
||||
_opacity: float;
|
||||
_text: string;
|
||||
/** color in format [r, g, b], where each component is in the range [0, 255] */
|
||||
_tint: integer[];
|
||||
_bitmapFontResourceName: string;
|
||||
_textureAtlasResourceName: string;
|
||||
_scale: number;
|
||||
_wordWrap: boolean;
|
||||
_wrappingWidth: float;
|
||||
_align: string;
|
||||
|
||||
_renderer: gdjs.BitmapTextRuntimeObjectPixiRenderer;
|
||||
|
||||
/**
|
||||
* @param runtimeScene The scene the object belongs to.
|
||||
* @param objectData The object data used to initialize the object
|
||||
*/
|
||||
constructor(
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
objectData: BitmapTextObjectData
|
||||
) {
|
||||
super(runtimeScene, objectData);
|
||||
|
||||
this._opacity = objectData.content.opacity;
|
||||
this._text = objectData.content.text;
|
||||
this._tint = gdjs.hexToRGBColor(objectData.content.tint);
|
||||
|
||||
this._bitmapFontResourceName = objectData.content.bitmapFontResourceName; // fnt/xml files
|
||||
this._textureAtlasResourceName =
|
||||
objectData.content.textureAtlasResourceName; // texture file used with fnt/xml (bitmap font file)
|
||||
this._scale = objectData.content.scale;
|
||||
this._wordWrap = objectData.content.wordWrap;
|
||||
this._wrappingWidth = 0;
|
||||
this._align = objectData.content.align;
|
||||
|
||||
this._renderer = new gdjs.BitmapTextRuntimeObjectRenderer(
|
||||
this,
|
||||
runtimeScene
|
||||
);
|
||||
|
||||
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
|
||||
this.onCreated();
|
||||
}
|
||||
|
||||
getRendererObject() {
|
||||
return this._renderer.getRendererObject();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
updateFromObjectData(
|
||||
oldObjectData: BitmapTextObjectDataType,
|
||||
newObjectData: BitmapTextObjectDataType
|
||||
): boolean {
|
||||
if (oldObjectData.content.opacity !== newObjectData.content.opacity) {
|
||||
this.setOpacity(newObjectData.content.opacity);
|
||||
}
|
||||
if (oldObjectData.content.text !== newObjectData.content.text) {
|
||||
this.setText(newObjectData.content.text);
|
||||
}
|
||||
if (oldObjectData.content.tint !== newObjectData.content.tint) {
|
||||
this._tint = gdjs.hexToRGBColor(newObjectData.content.tint);
|
||||
this._renderer.updateTint();
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.bitmapFontResourceName !==
|
||||
newObjectData.content.bitmapFontResourceName
|
||||
) {
|
||||
this.setBitmapFontResourceName(
|
||||
newObjectData.content.bitmapFontResourceName
|
||||
);
|
||||
}
|
||||
if (
|
||||
oldObjectData.content.textureAtlasResourceName !==
|
||||
newObjectData.content.textureAtlasResourceName
|
||||
) {
|
||||
this.setTextureAtlasResourceName(
|
||||
newObjectData.content.textureAtlasResourceName
|
||||
);
|
||||
}
|
||||
if (oldObjectData.content.scale !== newObjectData.content.scale) {
|
||||
this.setScale(newObjectData.content.scale);
|
||||
}
|
||||
if (oldObjectData.content.wordWrap !== newObjectData.content.wordWrap) {
|
||||
this.setWordWrap(newObjectData.content.wordWrap);
|
||||
}
|
||||
if (oldObjectData.content.align !== newObjectData.content.align) {
|
||||
this.setAlignment(newObjectData.content.align);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the extra parameters that could be set for an instance.
|
||||
*/
|
||||
extraInitializationFromInitialInstance(initialInstanceData: InstanceData) {
|
||||
if (initialInstanceData.customSize) {
|
||||
this.setWrappingWidth(initialInstanceData.width);
|
||||
}
|
||||
}
|
||||
|
||||
onDestroyFromScene(runtimeScene: gdjs.RuntimeScene): void {
|
||||
super.onDestroyFromScene(runtimeScene);
|
||||
this._renderer.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text to display.
|
||||
*/
|
||||
setText(text: string): void {
|
||||
this._text = text;
|
||||
this._renderer.updateTextContent();
|
||||
this.hitBoxesDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the text displayed by the object.
|
||||
*/
|
||||
getText(): string {
|
||||
return this._text;
|
||||
}
|
||||
|
||||
setTint(rgbColorString: string): void {
|
||||
const splitValue = rgbColorString.split(';');
|
||||
if (splitValue.length !== 3) return;
|
||||
|
||||
this._tint[0] = parseInt(splitValue[0], 10);
|
||||
this._tint[1] = parseInt(splitValue[1], 10);
|
||||
this._tint[2] = parseInt(splitValue[2], 10);
|
||||
this._renderer.updateTint();
|
||||
}
|
||||
|
||||
getTint(): string {
|
||||
return this._tint[0] + ';' + this._tint[1] + ';' + this._tint[2];
|
||||
}
|
||||
|
||||
setScale(scale: float): void {
|
||||
this._scale = scale;
|
||||
this._renderer.updateScale();
|
||||
this.hitBoxesDirty = true;
|
||||
}
|
||||
|
||||
getScale(): float {
|
||||
return this._scale;
|
||||
}
|
||||
|
||||
getFontSize(): float {
|
||||
return this._renderer.getFontSize();
|
||||
}
|
||||
|
||||
setBitmapFontAndTextureAtlasResourceName(
|
||||
bitmapFontResourceName: string,
|
||||
textureAtlasResourceName: string
|
||||
): void {
|
||||
if (bitmapFontResourceName) {
|
||||
this.setBitmapFontResourceName(bitmapFontResourceName);
|
||||
this._renderer.updateFont();
|
||||
}
|
||||
if (textureAtlasResourceName) {
|
||||
this.setTextureAtlasResourceName(textureAtlasResourceName);
|
||||
this._renderer.updateFont();
|
||||
}
|
||||
}
|
||||
|
||||
setBitmapFontResourceName(bitmapFontResourceName: string): void {
|
||||
this._bitmapFontResourceName = bitmapFontResourceName;
|
||||
}
|
||||
|
||||
getBitmapFontResourceName(): string {
|
||||
return this._bitmapFontResourceName;
|
||||
}
|
||||
|
||||
setTextureAtlasResourceName(textureAtlasResourceName: string): void {
|
||||
this._textureAtlasResourceName = textureAtlasResourceName;
|
||||
}
|
||||
|
||||
getTextureAtlasResourceName(): string {
|
||||
return this._textureAtlasResourceName;
|
||||
}
|
||||
|
||||
setAlignment(align: string): void {
|
||||
this._align = align;
|
||||
this._renderer.updateAlignment();
|
||||
}
|
||||
|
||||
getAlignment(): string {
|
||||
return this._align;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on X axis.
|
||||
* @param x The new position X of the object.
|
||||
*/
|
||||
setX(x: float): void {
|
||||
super.setX(x);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object position on Y axis.
|
||||
* @param y The new position Y of the object.
|
||||
*/
|
||||
setY(y: float): void {
|
||||
super.setY(y);
|
||||
this._renderer.updatePosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the angle of the object.
|
||||
* @param angle The new angle of the object.
|
||||
*/
|
||||
setAngle(angle: float): void {
|
||||
super.setAngle(angle);
|
||||
this._renderer.updateAngle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object opacity.
|
||||
* @param opacity The new opacity of the object (0-255).
|
||||
*/
|
||||
setOpacity(opacity: float): void {
|
||||
if (opacity < 0) {
|
||||
opacity = 0;
|
||||
}
|
||||
if (opacity > 255) {
|
||||
opacity = 255;
|
||||
}
|
||||
this._opacity = opacity;
|
||||
this._renderer.updateOpacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object opacity.
|
||||
*/
|
||||
getOpacity(): float {
|
||||
return this._opacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the wrapping width.
|
||||
* @param width The new width in pixels.
|
||||
*/
|
||||
setWrappingWidth(width: float): void {
|
||||
this._wrappingWidth = width;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.hitBoxesDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wrapping width of the object.
|
||||
*/
|
||||
getWrappingWidth(): float {
|
||||
return this._wrappingWidth;
|
||||
}
|
||||
|
||||
setWordWrap(wordWrap: boolean): void {
|
||||
this._wordWrap = wordWrap;
|
||||
this._renderer.updateWrappingWidth();
|
||||
this.hitBoxesDirty = true;
|
||||
}
|
||||
|
||||
getWordWrap(): boolean {
|
||||
return this._wordWrap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the object.
|
||||
*/
|
||||
getWidth(): float {
|
||||
return this._renderer.getWidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the height of the object.
|
||||
*/
|
||||
getHeight(): float {
|
||||
return this._renderer.getHeight();
|
||||
}
|
||||
}
|
||||
gdjs.registerObject(
|
||||
'BitmapText::BitmapTextObject',
|
||||
// @ts-ignore
|
||||
gdjs.BitmapTextRuntimeObject
|
||||
);
|
||||
}
|
@@ -20,7 +20,6 @@ ADD_SUBDIRECTORY(PhysicsBehavior)
|
||||
ADD_SUBDIRECTORY(PlatformBehavior)
|
||||
ADD_SUBDIRECTORY(PrimitiveDrawing)
|
||||
ADD_SUBDIRECTORY(Shopify)
|
||||
ADD_SUBDIRECTORY(SkeletonObject)
|
||||
ADD_SUBDIRECTORY(SystemInfo)
|
||||
ADD_SUBDIRECTORY(TextEntryObject)
|
||||
ADD_SUBDIRECTORY(TextObject)
|
||||
|
@@ -20,39 +20,75 @@ import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsEx
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
createExtension: function(_/*: (string) => string */, gd/*: libGDevelop */) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
'DebuggerTools',
|
||||
_('Debugger Tools'),
|
||||
_(
|
||||
'Allow to interact with the editor debugger from the game.'
|
||||
),
|
||||
'Arthur Pacaud (arthuro555)',
|
||||
'MIT'
|
||||
);
|
||||
createExtension: function (
|
||||
_ /*: (string) => string */,
|
||||
gd /*: libGDevelop */
|
||||
) {
|
||||
const extension = new gd.PlatformExtension();
|
||||
extension.setExtensionInformation(
|
||||
'DebuggerTools',
|
||||
_('Debugger Tools'),
|
||||
_('Allow to interact with the editor debugger from the game.'),
|
||||
'Arthur Pacaud (arthuro555), Aurélien Vivet (Bouh)',
|
||||
'MIT'
|
||||
);
|
||||
|
||||
extension
|
||||
extension
|
||||
.addAction(
|
||||
'Pause',
|
||||
_('Pause game execution'),
|
||||
_(
|
||||
'This pauses the game, useful for inspecting the game state through the debugger. ' +
|
||||
'Note that events will be still executed until the end before the game is paused.'
|
||||
'Note that events will be still executed until the end before the game is paused.'
|
||||
),
|
||||
_('Pause game execution'),
|
||||
_('Debugger Tools'),
|
||||
'res/actions/bug32.png',
|
||||
'res/actions/bug32.png'
|
||||
)
|
||||
.addCodeOnlyParameter("currentScene", "")
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DebuggerTools/debuggertools.js')
|
||||
.setFunctionName('gdjs.evtTools.debuggerTools.pause');
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function(gd /*: libGDevelop */, extension /*: gdPlatformExtension*/) {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
extension
|
||||
.addAction(
|
||||
'EnableDebugDraw',
|
||||
_('Draw collisions hitboxes and points'),
|
||||
_(
|
||||
'This activates the display of rectangles and information on screen showing the objects bounding boxes (blue), the hitboxes (red) and some points of objects.'
|
||||
),
|
||||
_(
|
||||
'Enable debugging view of bounding boxes/collision masks: _PARAM1_ (include invisible objects: _PARAM2_, point names: _PARAM3_, custom points: _PARAM4_)'
|
||||
),
|
||||
_('Debugger Tools'),
|
||||
'res/actions/planicon24.png',
|
||||
'res/actions/planicon.png'
|
||||
)
|
||||
.addCodeOnlyParameter('currentScene', '')
|
||||
.addParameter('yesorno', _('Enable debug draw'), '', true)
|
||||
.setDefaultValue('yes')
|
||||
.addParameter(
|
||||
'yesorno',
|
||||
_('Show collisions for hidden objects'),
|
||||
'',
|
||||
true
|
||||
)
|
||||
.setDefaultValue('no')
|
||||
.addParameter('yesorno', _('Show points names'), '', true)
|
||||
.setDefaultValue('yes')
|
||||
.addParameter('yesorno', _('Show custom points'), '', true)
|
||||
.setDefaultValue('yes')
|
||||
.getCodeExtraInformation()
|
||||
.setIncludeFile('Extensions/DebuggerTools/debuggertools.js')
|
||||
.setFunctionName('gdjs.evtTools.debuggerTools.enableDebugDraw');
|
||||
|
||||
return extension;
|
||||
},
|
||||
runExtensionSanityTests: function (
|
||||
gd /*: libGDevelop */,
|
||||
extension /*: gdPlatformExtension*/
|
||||
) {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
@@ -12,6 +12,29 @@ namespace gdjs {
|
||||
export const pause = function (runtimeScene: gdjs.RuntimeScene) {
|
||||
runtimeScene.getGame().pause(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Enable or disable the debug draw.
|
||||
* @param runtimeScene - The current scene.
|
||||
* @param enableDebugDraw - true to enable the debug draw, false to disable it.
|
||||
* @param showHiddenInstances - true to apply the debug draw to hidden objects.
|
||||
* @param showPointsNames - true to show point names.
|
||||
* @param showCustomPoints - true to show custom points of Sprite objects.
|
||||
*/
|
||||
export const enableDebugDraw = function (
|
||||
runtimeScene: gdjs.RuntimeScene,
|
||||
enableDebugDraw: boolean,
|
||||
showHiddenInstances: boolean,
|
||||
showPointsNames: boolean,
|
||||
showCustomPoints: boolean
|
||||
) {
|
||||
runtimeScene.enableDebugDraw(
|
||||
enableDebugDraw,
|
||||
showHiddenInstances,
|
||||
showPointsNames,
|
||||
showCustomPoints
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -785,7 +785,7 @@ namespace gdjs {
|
||||
variables: gdjs.dialogueTree.runner.variables.data,
|
||||
visited: gdjs.dialogueTree.runner.visited,
|
||||
};
|
||||
gdjs.evtTools.network._objectToVariable(dialogueState, outputVariable);
|
||||
outputVariable.fromJSObject(dialogueState);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -795,9 +795,7 @@ namespace gdjs {
|
||||
* @param inputVariable The structured variable where to load the State from.
|
||||
*/
|
||||
gdjs.dialogueTree.loadState = function (inputVariable: gdjs.Variable) {
|
||||
const loadedState = JSON.parse(
|
||||
gdjs.evtTools.network.variableStructureToJSON(inputVariable)
|
||||
);
|
||||
const loadedState = inputVariable.toJSObject();
|
||||
if (!loadedState) {
|
||||
console.error('Load state variable is empty:', inputVariable);
|
||||
return;
|
||||
|
@@ -39,12 +39,14 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
|
||||
type: '',
|
||||
behaviors: [{ name: 'Behavior1', type: 'DraggableBehavior::Draggable' }],
|
||||
variables: [],
|
||||
effects: [],
|
||||
});
|
||||
var object2 = new gdjs.RuntimeObject(runtimeScene, {
|
||||
name: 'obj1',
|
||||
type: '',
|
||||
behaviors: [{ name: 'Behavior1', type: 'DraggableBehavior::Draggable' }],
|
||||
variables: [],
|
||||
effects: [],
|
||||
});
|
||||
runtimeScene.addObject(object);
|
||||
runtimeScene.addObject(object2);
|
||||
|
@@ -125,6 +125,12 @@ module.exports = {
|
||||
.setValue('7')
|
||||
.setLabel(_('Quality (between 0 and 20)'))
|
||||
.setType('number');
|
||||
advancedBloomProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const asciiEffect = extension
|
||||
.addEffect('Ascii')
|
||||
@@ -215,8 +221,8 @@ module.exports = {
|
||||
|
||||
const blurEffect = extension
|
||||
.addEffect('Blur')
|
||||
.setFullName(_('Blur'))
|
||||
.setDescription(_('Blur the rendered image.'))
|
||||
.setFullName(_('Blur (Gaussian, slow - prefer to use Kawase blur)'))
|
||||
.setDescription(_('Blur the rendered image. This is slow, so prefer to use Kawase blur in most cases.'))
|
||||
.addIncludeFile('Extensions/Effects/blur-pixi-filter.js');
|
||||
const blurProperties = blurEffect.getProperties();
|
||||
blurProperties
|
||||
@@ -412,6 +418,12 @@ module.exports = {
|
||||
.setLabel(_('Noise Frequency'))
|
||||
.setType('number')
|
||||
.setDescription('Number of updates per second (0: no updates)');
|
||||
crtProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const displacementEffect = extension
|
||||
.addEffect('Displacement')
|
||||
@@ -511,6 +523,12 @@ module.exports = {
|
||||
.setValue('false')
|
||||
.setLabel(_('Shadow only (shows only the shadow when enabled)'))
|
||||
.setType('boolean');
|
||||
dropShadowProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const glitchEffect = extension
|
||||
.addEffect('Glitch')
|
||||
@@ -680,12 +698,18 @@ module.exports = {
|
||||
.setValue('100')
|
||||
.setLabel(_('Center Y (between -1000 and 100)'))
|
||||
.setType('number');
|
||||
godrayProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const kawaseBlurEffect = extension
|
||||
.addEffect('KawaseBlur')
|
||||
.setFullName(_('Kawase blur'))
|
||||
.setFullName(_('Blur (Kawase, fast)'))
|
||||
.setDescription(
|
||||
_('A much faster blur than Gaussian blur, but more complicated to use.')
|
||||
_('Blur the rendered image, with much better performance than Gaussian blur.')
|
||||
)
|
||||
.addIncludeFile('Extensions/Effects/pixi-filters/filter-kawase-blur.js')
|
||||
.addIncludeFile('Extensions/Effects/kawase-blur-pixi-filter.js');
|
||||
@@ -710,6 +734,12 @@ module.exports = {
|
||||
.setValue('3')
|
||||
.setLabel(_('Quality (between 1 and 20)'))
|
||||
.setType('number');
|
||||
kawaseBlurProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const lightNightEffect = extension
|
||||
.addEffect('LightNight')
|
||||
@@ -839,6 +869,12 @@ module.exports = {
|
||||
.setValue('1')
|
||||
.setLabel(_('Color of the outline'))
|
||||
.setType('color');
|
||||
outlineProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const pixelateEffect = extension
|
||||
.addEffect('Pixelate')
|
||||
@@ -891,6 +927,12 @@ module.exports = {
|
||||
.setValue('0.5')
|
||||
.setLabel(_('Center Y (between 0 and 1, 0.5 is image middle)'))
|
||||
.setType('number');
|
||||
radialBlurProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
const reflectionEffect = extension
|
||||
.addEffect('Reflection')
|
||||
@@ -1061,7 +1103,7 @@ module.exports = {
|
||||
.setValue('20')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for filter area'));
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
twistProperties
|
||||
.getOrCreate('offsetX')
|
||||
.setValue('0.5')
|
||||
@@ -1100,6 +1142,12 @@ module.exports = {
|
||||
.setValue('0.3')
|
||||
.setLabel(_('strength (between 0 and 5)'))
|
||||
.setType('number');
|
||||
zoomBlurProperties
|
||||
.getOrCreate('padding')
|
||||
.setValue('0')
|
||||
.setLabel(_('Padding'))
|
||||
.setType('number')
|
||||
.setDescription(_('Padding for the visual effect area'));
|
||||
|
||||
return extension;
|
||||
},
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const adjustmentFilter = filter as PIXI.filters.AdjustmentFilter;
|
||||
const adjustmentFilter = (filter as unknown) as PIXI.filters.AdjustmentFilter;
|
||||
if (parameterName === 'gamma') {
|
||||
adjustmentFilter.gamma = value;
|
||||
} else if (parameterName === 'saturation') {
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const advancedBloomFilter = filter as PIXI.filters.AdvancedBloomFilter;
|
||||
const advancedBloomFilter = (filter as unknown) as PIXI.filters.AdvancedBloomFilter;
|
||||
if (parameterName === 'threshold') {
|
||||
advancedBloomFilter.threshold = value;
|
||||
} else if (parameterName === 'bloomScale') {
|
||||
@@ -17,6 +17,8 @@ namespace gdjs {
|
||||
advancedBloomFilter.blur = value;
|
||||
} else if (parameterName === 'quality') {
|
||||
advancedBloomFilter.quality = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
advancedBloomFilter.padding = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const asciiFilter = filter as PIXI.filters.AsciiFilter;
|
||||
const asciiFilter = (filter as unknown) as PIXI.filters.AsciiFilter;
|
||||
if (parameterName === 'size') {
|
||||
asciiFilter.size = value;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const bevelFilter = filter as PIXI.filters.BevelFilter;
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'rotation') {
|
||||
bevelFilter.rotation = value;
|
||||
} else if (parameterName === 'thickness') {
|
||||
@@ -21,7 +21,7 @@ namespace gdjs {
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {
|
||||
const bevelFilter = filter as PIXI.filters.BevelFilter;
|
||||
const bevelFilter = (filter as unknown) as PIXI.filters.BevelFilter;
|
||||
if (parameterName === 'lightColor') {
|
||||
bevelFilter.lightColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
|
@@ -1,4 +1,5 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('BlackAndWhite', {
|
||||
makePIXIFilter: function (layer, effectData) {
|
||||
const colorMatrix = new PIXI.filters.ColorMatrixFilter();
|
||||
@@ -7,7 +8,8 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const colorMatrix = filter as PIXI.filters.ColorMatrixFilter;
|
||||
// @ts-ignore - unsure why PIXI.filters is not recognised.
|
||||
const colorMatrix = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
|
||||
if (parameterName !== 'opacity') {
|
||||
return;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('BlendingMode', {
|
||||
makePIXIFilter: function (layer, effectData) {
|
||||
const blendingModeFilter = new PIXI.filters.AlphaFilter();
|
||||
@@ -6,7 +7,8 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const blendingModeFilter = filter as PIXI.filters.AlphaFilter;
|
||||
// @ts-ignore - unsure why PIXI.filters is not recognised.
|
||||
const blendingModeFilter = (filter as unknown) as PIXI.filters.AlphaFilter;
|
||||
if (parameterName === 'alpha') {
|
||||
blendingModeFilter.alpha = value;
|
||||
} else if (parameterName === 'blendmode') {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Blur', {
|
||||
makePIXIFilter: function (layer, effectData) {
|
||||
const blur = new PIXI.filters.BlurFilter();
|
||||
|
@@ -1,4 +1,5 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Brightness', {
|
||||
makePIXIFilter: function (layer, effectData) {
|
||||
const brightness = new PIXI.filters.ColorMatrixFilter();
|
||||
@@ -7,7 +8,8 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const brightnessFilter = filter as PIXI.filters.ColorMatrixFilter;
|
||||
// @ts-ignore - unsure why PIXI.filters is not recognised.
|
||||
const brightnessFilter = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
|
||||
if (parameterName !== 'brightness') {
|
||||
return;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const bulgePinchFilter = filter as PIXI.filters.BulgePinchFilter;
|
||||
const bulgePinchFilter = (filter as unknown) as PIXI.filters.BulgePinchFilter;
|
||||
if (parameterName === 'centerX') {
|
||||
bulgePinchFilter.center[0] = value;
|
||||
} else if (parameterName === 'centerY') {
|
||||
|
@@ -6,7 +6,6 @@ namespace gdjs {
|
||||
.getGame()
|
||||
.getImageManager()
|
||||
.getPIXITexture(effectData.stringParameters.colorMapTexture);
|
||||
const colorMapSprite = new PIXI.Sprite(colorMapTexture);
|
||||
const colorMapFilter = new PIXI.filters.ColorMapFilter(
|
||||
colorMapTexture,
|
||||
effectData.booleanParameters.nearest,
|
||||
@@ -20,7 +19,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const colorMapFilter = filter as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
if (parameterName === 'mix') {
|
||||
colorMapFilter.mix = gdjs.PixiFiltersTools.clampValue(
|
||||
value / 100,
|
||||
@@ -31,7 +30,7 @@ namespace gdjs {
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {
|
||||
const colorMapFilter = filter as PIXI.filters.ColorMapFilter;
|
||||
const colorMapFilter = (filter as unknown) as PIXI.filters.ColorMapFilter;
|
||||
if (parameterName === 'nearest') {
|
||||
colorMapFilter.nearest = value;
|
||||
}
|
||||
|
@@ -6,13 +6,13 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const colorReplaceFilter = filter as PIXI.filters.ColorReplaceFilter;
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter;
|
||||
if (parameterName === 'epsilon') {
|
||||
colorReplaceFilter.epsilon = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {
|
||||
const colorReplaceFilter = filter as PIXI.filters.ColorReplaceFilter;
|
||||
const colorReplaceFilter = (filter as unknown) as PIXI.filters.ColorReplaceFilter;
|
||||
if (parameterName === 'originalColor') {
|
||||
colorReplaceFilter.originalColor = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
|
@@ -42,6 +42,8 @@ namespace gdjs {
|
||||
filter.animationSpeed = value;
|
||||
} else if (parameterName === 'animationFrequency') {
|
||||
filter.animationFrequency = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
filter.padding = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
|
@@ -1,4 +1,5 @@
|
||||
namespace gdjs {
|
||||
import PIXI = GlobalPIXIModule.PIXI;
|
||||
gdjs.PixiFiltersTools.registerFilterCreator('Displacement', {
|
||||
makePIXIFilter: function (layer, effectData) {
|
||||
const displacementMapTexture = layer
|
||||
@@ -15,7 +16,8 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const displacementFilter = filter as PIXI.filters.DisplacementFilter;
|
||||
// @ts-ignore - unsure why PIXI.filters is not recognised.
|
||||
const displacementFilter = (filter as unknown) as PIXI.filters.DisplacementFilter;
|
||||
if (parameterName === 'scaleX') {
|
||||
displacementFilter.scale.x = value;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const dotFilter = filter as PIXI.filters.DotFilter;
|
||||
const dotFilter = (filter as unknown) as PIXI.filters.DotFilter;
|
||||
if (parameterName === 'scale') {
|
||||
dotFilter.scale = value;
|
||||
} else if (parameterName === 'angle') {
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const dropShadowFilter = filter as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'blur') {
|
||||
dropShadowFilter.blur = value;
|
||||
} else if (parameterName === 'quality') {
|
||||
@@ -17,10 +17,12 @@ namespace gdjs {
|
||||
dropShadowFilter.distance = value;
|
||||
} else if (parameterName === 'rotation') {
|
||||
dropShadowFilter.rotation = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
dropShadowFilter.padding = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {
|
||||
const dropShadowFilter = filter as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'color') {
|
||||
dropShadowFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(
|
||||
value
|
||||
@@ -28,7 +30,7 @@ namespace gdjs {
|
||||
}
|
||||
},
|
||||
updateBooleanParameter: function (filter, parameterName, value) {
|
||||
const dropShadowFilter = filter as PIXI.filters.DropShadowFilter;
|
||||
const dropShadowFilter = (filter as unknown) as PIXI.filters.DropShadowFilter;
|
||||
if (parameterName === 'shadowOnly') {
|
||||
dropShadowFilter.shadowOnly = value;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const glowFilter = filter as PIXI.filters.GlowFilter;
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter;
|
||||
if (parameterName === 'innerStrength') {
|
||||
glowFilter.innerStrength = value;
|
||||
} else if (parameterName === 'outerStrength') {
|
||||
@@ -17,7 +17,7 @@ namespace gdjs {
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {
|
||||
const glowFilter = filter as PIXI.filters.GlowFilter;
|
||||
const glowFilter = (filter as unknown) as PIXI.filters.GlowFilter;
|
||||
if (parameterName === 'color') {
|
||||
glowFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
|
||||
}
|
||||
|
@@ -26,6 +26,8 @@ namespace gdjs {
|
||||
filter.y = value;
|
||||
} else if (parameterName === 'animationSpeed') {
|
||||
filter.animationSpeed = value;
|
||||
} else if (parameterName === 'padding') {
|
||||
filter.padding = value;
|
||||
}
|
||||
},
|
||||
updateStringParameter: function (filter, parameterName, value) {},
|
||||
|
@@ -6,7 +6,7 @@ namespace gdjs {
|
||||
},
|
||||
update: function (filter, layer) {},
|
||||
updateDoubleParameter: function (filter, parameterName, value) {
|
||||
const kawaseBlurFilter = filter as PIXI.filters.KawaseBlurFilter;
|
||||
const kawaseBlurFilter = (filter as unknown) as PIXI.filters.KawaseBlurFilter;
|
||||
if (parameterName === 'pixelizeX') {
|
||||
// @ts-ignore: fix these wrong parameters
|
||||
kawaseBlurFilter.pixelizeX = value;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user