Compare commits

...

59 Commits

Author SHA1 Message Date
Florian Rival
1991cc634a Change the default behavior when clicking outside a window: it won't be closed anymore.
* This avoids a recurring issue where misclicking outside a window would cancel any changes made in the window.
* You can still press Escape to quickly close a dialog.
* Note that this behavior can be customized in the preferences. You can choose to cancel the changes, apply any changes or do nothing.
2021-05-09 23:10:59 +01:00
Florian Rival
d653f846b6 Update Bitmap Text description/wording
Don't show in changelog
2021-05-09 22:58:32 +01:00
Florian Rival
9a8ec971f2 Update translations 2021-05-09 20:37:45 +01:00
Florian Rival
87c5007a25 Add Bitmap Text example
Don't show in changelog
2021-05-09 19:45:29 +01:00
Florian Rival
666a9c747a Add Bim Bam (Bust-a-Move clone) example (thanks D8H) 2021-05-09 12:48:17 +01:00
Florian Rival
cf59e6fb1e Add Tactical Game Grid Movement example (thanks D8H) 2021-05-09 12:36:01 +01:00
Florian Rival
ab04db387a Add "Menu with tweens" example (thanks Dreamkingmovies) 2021-05-09 12:05:50 +01:00
aphoenixholland
7a7a0d0eec Add an option to Tween behavior scale actions to scale an object from its center (#2611) 2021-05-09 11:44:23 +01:00
Arthur Pacaud
a27d1e97bc Rework GetUsedExtensions (#2588)
Only show in developer changelog
2021-05-07 22:46:02 +02:00
Aurélien Vivet
076732abd9 Automatically disable smoothing of assets from asset store if the project is using the "nearest" scale mode ("pixel-perfect") (#2620) 2021-05-07 15:10:13 +01:00
Aurélien Vivet
9d09ad4dd9 Add Bitmap Text objects, an efficient way to display texts using custom "bitmap fonts" (#2432)
* This allows to display texts on screen that use a "bitmap font", generated with softwares like [BMFont](https://www.angelcode.com/products/bmfont/) or [bmGlyph](http://www.bmglyph.com/).
* Bitmap fonts allow advanced effects and custom design of each character, with complete control over the appearance of the text. This is useful for making a custom score counter, titles, button labels...
* They also render very well in a pixel-perfect, pixel-art or retro-like game.
* Finally, these Bitmap Texts are fast and efficient to render on screen: useful for scores or texts that are updated frequently.
2021-05-07 14:57:00 +01:00
Oxey405
c16d155066 Fix multi-user compatibility on Linux (previews/exports not generated in same folders anymore) (#2590) 2021-05-06 19:31:10 +01:00
Florian Rival
cbdfd344e3 Fix shortcut in preview and text entry not working anymore
Fix #2605

Don't show in changelog
2021-05-06 19:29:18 +01:00
Henrik Hedlund
8cce4ab9f2 Add warning hint about overriding the Peer ID in P2P extension (#2606) 2021-05-04 08:54:38 +01:00
Florian Rival
3266559cb6 Add actions, conditions and expressions to get the position of an object center or set its position using its center (#2593)
* This is useful for making concise actions or conditions.
* This is also useful because for some objects, the center is not located at half the width and the height of the object.
* You can use `Object.CenterX()` and `Object.CenterY()` to get the position of the center of an object in an expression.
2021-05-02 18:43:28 +01:00
Henrik Hedlund
990b04d629 Allow setting the client ID in the peer-to-peer extension (#2598)
* By default, a long unique ID is generated. If you use your own broker server, a game could generate a simple, but unique, ID for each game (e.g. 639239), and then specify that as the client ID. Other players can then connect to that peer using the simpler ID.
2021-05-02 11:04:30 +01:00
Florian Rival
c295456231 Fix sprite objects updating their displayed image one frame too late (#2597)
* This fixes some "flickering" when a sprite is just created, when a scene is changed or when external layout objects are created on a scene.

Fixes #1285
2021-05-01 18:05:25 +01:00
Florian Rival
79e033d57b Increase timeout for GDJS tests and fix a type issue
Don't show in changelog
2021-04-30 11:48:08 +02:00
Florian Rival
f0fc709a84 Fix tests (fix regression due to inexact rad/deg conversion) 2021-04-30 09:57:31 +02:00
D8H
b80ed7e6f5 Improve the type definitions of LinkedObjects (#2594)
Only show in developer changelog
2021-04-30 08:40:16 +01:00
D8H
f23936a6c4 Add tests on moving platforms (#2581)
Only show in developer changelog
2021-04-29 20:53:26 +01:00
Arthur Pacaud
1dff166df0 Add network and persistence configuration to firestore in Firebase (#2582) 2021-04-28 21:35:22 +02:00
Aurélien Vivet
50278b1ab2 Fix page scrolling when keyboard was used in games embedded in web pages (#2589) 2021-04-27 21:38:53 +01:00
Aurélien Vivet
5f4fde7a56 Add new expressions XFromAngleAndDistance and YFromAngleAndDistance (#2558) 2021-04-25 21:08:29 +01:00
Aurélien Vivet
5384225a9b Fix typo and mobile controls on Platformer project example (#2578)
Don't show in changelog
2021-04-24 18:12:05 +02:00
Arthur Pacaud
5ecdfa1c7f Convert Firebase extension to TypeScript (#2417)
Only show in developer changelog
2021-04-24 17:58:36 +02:00
Nilay Majorwar
df6910e062 Rework the behaviors list with collapsible panels (#2553)
* This is useful to hide behaviors when they are too many of them
* This also creates a more visible distinction between each behavior
2021-04-23 12:05:53 +01:00
D8H
5a42d6b94c Add more type definitions and new tests for on moving platforms for the Platformer behavior (#2573)
Only show in developer changelog
2021-04-23 11:55:18 +01:00
Arthur Pacaud
afa9b2a2ae Fix invalid values ("NaN") being potentially stored in variables and corrupting the project files (#2568) 2021-04-20 16:47:20 +01:00
Florian Rival
1dae099be9 Fix a potential crash when instances are selected and an object is deleted (#2557) 2021-04-18 18:37:06 +01:00
Arthur Pacaud
6f64fd3d1c Fix "Sound is playing" condition not consistent when an audio file is being loaded (#2555)
* Because of this, this could create some glitches when playing sounds using the condition to check if a sound was already playing (for example, it could trigger multiple times a sound).
2021-04-18 18:34:05 +01:00
Florian Rival
6c0bd92b24 Fix crash when adding an instance of a global object on the scene 2021-04-17 12:01:05 +01:00
Arthur Pacaud
0bcaa835e6 Improve the file watcher in development mode (#2554)
* Use chokidar for a more reliable and robust change detection
2021-04-17 11:06:26 +01:00
Nilay Majorwar
32ca97650c Rework the collisions editor and points editor (#2481)
* Show the preview and the polygons/points side by side (on large screens), so it's easier to edit.
* The split can be dragged to give more space to the preview or to the tables.
* Show point name in tooltip when hovering on point.
* Improve the dragging of points and polygon vertices so that they continue to follow the cursor even if dragging outside of the image bounds.
* Allow to collapse polygon tables, useful if you have lots of polygons in an object.
* The checkered background in the editors are now also using different colors following the selected theme.
2021-04-14 22:26:31 +01:00
Arthur Pacaud
e19d63ce96 Improve spacing of descriptions for checkboxes in properties (#2542) 2021-04-13 10:25:01 +01:00
Aurélien Vivet
352e5daf1e Addition of the version number under the name of the extension in the presentation panel. (#2540) 2021-04-13 11:08:01 +02:00
Aurélien Vivet
003f56e9bc Remove the rest of the skeleton object (#2539)
Don't show in changelog
2021-04-13 00:22:36 +01:00
D8H
4b3fa9fc39 Fix hitboxes not invalidated in TestRuntimeObject (#2534)
Only show in developer changelog
2021-04-11 20:22:54 +01:00
Florian Rival
e3fa31c4a4 Merge branch 'master' of github.com:4ian/GDevelop 2021-04-11 15:49:51 +01:00
Florian Rival
1ad0ab9881 Add Goose Bomberman example (thanks D8H) 2021-04-11 15:48:33 +01:00
Aurélien Vivet
355c53cb12 Fix Video object wrongly starting to play automatically (#2533) 2021-04-11 14:40:58 +01:00
Florian Rival
2a9b27b503 Add a new Dialogue Tree example (thanks potato-gamer-coder and Midhil457!) 2021-04-11 13:26:32 +01:00
D8H
2fa2824ca2 Add a test for platformer object to fall when a platform is removed (#2529)
Only show in developer changelog
2021-04-11 03:07:33 +01:00
Florian Rival
85e3ed42fa Add experimental configuration for GitHub workspaces
Don't show in changelog
2021-04-11 01:58:12 +00:00
Aurélien Vivet
8a178a85fb Add a preference to choose if clicking outside a dialog is cancelling changes, applying changes or doing nothing (#2484) 2021-04-10 19:36:42 +01:00
Florian Rival
54ef7482cf Fix performance issues on iOS by upgrading internal rendering engine to PixiJS v6 (#2447)
* Thanks @Bouh and @arthuro555 for the help!

Co-authored-by: Bouh <bouh.vivez@gmail.com>
2021-04-09 23:58:18 +01:00
Aurélien Vivet
c846a7a068 Change the wording of the button to "Edit collision masks" (#2525) 2021-04-09 15:46:29 +01:00
Florian Rival
86eff4e408 Fix sounds/musics playing for a very short time at the default volume instead of the specified one
Fix #2490
2021-04-08 23:59:34 +01:00
D8H
916938b4a8 [Top-down] Stick controls now comply with the "allow diagonals" setting (#2518)
* Test cases on stick controls for forbidden diagonals


add tests

* Fix: stick controls now comply with allowDiagonals setting

* Remove only
2021-04-07 19:01:40 +00:00
D8H
49827984ac Allow an object moving vertically to change direction when diagonals are forbidden in the Top-down behavior. (#2516)
* If multiple keys are pressed, the last one is used to move the object.
2021-04-07 00:19:05 +01:00
Aurélien Vivet
02eac6ba5e Small fixes (#2514)
* Remove useless type

* Fix type
2021-04-06 22:43:09 +00:00
Arthur Pacaud
479167638b Update the discord invite URL (#2511) 2021-04-05 22:00:04 +02:00
Florian Rival
fada85d41d Fix export to Android/iOS failing if AdMob id was containing invalid characters (#2510) 2021-04-05 13:31:12 +01:00
Florian Rival
3017798283 Remove deprecated/unmaintained SkeletonObject extension (#2509)
This should probably be restarted from scratch with a well known/battle tested library.

Don't show in changelog
2021-04-03 23:58:02 +01:00
Florian Rival
515308ed9d Add Titan Souls Demo game (Thanks @HelperWesley and @arthuro555) 2021-04-03 22:36:50 +01:00
Tristan Rhodes
7369e05e01 Improve wording on some movement related action sentences (#2501) 2021-04-02 20:09:51 +01:00
Aurélien Vivet
55da9eb2ef Add an action to display collision hitboxes and points of objects during the game (#2394)
* This is useful to check the proper set up of objects and check the position of points of objects during the game.
2021-04-02 00:11:22 +01:00
Arthur Pacaud
01a45a10df Improve the p2p chat example (#2488) 2021-04-01 23:54:38 +01:00
Florian Rival
32d313f538 Bump newIDE version 2021-03-30 00:14:05 +01:00
807 changed files with 136484 additions and 20656 deletions

6
.devcontainer/Dockerfile Normal file
View 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
View 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.

View 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.'"
}

View File

@@ -45,7 +45,6 @@
"name": "Linux",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/IDE",
"${workspaceRoot}/GDCpp",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",

8
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"xaver.clang-format",
"ms-vscode.cpptools",
"flowtype.flow-for-vscode"
]
}

18
.vscode/settings.json vendored
View File

@@ -90,7 +90,23 @@
"__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"
},
"files.exclude": {
"Binaries/*build*": true,

View File

@@ -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.

View File

@@ -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."),
@@ -202,7 +236,7 @@ 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"),
"res/actions/force24.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"),
@@ -636,7 +670,7 @@ 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"),
_("Move _PARAM0_ toward _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
_("Movement"),
"res/actions/forceVers24.png",
"res/actions/forceVers.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."),
@@ -711,7 +745,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.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."),
@@ -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"))

View File

@@ -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
}

View File

@@ -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,

View 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

View 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

View 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

View 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

View File

@@ -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 =

View File

@@ -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.

View File

@@ -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;
};

View File

@@ -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,

View File

@@ -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,

View File

@@ -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());
@@ -651,18 +630,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 =
@@ -730,68 +697,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
#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 +822,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 +1020,6 @@ void Project::Init(const gd::Project& game) {
currentPlatform = game.currentPlatform;
#endif
extensionsUsed = game.extensionsUsed;
platforms = game.platforms;
resourcesManager = game.resourcesManager;

View File

@@ -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.
@@ -1002,7 +988,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;

View File

@@ -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); }

View File

@@ -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
*

View File

@@ -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;
}

View File

@@ -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_'),

View File

@@ -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 (

View 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.width / 2;
this._pixiObject.position.y =
this._instance.getY() + this._pixiObject.height / 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
);
},
};

View File

@@ -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;
}

View File

@@ -0,0 +1,174 @@
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._pixiObject.width / 2;
this._pixiObject.position.y =
this._object.y + this._pixiObject.height / 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;
}
getHeight(): float {
return this._pixiObject.height;
}
}
export const BitmapTextRuntimeObjectRenderer = BitmapTextRuntimeObjectPixiRenderer;
}

View File

@@ -0,0 +1,313 @@
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();
}
/**
* 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();
}
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 {
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();
}
/**
* Get the wrapping width of the object.
*/
getWrappingWidth(): float {
return this._wrappingWidth;
}
setWordWrap(wordWrap: boolean): void {
this._wordWrap = wordWrap;
this._renderer.updateWrappingWidth();
}
getWordWrap(): boolean {
return this._wordWrap;
}
/**
* Get the width of the object.
*/
getWidth(): float {
return this._renderer.getWidth() * this.getScale();
}
/**
* Get the height of the object.
*/
getHeight(): float {
return this._renderer.getHeight() * this.getScale();
}
}
gdjs.registerObject(
'BitmapText::BitmapTextObject',
// @ts-ignore
gdjs.BitmapTextRuntimeObject
);
}

View File

@@ -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)

View File

@@ -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 [];
},
};

View File

@@ -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
);
};
}
}
}

View File

@@ -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') {

View File

@@ -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') {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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') {

View File

@@ -1,4 +1,5 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
gdjs.PixiFiltersTools.registerFilterCreator('Blur', {
makePIXIFilter: function (layer, effectData) {
const blur = new PIXI.filters.BlurFilter();

View File

@@ -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;
}

View File

@@ -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') {

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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') {

View File

@@ -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') {
@@ -20,7 +20,7 @@ namespace gdjs {
}
},
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 +28,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;
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -1,4 +1,5 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
export class LightNightPixiFilter extends PIXI.Filter {
constructor() {
const vertexShader = undefined;

View File

@@ -1,4 +1,5 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
export class NightPixiFilter extends PIXI.Filter {
constructor() {
const vertexShader = undefined;

View File

@@ -1,4 +1,5 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
gdjs.PixiFiltersTools.registerFilterCreator('Noise', {
makePIXIFilter: function (layer, effectData) {
const noiseFilter = new PIXI.filters.NoiseFilter();
@@ -6,7 +7,8 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const noiseFilter = filter as PIXI.filters.NoiseFilter;
// @ts-ignore - unsure why PIXI.filters is not recognised.
const noiseFilter = (filter as unknown) as PIXI.filters.NoiseFilter;
if (parameterName !== 'noise') {
return;
}

View File

@@ -6,13 +6,13 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const outlineFilter = filter as PIXI.filters.OutlineFilter;
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
if (parameterName === 'thickness') {
outlineFilter.thickness = value;
}
},
updateStringParameter: function (filter, parameterName, value) {
const outlineFilter = filter as PIXI.filters.OutlineFilter;
const outlineFilter = (filter as unknown) as PIXI.filters.OutlineFilter;
if (parameterName === 'color') {
outlineFilter.color = gdjs.PixiFiltersTools.rgbOrHexToHexNumber(value);
}

View File

@@ -8,7 +8,7 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const pixelateFilter = filter as PIXI.filters.PixelateFilter;
const pixelateFilter = (filter as unknown) as PIXI.filters.PixelateFilter;
if (parameterName === 'size') {
pixelateFilter.size = value;
}

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class AdjustmentFilter extends PIXI.Filter {
constructor(options?: AdjustmentOptions);
gamma: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class AdvancedBloomFilter extends PIXI.Filter {
constructor(options?: AdvancedBloomOptions);
constructor(threshold?: number);

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class AsciiFilter extends PIXI.Filter {
constructor(size?: number);
size: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class BevelFilter extends PIXI.Filter {
constructor(options?: BevelOptions);
rotation: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class BloomFilter extends PIXI.Filter {
constructor(
blur?: number | PIXI.Point | number[],

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export interface BulgePinchFilterOptions {
center?: PIXI.Point | [number, number];
radius?: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ColorMapFilter extends PIXI.Filter {
constructor(
colorMap?:

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ColorOverlayFilter extends PIXI.Filter {
constructor(color?: number | [number, number, number]);
color: number | [number, number, number];

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ColorReplaceFilter extends PIXI.Filter {
constructor(
originalColor?: number | number[],

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ConvolutionFilter extends PIXI.Filter {
constructor(matrix: number[], width: number, height: number);
height: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
class CrossHatchFilter extends PIXI.Filter {
constructor();
}

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class CRTFilter extends PIXI.Filter {
constructor(options?: CRTFilterOptions);
curvature: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class DotFilter extends PIXI.Filter {
constructor(scale?: number, angle?: number);
angle: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class DropShadowFilter extends PIXI.Filter {
constructor(options?: DropShadowFilterOptions);
alpha: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class EmbossFilter extends PIXI.Filter {
constructor(strength?: number);
strength: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class GlitchFilter extends PIXI.Filter {
constructor(options?: GlitchFilterOptions);
slices: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class GlowFilter extends PIXI.Filter {
constructor(options?: GlowFilterOptions);
color: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class GodrayFilter extends PIXI.Filter {
constructor(options?: GodrayFilterOptions);
angle: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class KawaseBlurFilter extends PIXI.Filter {
constructor(blur?: number | number[], quality?: number, clamp?: boolean);
kernels: number[];

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class MotionBlurFilter extends PIXI.Filter {
constructor(
velocity: PIXI.ObservablePoint | PIXI.Point | number[],

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class MultiColorReplaceFilter extends PIXI.Filter {
constructor(
replacements: Array<number[] | number[][]>,

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class OldFilmFilter extends PIXI.Filter {
constructor(options?: OldFilmFilterOptions, seed?: number);
constructor(seed?: number);

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class OutlineFilter extends PIXI.Filter {
constructor(thickness?: number, color?: number, quality?: number);
color: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class PixelateFilter extends PIXI.Filter {
constructor(size?: PIXI.Point | number[] | number);
size: PIXI.Point | number[] | number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class RadialBlurFilter extends PIXI.Filter {
constructor(
angle?: number,

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ReflectionFilter extends PIXI.Filter {
constructor(options?: ReflectionFilterOptions);
mirror: boolean;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class RGBSplitFilter extends PIXI.Filter {
constructor(red?: PIXI.Point, green?: PIXI.Point, blue?: PIXI.Point);
red: PIXI.Point;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class ShockwaveFilter extends PIXI.Filter {
constructor(
center?: PIXI.Point | number[],

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class SimpleLightmapFilter extends PIXI.Filter {
constructor(texture: PIXI.Texture, color?: number[] | number);
alpha: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class TiltShiftFilter extends PIXI.Filter {
constructor(
blur?: number,

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export class TwistFilter extends PIXI.Filter {
constructor(radius?: number, angle?: number, padding?: number);
angle: number;

View File

@@ -1,4 +1,5 @@
declare namespace PIXI.filters {
import PIXI = GlobalPIXIModule.PIXI;
export interface ZoomBlurFilterOptions {
strength?: number;
center?: PIXI.Point | [number, number];

View File

@@ -5,7 +5,7 @@ namespace gdjs {
return radialBlurFilter;
},
update: function (filter, layer) {
const radialBlurFilter = filter as PIXI.filters.RadialBlurFilter;
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter;
radialBlurFilter.center[0] = Math.round(
// @ts-ignore - extra properties are stored on the filter.
radialBlurFilter._centerX * layer.getWidth()
@@ -16,7 +16,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const radialBlurFilter = filter as PIXI.filters.RadialBlurFilter;
const radialBlurFilter = (filter as unknown) as PIXI.filters.RadialBlurFilter;
if (parameterName === 'radius') {
radialBlurFilter.radius = value < 0 ? -1 : value;
} else if (parameterName === 'angle') {

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const rgbSplitFilter = filter as PIXI.filters.RGBSplitFilter;
const rgbSplitFilter = (filter as unknown) as PIXI.filters.RGBSplitFilter;
if (parameterName === 'redX') {
rgbSplitFilter.red.x = value;
} else if (parameterName === 'redY') {

View File

@@ -1,4 +1,5 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
gdjs.PixiFiltersTools.registerFilterCreator('Sepia', {
makePIXIFilter: function (layer, effectData) {
const colorMatrixFilter = new PIXI.filters.ColorMatrixFilter();
@@ -7,7 +8,8 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const colorMatrixFilter = filter as PIXI.filters.ColorMatrixFilter;
// @ts-ignore - unsure why PIXI.filters is not recognised.
const colorMatrixFilter = (filter as unknown) as PIXI.filters.ColorMatrixFilter;
if (parameterName !== 'opacity') {
return;
}

View File

@@ -6,7 +6,7 @@ namespace gdjs {
},
update: function (filter, layer) {},
updateDoubleParameter: function (filter, parameterName, value) {
const tiltShiftFilter = filter as PIXI.filters.TiltShiftFilter;
const tiltShiftFilter = (filter as unknown) as PIXI.filters.TiltShiftFilter;
if (parameterName === 'blur') {
tiltShiftFilter.blur = value;
} else if (parameterName === 'gradientBlur') {

View File

@@ -1,12 +1,17 @@
namespace gdjs {
// Use a different name for PIXI to avoid confusing Typescript between the
// PIXI module, and the PIXI "namespace" where filters are added. Could maybe
// be removed when filters typings are reworked.
import PIXI_ = GlobalPIXIModule.PIXI;
gdjs.PixiFiltersTools.registerFilterCreator('Twist', {
makePIXIFilter: function (layer, effectData) {
const twistFilter = new PIXI.filters.TwistFilter();
twistFilter.offset = new PIXI.Point(0, 0);
twistFilter.offset = new PIXI_.Point(0, 0);
return twistFilter;
},
update: function (filter, layer) {
const twistFilter = filter as PIXI.filters.TwistFilter;
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter;
twistFilter.offset.x = Math.round(
// @ts-ignore - extra properties are stored on the filter.
twistFilter._offsetX * layer.getWidth()
@@ -17,7 +22,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const twistFilter = filter as PIXI.filters.TwistFilter;
const twistFilter = (filter as unknown) as PIXI.filters.TwistFilter;
if (parameterName === 'radius') {
twistFilter.radius = value;
} else if (parameterName === 'angle') {

View File

@@ -5,7 +5,7 @@ namespace gdjs {
return zoomBlurFilter;
},
update: function (filter, layer) {
const zoomBlurFilter = filter as PIXI.filters.ZoomBlurFilter;
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter;
zoomBlurFilter.center[0] = Math.round(
// @ts-ignore - extra properties are stored on the filter.
zoomBlurFilter._centerX * layer.getWidth()
@@ -16,7 +16,7 @@ namespace gdjs {
);
},
updateDoubleParameter: function (filter, parameterName, value) {
const zoomBlurFilter = filter as PIXI.filters.ZoomBlurFilter;
const zoomBlurFilter = (filter as unknown) as PIXI.filters.ZoomBlurFilter;
if (parameterName === 'centerX') {
// @ts-ignore - extra properties are stored on the filter.
zoomBlurFilter._centerX = value;

View File

@@ -1,5 +1,7 @@
//A simple PIXI filter doing some color changes
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
const DummyPixiFilter = function () {
var vertexShader = null;
var fragmentShader = [

View File

@@ -1,4 +1,6 @@
namespace gdjs {
import PIXI = GlobalPIXIModule.PIXI;
/**
* The PIXI.js renderer for the DummyRuntimeObject.
* @ignore

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More