Compare commits

...

134 Commits

Author SHA1 Message Date
Davy Hélard
55fc686a5b Fix expression default type. 2022-10-29 22:02:37 +02:00
Davy Hélard
5580189f88 Remove unused imports. 2022-10-29 20:49:29 +02:00
Davy Hélard
9a6d1d6d32 Remove useless lines added by mistake. 2022-10-29 19:42:54 +02:00
Davy Hélard
6c9739c01d Fix object parameter extraInfo declaration. 2022-10-29 19:41:07 +02:00
Davy Hélard
cd3c997b28 Review changes: more renaming 2022-10-29 17:53:15 +02:00
Davy Hélard
8064c4de57 Review changes: renaming 2022-10-29 14:54:09 +02:00
Davy Hélard
8666851f54 Documentation. 2022-10-29 13:40:53 +02:00
Davy Hélard
6d568b2f2c Fix type conversion to expressionType. 2022-10-29 13:40:52 +02:00
Davy Hélard
180d4318aa Add ValueTypeEditor to edit type definitions. 2022-10-29 13:40:52 +02:00
Davy Hélard
65a57f86da Allow to define type extraInfo for operands. 2022-10-29 13:40:52 +02:00
Davy Hélard
6a3e7f9c58 Define expression types with ValueTypeMetadata. 2022-10-29 13:40:52 +02:00
Davy Hélard
74f1d571ba Extract ValueTypeMetadata from ParameterMetadata. 2022-10-29 13:40:51 +02:00
Davy Hélard
a7cb3fc5a2 Add some comment about parameter types. 2022-10-29 13:40:51 +02:00
Davy Hélard
08d3c3323a Move out changes to mapFor. 2022-10-29 13:40:51 +02:00
Davy Hélard
fec603b811 Format 2022-10-29 13:40:51 +02:00
Davy Hélard
d68affc117 Add tests for shiftSentenceParamIndexes 2022-10-29 13:40:50 +02:00
Davy Hélard
77cd6c44d6 Review change: memory leak in test. 2022-10-29 13:40:50 +02:00
Davy Hélard
2b4c8813e4 Review changes 2022-10-29 13:40:50 +02:00
Davy Hélard
2ef9266ec4 Disable the "Add parameter" button for ActionWithOperator. 2022-10-29 13:40:49 +02:00
Davy Hélard
ceba6cf739 Split function types and returned types in 2 drop-down lists. 2022-10-29 13:40:49 +02:00
Davy Hélard
18f2085de7 Better disable parameters in UI. 2022-10-29 13:40:49 +02:00
Davy Hélard
b586fb87ed Show the right parameters in the editor. 2022-10-29 13:40:49 +02:00
Davy Hélard
8aed02ab17 Allow event extensions to define an action with an operator. 2022-10-29 13:40:48 +02:00
Davy Hélard
8c383fc448 Cleanup stories imports. 2022-10-29 13:40:48 +02:00
Davy Hélard
af3a2016f2 Fix flow. 2022-10-29 13:40:48 +02:00
Davy Hélard
7a20161794 Use the icon of expressions. 2022-10-29 13:40:47 +02:00
Davy Hélard
0feb4ef321 Put operator and operand first. 2022-10-29 13:40:47 +02:00
Davy Hélard
5cbcd16523 Allow event extensions to define a condition with an operator from an expression. 2022-10-29 13:40:47 +02:00
D8H
71f20d7852 Refactor to make some ParameterMetadata attributes private (type, supplementaryInformation and optional) (#4437) 2022-10-29 13:02:18 +02:00
D8H
9d121d0085 Suffix properties private instruction names with "property" to avoid them to overlap public ones (#4436) 2022-10-29 13:01:07 +02:00
Clément Pasteau
6292e338bc Fix importing path correctly on web (#4458) 2022-10-28 17:58:24 +02:00
Clément Pasteau
c5eb0bcc00 Bump version to 5.1.149 (#4451) 2022-10-28 11:23:50 +02:00
github-actions[bot]
a732fda4d9 Update translations [skip ci] (#4430)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-10-28 11:20:33 +02:00
Clément Pasteau
398bff8492 Fix input not being positioned properly (#4450) 2022-10-28 11:11:24 +02:00
D8H
f30e92a953 Make scene properties look the same as behavior properties (#4448)
* For instance, scene properties are used by the Physics2 behavior.
2022-10-27 21:48:52 +02:00
AlexandreS
8210c25acb UI improvements (#4440)
- Make some popovers and panels more discernable from the background
- Use the same drag and drop behavior for layers list as for the objects list on the scene editor
- Add object icons in the list of objects in a group
2022-10-27 10:23:05 +02:00
AlexandreS
6a13940e17 Add possibility to send instances to back or to front (Z order) in context menu (#4443) 2022-10-27 09:47:54 +02:00
AlexandreS
622aa7c08c Add warning message when updating liluo.io thumbnail from the project icons dialog (#4438) 2022-10-26 11:52:49 +02:00
Clément Pasteau
a71558a490 Create condition to know when a draggable object was just dropped (#4441) 2022-10-26 09:31:14 +02:00
Clément Pasteau
37539aa788 Rename Panel actions for consistency (#4439) 2022-10-25 18:45:23 +02:00
AlexandreS
789f819f25 Fix events sheet not wrapping on small screens (#4434) 2022-10-25 10:43:27 +02:00
AlexandreS
52ebfb8100 Remove starting value in tween variable actions
Also:
- Change phrasing for object tweens
2022-10-25 08:53:37 +02:00
Clément Pasteau
ecc5c689d2 Revert service worker update (#4432)
Do not show in changelog
2022-10-24 18:48:30 +02:00
Florian Rival
5b1e169557 Show variables that were used in the events, but not defined, in the autocompletions by default
* If you've not activated this since this was introduced, you can do so in the preferences.
2022-10-24 17:43:30 +02:00
Clément Pasteau
386e23b042 Bump version to 5.1.148 (#4429) 2022-10-24 12:11:18 +02:00
github-actions[bot]
fc76bafc7c Update translations [skip ci] (#4393)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-10-24 12:11:00 +02:00
AlexandreS
de53f4df4f Fix project name not updating in recent project files after saving (#4428) 2022-10-24 12:02:16 +02:00
D8H
9fedf124db Allow assets to declare extension dependencies without behaviors (#4354) 2022-10-22 14:40:47 +02:00
Clément Pasteau
2c68bb4bdd Modify the asset store to handle priced asset packs 2022-10-21 18:16:38 +02:00
AlexandreS
2360cf899f Performance optimization: Prevent pixi from rendering if any dialog is opened (#4415) 2022-10-21 15:01:04 +02:00
AlexandreS
3fc57c2b06 Add some particle emitter actions conditions and expressions (#4419)
- Max number of displayed particles
- Particle rotation min and max speeds
- Additive rendering setting
2022-10-21 14:04:44 +02:00
AlexandreS
b4f41e96ae Fix: Set line particle emitter origin at 0 to prevent rotation offset (#4421) 2022-10-21 12:29:09 +02:00
AlexandreS
b20108ddcb Fix particle emitter incoherent rotation speed of the particles (#4417) 2022-10-21 12:28:09 +02:00
AlexandreS
a58b039994 Update instance properties panel after a layer was created or renamed (#4420) 2022-10-21 12:13:57 +02:00
D8H
a7f218622e Add a button to export custom objects for the asset store (#4363)
* Don't show in changelog
2022-10-21 11:38:32 +02:00
AlexandreS
8d95eb4269 Fix: Ensure particle max force is not zero to prevent PIXI bug (#4418) 2022-10-20 18:20:27 +02:00
AlexandreS
4e46690418 Create homemade solution to display in app tutorials (#4394)
Do not show in changelog
2022-10-20 15:39:12 +02:00
Florian Rival
db1737281e Add word wrap in the code editors to avoid horizontal scrolling (#4413)
* Also fix some text overflowing out of the screen for some languages.

Fix #4412
2022-10-19 14:38:57 +02:00
AlexandreS
d5eecda570 Improve new scrollbars on scene editor canvas (#4411)
Do not show in changelog
2022-10-19 11:22:07 +02:00
D8H
80cb6d697c Handle custom objects at runtime (#4294)
* Don't show in changelog
2022-10-18 13:36:48 +02:00
Clément Pasteau
6b08fec747 Add missing translation for pasting an object (#4408) 2022-10-18 12:31:00 +02:00
D8H
2c92ce74ce Fix custom object configurations copy constructor (#4404)
* Don't show in changelog
2022-10-17 16:26:27 +02:00
D8H
30643ced07 Add some stories for event-based objects (#4401)
* Don't show in changelog
2022-10-16 23:57:18 +02:00
Peter Anderson
bf27761cff Fix grammar: change 'let' to 'leave'. (#4399) 2022-10-16 13:43:14 +02:00
Florian Rival
58df3aeca1 Show an error message if a sentence of a function of an extension is using a parameter that does not exist (#4395) 2022-10-14 23:15:30 +02:00
AlexandreS
69f8961e9e Fix: Keep variable name checks only for top level variables (#4392) 2022-10-14 15:57:59 +02:00
github-actions[bot]
1abb39ec17 Update translations [skip ci] (#4360)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-10-14 14:31:07 +02:00
Clément Pasteau
c5226c1e45 Fix clearing storage provider on project close (#4390)
Do not show in changelog
2022-10-14 14:06:02 +02:00
Florian Rival
d40789005b Add link to Liluo.io in the README
Don't show in changelog
2022-10-13 18:24:02 +02:00
D8H
fcbe5c364e Add a field to define behavior property descriptions (#4389) 2022-10-13 15:38:09 +02:00
D8H
df3433c55f Add autocompletion for timers, tweens and other extensions identifiers (#4386) 2022-10-13 13:39:53 +02:00
D8H
7d892fd976 Update extension field hints to fit the good practices (#4375) 2022-10-13 13:19:51 +02:00
D8H
56320d7253 Move some stories to LayoutEditor and ObjectEditor (#4388)
* Add a story for a custom object property editor.
* Add a story for the particle emitter editor.
2022-10-13 09:51:49 +02:00
AlexandreS
05acd061bd Fix leaderboard entry creation duplicate conditions to avoid spamming servers 2022-10-12 18:03:01 +02:00
Clément Pasteau
7991ceb351 Improve the editor scrollbars to be more intuitive (#4377) 2022-10-12 16:35:27 +02:00
Clément Pasteau
bf6d18ccbe Notify when a new version is available to be automatically installed on the web (#4371) 2022-10-12 16:31:58 +02:00
AlexandreS
536b7dcc62 Fix: Wrap text of game feedback when it's a single really long word 2022-10-12 11:45:51 +02:00
AlexandreS
a157f32d4a Fix: Update window border in scene editor when the project resolution is changed 2022-10-12 11:02:37 +02:00
Clément Pasteau
49f579f32d Allow using private assets in the asset store (#4355)
* Once a pack is bought, the assets are visible in the asset store directly
* The asset can be added when the project is saved locally, or on the cloud
* Fix Storage Provider being correctly reset when closing/opening a project
2022-10-11 13:59:40 +02:00
Clément Pasteau
8f4ecd373f Get Game categories from backend allowing more flexibility for jams (#4370)
Do not show in changelog
2022-10-07 18:32:33 +02:00
Aurélien Vivet
a3a53415b1 Add missing id for the onboarding (#4369)
Don't show in changelog
2022-10-07 15:49:13 +02:00
Aurélien Vivet
c278c0a432 Fix parameters order in the events sheet sentence of "Change the gradient of the text" action (#4368) 2022-10-07 10:40:39 +02:00
AlexandreS
862f270b83 Fix extension icon store displaying white hard-to-see icons on light theme 2022-10-07 09:56:55 +02:00
AlexandreS
7232dbc2fa Fix: Reinitialize object default hitboxes when reinitializing it (#4362) 2022-10-06 17:38:39 +02:00
AlexandreS
78cbe48718 Fix points editor not updating correctly when deleting points 2022-10-06 12:40:04 +02:00
Florian Rival
e153d295de Bump newIDE version 2022-10-06 10:35:33 +02:00
AlexandreS
1b8510655e Revert "Add expression and condition to get highest z order of a layer (#4346)" (#4359)
Don't show in changelog
2022-10-06 10:34:41 +02:00
github-actions[bot]
bd88127563 Update translations [skip ci] (#4342)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-10-06 10:25:39 +02:00
AlexandreS
01b9f09604 Fix: Add parameter to file reading actions to remove CR characters from files (#4352)
⚠️ If you had encountered an issue linked to this and changed your events to fix it, you might need to update your project and set this new parameter to "No"
2022-10-05 14:11:21 +02:00
Florian Rival
0db30f02c9 Add support for opening onboarding directly on the web-app
https://editor.gdevelop.io/?initial-dialog=onboarding

Don't show in changelog
2022-10-04 16:03:12 +02:00
D8H
a852e91690 Add missing expression group icons (#4353) 2022-10-04 14:56:59 +02:00
AlexandreS
79d6281061 Add expression and condition to get highest z order of a layer (#4346) 2022-10-04 14:31:49 +02:00
AlexandreS
eba6b2540c Add price to assets home private asset packs thumbnails and display them in their dialog (#4350)
Don't show in changelog
2022-10-04 12:13:25 +02:00
D8H
0706a54305 Reorganize extensions categories (#4345) 2022-10-04 10:37:27 +02:00
D8H
d929fd6e48 Add a test on sprite hit-boxes after a camera displacement (#4349)
* Don't show in changelog
2022-10-03 14:17:01 +02:00
Florian Rival
4dbabab052 Bump newIDE version 2022-09-30 15:43:18 +02:00
D8H
827c5d6442 Add an extension category filter (#4341) 2022-09-30 15:14:23 +02:00
Florian Rival
46be0e0ffc Change previews so that they use the development environment for GDevelop APIs if running GDevelop development version (#4343)
Only show in developer changelog
2022-09-30 14:55:50 +02:00
github-actions[bot]
72e3cf5b99 Update translations (#4313) 2022-09-30 10:12:34 +02:00
D8H
54f32a2542 Add new categories for extensions (#4331) 2022-09-29 18:24:06 +02:00
D8H
b826f66455 Make the custom object renderer works better with 9-patch and text child-objects (#4335)
* Don't show in changelogs.
2022-09-29 17:16:41 +02:00
D8H
6fc03cccc6 Add help buttons in the expression editor and the extension details dialog (#4337) 2022-09-29 15:44:16 +02:00
AlexandreS
ed7313a330 Add invert condition shortcut (J key by default - configurable in your preferences) (#4334) 2022-09-29 11:18:33 +02:00
D8H
7390f7cd6a Ensure required behavior properties can't be hidden (#4336) 2022-09-29 09:54:01 +02:00
D8H
4619ae824b Allow event-based objects to define a default name for created objects (#4329)
* Don't show in changelogs
2022-09-28 17:43:51 +02:00
D8H
0f69ee435f Add tests on behavior properties initialization and unserialization (#4314)
* Don't show in changelogs
2022-09-28 17:43:18 +02:00
AlexandreS
f46241d5a2 Fix bug that prevented converting a variable to JSON when one previously tried to access an out-of-index child in a variable array (#4333) 2022-09-28 17:39:53 +02:00
D8H
4c8ec48004 Add subsections for extensions categories in the Wiki (#4332)
* Add a warning message on pages for extensions from the community list.
2022-09-28 15:34:03 +02:00
AlexandreS
3ac121be4c Add asset packs that can be purchased in the Asset store home (#4328)
Do not show in changelog
2022-09-28 15:29:45 +02:00
D8H
3aa636861c Custom objects take the icon of one of their sprite child (#4316)
* Don't show in changelogs.
2022-09-27 16:19:12 +02:00
D8H
6d4b422be6 Fix extension description links on the Wiki (#4325) 2022-09-27 16:18:18 +02:00
Clément Pasteau
b8ee27f62c Improve player authentication
* Improve player authentication by indicating when the game is not registered
* Show a link to open the window if blocked

Do not show in changelog
2022-09-27 15:19:06 +02:00
AlexandreS
6996ff452d Fix various memory leaks when using the app (#4323) 2022-09-23 18:34:34 +02:00
AlexandreS
da7934c6ac Add context menu items to manipulate the view on the scene editor (#4307)
- Return to initial position (view matches the game resolution)
- Fit zoom to selected instances
- Fit zoom to the whole scene
- Select all instances of an object on the scene (in the context menu of an object)
2022-09-23 13:27:40 +02:00
Clément Pasteau
90bebcb404 Create GDevelop Authentication extension
* This is an experimental extension!
* It allows you to provide a login/register form to your players, with 1 action
* It connects the player automatically when they launch your game again
* It also provides a new action to submit a leaderboard entry without having to enter a username
* This is the beginning of Player Authentication and more features will come allowing creators to interact with their players
2022-09-23 10:44:58 +02:00
D8H
a29e7aae44 Bump newIDE version (#4317) 2022-09-22 12:22:11 +02:00
D8H
52201e2a36 Fix tiles rotation that was no longer applied in tile maps (#4315) 2022-09-22 10:25:38 +02:00
Florian Rival
50465badd7 Bump newIDE version 2022-09-21 10:01:17 +02:00
D8H
6e1bfb0190 Fix properties on the scene of the Physics behavior not working ("shared data" of behaviors not handled properly) (#4310) 2022-09-21 09:56:38 +02:00
Aurélien Vivet
40c7c57670 Add issue template for Asset Store Submission [skip ci] (#4309)
Don't show in changelog
2022-09-20 21:43:43 +02:00
github-actions[bot]
e51c73b293 Update translations [skip ci] (#4306)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-09-19 11:16:17 +02:00
Florian Rival
29d5d5fe75 Bump newIDE version 2022-09-19 10:23:17 +02:00
AlexandreS
6e1f2c4eee Fix parameter fields being reset to their old value after being changed (#4308) 2022-09-19 09:28:50 +02:00
Florian Rival
2f2a89faf6 Use a purple heart instead of a red one to look less like an error
Don't show in changelog
2022-09-16 12:23:15 +02:00
AlexandreS
4100b24dfd Improve display of black icons on dark themes (#4302) 2022-09-16 12:22:11 +02:00
AlexandreS
c616abe1c5 Bump newIDE version 2022-09-16 10:45:10 +02:00
Aurélien Vivet
35084de4f6 Add a new expression: Pi number (3.1415...) (#4304) 2022-09-16 10:30:46 +02:00
github-actions[bot]
6ecb5e9d8c Update translations [skip ci] (#4291)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-09-16 10:09:03 +02:00
D8H
9532a8f6de Fix extension upgrades that was leaving duplicated behaviors. (#4301)
- Don't show in changelogs (the regression is between the 140 and the 141)
2022-09-15 15:43:28 +02:00
D8H
00a5b0b402 Fix events-based behavior default name. (#4300)
* Don't show in changelogs (the regression is between the 140 and the 141)
2022-09-15 11:57:28 +02:00
D8H
629567ad21 Fix tile maps with rectangular tiles (#4299) 2022-09-14 19:04:42 +02:00
D8H
5f21229ccc Remove a file commited by mistake (#4296) 2022-09-14 18:40:48 +02:00
Florian Rival
27cf2ef596 Remove shadow on home page menu buttons
Don't show in changelog
2022-09-14 16:44:47 +02:00
AlexandreS
2bc9a6d19d Fix previews on private navigation for cloud projects
Do not show in changelog
2022-09-14 16:29:15 +02:00
655 changed files with 26167 additions and 11255 deletions

View File

@@ -0,0 +1,19 @@
---
name: "📦 Asset Store submission"
about: Submit a free asset pack for the GDevelop Asset Store.
title: ''
labels: "📦 Asset Store submission"
assignees: ''
---
BEFORE opening a new submission, please make sure that you:
- You have packaged the asset pack according [these rules](https://wiki.gdevelop.io/gdevelop5/community/contribute-to-the-assets-store). Otherwise, your package may be rejected or we will ask you to do the changes.
## Description
- License:
- Author:
- Link to the original website:
- Zip file:

View File

@@ -43,7 +43,7 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
std::size_t relationalOperatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "relationalOperator")
if (instrInfos.parameters[i].GetType() == "relationalOperator")
relationalOperatorIndex = i;
}
// Ensure that there is at least one parameter after the relational operator
@@ -95,7 +95,7 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -164,7 +164,7 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -215,7 +215,7 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -293,7 +293,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
// Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString();
@@ -303,11 +303,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -485,7 +485,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
@@ -493,11 +493,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -679,21 +679,21 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
supplementaryParametersTypes) {
gd::String argOutput;
if (ParameterMetadata::IsExpression("number", metadata.type)) {
if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "number", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("string", metadata.type)) {
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "string", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("variable", metadata.type)) {
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, metadata.type, parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.type)) {
*this, context, metadata.GetType(), parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.GetType())) {
// It would be possible to run a gd::ExpressionCodeGenerator if later
// objects can have nested objects, or function returning objects.
argOutput =
GenerateObject(parameter.GetPlainString(), metadata.type, context);
} else if (metadata.type == "relationalOperator") {
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context);
} else if (metadata.GetType() == "relationalOperator") {
auto parameterString = parameter.GetPlainString();
argOutput += parameterString == "=" ? "==" : parameterString;
if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
@@ -703,7 +703,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
}
argOutput = "\"" + argOutput + "\"";
} else if (metadata.type == "operator") {
} else if (metadata.GetType() == "operator") {
argOutput += parameter.GetPlainString();
if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
argOutput != "/" && argOutput != "*") {
@@ -712,28 +712,28 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
}
argOutput = "\"" + argOutput + "\"";
} else if (ParameterMetadata::IsBehavior(metadata.type)) {
} else if (ParameterMetadata::IsBehavior(metadata.GetType())) {
argOutput = GenerateGetBehaviorNameCode(parameter.GetPlainString());
} else if (metadata.type == "key") {
} else if (metadata.GetType() == "key") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.type == "audioResource" ||
metadata.type == "bitmapFontResource" ||
metadata.type == "fontResource" ||
metadata.type == "imageResource" ||
metadata.type == "jsonResource" ||
metadata.type == "videoResource" ||
} else if (metadata.GetType() == "audioResource" ||
metadata.GetType() == "bitmapFontResource" ||
metadata.GetType() == "fontResource" ||
metadata.GetType() == "imageResource" ||
metadata.GetType() == "jsonResource" ||
metadata.GetType() == "videoResource" ||
// Deprecated, old parameter names:
metadata.type == "password" || metadata.type == "musicfile" ||
metadata.type == "soundfile" || metadata.type == "police") {
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.type == "mouse") {
} else if (metadata.GetType() == "mouse") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.type == "yesorno") {
} else if (metadata.GetType() == "yesorno") {
auto parameterString = parameter.GetPlainString();
argOutput += (parameterString == "yes" || parameterString == "oui")
? GenerateTrue()
: GenerateFalse();
} else if (metadata.type == "trueorfalse") {
} else if (metadata.GetType() == "trueorfalse") {
auto parameterString = parameter.GetPlainString();
// This is duplicated in AdvancedExtension.cpp for GDJS
argOutput += (parameterString == "True" || parameterString == "Vrai")
@@ -741,21 +741,21 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
: GenerateFalse();
}
// Code only parameter type
else if (metadata.type == "inlineCode") {
argOutput += metadata.supplementaryInformation;
else if (metadata.GetType() == "inlineCode") {
argOutput += metadata.GetExtraInfo();
} else {
// Try supplementary types if provided
if (supplementaryParametersTypes) {
for (std::size_t i = 0; i < supplementaryParametersTypes->size(); ++i) {
if ((*supplementaryParametersTypes)[i].first == metadata.type)
if ((*supplementaryParametersTypes)[i].first == metadata.GetType())
argOutput += (*supplementaryParametersTypes)[i].second;
}
}
// Type unknown
if (argOutput.empty()) {
if (!metadata.type.empty())
cout << "Warning: Unknown type of parameter \"" << metadata.type
if (!metadata.GetType().empty())
cout << "Warning: Unknown type of parameter \"" << metadata.GetType()
<< "\"." << std::endl;
argOutput += "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
}
@@ -1030,7 +1030,7 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
for (std::size_t i = 0; i < instrInfos.parameters.size();
++i) // Some conditions already have a "conditionInverted" parameter
{
if (instrInfos.parameters[i].type == "conditionInverted")
if (instrInfos.parameters[i].GetType() == "conditionInverted")
conditionAlreadyTakeCareOfInversion = true;
}
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
@@ -1051,7 +1051,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call
// Add a static_cast if necessary
gd::String objectFunctionCallNamePart =
(!instrInfos.parameters[0].supplementaryInformation.empty())
(!instrInfos.parameters[0].GetExtraInfo().empty())
? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName

View File

@@ -184,8 +184,8 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
for (std::size_t j = 0;
j < parameters.size() && j < metadata.parameters.size();
++j) {
if (metadata.parameters[j].type == "relationalOperator" ||
metadata.parameters[j].type == "operator") {
if (metadata.parameters[j].GetType() == "relationalOperator" ||
metadata.parameters[j].GetType() == "operator") {
if (j == parameters.size() - 1) {
std::cout << "ERROR: No more parameters after a [relational]operator "
"when trying to update an instruction from GD2.x";

View File

@@ -36,8 +36,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the X position of the object."),
_("the X position"),
_("Position"),
"res/conditions/position24.png",
"res/conditions/position.png")
"res/conditions/position24_black.png",
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
@@ -48,8 +48,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the X position of an object."),
_("the X position"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
@@ -60,8 +60,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the Y position of an object."),
_("the Y position"),
_("Position"),
"res/conditions/position24.png",
"res/conditions/position.png")
"res/conditions/position24_black.png",
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
@@ -72,8 +72,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the Y position of an object."),
_("the Y position"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
@@ -85,8 +85,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the position of _PARAM0_: _PARAM1_ _PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"), "number")
@@ -102,8 +102,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"_PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position/Center"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("X position"))
@@ -118,7 +118,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the X position of the center of rotation"),
_("the X position of the center"),
_("Position/Center"),
"res/actions/position24.png")
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -129,7 +129,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the Y position of the center of rotation"),
_("the Y position of the center"),
_("Position/Center"),
"res/actions/position24.png")
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -140,7 +140,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) left position"),
_("the bounding box left position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-left.svg")
"res/conditions/bounding-box-left_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -151,7 +151,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating the object) top position"),
_("the bounding box top position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-top.svg")
"res/conditions/bounding-box-top_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -162,7 +162,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) right position"),
_("the bounding box right position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-right.svg")
"res/conditions/bounding-box-right_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -173,7 +173,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) bottom position"),
_("the bounding box bottom position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-bottom.svg")
"res/conditions/bounding-box-bottom_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -184,7 +184,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) center X position"),
_("the bounding box center X position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center.svg")
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -195,7 +195,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) center Y position"),
_("the bounding box center Y position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center.svg")
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
@@ -222,8 +222,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the angle of rotation of an object (in degrees)."),
_("the angle"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/direction24_black.png",
"res/actions/direction_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number");
@@ -234,8 +234,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"counterclockwise otherwise."),
_("Rotate _PARAM0_ at speed _PARAM1_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
@@ -248,8 +248,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Rotate an object towards an angle with the specified speed."),
_("Rotate _PARAM0_ towards _PARAM1_ at speed _PARAM2_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle to rotate towards (in degrees)"))
@@ -264,8 +264,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Rotate _PARAM0_ towards _PARAM1_;_PARAM2_ at speed "
"_PARAM3_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
@@ -512,8 +512,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the angle of the specified object."),
_("the angle (in degrees)"),
_("Angle"),
"res/conditions/direction24.png",
"res/conditions/direction.png")
"res/conditions/direction24_black.png",
"res/conditions/direction_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
@@ -886,7 +886,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("expression", _("Time in seconds"))
.SetHidden();
@@ -900,7 +900,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetManipulatedType("number");
@@ -913,7 +913,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timerPaused24.png",
"res/conditions/timerPaused.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction(
@@ -926,7 +926,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddAction("PauseObjectTimer",
_("Pause an object timer"),
@@ -936,7 +936,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/pauseTimer24.png",
"res/actions/pauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction("UnPauseObjectTimer",
@@ -947,7 +947,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/unPauseTimer24.png",
"res/actions/unPauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction("RemoveObjectTimer",
@@ -958,28 +958,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddExpression("X",
_("X position"),
_("X position of the object"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Y",
_("Y position"),
_("Y position of the object"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Angle",
_("Angle"),
_("Current angle, in degrees, of the object"),
_("Angle"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("ForceX",
@@ -1022,14 +1022,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Width"),
_("Width of the object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Largeur",
_("Width"),
_("Width of the object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.SetHidden();
@@ -1037,14 +1037,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Height"),
_("Height of the object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Hauteur",
_("Height"),
_("Height of the object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.SetHidden();
@@ -1127,7 +1127,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Object timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddExpression("AngleToObject",
_("Angle between two objects"),
@@ -1135,7 +1135,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"If you need the angle to an arbitrary position, "
"use AngleToPosition."),
_("Angle"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Object"));
@@ -1146,7 +1146,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
@@ -1158,7 +1158,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
@@ -1169,7 +1169,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"\"target\" position (in degrees). If you need the angle "
"between two objects, use AngleToObject."),
_("Angle"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Target X position"))
.AddParameter("expression", _("Target Y position"));
@@ -1565,7 +1565,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Object name"),
_("Return the name of the object"),
"",
"res/conditions/text.png")
"res/conditions/text_black.png")
.AddParameter("object", _("Object"));
obj.AddStrExpression("Layer",

View File

@@ -22,6 +22,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"object or a position.",
"Florian Rival",
"Open source (MIT License)")
.SetCategory("Camera")
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png");

View File

@@ -21,14 +21,14 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/common-conversions");
extension.AddInstructionOrExpressionGroupMetadata(_("Conversion"))
.SetIcon("res/conditions/toujours24.png");
.SetIcon("res/conditions/toujours24_black.png");
extension
.AddExpression("ToNumber",
_("Text > Number"),
_("Convert the text to a number"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text to convert to a number"));
extension
@@ -36,7 +36,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Number > Text"),
_("Convert the result of the expression to text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Expression to be converted to text"));
extension
@@ -45,7 +45,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert the result of the expression to text, "
"without using the scientific notation"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Expression to be converted to text"));
extension
@@ -54,7 +54,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Degrees > Radians"),
_("Converts the angle, expressed in degrees, into radians"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Angle, in degrees"));
extension
@@ -63,7 +63,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Radians > Degrees"),
_("Converts the angle, expressed in radians, into degrees"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Angle, in radians"));
extension
@@ -71,7 +71,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert scene variable to JSON"),
_("Convert a scene variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("scenevar", _("Scene variable to be stringified"));
extension
@@ -79,7 +79,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert global variable to JSON"),
_("Convert a global variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("globalvar", _("The global variable to be stringified"));
extension
@@ -87,7 +87,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert object variable to JSON"),
_("Convert an object variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));

View File

@@ -33,7 +33,7 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.SetExtensionHelpPath("/all-features/advanced-conditions");
extension
.AddInstructionOrExpressionGroupMetadata(_("Events and control flow"))
.SetIcon("res/conditions/toujours24.png");
.SetIcon("res/conditions/toujours24_black.png");
extension
.AddCondition("Always",
@@ -42,8 +42,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"the condition is inverted)."),
_("Always"),
"",
"res/conditions/toujours24.png",
"res/conditions/toujours.png")
"res/conditions/toujours24_black.png",
"res/conditions/toujours_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced();
@@ -61,8 +61,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Check if one of the sub conditions is true"),
_("If one of these conditions is true:"),
"",
"res/conditions/or24.png",
"res/conditions/or.png")
"res/conditions/or24_black.png",
"res/conditions/or_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -72,8 +72,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Check if all sub conditions are true"),
_("If all of these conditions are true:"),
"",
"res/conditions/and24.png",
"res/conditions/and.png")
"res/conditions/and24_black.png",
"res/conditions/and_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -84,8 +84,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Return the contrary of the result of the sub conditions"),
_("Invert the logical result of these conditions:"),
"",
"res/conditions/not24.png",
"res/conditions/not.png")
"res/conditions/not24_black.png",
"res/conditions/not_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -104,8 +104,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Compare the two numbers."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24.png",
"res/conditions/egal.png")
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("expression", _("First expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "number")
@@ -125,8 +125,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Compare the two strings."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24.png",
"res/conditions/egal.png")
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "string")

View File

@@ -21,7 +21,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/storage")
.SetCategory("Device");
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Storage"))
.SetIcon("res/conditions/fichier24.png");

View File

@@ -485,6 +485,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
extension
.AddExpression("Pi",
_("Number Pi (3.1415...)"),
_("The number Pi (3.1415...)"),
"",
"res/mathfunction.png")
.SetHelpPath("/all-features/expressions");
}
} // namespace gd

View File

@@ -22,6 +22,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/sprite");
extension.AddInstructionOrExpressionGroupMetadata(_("Sprite"))
.SetIcon("CppPlatform/Extensions/spriteicon.png");
gd::ObjectMetadata& obj =
extension
@@ -79,8 +81,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"is in 8 directions mode, the valid directions are 0..7"),
_("the direction"),
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/direction24_black.png",
"res/actions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite")
@@ -140,8 +142,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Rotate an object towards a position.",
"Rotate _PARAM0_ towards _PARAM1_;_PARAM2_",
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object to be rotated"), "Sprite")
.AddParameter("expression", _("X position"))
@@ -156,8 +158,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the specified object."),
_("the scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
@@ -168,8 +170,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the width of an object."),
_("the width's scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
@@ -180,8 +182,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the height of an object."),
_("the height's scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
@@ -192,8 +194,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the width of a Sprite object."),
_("the width"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
@@ -204,8 +206,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the width of a Sprite object."),
_("the width"),
_("Size"),
"res/conditions/scaleWidth24.png",
"res/conditions/scaleWidth.png")
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
@@ -216,8 +218,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the height of a Sprite object."),
_("the height"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
@@ -228,8 +230,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the height of a Sprite object."),
_("the height"),
_("Size"),
"res/conditions/scaleHeight24.png",
"res/conditions/scaleHeight.png")
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
@@ -240,8 +242,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the size of an object."),
_("Change the size of _PARAM0_: set to _PARAM1_x_PARAM2_"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Width"))
@@ -281,8 +283,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"from 0 to 7. Otherwise, the direction is in degrees."),
_("the direction"),
_("Direction"),
"res/conditions/direction24.png",
"res/conditions/direction.png")
"res/conditions/direction24_black.png",
"res/conditions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite")
@@ -330,8 +332,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the scale of the width of an object."),
_("the width's scale"),
_("Size"),
"res/conditions/scaleWidth24.png",
"res/conditions/scaleWidth.png")
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
@@ -342,8 +344,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the scale of the height of an object."),
_("the height's scale"),
_("Size"),
"res/conditions/scaleHeight24.png",
"res/conditions/scaleHeight.png")
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
@@ -449,8 +451,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Rotate an object towards another.",
"Rotate _PARAM0_ towards _PARAM1_",
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPtr", "Rotate toward this object")
@@ -461,7 +463,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("X position of a point"),
_("X position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"), "", true);
@@ -470,7 +472,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Y position of a point"),
_("Y position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"), "", true);
@@ -479,7 +481,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("X position of a point"),
_("X position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
@@ -488,7 +490,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Y position of a point"),
_("Y position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
@@ -497,7 +499,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Direction"),
_("Direction of the object"),
_("Direction"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
@@ -505,7 +507,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Direction"),
_("Direction of the object"),
_("Direction"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite");
@@ -550,14 +552,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the width of an object"),
_("Scale of the width of an object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleY",
_("Scale of the height of an object"),
_("Scale of the height of an object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Opacity",

View File

@@ -21,20 +21,20 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
extension.AddInstructionOrExpressionGroupMetadata(_("Text manipulation"))
.SetIcon("res/actions/text24.png");
.SetIcon("res/actions/text24_black.png");
extension.AddStrExpression("NewLine",
_("Insert a new line"),
_("Insert a new line"),
"",
"res/conditions/toujours24.png");
"res/conditions/toujours24_black.png");
extension
.AddStrExpression("FromCodePoint",
_("Get character from code point"),
_("Get character from code point"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Code point"));
@@ -43,7 +43,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Uppercase a text"),
_("Uppercase a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -52,7 +52,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Lowercase a text"),
_("Lowercase a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -61,7 +61,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Get a portion of a text"),
_("Get a portion of a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("expression",
@@ -74,7 +74,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Get a character from a text"),
_("Get a character from a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter(
@@ -86,7 +86,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Repeat a text"),
_("Repeat a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text to repeat"))
.AddParameter("expression", _("Repetition count"));
@@ -96,7 +96,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Length of a text"),
_("Length of a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -106,7 +106,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Search in a text (return the position of the result or "
"-1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"));
@@ -117,7 +117,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Search in a text from the end (return the position of "
"the result or -1 if not found)",
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -131,7 +131,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"the result, from the beginning of the string, or -1 if not "
"found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"));
@@ -142,7 +142,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Search in a text, starting from a position (return the "
"position of the result or -1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -157,7 +157,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Search in a text from the end, starting from a position (return "
"the position of the result or -1 if not found)",
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -175,7 +175,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
" the position of the result, from the beginning of the string, or "
"-1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))

View File

@@ -36,7 +36,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Time in seconds"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.SetHidden();
extension
@@ -50,7 +50,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetManipulatedType("number");
@@ -78,7 +78,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timerPaused24.png",
"res/conditions/timerPaused.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -93,7 +93,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
extension
.AddAction("PauseTimer",
@@ -105,7 +105,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/pauseTimer24.png",
"res/actions/pauseTimer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -118,7 +118,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/unPauseTimer24.png",
"res/actions/unPauseTimer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -131,7 +131,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -153,8 +153,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"the next actions (and sub-events)."),
_("Wait _PARAM0_ seconds"),
"",
"res/timer.svg",
"res/timer.svg")
"res/timer_black.svg",
"res/timer_black.svg")
.AddParameter("expression", "Time to wait in seconds")
.SetHelpPath("/all-features/timers-and-time/wait-action");
@@ -191,7 +191,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"",
"res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
extension
.AddExpression("TimeFromStart",

View File

@@ -20,6 +20,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
"these features can be applied.",
"Florian Rival",
"Open source (MIT License)")
.SetCategory("User interface")
.SetExtensionHelpPath("/all-features/window");
extension
.AddInstructionOrExpressionGroupMetadata(

View File

@@ -21,7 +21,7 @@ namespace gd {
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace_,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
@@ -45,32 +45,32 @@ BehaviorMetadata::BehaviorMetadata(
gd::LogFatalError(
"Trying to create a BehaviorMetadata that has no "
"behavior. This will crash - please double check that the "
"BehaviorMetadata is valid for: " + name_);
"BehaviorMetadata is valid for: " + nameWithNamespace);
}
if (instance) instance->SetTypeName(name_);
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(name_);
if (instance) instance->SetTypeName(nameWithNamespace);
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(nameWithNamespace);
}
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon24x24_): BehaviorMetadata(
extensionNamespace,
name_,
nameWithNamespace,
fullname_,
// Default name is the name
name_,
defaultName_,
description_,
group_,
icon24x24_,
// Class name is the name, actually unused
name_,
defaultName_,
// It is only used to get the name for GetName.
gd::make_unique<gd::Behavior>("", name_),
gd::make_unique<gd::Behavior>("", nameWithNamespace),
nullptr){
isEventBased = true;
};

View File

@@ -29,7 +29,7 @@ class GD_CORE_API BehaviorMetadata {
public:
BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
@@ -46,8 +46,9 @@ class GD_CORE_API BehaviorMetadata {
*/
BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon24x24_);

View File

@@ -37,22 +37,24 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
gd::ParameterMetadata info;
info.type = type;
info.SetType(type);
info.description = description;
info.codeOnly = false;
info.optional = parameterIsOptional;
info.supplementaryInformation =
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: supplementaryInformation; // Otherwise don't change anything
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -64,9 +66,9 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation) {
gd::ParameterMetadata info;
info.type = type;
info.SetType(type);
info.codeOnly = true;
info.supplementaryInformation = supplementaryInformation;
info.SetExtraInfo(supplementaryInformation);
parameters.push_back(info);
return *this;

View File

@@ -222,6 +222,18 @@ class GD_CORE_API ExpressionMetadata {
return *this;
};
/**
* \brief Set the additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter), for the last added parameter.
*
* \see AddParameter
*/
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
/**
* \brief Mark this (object) expression as requiring the specified capability,
* offered by the base object.
@@ -256,7 +268,30 @@ class GD_CORE_API ExpressionMetadata {
*/
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
return codeExtraInformation;
};
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
}
ExpressionCodeGenerationInformation codeExtraInformation;

View File

@@ -55,15 +55,17 @@ InstructionMetadata& InstructionMetadata::AddParameter(
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
ParameterMetadata info;
info.type = type;
info.SetType(type);
info.description = description;
info.codeOnly = false;
info.optional = parameterIsOptional;
info.supplementaryInformation =
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
@@ -71,7 +73,7 @@ InstructionMetadata& InstructionMetadata::AddParameter(
// extension
// namespace.
)
: supplementaryInformation; // Otherwise don't change anything
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -83,17 +85,19 @@ InstructionMetadata& InstructionMetadata::AddParameter(
InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation) {
ParameterMetadata info;
info.type = type;
info.SetType(type);
info.codeOnly = true;
info.supplementaryInformation = supplementaryInformation;
info.SetExtraInfo(supplementaryInformation);
parameters.push_back(info);
return *this;
}
InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
const gd::String& type, const gd::String& typeExtraInfo) {
const gd::String& expressionValueType =
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
SetManipulatedType(expressionValueType);
if (type == "boolean") {
AddParameter("yesorno", _("New value"));
@@ -117,8 +121,8 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
"_PARAM" + gd::String::From(valueParamIndex) + "_");
}
} else {
AddParameter("operator", _("Modification's sign"), type);
AddParameter(type == "number" ? "expression" : type, _("Value"));
AddParameter("operator", _("Modification's sign"), expressionValueType);
AddParameter(type, _("Value"), typeExtraInfo);
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
@@ -151,8 +155,10 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
InstructionMetadata&
InstructionMetadata::UseStandardRelationalOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
const gd::String& type, const gd::String& typeExtraInfo) {
const gd::String& expressionValueType =
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
SetManipulatedType(expressionValueType);
if (type == "boolean") {
if (isObjectInstruction || isBehaviorInstruction) {
@@ -168,8 +174,8 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
templateSentence.FindAndReplace("<subject>", sentence);
}
} else {
AddParameter("relationalOperator", _("Sign of the test"), type);
AddParameter(type == "number" ? "expression" : type, _("Value to compare"));
AddParameter("relationalOperator", _("Sign of the test"), expressionValueType);
AddParameter(type, _("Value to compare"), typeExtraInfo);
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;

View File

@@ -206,7 +206,7 @@ class GD_CORE_API InstructionMetadata {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
};
}
/**
* \brief Set the additional information, used for some parameters
@@ -218,20 +218,26 @@ class GD_CORE_API InstructionMetadata {
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
};
}
/**
* \brief Add the default parameters for an instruction manipulating the
* specified type ("string", "number") with the default operators.
*
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardOperatorParameters(const gd::String &type);
InstructionMetadata &UseStandardOperatorParameters(const gd::String &type, const gd::String& typeExtraInfo = "");
/**
* \brief Add the default parameters for an instruction comparing the
* specified type ("string", "number") with the default relational operators.
*
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardRelationalOperatorParameters(
const gd::String &type);
const gd::String &type, const gd::String& typeExtraInfo = "");
/**
* \brief Mark the instruction as an object instruction. Automatically called
@@ -276,7 +282,7 @@ class GD_CORE_API InstructionMetadata {
*/
const gd::String &GetRequiredBaseObjectCapability() const {
return requiredBaseObjectCapability;
};
}
/**
* \brief Consider that the instruction is easy for a user to understand.
@@ -361,7 +367,7 @@ class GD_CORE_API InstructionMetadata {
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text.png");
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
@@ -487,6 +493,29 @@ class GD_CORE_API InstructionMetadata {
return codeExtraInformation.SetAsyncFunctionName(functionName);
}
/**
* \brief Erase any existing include file and add the specified include.
*/
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
};
std::vector<ParameterMetadata> parameters;
private:

View File

@@ -80,6 +80,16 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
};
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
MultipleInstructionMetadata &SetParameterExtraInfo(const gd::String &defaultValue) {
if (expression) expression->SetParameterExtraInfo(defaultValue);
if (condition) condition->SetParameterExtraInfo(defaultValue);
if (action) action->SetParameterExtraInfo(defaultValue);
return *this;
};
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
@@ -116,9 +126,9 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::UseStandardOperatorParameters
* \see gd::InstructionMetadata::UseStandardRelationalOperatorParameters
*/
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type) {
if (condition) condition->UseStandardRelationalOperatorParameters(type);
if (action) action->UseStandardOperatorParameters(type);
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type, const gd::String& typeExtraInfo = "") {
if (condition) condition->UseStandardRelationalOperatorParameters(type, typeExtraInfo);
if (action) action->UseStandardOperatorParameters(type, typeExtraInfo);
return *this;
}
@@ -154,6 +164,34 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
if (expression)
return expression->GetCodeExtraInformation().GetIncludeFiles();
if (condition)
return condition->GetCodeExtraInformation().GetIncludeFiles();
if (action)
return action->GetCodeExtraInformation().GetIncludeFiles();
// It can't actually happen.
throw std::logic_error("no instruction metadata");
}
/**
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
MultipleInstructionMetadata &SetPrivate() {
if (expression)
expression->SetPrivate();
if (condition)
condition->SetPrivate();
if (action)
action->SetPrivate();
return *this;
}
/**
* \see gd::InstructionMetadata::MarkAsSimple
*/

View File

@@ -10,12 +10,10 @@
namespace gd {
ParameterMetadata::ParameterMetadata() : optional(false), codeOnly(false) {}
ParameterMetadata::ParameterMetadata() : codeOnly(false) {}
void ParameterMetadata::SerializeTo(SerializerElement& element) const {
element.SetAttribute("type", type);
element.SetAttribute("supplementaryInformation", supplementaryInformation);
element.SetAttribute("optional", optional);
valueTypeMetadata.SerializeTo(element);
element.SetAttribute("description", description);
element.SetAttribute("longDescription", longDescription);
element.SetAttribute("codeOnly", codeOnly);
@@ -24,10 +22,7 @@ void ParameterMetadata::SerializeTo(SerializerElement& element) const {
}
void ParameterMetadata::UnserializeFrom(const SerializerElement& element) {
type = element.GetStringAttribute("type");
supplementaryInformation =
element.GetStringAttribute("supplementaryInformation");
optional = element.GetBoolAttribute("optional");
valueTypeMetadata.UnserializeFrom(element);
description = element.GetStringAttribute("description");
longDescription = element.GetStringAttribute("longDescription");
codeOnly = element.GetBoolAttribute("codeOnly");
@@ -35,18 +30,4 @@ void ParameterMetadata::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("name");
}
// TODO factorize in a file with an enum and helpers?
const gd::String ParameterMetadata::numberType = "number";
const gd::String ParameterMetadata::stringType = "string";
const gd::String &ParameterMetadata::GetExpressionValueType(const gd::String &parameterType) {
if (parameterType == "number" || gd::ParameterMetadata::IsExpression("number", parameterType)) {
return ParameterMetadata::numberType;
}
if (parameterType == "string" || gd::ParameterMetadata::IsExpression("string", parameterType)) {
return ParameterMetadata::stringType;
}
return parameterType;
}
} // namespace gd

View File

@@ -6,16 +6,13 @@
#ifndef PARAMETER_METADATA_H
#define PARAMETER_METADATA_H
#if defined(GD_IDE_ONLY)
#include <map>
#include <memory>
#include "GDCore/String.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
namespace gd {
class Project;
class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
} // namespace gd
@@ -32,17 +29,32 @@ class GD_CORE_API ParameterMetadata {
ParameterMetadata();
virtual ~ParameterMetadata(){};
/**
* \brief Return the metadata of the parameter type.
*/
gd::ValueTypeMetadata &GetValueTypeMetadata() { return valueTypeMetadata; }
/**
* \brief Set the metadata of the parameter type.
*/
ParameterMetadata &SetValueTypeMetadata(const gd::ValueTypeMetadata &valueTypeMetadata_) {
valueTypeMetadata = valueTypeMetadata_;
return *this;
}
/**
* \brief Return the type of the parameter.
* \see gd::ParameterMetadata::IsObject
* \deprecated Use gd::ValueTypeMetadata instead.
*/
const gd::String &GetType() const { return type; }
const gd::String &GetType() const { return valueTypeMetadata.GetName(); }
/**
* \brief Set the type of the parameter.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetType(const gd::String &type_) {
type = type_;
valueTypeMetadata.SetName(type_);
return *this;
}
@@ -71,29 +83,33 @@ class GD_CORE_API ParameterMetadata {
* \brief Return an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
* \deprecated Use gd::ValueTypeMetadata instead.
*/
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
const gd::String &GetExtraInfo() const { return valueTypeMetadata.GetExtraInfo(); }
/**
* \brief Set an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
supplementaryInformation = supplementaryInformation_;
valueTypeMetadata.SetExtraInfo(supplementaryInformation_);
return *this;
}
/**
* \brief Return true if the parameter is optional.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
bool IsOptional() const { return optional; }
bool IsOptional() const { return valueTypeMetadata.IsOptional(); }
/**
* \brief Set if the parameter is optional.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetOptional(bool optional_ = true) {
optional = optional_;
valueTypeMetadata.SetOptional(optional_);
return *this;
}
@@ -151,26 +167,27 @@ class GD_CORE_API ParameterMetadata {
return *this;
}
// TODO Remove these deprecated functions.
/**
* \brief Return true if the type of the parameter is representing one object
* (or more, i.e: an object group).
*
* \see gd::ParameterMetadata::GetType
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListOrEmptyIfJustDeclared" ||
parameterType == "objectListOrEmptyWithoutPicking";
return gd::ValueTypeMetadata::IsTypeObject(parameterType);
}
/**
* \brief Return true if the type of the parameter is "behavior".
*
* \see gd::ParameterMetadata::GetType
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsBehavior(const gd::String &parameterType) {
return parameterType == "behavior";
return gd::ValueTypeMetadata::IsTypeBehavior(parameterType);
}
/**
@@ -179,42 +196,22 @@ class GD_CORE_API ParameterMetadata {
* \note If you had a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsExpression(const gd::String &type,
const gd::String &parameterType) {
if (type == "number") {
return parameterType == "expression" || parameterType == "camera" ||
parameterType == "forceMultiplier";
} else if (type == "string") {
return parameterType == "string" || parameterType == "layer" ||
parameterType == "color" || parameterType == "file" ||
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||
parameterType == "layerEffectParameterName" ||
parameterType == "objectEffectName" ||
parameterType == "objectEffectParameterName" ||
parameterType == "objectPointName" ||
parameterType == "objectAnimationName" ||
parameterType == "functionParameterName" ||
parameterType == "externalLayoutName" ||
parameterType == "leaderboardId";
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
}
return false;
return gd::ValueTypeMetadata::IsTypeExpression(type, parameterType);
}
/**
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static const gd::String &GetExpressionValueType(const gd::String &parameterType);
static const gd::String numberType;
static const gd::String stringType;
static const gd::String &GetExpressionValueType(const gd::String &parameterType) {
return gd::ValueTypeMetadata::GetPrimitiveValueType(parameterType);
}
/** \name Serialization
*/
@@ -232,14 +229,12 @@ class GD_CORE_API ParameterMetadata {
// TODO: Deprecated public fields. Any direct usage should be moved to
// getter/setter.
gd::String type; ///< Parameter type
gd::String supplementaryInformation; ///< Used if needed
bool optional; ///< True if the parameter is optional
gd::String description; ///< Description shown in editor
bool codeOnly; ///< True if parameter is relative to code generation only,
///< i.e. must not be shown in editor
private:
gd::ValueTypeMetadata valueTypeMetadata; ///< Parameter type
gd::String longDescription; ///< Long description shown in the editor.
gd::String defaultValue; ///< Used as a default value in editor or if an
///< optional parameter is empty.
@@ -249,5 +244,4 @@ class GD_CORE_API ParameterMetadata {
} // namespace gd
#endif
#endif // PARAMETER_METADATA_H

View File

@@ -85,7 +85,7 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
const gd::Expression& parameterValue =
pNb < parameters.size() ? parameters[pNb].GetPlainString() : "";
const gd::Expression& parameterValueOrDefault =
parameterValue.GetPlainString().empty() && parameterMetadata.optional
parameterValue.GetPlainString().empty() && parameterMetadata.IsOptional()
? Expression(parameterMetadata.GetDefaultValue())
: parameterValue;

View File

@@ -0,0 +1,49 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ValueTypeMetadata.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
ValueTypeMetadata::ValueTypeMetadata() : optional(false) {}
void ValueTypeMetadata::SerializeTo(SerializerElement& element) const {
element.SetAttribute("type", name);
if (!supplementaryInformation.empty()) {
element.SetAttribute("supplementaryInformation", supplementaryInformation);
}
if (optional) {
element.SetAttribute("optional", optional);
}
if (!defaultValue.empty()) {
element.SetAttribute("defaultValue", defaultValue);
}
}
void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("type");
supplementaryInformation =
element.GetStringAttribute("supplementaryInformation");
optional = element.GetBoolAttribute("optional");
defaultValue = element.GetStringAttribute("defaultValue");
}
const gd::String ValueTypeMetadata::numberType = "number";
const gd::String ValueTypeMetadata::stringType = "string";
const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String &parameterType) {
if (parameterType == "number" || gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
return ValueTypeMetadata::numberType;
}
if (parameterType == "string" || gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
return ValueTypeMetadata::stringType;
}
return parameterType;
}
} // namespace gd

View File

@@ -0,0 +1,219 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef VALUE_TYPE_METADATA_H
#define VALUE_TYPE_METADATA_H
#include <map>
#include <memory>
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
} // namespace gd
namespace gd {
/**
* \brief Define a type for parameters of a function (action, condition or
* expression) or the returned value of an expression.
*
* \see gd::EventsFunction
* \ingroup Events
*/
class GD_CORE_API ValueTypeMetadata {
public:
ValueTypeMetadata();
virtual ~ValueTypeMetadata(){};
/**
* \brief Return the string representation of the type.
*/
const gd::String &GetName() const { return name; }
/**
* \brief Set the string representation of the type.
*/
ValueTypeMetadata &SetName(const gd::String &name_) {
name = name_;
return *this;
}
/**
* \brief Return an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
/**
* \brief Set an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
ValueTypeMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
supplementaryInformation = supplementaryInformation_;
return *this;
}
/**
* \brief Return true if the parameter is optional.
*/
bool IsOptional() const { return optional; }
/**
* \brief Set if the parameter is optional.
*/
ValueTypeMetadata &SetOptional(bool optional_ = true) {
optional = optional_;
return *this;
}
/**
* \brief Get the default value for the parameter.
*/
const gd::String &GetDefaultValue() const { return defaultValue; }
/**
* \brief Set the default value, if the parameter is optional.
*/
ValueTypeMetadata &SetDefaultValue(const gd::String &defaultValue_) {
defaultValue = defaultValue_;
return *this;
}
/**
* \brief Return true if the type is defined.
*/
bool IsDefined() const {
return !name.empty();
}
/**
* \brief Return true if the type is representing one object
* (or more, i.e: an object group).
*/
bool IsObject() const {
return gd::ValueTypeMetadata::IsTypeObject(name);
}
/**
* \brief Return true if the type is "behavior".
*/
bool IsBehavior() const {
return gd::ValueTypeMetadata::IsTypeBehavior(name);
}
/**
* \brief Return true if the type is an expression of the
* given type.
*/
bool IsNumber() const {
return gd::ValueTypeMetadata::IsTypeExpression("number", name);
}
/**
* \brief Return true if the type is a string.
*/
bool IsString() const {
return gd::ValueTypeMetadata::IsTypeExpression("string", name);
}
/**
* \brief Return true if the type of the parameter is a number.
* \note If you had a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
*/
bool IsVariable() const {
return gd::ValueTypeMetadata::IsTypeExpression("variable", name);
}
/**
* \brief Return true if the type is representing one object
* (or more, i.e: an object group).
*/
static bool IsTypeObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListOrEmptyIfJustDeclared" ||
parameterType == "objectListOrEmptyWithoutPicking";
}
/**
* \brief Return true if the type is "behavior".
*/
static bool IsTypeBehavior(const gd::String &parameterType) {
return parameterType == "behavior";
}
/**
* \brief Return true if the type is an expression of the given type.
* \note If you are adding a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
*/
static bool IsTypeExpression(const gd::String &type,
const gd::String &parameterType) {
if (type == "number") {
return parameterType == "number" || parameterType == "expression" ||
parameterType == "camera" || parameterType == "forceMultiplier";
} else if (type == "string") {
return parameterType == "string" || parameterType == "layer" ||
parameterType == "color" || parameterType == "file" ||
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||
parameterType == "layerEffectParameterName" ||
parameterType == "objectEffectName" ||
parameterType == "objectEffectParameterName" ||
parameterType == "objectPointName" ||
parameterType == "objectAnimationName" ||
parameterType == "functionParameterName" ||
parameterType == "externalLayoutName" ||
parameterType == "leaderboardId" ||
parameterType == "identifier";
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
}
return false;
}
/**
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
*/
static const gd::String &GetPrimitiveValueType(const gd::String &parameterType);
static const gd::String numberType;
static const gd::String stringType;
/** \name Serialization
*/
///@{
/**
* \brief Serialize the ParameterMetadata to the specified element
*/
void SerializeTo(gd::SerializerElement &element) const;
/**
* \brief Load the ParameterMetadata from the specified element
*/
void UnserializeFrom(const gd::SerializerElement &element);
///@}
private:
gd::String name; ///< Parameter type
gd::String supplementaryInformation; ///< Used if needed
bool optional; ///< True if the parameter is optional
gd::String defaultValue; ///< Used as a default value in editor or if an
///< optional parameter is empty.
};
} // namespace gd
#endif // VALUE_TYPE_METADATA_H

View File

@@ -295,6 +295,8 @@ gd::BehaviorMetadata& PlatformExtension::AddEventsBasedBehavior(
behaviorsInfo[nameWithNamespace] = BehaviorMetadata(GetNameSpace(),
nameWithNamespace,
fullname,
// Default name is the name
name,
description,
group,
icon24x24)

View File

@@ -73,4 +73,54 @@ bool ArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
ReadOnlyArbitraryEventsWorker::~ReadOnlyArbitraryEventsWorker() {}
void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events) {
DoVisitEventList(events);
for (std::size_t i = 0; i < events.size(); ++i) {
VisitEvent(events[i]);
if (events[i].CanHaveSubEvents()) {
VisitEventList(events[i].GetSubEvents());
}
}
}
void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
DoVisitEvent(event);
const vector<const gd::InstructionsList*> conditionsVectors =
event.GetAllConditionsVectors();
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
VisitInstructionList(*conditionsVectors[j], true);
}
const vector<const gd::InstructionsList*> actionsVectors = event.GetAllActionsVectors();
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
VisitInstructionList(*actionsVectors[j], false);
}
}
void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
const gd::InstructionsList& instructions, bool areConditions) {
DoVisitInstructionList(instructions, areConditions);
for (std::size_t i = 0; i < instructions.size(); ++i) {
VisitInstruction(instructions[i], areConditions);
if (!instructions[i].GetSubInstructions().empty()) {
VisitInstructionList(instructions[i].GetSubInstructions(),
areConditions);
}
}
}
void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& instruction,
bool isCondition) {
DoVisitInstruction(instruction, isCondition);
}
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
} // namespace gd

View File

@@ -121,6 +121,101 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
const gd::ObjectsContainer* currentObjectsContainer;
};
/**
* \brief ReadOnlyArbitraryEventsWorker is an abstract class used to browse events (and
* instructions). It can be used to implement autocompletion for example.
*
* \see gd::ReadOnlyArbitraryEventsWorkerWithContext
*
* \ingroup IDE
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorker {
public:
ReadOnlyArbitraryEventsWorker(){};
virtual ~ReadOnlyArbitraryEventsWorker();
/**
* \brief Launch the worker on the specified events list.
*/
void Launch(const gd::EventsList& events) { VisitEventList(events); };
private:
void VisitEventList(const gd::EventsList& events);
void VisitEvent(const gd::BaseEvent& event);
void VisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions);
void VisitInstruction(const gd::Instruction& instruction, bool isCondition);
/**
* Called to do some work on an event list.
*/
virtual void DoVisitEventList(const gd::EventsList& events){};
/**
* Called to do some work on an event
*/
virtual void DoVisitEvent(const gd::BaseEvent& event) {};
/**
* Called to do some work on an instruction list
*/
virtual void DoVisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions){};
/**
* Called to do some work on an instruction.
*/
virtual void DoVisitInstruction(const gd::Instruction& instruction,
bool isCondition) {};
};
/**
* \brief An events worker that will know about the context (the objects
* container). Useful for workers working on expressions notably.
*
* \see gd::ReadOnlyArbitraryEventsWorker
*
* \ingroup IDE
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
: public ReadOnlyArbitraryEventsWorker {
public:
ReadOnlyArbitraryEventsWorkerWithContext()
: currentGlobalObjectsContainer(nullptr),
currentObjectsContainer(nullptr){};
virtual ~ReadOnlyArbitraryEventsWorkerWithContext();
/**
* \brief Launch the worker on the specified events list,
* giving the objects container on which the events are applying to.
*/
void Launch(const gd::EventsList& events,
const gd::ObjectsContainer& globalObjectsContainer_,
const gd::ObjectsContainer& objectsContainer_) {
currentGlobalObjectsContainer = &globalObjectsContainer_;
currentObjectsContainer = &objectsContainer_;
ReadOnlyArbitraryEventsWorker::Launch(events);
};
void Launch(gd::EventsList& events) = delete;
protected:
const gd::ObjectsContainer& GetGlobalObjectsContainer() {
// Pointers are guaranteed to be not nullptr after
// Launch was called.
return *currentGlobalObjectsContainer;
};
const gd::ObjectsContainer& GetObjectsContainer() {
// Pointers are guaranteed to be not nullptr after
// Launch was called.
return *currentObjectsContainer;
};
private:
const gd::ObjectsContainer* currentGlobalObjectsContainer;
const gd::ObjectsContainer* currentObjectsContainer;
};
} // namespace gd
#endif // GDCORE_ARBITRARYEVENTSWORKER_H

View File

@@ -120,7 +120,7 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.type;
const gd::String& type = parameterMetadata.GetType();
if (gd::ParameterMetadata::IsBehavior(type)) {
if (lastObjectName == objectName) {

View File

@@ -0,0 +1,254 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventsIdentifiersFinder.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/IDE/DependenciesAnalyzer.h"
using namespace std;
namespace gd {
namespace {
/**
* \brief Go through the nodes to search for identifier occurrences.
*
* \see gd::ExpressionParser2
*/
class GD_CORE_API IdentifierFinderExpressionNodeWorker
: public ExpressionParser2NodeWorker {
public:
IdentifierFinderExpressionNodeWorker(std::set<gd::String>& results_,
const gd::Platform &platform_,
const gd::ObjectsContainer &globalObjectsContainer_,
const gd::ObjectsContainer &objectsContainer_,
const gd::String& identifierType_,
const gd::String& objectName_ = "")
: results(results_),
platform(platform_),
globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_),
identifierType(identifierType_),
objectName(objectName_){};
virtual ~IdentifierFinderExpressionNodeWorker(){};
protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
node.expression->Visit(*this);
}
void OnVisitOperatorNode(OperatorNode& node) override {
node.leftHandSide->Visit(*this);
node.rightHandSide->Visit(*this);
}
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
node.factor->Visit(*this);
}
void OnVisitNumberNode(NumberNode& node) override {}
void OnVisitTextNode(TextNode& node) override {}
void OnVisitVariableNode(VariableNode& node) override {
if (node.child) node.child->Visit(*this);
}
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
if (node.child) node.child->Visit(*this);
}
void OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) override {
node.expression->Visit(*this);
if (node.child) node.child->Visit(*this);
}
void OnVisitIdentifierNode(IdentifierNode& node) override {}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
bool considerFunction = objectName.empty() || node.objectName == objectName;
const bool isObjectFunction = !node.objectName.empty();
const gd::ExpressionMetadata &metadata = isObjectFunction ?
MetadataProvider::GetObjectAnyExpressionMetadata(
platform,
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
node.functionName):
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
return;
}
size_t parameterIndex = 0;
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
auto& parameterMetadata = metadata.parameters[metadataIndex];
if (parameterMetadata.IsCodeOnly()) {
continue;
}
auto& parameterNode = node.parameters[parameterIndex];
++parameterIndex;
if (considerFunction && parameterMetadata.GetType() == "identifier"
&& parameterMetadata.GetExtraInfo() == identifierType) {
// Store the value of the parameter
results.insert(
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
} else {
parameterNode->Visit(*this);
}
}
}
void OnVisitEmptyNode(EmptyNode& node) override {}
private:
const gd::Platform &platform;
const gd::ObjectsContainer &globalObjectsContainer;
const gd::ObjectsContainer &objectsContainer;
std::set<gd::String>& results; ///< Reference to the std::set where argument
///< values must be stored.
gd::String identifierType; ///< The type of the parameters to be searched for.
gd::String objectName; ///< If not empty, parameters will be taken into
///< account only if related to this object.
};
/**
* \brief Go through the events to search for identifier occurrences.
*/
class GD_CORE_API IdentifierFinderEventWorker
: public ReadOnlyArbitraryEventsWorkerWithContext {
public:
IdentifierFinderEventWorker(std::set<gd::String>& results_,
const gd::Platform &platform_,
const gd::String& identifierType_,
const gd::String& objectName_ = "")
: results(results_),
platform(platform_),
identifierType(identifierType_),
objectName(objectName_){};
virtual ~IdentifierFinderEventWorker(){};
void DoVisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions) override {
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
auto& instruction = instructions[aId];
gd::String lastObjectParameter = "";
const gd::InstructionMetadata& instrInfos =
areConditions ? MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// The parameter has the searched type...
if (instrInfos.parameters[pNb].GetType() == "identifier"
&& instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
//...remember the value of the parameter.
if (objectName.empty() || lastObjectParameter == objectName) {
results.insert(instruction.GetParameter(pNb).GetPlainString());
}
}
// Search in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].GetType()) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].GetType())) {
auto node = instruction.GetParameter(pNb).GetRootNode();
IdentifierFinderExpressionNodeWorker searcher(
results,
platform,
GetGlobalObjectsContainer(),
GetObjectsContainer(),
identifierType,
objectName);
node->Visit(searcher);
}
// Remember the value of the last "object" parameter.
else if (gd::ParameterMetadata::IsObject(
instrInfos.parameters[pNb].GetType())) {
lastObjectParameter =
instruction.GetParameter(pNb).GetPlainString();
}
}
}
};
private:
const gd::Platform &platform;
std::set<gd::String>& results; ///< Reference to the std::set where argument
///< values must be stored.
gd::String identifierType; ///< The type of the parameters to be searched for.
gd::String objectName; ///< If not empty, parameters will be taken into
///< account only if related to this object.
};
} // namespace
std::set<gd::String> EventsIdentifiersFinder::FindAllIdentifierExpressions(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& identifierType,
const gd::String& contextObjectName) {
std::set<gd::String> results;
const bool isObjectIdentifier = identifierType.find("object") == 0;
// The object from the context is only relevent for object identifiers.
auto& actualObjectName = isObjectIdentifier ? contextObjectName : "";
FindArgumentsInEventsAndDependencies(
results,
platform,
project,
layout,
identifierType,
actualObjectName);
return results;
}
void EventsIdentifiersFinder::FindArgumentsInEventsAndDependencies(
std::set<gd::String>& results,
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& identifierType,
const gd::String& objectName) {
IdentifierFinderEventWorker eventWorker(results,
platform,
identifierType,
objectName);
eventWorker.Launch(layout.GetEvents(), project, layout);
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
dependenciesAnalyzer.Analyze();
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
IdentifierFinderEventWorker eventWorker(results,
platform,
identifierType,
objectName);
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
}
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
IdentifierFinderEventWorker eventWorker(results,
platform,
identifierType,
objectName);
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
}
}
} // namespace gd

View File

@@ -0,0 +1,81 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef EVENTSIDENTIFIERSFINDER_H
#define EVENTSIDENTIFIERSFINDER_H
#include <set>
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/String.h"
namespace gd {
class Instruction;
class Platform;
class Object;
class Project;
class Layout;
} // namespace gd
namespace gd {
/**
* \brief Perform a search over a layout, searching for layout or object custom
* identifiers.
*
* \todo Refactor this class using ArbitraryEventsWorker
*
* \ingroup IDE
*/
class EventsIdentifiersFinder {
public:
EventsIdentifiersFinder(){};
virtual ~EventsIdentifiersFinder(){};
/**
* Construct a list containing all the expressions for a given identifier used
* in the layout.
*
* \param project The project to use.
* \param layout The layout to use.
* \param identifierType The identifier type to be analyzed.
* \param objectName If not empty, parameters will be taken into account
* only if the last object parameter is filled with
* this value.
* \return A std::set containing the names of all identifiers used.
*/
static std::set<gd::String> FindAllIdentifierExpressions(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& identifierType,
const gd::String& objectName = "");
private:
/**
* Construct a list containing all the expressions for a given identifier used
* in the layout. It searches in events dependencies.
*
* \param results A std::set to fill with the expressions used for all parameters of the
* specified identifier type
* \param platform The platform of the project
* \param project The project to use.
* \param layout The layout to use.
* \param events The events to be analyzed
* \param identifierType The identifier type to be analyzed
* \param objectName If not empty, parameters will be taken into account
* only if the last object parameter is filled with
* this value.
*/
static void FindArgumentsInEventsAndDependencies(
std::set<gd::String>& results,
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& identifierType,
const gd::String& objectName = "");
};
} // namespace gd
#endif // EVENTSIDENTIFIERSFINDER_H

View File

@@ -30,7 +30,7 @@ bool EventsLeaderboardsLister::DoVisitInstruction(gd::Instruction& instruction,
for (int i = 0; i < instruction.GetParametersCount() &&
i < instrInfo.GetParametersCount();
++i)
if (instrInfo.GetParameter(i).type == "leaderboardId") {
if (instrInfo.GetParameter(i).GetType() == "leaderboardId") {
leaderboardIds.insert(instruction.GetParameter(i).GetPlainString());
}
return false;

View File

@@ -32,7 +32,7 @@ bool EventsLeaderboardsRenamer::DoVisitInstruction(gd::Instruction& instruction,
++i) {
const gd::ParameterMetadata parameter = instrInfo.GetParameter(i);
if (parameter.type == "leaderboardId") {
if (parameter.GetType() == "leaderboardId") {
const gd::String leaderboardId =
instruction.GetParameter(i).GetPlainString();

View File

@@ -237,12 +237,12 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Replace object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
actions[aId].GetParameter(pNb).GetPlainString() == oldName)
actions[aId].SetParameter(pNb, gd::Expression(newName));
// Replace object's name in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
"number", instrInfos.parameters[pNb].GetType())) {
auto node = actions[aId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
@@ -252,7 +252,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
}
// Replace object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
"string", instrInfos.parameters[pNb].GetType())) {
auto node = actions[aId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
@@ -291,12 +291,12 @@ bool EventsRefactorer::RenameObjectInConditions(
conditions[cId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Replace object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
conditions[cId].GetParameter(pNb).GetPlainString() == oldName)
conditions[cId].SetParameter(pNb, gd::Expression(newName));
// Replace object's name in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
"number", instrInfos.parameters[pNb].GetType())) {
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectRenamer::Rename(platform, project, layout, "number", *node, oldName, newName)) {
@@ -306,7 +306,7 @@ bool EventsRefactorer::RenameObjectInConditions(
}
// Replace object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
"string", instrInfos.parameters[pNb].GetType())) {
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectRenamer::Rename(platform, project, layout, "string", *node, oldName, newName)) {
@@ -425,14 +425,14 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Find object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
actions[aId].GetParameter(pNb).GetPlainString() == name) {
deleteMe = true;
break;
}
// Find object's name in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
"number", instrInfos.parameters[pNb].GetType())) {
auto node = actions[aId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
@@ -442,7 +442,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
}
// Find object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
"string", instrInfos.parameters[pNb].GetType())) {
auto node = actions[aId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {
@@ -485,14 +485,14 @@ bool EventsRefactorer::RemoveObjectInConditions(
conditions[cId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Find object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
conditions[cId].GetParameter(pNb).GetPlainString() == name) {
deleteMe = true;
break;
}
// Find object's name in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
"number", instrInfos.parameters[pNb].GetType())) {
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "number", *node, name)) {
@@ -502,7 +502,7 @@ bool EventsRefactorer::RemoveObjectInConditions(
}
// Find object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
"string", instrInfos.parameters[pNb].GetType())) {
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
if (ExpressionObjectFinder::CheckIfHasObject(platform, globalObjectsContainer, objectsContainer, "string", *node, name)) {

View File

@@ -13,6 +13,7 @@
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
@@ -22,28 +23,28 @@
using namespace std;
namespace gd {
namespace {
/**
* \brief Go through the nodes and change the given object name to a new one.
* \brief Go through the nodes to search for variable occurrences.
*
* \see gd::ExpressionParser2
*/
class GD_CORE_API ExpressionParameterSearcher
class GD_CORE_API VariableFinderExpressionNodeWorker
: public ExpressionParser2NodeWorker {
public:
ExpressionParameterSearcher(const gd::Platform &platform_,
VariableFinderExpressionNodeWorker(std::set<gd::String>& results_,
const gd::Platform &platform_,
const gd::ObjectsContainer &globalObjectsContainer_,
const gd::ObjectsContainer &objectsContainer_,
std::set<gd::String>& results_,
const gd::String& parameterType_,
const gd::String& objectName_ = "")
: platform(platform_),
: results(results_),
platform(platform_),
globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_),
results(results_),
parameterType(parameterType_),
objectName(objectName_){};
virtual ~ExpressionParameterSearcher(){};
virtual ~VariableFinderExpressionNodeWorker(){};
protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
@@ -74,27 +75,34 @@ class GD_CORE_API ExpressionParameterSearcher
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
bool considerFunction = objectName.empty() || node.objectName == objectName;
const gd::ExpressionMetadata &metadata = node.objectName.empty() ?
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName) :
const bool isObjectFunction = !node.objectName.empty();
const gd::ExpressionMetadata &metadata = isObjectFunction ?
MetadataProvider::GetObjectAnyExpressionMetadata(
platform,
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName),
node.functionName);
node.functionName):
MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
return;
}
for (size_t i = 0; i < node.parameters.size() &&
i < metadata.parameters.size();
++i) {
auto& parameterMetadata = metadata.parameters[i];
size_t parameterIndex = 0;
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
auto& parameterMetadata = metadata.parameters[metadataIndex];
if (parameterMetadata.IsCodeOnly()) {
continue;
}
auto& parameterNode = node.parameters[parameterIndex];
++parameterIndex;
if (considerFunction && parameterMetadata.GetType() == parameterType) {
// Store the value of the parameter
results.insert(
gd::ExpressionParser2NodePrinter::PrintNode(*node.parameters[i]));
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode));
} else {
node.parameters[i]->Visit(*this);
parameterNode->Visit(*this);
}
}
}
@@ -112,18 +120,87 @@ class GD_CORE_API ExpressionParameterSearcher
///< account only if related to this object.
};
/**
* \brief Go through the events to search for variable occurrences.
*/
class GD_CORE_API VariableFinderEventWorker
: public ReadOnlyArbitraryEventsWorkerWithContext {
public:
VariableFinderEventWorker(std::set<gd::String>& results_,
const gd::Platform &platform_,
const gd::String& parameterType_,
const gd::String& objectName_ = "")
: results(results_),
platform(platform_),
parameterType(parameterType_),
objectName(objectName_){};
virtual ~VariableFinderEventWorker(){};
void DoVisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions) override {
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
auto& instruction = instructions[aId];
gd::String lastObjectParameter = "";
const gd::InstructionMetadata& instrInfos =
areConditions ? MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// The parameter has the searched type...
if (instrInfos.parameters[pNb].GetType() == parameterType) {
//...remember the value of the parameter.
if (objectName.empty() || lastObjectParameter == objectName)
results.insert(instruction.GetParameter(pNb).GetPlainString());
}
// Search in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].GetType()) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].GetType())) {
auto node = instruction.GetParameter(pNb).GetRootNode();
VariableFinderExpressionNodeWorker searcher(
results,
platform,
GetGlobalObjectsContainer(),
GetObjectsContainer(),
parameterType,
objectName);
node->Visit(searcher);
}
// Remember the value of the last "object" parameter.
else if (gd::ParameterMetadata::IsObject(
instrInfos.parameters[pNb].GetType())) {
lastObjectParameter =
instruction.GetParameter(pNb).GetPlainString();
}
}
}
};
private:
const gd::Platform &platform;
std::set<gd::String>& results; ///< Reference to the std::set where argument
///< values must be stored.
gd::String parameterType; ///< The type of the parameters to be searched for.
gd::String objectName; ///< If not empty, parameters will be taken into
///< account only if related to this object.
};
} // namespace
std::set<gd::String> EventsVariablesFinder::FindAllGlobalVariables(
const gd::Platform& platform, const gd::Project& project) {
std::set<gd::String> results;
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
std::set<gd::String> results2 =
FindArgumentsInEventsAndDependencies(
FindArgumentsInEventsAndDependencies(
results,
platform,
project,
project.GetLayout(i),
"globalvar");
results.insert(results2.begin(), results2.end());
}
return results;
@@ -135,9 +212,12 @@ std::set<gd::String> EventsVariablesFinder::FindAllLayoutVariables(
const gd::Layout& layout) {
std::set<gd::String> results;
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
platform, project, layout, "scenevar");
results.insert(results2.begin(), results2.end());
FindArgumentsInEventsAndDependencies(
results,
platform,
project,
layout,
"scenevar");
return results;
}
@@ -149,159 +229,51 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
const gd::Object& object) {
std::set<gd::String> results;
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
FindArgumentsInEventsAndDependencies(
results,
platform,
project,
layout,
"objectvar",
object.GetName());
results.insert(results2.begin(), results2.end());
return results;
}
std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::InstructionsList& instructions,
bool instructionsAreConditions,
const gd::String& parameterType,
const gd::String& objectName) {
std::set<gd::String> results;
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
gd::String lastObjectParameter = "";
const gd::InstructionMetadata& instrInfos =
instructionsAreConditions ? MetadataProvider::GetConditionMetadata(
platform, instructions[aId].GetType())
: MetadataProvider::GetActionMetadata(
platform, instructions[aId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// The parameter has the searched type...
if (instrInfos.parameters[pNb].type == parameterType) {
//...remember the value of the parameter.
if (objectName.empty() || lastObjectParameter == objectName)
results.insert(instructions[aId].GetParameter(pNb).GetPlainString());
}
// Search in expressions
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
auto node = instructions[aId].GetParameter(pNb).GetRootNode();
ExpressionParameterSearcher searcher(
platform,
project,
layout,
results,
parameterType,
objectName);
node->Visit(searcher);
}
// Remember the value of the last "object" parameter.
else if (gd::ParameterMetadata::IsObject(
instrInfos.parameters[pNb].type)) {
lastObjectParameter =
instructions[aId].GetParameter(pNb).GetPlainString();
}
}
if (!instructions[aId].GetSubInstructions().empty())
FindArgumentsInInstructions(platform,
project,
layout,
instructions[aId].GetSubInstructions(),
instructionsAreConditions,
parameterType);
}
return results;
}
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
void EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
std::set<gd::String>& results,
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& parameterType,
const gd::String& objectName) {
std::set<gd::String> results;
std::set<gd::String> results2 = FindArgumentsInEvents(
platform, project, layout, layout.GetEvents(), parameterType, objectName);
results.insert(results2.begin(), results2.end());
VariableFinderEventWorker eventWorker(results,
platform,
parameterType,
objectName);
eventWorker.Launch(layout.GetEvents(), project, layout);
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
dependenciesAnalyzer.Analyze();
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
std::set<gd::String> results3 = FindArgumentsInEvents(
platform, project, layout, externalEvents.GetEvents(), parameterType, objectName);
results.insert(results3.begin(), results3.end());
VariableFinderEventWorker eventWorker(results,
platform,
parameterType,
objectName);
eventWorker.Launch(externalEvents.GetEvents(), project, layout);
}
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
std::set<gd::String> results3 = FindArgumentsInEvents(
platform, project, dependencyLayout, dependencyLayout.GetEvents(), parameterType, objectName);
results.insert(results3.begin(), results3.end());
VariableFinderEventWorker eventWorker(results,
platform,
parameterType,
objectName);
eventWorker.Launch(dependencyLayout.GetEvents(), project, dependencyLayout);
}
return results;
}
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEvents(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::EventsList& events,
const gd::String& parameterType,
const gd::String& objectName) {
std::set<gd::String> results;
for (std::size_t i = 0; i < events.size(); ++i) {
vector<const gd::InstructionsList*> conditionsVectors =
events[i].GetAllConditionsVectors();
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
std::set<gd::String> results2 =
FindArgumentsInInstructions(platform,
project,
layout,
*conditionsVectors[j],
/*conditions=*/true,
parameterType,
objectName);
results.insert(results2.begin(), results2.end());
}
vector<const gd::InstructionsList*> actionsVectors =
events[i].GetAllActionsVectors();
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
std::set<gd::String> results2 =
FindArgumentsInInstructions(platform,
project,
layout,
*actionsVectors[j],
/*conditions=*/false,
parameterType,
objectName);
results.insert(results2.begin(), results2.end());
}
if (events[i].CanHaveSubEvents()) {
std::set<gd::String> results2 =
FindArgumentsInEvents(platform,
project,
layout,
events[i].GetSubEvents(),
parameterType,
objectName);
results.insert(results2.begin(), results2.end());
}
}
return results;
}
} // namespace gd

View File

@@ -23,7 +23,6 @@ namespace gd {
* \brief Perform a search over a project or a layout, searching for layout,
* global or object variables.
*
* \todo Refactor this class using ArbitraryEventsWorker
* \todo Rework this class to return the shapes (maybe even types?) of the
* variables (in particular for structures and arrays), so we can use this
* for better autocompletions in the variables dialogs in the IDE.
@@ -74,34 +73,13 @@ class EventsVariablesFinder {
const gd::Object& object);
private:
/**
* Construct a list of the value of the arguments for parameters of type @
* parameterType
*
* \param project The project used
* \param project The layout used
* \param instructions The instructions to be analyzed
* \param instructionsAreConditions True if the instructions are conditions.
* \param parameterType The parameters type to be analyzed
* \param objectName If not empty, parameters will be taken into account only
* if the last object parameter is filled with this value.
*
* \return A std::set filled with the values used for all parameters of the
* specified type
*/
static std::set<gd::String> FindArgumentsInInstructions(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::InstructionsList& instructions,
bool instructionsAreConditions,
const gd::String& parameterType,
const gd::String& objectName = "");
/**
* Construct a list of the value of the arguments for parameters of type @
* parameterType. It searchs in events dependencies.
* parameterType. It searches in events dependencies.
*
* \param results A std::set to fill with the values used for all parameters of the
* specified type
* \param platform The platform of the project
* \param project The project used
* \param layout The layout used
@@ -110,40 +88,14 @@ class EventsVariablesFinder {
* \param objectName If not empty, parameters will be taken into account
* only if the last object parameter is filled with
* this value.
*
* \return A std::set filled with the values used for all parameters of the
* specified type
*/
static std::set<gd::String> FindArgumentsInEventsAndDependencies(
static void FindArgumentsInEventsAndDependencies(
std::set<gd::String>& results,
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::String& parameterType,
const gd::String& objectName = "");
/**
* Construct a list of the value of the arguments for parameters of type @
* parameterType. It doesn't search in events dependencies.
*
* \param platform The platform of the project
* \param project The project used
* \param layout The layout used
* \param events The events to be analyzed
* \param parameterType The parameters type to be analyzed
* \param objectName If not empty, parameters will be taken into account
* only if the last object parameter is filled with
* this value.
*
* \return A std::set filled with the values used for all parameters of the
* specified type
*/
static std::set<gd::String> FindArgumentsInEvents(
const gd::Platform& platform,
const gd::Project& project,
const gd::Layout& layout,
const gd::EventsList& events,
const gd::String& parameterType,
const gd::String& objectName);
};
} // namespace gd

View File

@@ -36,7 +36,7 @@ size_t GetMinimumParametersNumber(
size_t initialParameterIndex) {
size_t nb = 0;
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
if (!parameters[i].optional && !parameters[i].codeOnly) nb++;
if (!parameters[i].IsOptional() && !parameters[i].codeOnly) nb++;
}
return nb;

View File

@@ -150,7 +150,7 @@ bool ExpressionsParameterMover::DoVisitInstruction(gd::Instruction& instruction,
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
pNb < instruction.GetParametersCount();
++pNb) {
const gd::String& type = metadata.parameters[pNb].type;
const gd::String& type = metadata.parameters[pNb].GetType();
const gd::Expression& expression = instruction.GetParameter(pNb);
auto node = expression.GetRootNode();

View File

@@ -20,6 +20,7 @@ namespace gd {
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
const gd::Project& project,
const gd::EventsFunctionsContainer functionContainer,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer) {
@@ -31,8 +32,12 @@ void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
// to parameters
outputObjectsContainer.GetObjects().clear();
outputObjectsContainer.GetObjectGroups().Clear();
auto &parameters = eventsFunction.GetParametersForEvents(functionContainer);
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project, eventsFunction.GetParameters(), outputObjectsContainer);
project,
parameters,
outputObjectsContainer);
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
}
@@ -44,6 +49,7 @@ void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsBasedBehavior.GetEventsFunctions(),
eventsFunction,
outputGlobalObjectsContainer,
outputObjectsContainer);
@@ -81,6 +87,7 @@ void EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsBasedObject.GetEventsFunctions(),
eventsFunction,
outputGlobalObjectsContainer,
outputObjectsContainer);

View File

@@ -10,6 +10,7 @@
#include "GDCore/String.h"
namespace gd {
class Project;
class EventsFunctionsContainer;
class ObjectsContainer;
class ParameterMetadata;
class EventsFunction;
@@ -34,6 +35,7 @@ class GD_CORE_API EventsFunctionTools {
*/
static void FreeEventsFunctionToObjectsContainer(
const gd::Project& project,
const gd::EventsFunctionsContainer functionContainer,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer);

View File

@@ -5,6 +5,8 @@
*/
#include "ProjectStripper.h"
#include "GDCore/Project/EventsFunctionsContainer.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/ExternalLayout.h"
#include "GDCore/Project/Layout.h"
@@ -12,7 +14,7 @@
namespace gd {
void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project& project) {
void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project &project) {
project.GetObjectGroups().Clear();
while (project.GetExternalEventsCount() > 0)
project.RemoveExternalEvents(project.GetExternalEvents(0).GetName());
@@ -22,7 +24,28 @@ void GD_CORE_API ProjectStripper::StripProjectForExport(gd::Project& project) {
project.GetLayout(i).GetEvents().Clear();
}
project.ClearEventsFunctionsExtensions();
// Keep the EventsBasedObject object list because it's useful for the Runtime
// to create the child-object.
for (unsigned int extensionIndex = 0;
extensionIndex < project.GetEventsFunctionsExtensionsCount();
++extensionIndex) {
auto &extension = project.GetEventsFunctionsExtension(extensionIndex);
auto &eventsBasedObjects = extension.GetEventsBasedObjects();
if (eventsBasedObjects.size() == 0) {
project.RemoveEventsFunctionsExtension(extension.GetName());
extensionIndex--;
continue;
}
for (unsigned int objectIndex = 0; objectIndex < eventsBasedObjects.size();
++objectIndex) {
auto &eventsBasedObject = eventsBasedObjects.at(objectIndex);
eventsBasedObject.SetFullName("");
eventsBasedObject.SetDescription("");
eventsBasedObject.GetEventsFunctions().GetInternalVector().clear();
eventsBasedObject.GetPropertyDescriptors().GetInternalVector().clear();
}
extension.GetEventsBasedBehaviors().Clear();
}
}
} // namespace gd
} // namespace gd

View File

@@ -154,7 +154,11 @@ void WholeProjectRefactorer::ExposeProjectEvents(
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
project,
eventsFunctionsExtension,
*eventsFunction,
globalObjectsAndGroups,
objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(),
globalObjectsAndGroups,
@@ -334,8 +338,10 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
[&project, &oldName, &newName](
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction.IsExpression()) {
// Nothing to do, expressions are not including the extension name
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(oldName,
@@ -345,11 +351,6 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsBasedBehavior.GetName(),
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
// Nothing to do, expressions are not including the extension name
}
};
@@ -394,8 +395,10 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
[&project, &oldName, &newName](
const gd::EventsBasedObject& eventsBasedObject,
const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction.IsExpression()) {
// Nothing to do, expressions are not including the extension name
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(oldName,
@@ -405,11 +408,6 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsBasedObject.GetName(),
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
// Nothing to do, expressions are not including the extension name
}
};
@@ -456,9 +454,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
// Free expressions
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
eventsFunction->GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction->IsExpression()) {
renameEventsFunction(*eventsFunction);
}
}
@@ -467,9 +463,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
eventsFunction->GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction->IsExpression()) {
renameBehaviorEventsFunction(*eventsBasedBehavior, *eventsFunction);
}
}
@@ -477,8 +471,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
// Free instructions
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
renameEventsFunction(*eventsFunction);
}
}
@@ -488,8 +481,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
renameBehaviorEventsFunction(*eventsBasedBehavior, *eventsFunction);
}
}
@@ -510,8 +502,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
auto& objectEventsFunctions = eventsBasedObject->GetEventsFunctions();
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
renameObjectEventsFunction(*eventsBasedObject, *eventsFunction);
}
}
@@ -563,6 +554,16 @@ void WholeProjectRefactorer::RenameEventsFunction(
oldFunctionName),
GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
newFunctionName));
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
for (auto&& otherFunction : eventsFunctionsExtension.GetInternalVector())
{
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
otherFunction->GetGetterName() == oldFunctionName) {
otherFunction->SetGetterName(newFunctionName);
}
}
}
}
void WholeProjectRefactorer::RenameBehaviorEventsFunction(
@@ -577,8 +578,20 @@ void WholeProjectRefactorer::RenameBehaviorEventsFunction(
const gd::EventsFunction& eventsFunction =
eventsFunctions.GetEventsFunction(oldFunctionName);
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
// Order is important: we first rename the expressions then the instructions,
// to avoid being unable to fetch the metadata (the types of parameters) of
// instructions after they are renamed.
if (eventsFunction.IsExpression()) {
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
oldFunctionName,
newFunctionName);
ExposeProjectEvents(project, renamer);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
@@ -588,18 +601,15 @@ void WholeProjectRefactorer::RenameBehaviorEventsFunction(
eventsBasedBehavior.GetName(),
newFunctionName));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
oldFunctionName,
newFunctionName);
ExposeProjectEvents(project, renamer);
}
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
for (auto&& otherFunction : eventsBasedBehavior.GetEventsFunctions().GetInternalVector())
{
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
otherFunction->GetGetterName() == oldFunctionName) {
otherFunction->SetGetterName(newFunctionName);
}
}
}
}
@@ -615,8 +625,17 @@ void WholeProjectRefactorer::RenameObjectEventsFunction(
const gd::EventsFunction& eventsFunction =
eventsFunctions.GetEventsFunction(oldFunctionName);
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction.IsExpression()) {
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedObjectExpression(
GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()),
oldFunctionName,
newFunctionName);
ExposeProjectEvents(project, renamer);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
@@ -626,18 +645,15 @@ void WholeProjectRefactorer::RenameObjectEventsFunction(
eventsBasedObject.GetName(),
newFunctionName));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedObjectExpression(
GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()),
oldFunctionName,
newFunctionName);
ExposeProjectEvents(project, renamer);
}
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
for (auto&& otherFunction : eventsBasedObject.GetEventsFunctions().GetInternalVector())
{
if (otherFunction->GetFunctionType() == gd::EventsFunction::ActionWithOperator &&
otherFunction->GetGetterName() == oldFunctionName) {
otherFunction->SetGetterName(newFunctionName);
}
}
}
}
@@ -655,21 +671,22 @@ void WholeProjectRefactorer::MoveEventsFunctionParameter(
const gd::String& eventsFunctionType = GetEventsFunctionFullType(
eventsFunctionsExtension.GetName(), functionName);
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project, eventsFunctionType, oldIndex, newIndex);
ExposeProjectEvents(project, mover);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction.IsExpression()) {
gd::ExpressionsParameterMover mover =
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
mover.SetFreeExpressionMovedParameter(
eventsFunctionType, oldIndex, newIndex);
ExposeProjectEvents(project, mover);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project,
eventsFunctionType,
oldIndex + operatorIndexOffset,
newIndex + operatorIndexOffset);
ExposeProjectEvents(project, mover);
}
}
void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
@@ -690,15 +707,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
eventsBasedBehavior.GetName(),
functionName);
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project, eventsFunctionType, oldIndex, newIndex);
ExposeProjectEvents(project, mover);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction.IsExpression()) {
gd::ExpressionsParameterMover mover =
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
mover.SetBehaviorExpressionMovedParameter(
@@ -709,6 +718,15 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
newIndex);
ExposeProjectEvents(project, mover);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project,
eventsFunctionType,
oldIndex + operatorIndexOffset,
newIndex + operatorIndexOffset);
ExposeProjectEvents(project, mover);
}
}
void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
@@ -729,15 +747,7 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
eventsBasedObject.GetName(),
functionName);
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project, eventsFunctionType, oldIndex, newIndex);
ExposeProjectEvents(project, mover);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction.IsExpression()) {
gd::ExpressionsParameterMover mover =
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
mover.SetObjectExpressionMovedParameter(
@@ -748,6 +758,15 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
newIndex);
ExposeProjectEvents(project, mover);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
const int operatorIndexOffset = eventsFunction.IsExpression() ? 2 : 0;
gd::InstructionsParameterMover mover = gd::InstructionsParameterMover(
project,
eventsFunctionType,
oldIndex + operatorIndexOffset,
newIndex + operatorIndexOffset);
ExposeProjectEvents(project, mover);
}
}
void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
@@ -1088,8 +1107,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
&eventsFunctionsExtension,
&oldBehaviorName,
&newBehaviorName](const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction.IsExpression()) {
// Nothing to do, expressions are not including the name of the
// behavior
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
@@ -1101,12 +1123,6 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
newBehaviorName,
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
// Nothing to do, expressions are not including the name of the
// behavior
}
};
@@ -1151,17 +1167,14 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
// Behavior expressions
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
eventsFunction->GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction->IsExpression()) {
renameBehaviorEventsFunction(*eventsFunction);
}
}
// Behavior instructions
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
renameBehaviorEventsFunction(*eventsFunction);
}
}
@@ -1197,8 +1210,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
&eventsFunctionsExtension,
&oldObjectName,
&newObjectName](const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction.IsExpression()) {
// Nothing to do, expressions are not including the name of the
// object
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
@@ -1210,12 +1226,6 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
newObjectName,
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
// Nothing to do, expressions are not including the name of the
// object
}
};
@@ -1260,17 +1270,14 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
// Object expressions
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Expression ||
eventsFunction->GetFunctionType() ==
gd::EventsFunction::StringExpression) {
if (eventsFunction->IsExpression()) {
renameObjectEventsFunction(*eventsFunction);
}
}
// Object instructions
for (auto&& eventsFunction : objectEventsFunctions.GetInternalVector()) {
if (eventsFunction->GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction->GetFunctionType() == gd::EventsFunction::Condition) {
if (eventsFunction->IsAction() || eventsFunction->IsCondition()) {
renameObjectEventsFunction(*eventsFunction);
}
}
@@ -1292,20 +1299,20 @@ void WholeProjectRefactorer::DoRenameEventsFunction(
const gd::EventsFunction& eventsFunction,
const gd::String& oldFullType,
const gd::String& newFullType) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
eventsFunction.GetFunctionType() == gd::EventsFunction::Condition) {
gd::InstructionsTypeRenamer renamer =
gd::InstructionsTypeRenamer(project, oldFullType, newFullType);
ExposeProjectEvents(project, renamer);
} else if (eventsFunction.GetFunctionType() ==
gd::EventsFunction::Expression ||
eventsFunction.GetFunctionType() ==
gd::EventsFunction::StringExpression) {
// Order is important: we first rename the expressions then the instructions,
// to avoid being unable to fetch the metadata (the types of parameters) of
// instructions after they are renamed.
if (eventsFunction.IsExpression()) {
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedFreeExpression(oldFullType, newFullType);
ExposeProjectEvents(project, renamer);
}
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer =
gd::InstructionsTypeRenamer(project, oldFullType, newFullType);
ExposeProjectEvents(project, renamer);
}
}
void WholeProjectRefactorer::DoRenameBehavior(

View File

@@ -10,8 +10,10 @@
namespace gd {
AbstractEventsBasedEntity::AbstractEventsBasedEntity(const gd::String& _name)
: name(_name), fullName("") {}
AbstractEventsBasedEntity::AbstractEventsBasedEntity(
const gd::String& _name,
gd::EventsFunctionsContainer::FunctionOwner functionContainerSource)
: name(_name), fullName(""), eventsFunctionsContainer(functionContainerSource) {}
void AbstractEventsBasedEntity::SerializeTo(SerializerElement& element) const {
element.SetAttribute("description", description);

View File

@@ -29,7 +29,9 @@ namespace gd {
*/
class GD_CORE_API AbstractEventsBasedEntity {
public:
AbstractEventsBasedEntity(const gd::String& _name);
AbstractEventsBasedEntity(
const gd::String& _name,
gd::EventsFunctionsContainer::FunctionOwner functionContainerSource);
virtual ~AbstractEventsBasedEntity(){};
/**

View File

@@ -22,16 +22,14 @@ void CustomObjectConfiguration::Init(const gd::CustomObjectConfiguration& object
// There is no default copy for a map of unique_ptr like childObjectConfigurations.
childObjectConfigurations.clear();
for (auto& it : objectConfiguration.childObjectConfigurations) {
childObjectConfigurations[it.first] =
gd::make_unique<gd::ObjectConfiguration>(*it.second);
childObjectConfigurations[it.first] = it.second->Clone();
}
}
gd::ObjectConfiguration CustomObjectConfiguration::badObjectConfiguration;
std::unique_ptr<gd::ObjectConfiguration> CustomObjectConfiguration::Clone() const {
CustomObjectConfiguration* clone = new CustomObjectConfiguration(*this);
return std::unique_ptr<gd::ObjectConfiguration>(clone);
return gd::make_unique<gd::CustomObjectConfiguration>(*this);
}
gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(const gd::String &objectName) {
@@ -51,7 +49,7 @@ gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(
if (configurationPosition == childObjectConfigurations.end()) {
childObjectConfigurations.insert(std::make_pair(
objectName,
project->CreateObjectConfiguration(childObject.GetType())));
childObject.GetConfiguration().Clone()));
return *(childObjectConfigurations[objectName]);
}
else {

View File

@@ -110,6 +110,11 @@ class GD_CORE_API EffectsContainer {
*/
void UnserializeFrom(const SerializerElement& element);
/**
* \brief Clear all effects of the container.
*/
inline void Clear() { effects.clear(); }
private:
std::vector<std::shared_ptr<gd::Effect>> effects;
static Effect badEffect;

View File

@@ -11,7 +11,9 @@
namespace gd {
EventsBasedBehavior::EventsBasedBehavior()
: AbstractEventsBasedEntity("MyBehavior") {}
: AbstractEventsBasedEntity(
"MyBehavior",
gd::EventsFunctionsContainer::FunctionOwner::Behavior) {}
void EventsBasedBehavior::SerializeTo(SerializerElement& element) const {
AbstractEventsBasedEntity::SerializeTo(element);

View File

@@ -10,7 +10,10 @@
namespace gd {
EventsBasedObject::EventsBasedObject()
: AbstractEventsBasedEntity("MyObject"), ObjectsContainer() {
: AbstractEventsBasedEntity(
"MyObject",
gd::EventsFunctionsContainer::FunctionOwner::Object),
ObjectsContainer() {
}
EventsBasedObject::~EventsBasedObject() {}
@@ -23,12 +26,16 @@ EventsBasedObject::EventsBasedObject(const gd::EventsBasedObject &_eventBasedObj
}
void EventsBasedObject::SerializeTo(SerializerElement& element) const {
element.SetAttribute("defaultName", defaultName);
AbstractEventsBasedEntity::SerializeTo(element);
SerializeObjectsTo(element.AddChild("objects"));
}
void EventsBasedObject::UnserializeFrom(gd::Project& project,
const SerializerElement& element) {
defaultName = element.GetStringAttribute("defaultName");
AbstractEventsBasedEntity::UnserializeFrom(project, element);
UnserializeObjectsFrom(project, element.GetChild("objects"));
}

View File

@@ -38,6 +38,19 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
*/
EventsBasedObject* Clone() const { return new EventsBasedObject(*this); };
/**
* \brief Get the default name for created objects.
*/
const gd::String& GetDefaultName() const { return defaultName; };
/**
* \brief Set the default name for created objects.
*/
EventsBasedObject& SetDefaultName(const gd::String& defaultName_) {
defaultName = defaultName_;
return *this;
}
EventsBasedObject& SetDescription(const gd::String& description_) override {
AbstractEventsBasedEntity::SetDescription(description_);
return *this;
@@ -65,6 +78,7 @@ class GD_CORE_API EventsBasedObject: public AbstractEventsBasedEntity, public Ob
const SerializerElement& element) override;
private:
gd::String defaultName;
};
} // namespace gd

View File

@@ -7,10 +7,54 @@
#include "EventsFunction.h"
#include <vector>
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Project/EventsFunctionsContainer.h"
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
namespace gd {
EventsFunction::EventsFunction() : functionType(Action) {}
EventsFunction::EventsFunction() : functionType(Action) {
expressionType.SetName("expression");
}
const std::vector<gd::ParameterMetadata>& EventsFunction::GetParametersForEvents(
const gd::EventsFunctionsContainer& functionsContainer) const {
if (functionType != FunctionType::ActionWithOperator) {
// For most function types, the parameters are specified in the function.
return parameters;
}
// For ActionWithOperator, the parameters are auto generated.
actionWithOperationParameters.clear();
if (!functionsContainer.HasEventsFunctionNamed(getterName)) {
return actionWithOperationParameters;
}
const auto& expression = functionsContainer.GetEventsFunction(getterName);
const auto& expressionParameters = expression.parameters;
const auto functionsSource = functionsContainer.GetOwner();
const int expressionValueParameterIndex =
functionsSource == gd::EventsFunctionsContainer::FunctionOwner::Behavior ?
2 :
functionsSource == gd::EventsFunctionsContainer::FunctionOwner::Object ?
1 :
0;
for (size_t i = 0;
i < expressionValueParameterIndex && i < expressionParameters.size();
i++)
{
actionWithOperationParameters.push_back(expressionParameters[i]);
}
gd::ParameterMetadata parameterMetadata;
parameterMetadata.SetName("Value").SetValueTypeMetadata(expression.expressionType);
actionWithOperationParameters.push_back(parameterMetadata);
for (size_t i = expressionValueParameterIndex;
i < expressionParameters.size();
i++)
{
actionWithOperationParameters.push_back(expressionParameters[i]);
}
return actionWithOperationParameters;
}
void EventsFunction::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", name);
@@ -18,18 +62,33 @@ void EventsFunction::SerializeTo(SerializerElement& element) const {
element.SetAttribute("description", description);
element.SetAttribute("sentence", sentence);
element.SetAttribute("group", group);
element.SetAttribute("getterName", getterName);
element.SetBoolAttribute("private", isPrivate);
events.SerializeTo(element.AddChild("events"));
gd::String functionTypeStr = "Action";
if (functionType == Condition)
functionTypeStr = "Condition";
else if (functionType == Expression)
else if (functionType == Expression) {
functionTypeStr = "Expression";
else if (functionType == StringExpression)
functionTypeStr = "StringExpression";
// Compatibility code for version 5.1.147 and older.
// There is no longer distinction between number and string in the function
// type directly. The expression type is now used for this.
if (expressionType.IsString()) {
functionTypeStr = "StringExpression";
}
}
else if (functionType == ExpressionAndCondition) {
functionTypeStr = "ExpressionAndCondition";
}
else if (functionType == ActionWithOperator)
functionTypeStr = "ActionWithOperator";
element.SetAttribute("functionType", functionTypeStr);
if (this->IsExpression()) {
expressionType.SerializeTo(element.AddChild("expressionType"));
}
gd::SerializerElement& parametersElement = element.AddChild("parameters");
parametersElement.ConsiderAsArrayOf("parameter");
for (const auto& parameter : parameters) {
@@ -46,16 +105,32 @@ void EventsFunction::UnserializeFrom(gd::Project& project,
description = element.GetStringAttribute("description");
sentence = element.GetStringAttribute("sentence");
group = element.GetStringAttribute("group");
getterName = element.GetStringAttribute("getterName");
isPrivate = element.GetBoolAttribute("private");
events.UnserializeFrom(project, element.GetChild("events"));
gd::String functionTypeStr = element.GetStringAttribute("functionType");
if (functionTypeStr == "Condition")
functionType = Condition;
else if (functionTypeStr == "Expression")
else if (functionTypeStr == "Expression" || functionTypeStr == "StringExpression") {
functionType = Expression;
else if (functionTypeStr == "StringExpression")
functionType = StringExpression;
if (element.HasChild("expressionType")) {
expressionType.UnserializeFrom(element.GetChild("expressionType"));
}
else {
// Compatibility code for version 5.1.147 and older.
// There is no longer distinction between number and string in the function
// type directly. The expression type is now used for this.
expressionType.SetName(functionTypeStr == "StringExpression" ? "string" : "expression");
}
}
else if (functionTypeStr == "ExpressionAndCondition") {
functionType = ExpressionAndCondition;
expressionType.UnserializeFrom(element.GetChild("expressionType"));
}
else if (functionTypeStr == "ActionWithOperator")
functionType = ActionWithOperator;
else
functionType = Action;

View File

@@ -12,6 +12,7 @@
#include "GDCore/Events/EventsList.h"
#include "GDCore/Project/ObjectGroupsContainer.h"
#include "GDCore/String.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
// TODO: In theory (for separation of concerns between Project and
// extensions/events), this include should be removed and gd::ParameterMetadata
// replaced by a new gd::EventsFunctionParameter class.
@@ -19,6 +20,7 @@
namespace gd {
class SerializerElement;
class Project;
class EventsFunctionsContainer;
} // namespace gd
namespace gd {
@@ -115,7 +117,40 @@ class GD_CORE_API EventsFunction {
return *this;
}
enum FunctionType { Action, Condition, Expression, StringExpression };
/**
* \brief Get the name of the ExpressionAndCondition to use as an operand
* that is defined in the editor.
*/
const gd::String& GetGetterName() const { return getterName; };
/**
* \brief Set the name of the ExpressionAndCondition to use as an operand
* that is defined in the editor.
*/
EventsFunction& SetGetterName(const gd::String& getterName_) {
getterName = getterName_;
return *this;
}
/**
* \brief Set the type of the expression
*/
EventsFunction& SetExpressionType(const gd::ValueTypeMetadata& type) {
expressionType = type;
return *this;
}
/**
* \brief Get the type of the expression
*/
const gd::ValueTypeMetadata& GetExpressionType() const { return expressionType; }
enum FunctionType {
Action,
Condition,
Expression,
ExpressionAndCondition,
ActionWithOperator };
/**
* \brief Set the type of the function
@@ -123,12 +158,40 @@ class GD_CORE_API EventsFunction {
EventsFunction& SetFunctionType(FunctionType type) {
functionType = type;
return *this;
};
}
/**
* \brief Get the type of the function
*/
FunctionType GetFunctionType() const { return functionType; };
FunctionType GetFunctionType() const { return functionType; }
/**
* \brief Return true if the function is an action.
*/
bool IsAction() const {
return functionType == gd::EventsFunction::Action ||
functionType == gd::EventsFunction::ActionWithOperator;
}
/**
* \brief Return true if the function is an expression.
*
* Note that a function can be both an expression and a condition.
*/
bool IsExpression() const {
return functionType == gd::EventsFunction::Expression ||
functionType == gd::EventsFunction::ExpressionAndCondition;
}
/**
* \brief Return true if the function is a condition.
*
* Note that a function can be both an expression and a condition.
*/
bool IsCondition() const {
return functionType == gd::EventsFunction::Condition ||
functionType == gd::EventsFunction::ExpressionAndCondition;
}
/**
* \brief Returns true if the function is private.
@@ -154,7 +217,20 @@ class GD_CORE_API EventsFunction {
gd::EventsList& GetEvents() { return events; };
/**
* \brief Return the parameters of the function.
* \brief Return the parameters of the function that are used in the events.
*
* \note During code/extension generation, new parameters are added
* to the generated function, like "runtimeScene" and "eventsFunctionContext".
* This should be transparent to the user.
*/
const std::vector<gd::ParameterMetadata>& GetParametersForEvents(
const gd::EventsFunctionsContainer& functionsContainer) const;
/**
* \brief Return the parameters of the function that are filled in the editor.
*
* \note They won't be used for ActionWithOperator, but they need to be kept
* to avoid to loose them when the function type is changed.
*
* \note During code/extension generation, new parameters are added
* to the generated function, like "runtimeScene" and "eventsFunctionContext".
@@ -202,9 +278,12 @@ class GD_CORE_API EventsFunction {
gd::String description;
gd::String sentence;
gd::String group;
gd::String getterName;
gd::ValueTypeMetadata expressionType;
gd::EventsList events;
FunctionType functionType;
std::vector<gd::ParameterMetadata> parameters;
mutable std::vector<gd::ParameterMetadata> actionWithOperationParameters;
gd::ObjectGroupsContainer objectGroups;
bool isPrivate = false;
};

View File

@@ -25,7 +25,24 @@ namespace gd {
*/
class GD_CORE_API EventsFunctionsContainer
: private SerializableWithNameList<gd::EventsFunction> {
public:
public:
enum FunctionOwner {
Extension,
Object,
Behavior};
EventsFunctionsContainer(FunctionOwner source_) : owner(source_) {}
/**
* \brief Get the source of the function container.
*
* \note For instance, it can be useful to handle specific parameters for
* behaviors.
*/
FunctionOwner GetOwner() const {
return owner;
}
/** \name Events Functions management
*/
///@{
@@ -139,6 +156,9 @@ class GD_CORE_API EventsFunctionsContainer
void Init(const gd::EventsFunctionsContainer& other) {
return SerializableWithNameList<gd::EventsFunction>::Init(other);
};
private:
FunctionOwner owner;
};
} // namespace gd

View File

@@ -13,10 +13,14 @@
namespace gd {
EventsFunctionsExtension::EventsFunctionsExtension() {}
EventsFunctionsExtension::EventsFunctionsExtension() :
gd::EventsFunctionsContainer(
gd::EventsFunctionsContainer::FunctionOwner::Extension) {}
EventsFunctionsExtension::EventsFunctionsExtension(
const EventsFunctionsExtension& other) {
const EventsFunctionsExtension& other) :
gd::EventsFunctionsContainer(
gd::EventsFunctionsContainer::FunctionOwner::Extension) {
Init(other);
}
@@ -168,24 +172,10 @@ void EventsFunctionsExtension::UnserializeExtensionImplementationFrom(
gd::Project& project,
const SerializerElement& element) {
UnserializeEventsFunctionsFrom(project, element.GetChild("eventsFunctions"));
auto &behaviorsElement = element.GetChild("eventsBasedBehaviors");
behaviorsElement.ConsiderAsArrayOf("eventsBasedBehavior");
for (std::size_t i = 0; i < behaviorsElement.GetChildrenCount(); ++i) {
const gd::String &behaviorName =
behaviorsElement.GetChild(i).GetStringAttribute("name");
if (eventsBasedBehaviors.Has(behaviorName)) {
eventsBasedBehaviors.Get(behaviorName).UnserializeFrom(project, behaviorsElement.GetChild(i));
}
}
auto &objectsElement = element.GetChild("eventsBasedObjects");
objectsElement.ConsiderAsArrayOf("eventsBasedObject");
for (std::size_t i = 0; i < objectsElement.GetChildrenCount(); ++i) {
const gd::String &objectName =
objectsElement.GetChild(i).GetStringAttribute("name");
if (eventsBasedObjects.Has(objectName)) {
eventsBasedObjects.Get(objectName).UnserializeFrom(project, objectsElement.GetChild(i));
}
}
eventsBasedBehaviors.UnserializeElementsFrom(
"eventsBasedBehavior", project, element.GetChild("eventsBasedBehaviors"));
eventsBasedObjects.UnserializeElementsFrom(
"eventsBasedObject", project, element.GetChild("eventsBasedObjects"));
}
bool EventsFunctionsExtension::IsExtensionLifecycleEventsFunction(

View File

@@ -20,7 +20,9 @@ class Project;
} // namespace gd
namespace gd {
// TODO Remove the EventsFunctionsContainer inheritance and make it an attribute.
// This will allow to get EventsFunctionsContainer the same way for extensions,
// objects and behaviors.
/**
* \brief Hold a list of Events Functions (gd::EventsFunction) and Events Based
* Behaviors.

View File

@@ -244,6 +244,15 @@ class GD_CORE_API HighestZOrderFinder : public gd::InitialInstanceFunctor {
*/
size_t GetInstancesCount() const { return instancesCount; }
void Reset() {
highestZOrder = 0;
lowestZOrder = 0;
instancesCount = 0;
firstCall = true;
layerRestricted = false;
layerName.clear();
}
private:
int highestZOrder;
int lowestZOrder;

View File

@@ -218,32 +218,8 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
if (behaviorsSharedData.find(name) != behaviorsSharedData.end()) continue;
if (project.HasEventsBasedBehavior(allBehaviorsTypes[i])) {
// Events based behaviors don't have shared data yet.
auto sharedData =
gd::make_unique<gd::BehaviorsSharedData>(name, allBehaviorsTypes[i]);
sharedData->InitializeContent();
behaviorsSharedData[name] = std::move(sharedData);
}
else {
const gd::BehaviorMetadata& behaviorMetadata =
gd::MetadataProvider::GetBehaviorMetadata(
project.GetCurrentPlatform(),
allBehaviorsTypes[i]);
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
continue;
}
gd::BehaviorsSharedData* behaviorsSharedDataBluePrint =
behaviorMetadata.GetSharedDataInstance();
if (!behaviorsSharedDataBluePrint) continue;
auto sharedData =
gd::make_unique<gd::BehaviorsSharedData>(
*behaviorsSharedDataBluePrint);
sharedData->SetName(name);
sharedData->SetTypeName(allBehaviorsTypes[i]);
sharedData->InitializeContent();
auto sharedData = CreateBehaviorsSharedData(project, name, allBehaviorsTypes[i]);
if (sharedData) {
behaviorsSharedData[name] = std::move(sharedData);
}
}
@@ -264,6 +240,33 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
}
}
std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(gd::Project& project, const gd::String& name, const gd::String& behaviorsType) {
if (project.HasEventsBasedBehavior(behaviorsType)) {
// Events based behaviors don't have shared data yet.
auto sharedData =
gd::make_unique<gd::BehaviorsSharedData>(name, behaviorsType);
sharedData->InitializeContent();
return std::move(sharedData);
}
const gd::BehaviorMetadata& behaviorMetadata =
gd::MetadataProvider::GetBehaviorMetadata(
project.GetCurrentPlatform(),
behaviorsType);
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
return nullptr;
}
gd::BehaviorsSharedData* behaviorsSharedDataBluePrint =
behaviorMetadata.GetSharedDataInstance();
if (!behaviorsSharedDataBluePrint) return nullptr;
auto sharedData = behaviorsSharedDataBluePrint->Clone();
sharedData->SetName(name);
sharedData->SetTypeName(behaviorsType);
sharedData->InitializeContent();
return std::unique_ptr<gd::BehaviorsSharedData>(sharedData);
}
void Layout::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", GetName());
element.SetAttribute("mangledName", GetMangledName());
@@ -367,20 +370,23 @@ void Layout::UnserializeFrom(gd::Project& project,
"Behavior"); // Compatibility with GD <= 4
gd::String name = sharedDataElement.GetStringAttribute("name", "", "Name");
auto behavior = gd::make_unique<gd::BehaviorsSharedData>(name, type);
// Compatibility with GD <= 4.0.98
// If there is only one child called "content" (in addition to "type" and
// "name"), it's the content of a JavaScript behavior. Move the content
// out of the "content" object (to put it directly at the root of the
// behavior shared data element).
if (sharedDataElement.HasChild("content")) {
behavior->UnserializeFrom(sharedDataElement.GetChild("content"));
auto sharedData = CreateBehaviorsSharedData(project, name, type);
if (sharedData) {
// Compatibility with GD <= 4.0.98
// If there is only one child called "content" (in addition to "type" and
// "name"), it's the content of a JavaScript behavior. Move the content
// out of the "content" object (to put it directly at the root of the
// behavior shared data element).
if (sharedDataElement.HasChild("content")) {
sharedData->UnserializeFrom(sharedDataElement.GetChild("content"));
}
// end of compatibility code
else {
sharedData->UnserializeFrom(sharedDataElement);
}
behaviorsSharedData[name] = std::move(sharedData);
}
// end of compatibility code
else {
behavior->UnserializeFrom(sharedDataElement);
}
behaviorsSharedData[name] = std::move(behavior);
}
}
@@ -402,7 +408,7 @@ void Layout::Init(const Layout& other) {
behaviorsSharedData.clear();
for (const auto& it : other.behaviorsSharedData) {
behaviorsSharedData[it.first] =
gd::make_unique<gd::BehaviorsSharedData>(*(it.second->Clone()));
std::unique_ptr<gd::BehaviorsSharedData>(it.second->Clone());
}
events = other.events;

View File

@@ -404,6 +404,11 @@ class GD_CORE_API Layout : public ObjectsContainer {
* Don't forget to update me if members were changed!
*/
void Init(const gd::Layout& other);
std::unique_ptr<gd::BehaviorsSharedData> CreateBehaviorsSharedData(
gd::Project& project,
const gd::String& name,
const gd::String& behaviorsType);
};
/**

View File

@@ -10,7 +10,8 @@
TEST_CASE("EventsFunctionsContainer", "[common]") {
SECTION("Sanity checks") {
gd::EventsFunctionsContainer eventsFunctionContainer;
gd::EventsFunctionsContainer eventsFunctionContainer(
gd::EventsFunctionsContainer::FunctionOwner::Extension);
eventsFunctionContainer.InsertNewEventsFunction("Function1", 0);
eventsFunctionContainer.InsertNewEventsFunction("Function2", 1);
eventsFunctionContainer.InsertNewEventsFunction("Function3", 2);
@@ -62,7 +63,8 @@ TEST_CASE("EventsFunctionsContainer", "[common]") {
}
SECTION("Serialization") {
gd::Project project;
gd::EventsFunctionsContainer eventsFunctionContainer;
gd::EventsFunctionsContainer eventsFunctionContainer(
gd::EventsFunctionsContainer::FunctionOwner::Extension);
eventsFunctionContainer.InsertNewEventsFunction("Function1", 0);
eventsFunctionContainer.InsertNewEventsFunction("Function2", 1);
eventsFunctionContainer.InsertNewEventsFunction("Function3", 2);
@@ -72,7 +74,8 @@ TEST_CASE("EventsFunctionsContainer", "[common]") {
eventsFunctionContainer.RemoveEventsFunction("Function2");
gd::EventsFunctionsContainer eventsFunctionContainer2;
gd::EventsFunctionsContainer eventsFunctionContainer2(
gd::EventsFunctionsContainer::FunctionOwner::Extension);
eventsFunctionContainer2.UnserializeEventsFunctionsFrom(project, element);
REQUIRE(eventsFunctionContainer.GetEventsFunctionsCount() == 2);
REQUIRE(eventsFunctionContainer.GetEventsFunction(0).GetName() ==

View File

@@ -0,0 +1,289 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering common features of GDevelop Core.
*/
#include "GDCore/IDE/Events/EventsIdentifiersFinder.h"
#include "GDCore/Events/Builtin/LinkEvent.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "catch.hpp"
namespace {
const void DeclareTimerExtension(gd::Project &project, gd::Platform &platform) {
std::shared_ptr<gd::PlatformExtension> extension =
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
gd::BuiltinExtensionsImplementer::ImplementsTimeExtension(*(extension.get()));
gd::BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
*(extension.get()));
// Add an instruction to test expressions.
extension
->AddAction("DoSomething", "Do something", "This does something",
"Do something please", "", "", "")
.AddParameter("expression", "Parameter 1 (a number)");
platform.AddExtension(extension);
project.AddPlatform(platform);
}
const gd::StandardEvent UseSceneTimer(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("ResetTimer");
instruction.SetParametersCount(2);
instruction.SetParameter(0, gd::Expression("scene"));
instruction.SetParameter(1, gd::Expression("\"" + name + "\""));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseObjectTimer(const gd::String &objectName,
const gd::String &timerName) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("ResetObjectTimer");
instruction.SetParametersCount(2);
instruction.SetParameter(0, gd::Expression(objectName));
instruction.SetParameter(1, gd::Expression("\"" + timerName + "\""));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseSceneTimerInExpression(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(
0, gd::Expression("1 + TimerElapsedTime(\"" + name + "\")"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent
UseObjectTimerInExpression(const gd::String &objectName,
const gd::String &timerName) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(0, gd::Expression("1 + " + objectName +
".ObjectTimerElapsedTime(\"" + timerName +
"\")"));
event.GetActions().Insert(instruction);
return event;
}
const void UseExternalEvents(gd::Layout &layout,
gd::ExternalEvents &externalEvents) {
gd::LinkEvent linkEvent;
linkEvent.SetTarget(externalEvents.GetName());
layout.GetEvents().InsertEvent(linkEvent);
}
} // namespace
TEST_CASE("EventsIdentifiersFinder (scene timers)", "[common]") {
SECTION("Can find scene timers in scenes") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(UseSceneTimer("MySceneTimer"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "sceneTimer");
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
}
SECTION("Can find scene timers in scene expressions") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(UseSceneTimerInExpression("MySceneTimer"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "sceneTimer");
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
}
SECTION("Can find scene timers in external layouts") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(UseSceneTimer("MySceneTimer"));
UseExternalEvents(layout, externalEvents);
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "sceneTimer");
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimer\"");
}
SECTION("Can find scene timers the right scene") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout1 = project.InsertNewLayout("Layout1", 0);
layout1.GetEvents().InsertEvent(UseSceneTimer("MySceneTimerInLayout1"));
auto &layout2 = project.InsertNewLayout("Layout2", 0);
layout2.GetEvents().InsertEvent(UseSceneTimer("MySceneTimerInLayout2"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout1, "sceneTimer");
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MySceneTimerInLayout1\"");
}
SECTION("Can find scene timers in the right external layouts") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout1 = project.InsertNewLayout("Layout1", 0);
auto &externalEvents1 =
project.InsertNewExternalEvents("ExternalEvents1", 0);
externalEvents1.GetEvents().InsertEvent(
UseSceneTimer("MySceneTimerInExternalEvents1"));
UseExternalEvents(layout1, externalEvents1);
auto &layout2 = project.InsertNewLayout("Layout2", 0);
auto &externalEvents2 =
project.InsertNewExternalEvents("ExternalEvents2", 0);
externalEvents2.GetEvents().InsertEvent(
UseSceneTimer("MySceneTimerInExternalEvents2"));
UseExternalEvents(layout2, externalEvents2);
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout1, "sceneTimer");
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) ==
"\"MySceneTimerInExternalEvents1\"");
}
}
TEST_CASE("EventsIdentifiersFinder (object timers)", "[common]") {
SECTION("Can find object timers in scenes") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
layout.GetEvents().InsertEvent(UseObjectTimer("MyObject", "MyObjectTimer"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "objectTimer", object.GetName());
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
}
SECTION("Can find object timers in scene expression") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
layout.GetEvents().InsertEvent(UseObjectTimerInExpression("MyObject", "MyObjectTimer"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "objectTimer", object.GetName());
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
}
SECTION("Can find object timers in external layouts") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(
UseObjectTimer("MyObject", "MyObjectTimer"));
UseExternalEvents(layout, externalEvents);
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "objectTimer", object.GetName());
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer\"");
}
SECTION("Can find object timers in scenes for the right object") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
layout.GetEvents().InsertEvent(
UseObjectTimer("MyObject1", "MyObjectTimer1"));
layout.GetEvents().InsertEvent(
UseObjectTimer("MyObject2", "MyObjectTimer2"));
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "objectTimer", object1.GetName());
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer1\"");
}
SECTION("Can find object timers in external layouts for the right object") {
gd::Project project;
gd::Platform platform;
DeclareTimerExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(
UseObjectTimer("MyObject1", "MyObjectTimer1"));
externalEvents.GetEvents().InsertEvent(
UseObjectTimer("MyObject2", "MyObjectTimer2"));
UseExternalEvents(layout, externalEvents);
auto identifierExpressions =
gd::EventsIdentifiersFinder::FindAllIdentifierExpressions(
platform, project, layout, "objectTimer", object1.GetName());
REQUIRE(identifierExpressions.size() == 1);
REQUIRE(*(identifierExpressions.begin()) == "\"MyObjectTimer1\"");
}
}

View File

@@ -0,0 +1,360 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering common features of GDevelop Core.
*/
#include "GDCore/IDE/Events/EventsVariablesFinder.h"
#include "GDCore/Events/Builtin/LinkEvent.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/Variable.h"
#include "catch.hpp"
namespace {
const void DeclareVariableExtension(gd::Project &project,
gd::Platform &platform) {
std::shared_ptr<gd::PlatformExtension> extension =
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
gd::BuiltinExtensionsImplementer::ImplementsVariablesExtension(
*(extension.get()));
gd::BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
*(extension.get()));
// Add an instruction to test expressions.
extension
->AddAction("DoSomething", "Do something", "This does something",
"Do something please", "", "", "")
.AddParameter("expression", "Parameter 1 (a number)");
platform.AddExtension(extension);
project.AddPlatform(platform);
}
const gd::StandardEvent UseGlobalVariable(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("ModVarGlobal");
instruction.SetParametersCount(2);
instruction.SetParameter(0, gd::Expression(name));
instruction.SetParameter(1, gd::Expression("0"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseSceneVariable(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("ModVarScene");
instruction.SetParametersCount(2);
instruction.SetParameter(0, gd::Expression(name));
instruction.SetParameter(1, gd::Expression("0"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseObjectVariable(const gd::String &objectName,
const gd::String &variableName) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("ModVarObjet");
instruction.SetParametersCount(3);
instruction.SetParameter(0, gd::Expression(objectName));
instruction.SetParameter(1, gd::Expression(variableName));
instruction.SetParameter(2, gd::Expression("0"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseGlobalVariableInExpression(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(0,
gd::Expression("1 + GlobalVariable(" + name + ")"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent UseSceneVariableInExpression(const gd::String &name) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(0, gd::Expression("1 + Variable(" + name + ")"));
event.GetActions().Insert(instruction);
return event;
}
const gd::StandardEvent
UseObjectVariableInExpression(const gd::String &objectName,
const gd::String &variableName) {
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(
0,
gd::Expression("1 + " + objectName + ".Variable(" + variableName + ")"));
event.GetActions().Insert(instruction);
return event;
}
const void UseExternalEvents(gd::Layout &layout,
gd::ExternalEvents &externalEvents) {
gd::LinkEvent linkEvent;
linkEvent.SetTarget(externalEvents.GetName());
layout.GetEvents().InsertEvent(linkEvent);
}
} // namespace
TEST_CASE("EventsVariablesFinder (FindAllGlobalVariables)", "[common]") {
SECTION("Can find global variables in scenes") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(UseGlobalVariable("MyGlobalVariable"));
auto variableNames =
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
}
SECTION("Can find global variables in scene expressions") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(
UseGlobalVariableInExpression("MyGlobalVariable"));
auto variableNames =
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
}
SECTION("Can find global variables in external layouts") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(
UseGlobalVariable("MyGlobalVariable"));
UseExternalEvents(layout, externalEvents);
auto variableNames =
gd::EventsVariablesFinder::FindAllGlobalVariables(platform, project);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyGlobalVariable");
}
}
TEST_CASE("EventsVariablesFinder (FindAllLayoutVariables)", "[common]") {
SECTION("Can find scene variables in scenes") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(UseSceneVariable("MySceneVariable"));
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
platform, project, layout);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
}
SECTION("Can find scene variables in scene expressions") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
layout.GetEvents().InsertEvent(
UseSceneVariableInExpression("MySceneVariable"));
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
platform, project, layout);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
}
SECTION("Can find scene variables in external layouts") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(UseSceneVariable("MySceneVariable"));
UseExternalEvents(layout, externalEvents);
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
platform, project, layout);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MySceneVariable");
}
SECTION("Can find scene variables the right scene") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout1 = project.InsertNewLayout("Layout1", 0);
layout1.GetEvents().InsertEvent(
UseSceneVariable("MySceneVariableInLayout1"));
auto &layout2 = project.InsertNewLayout("Layout2", 0);
layout2.GetEvents().InsertEvent(
UseSceneVariable("MySceneVariableInLayout2"));
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
platform, project, layout1);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MySceneVariableInLayout1");
}
SECTION("Can find scene variables in the right external layouts") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout1 = project.InsertNewLayout("Layout1", 0);
auto &externalEvents1 =
project.InsertNewExternalEvents("ExternalEvents1", 0);
externalEvents1.GetEvents().InsertEvent(
UseSceneVariable("MySceneVariableInExternalEvents1"));
UseExternalEvents(layout1, externalEvents1);
auto &layout2 = project.InsertNewLayout("Layout2", 0);
auto &externalEvents2 =
project.InsertNewExternalEvents("ExternalEvents2", 0);
externalEvents2.GetEvents().InsertEvent(
UseSceneVariable("MySceneVariableInExternalEvents2"));
UseExternalEvents(layout2, externalEvents2);
auto variableNames = gd::EventsVariablesFinder::FindAllLayoutVariables(
platform, project, layout1);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MySceneVariableInExternalEvents1");
}
}
TEST_CASE("EventsVariablesFinder (FindAllObjectVariables)", "[common]") {
SECTION("Can find object variables in scenes") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
layout.GetEvents().InsertEvent(
UseObjectVariable("MyObject", "MyObjectVariable"));
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
platform, project, layout, object);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
}
SECTION("Can find object variables in scene expressions") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
layout.GetEvents().InsertEvent(
UseObjectVariableInExpression("MyObject", "MyObjectVariable"));
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
platform, project, layout, object);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
}
SECTION("Can find object variables in external layouts") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object = layout.InsertNewObject(project, "", "MyObject", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(
UseObjectVariable("MyObject", "MyObjectVariable"));
UseExternalEvents(layout, externalEvents);
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
platform, project, layout, object);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyObjectVariable");
}
SECTION("Can find object variables in scenes for the right object") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
layout.GetEvents().InsertEvent(
UseObjectVariable("MyObject1", "MyObjectVariable1"));
layout.GetEvents().InsertEvent(
UseObjectVariable("MyObject2", "MyObjectVariable2"));
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
platform, project, layout, object1);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyObjectVariable1");
}
SECTION(
"Can find object variables in external layouts for the right object") {
gd::Project project;
gd::Platform platform;
DeclareVariableExtension(project, platform);
auto &layout = project.InsertNewLayout("Layout1", 0);
auto &object1 = layout.InsertNewObject(project, "", "MyObject1", 0);
auto &object2 = layout.InsertNewObject(project, "", "MyObject2", 0);
auto &externalEvents = project.InsertNewExternalEvents("ExternalEvents", 0);
externalEvents.GetEvents().InsertEvent(
UseObjectVariable("MyObject1", "MyObjectVariable1"));
externalEvents.GetEvents().InsertEvent(
UseObjectVariable("MyObject2", "MyObjectVariable2"));
UseExternalEvents(layout, externalEvents);
auto variableNames = gd::EventsVariablesFinder::FindAllObjectVariables(
platform, project, layout, object1);
REQUIRE(variableNames.size() == 1);
REQUIRE(*(variableNames.begin()) == "MyObjectVariable1");
}
}

View File

@@ -12,11 +12,12 @@
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/CustomObjectConfiguration.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/Variable.h"
@@ -29,14 +30,7 @@ using namespace gd;
namespace {
void SetupProject(gd::Project &project, gd::Platform &platform) {
SetupProjectWithDummyPlatform(project, platform);
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
gd::Object &object =
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
auto &configuration = object.GetConfiguration();
void SetupSpriteConfiguration(gd::ObjectConfiguration &configuration) {
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(&configuration);
REQUIRE(spriteConfiguration != nullptr);
gd::Animation animation;
@@ -44,11 +38,30 @@ void SetupProject(gd::Project &project, gd::Platform &platform) {
spriteConfiguration->AddAnimation(animation);
};
void CheckSpriteConfiguration(
SerializerElement &objectContainerElement) {
gd::Object &SetupProjectWithSprite(gd::Project &project,
gd::Platform &platform) {
SetupProjectWithDummyPlatform(project, platform);
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
gd::Object &object =
layout.InsertNewObject(project, "MyExtension::Sprite", "MyObject", 0);
SetupSpriteConfiguration(object.GetConfiguration());
return object;
};
void CheckSpriteConfigurationInElement(SerializerElement &projectElement) {
void CheckSpriteConfigurationInObjectElement(SerializerElement &objectElement) {
REQUIRE(objectElement.HasChild("animations"));
auto &animationsElement = objectElement.GetChild("animations");
animationsElement.ConsiderAsArrayOf("animation");
REQUIRE(animationsElement.GetChildrenCount() == 1);
auto &animationElement = animationsElement.GetChild(0);
REQUIRE(animationElement.GetStringAttribute("name") == "Idle");
};
void CheckSpriteConfigurationInProjectElement(
SerializerElement &projectElement) {
auto &layoutsElement = projectElement.GetChild("layouts");
layoutsElement.ConsiderAsArrayOf("layout");
REQUIRE(layoutsElement.GetChildrenCount() == 1);
@@ -64,24 +77,10 @@ void CheckSpriteConfigurationInElement(SerializerElement &projectElement) {
REQUIRE(objectElement.GetStringAttribute("name") == "MyObject");
REQUIRE(objectElement.GetStringAttribute("type") == "MyExtension::Sprite");
REQUIRE(objectElement.HasChild("animations"));
auto &animationsElement = objectElement.GetChild("animations");
animationsElement.ConsiderAsArrayOf("animation");
REQUIRE(animationsElement.GetChildrenCount() == 1);
auto &animationElement = animationsElement.GetChild(0);
REQUIRE(animationElement.GetStringAttribute("name") ==
"Idle");
CheckSpriteConfigurationInObjectElement(objectElement);
};
void CheckSpriteConfiguration(gd::Project &project) {
auto &layout = project.GetLayout("Scene");
auto &object = layout.GetObject("MyObject");
REQUIRE(object.GetName() == "MyObject");
REQUIRE(object.GetType() == "MyExtension::Sprite");
auto &configuration = object.GetConfiguration();
void CheckSpriteConfiguration(gd::ObjectConfiguration &configuration) {
auto *spriteConfiguration = dynamic_cast<gd::SpriteObject *>(&configuration);
REQUIRE(spriteConfiguration);
REQUIRE(spriteConfiguration->GetAnimationsCount() == 1);
@@ -89,6 +88,88 @@ void CheckSpriteConfiguration(gd::Project &project) {
auto &animation = spriteConfiguration->GetAnimation(0);
REQUIRE(animation.GetName() == "Idle");
};
void CheckSpriteConfiguration(gd::Object &object) {
REQUIRE(object.GetName() == "MyObject");
REQUIRE(object.GetType() == "MyExtension::Sprite");
CheckSpriteConfiguration(object.GetConfiguration());
};
void CheckSpriteConfiguration(gd::Project &project) {
auto &layout = project.GetLayout("Scene");
auto &object = layout.GetObject("MyObject");
CheckSpriteConfiguration(object);
};
gd::Object &SetupProjectWithCustomObject(gd::Project &project,
gd::Platform &platform) {
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
"MyEventsBasedObject", 0);
eventsBasedObject.SetFullName("My events based object");
eventsBasedObject.SetDescription("An events based object for test");
eventsBasedObject.InsertNewObject(project, "MyExtension::Sprite", "MyChild",
0);
gd::Layout &layout = project.InsertNewLayout("Scene", 0);
gd::Object &object = layout.InsertNewObject(
project, "MyEventsExtension::MyEventsBasedObject", "MyObject", 0);
auto &configuration = object.GetConfiguration();
auto *customObjectConfiguration =
dynamic_cast<gd::CustomObjectConfiguration *>(&configuration);
auto &spriteConfiguration =
customObjectConfiguration->GetChildObjectConfiguration("MyChild");
SetupSpriteConfiguration(spriteConfiguration);
return object;
};
void CheckCustomObjectConfigurationInProjectElement(
SerializerElement &projectElement) {
auto &layoutsElement = projectElement.GetChild("layouts");
layoutsElement.ConsiderAsArrayOf("layout");
REQUIRE(layoutsElement.GetChildrenCount() == 1);
auto &layoutElement = layoutsElement.GetChild(0);
REQUIRE(layoutElement.GetStringAttribute("name") == "Scene");
REQUIRE(layoutElement.HasChild("objects"));
auto &objectsElement = layoutElement.GetChild("objects");
objectsElement.ConsiderAsArrayOf("object");
REQUIRE(objectsElement.GetChildrenCount() == 1);
auto &objectElement = objectsElement.GetChild(0);
REQUIRE(objectElement.GetStringAttribute("name") == "MyObject");
REQUIRE(objectElement.GetStringAttribute("type") ==
"MyEventsExtension::MyEventsBasedObject");
auto &childrenContentElement = objectElement.GetChild("childrenContent");
REQUIRE(childrenContentElement.HasChild("MyChild"));
auto &childElement = childrenContentElement.GetChild("MyChild");
CheckSpriteConfigurationInObjectElement(childElement);
};
void CheckCustomObjectConfiguration(gd::Object &object) {
REQUIRE(object.GetName() == "MyObject");
REQUIRE(object.GetType() == "MyEventsExtension::MyEventsBasedObject");
auto &configuration = object.GetConfiguration();
auto *customObjectConfiguration =
dynamic_cast<gd::CustomObjectConfiguration *>(&configuration);
auto &spriteConfiguration =
customObjectConfiguration->GetChildObjectConfiguration("MyChild");
CheckSpriteConfiguration(spriteConfiguration);
};
void CheckCustomObjectConfiguration(gd::Project &project) {
auto &layout = project.GetLayout("Scene");
auto &object = layout.GetObject("MyObject");
CheckCustomObjectConfiguration(object);
};
} // namespace
TEST_CASE("ObjectSerialization", "[common]") {
@@ -96,16 +177,52 @@ TEST_CASE("ObjectSerialization", "[common]") {
SECTION("Save and load a project with a sprite configuration") {
gd::Platform platform;
gd::Project writtenProject;
SetupProject(writtenProject, platform);
SetupProjectWithSprite(writtenProject, platform);
CheckSpriteConfiguration(writtenProject);
SerializerElement projectElement;
writtenProject.SerializeTo(projectElement);
CheckSpriteConfigurationInElement(projectElement);
CheckSpriteConfigurationInProjectElement(projectElement);
gd::Project readProject;
readProject.AddPlatform(platform);
readProject.UnserializeFrom(projectElement);
CheckSpriteConfiguration(readProject);
}
SECTION("Clone a sprite object") {
gd::Platform platform;
gd::Project project;
auto &object = SetupProjectWithSprite(project, platform);
CheckSpriteConfiguration(object);
auto clonedObject = object.Clone();
CheckSpriteConfiguration(*(clonedObject.get()));
}
SECTION("Save and load a project with a custom object configuration") {
gd::Platform platform;
gd::Project writtenProject;
SetupProjectWithCustomObject(writtenProject, platform);
CheckCustomObjectConfiguration(writtenProject);
SerializerElement projectElement;
writtenProject.SerializeTo(projectElement);
CheckCustomObjectConfigurationInProjectElement(projectElement);
gd::Project readProject;
readProject.AddPlatform(platform);
readProject.UnserializeFrom(projectElement);
CheckCustomObjectConfiguration(readProject);
}
SECTION("Clone a custom object") {
gd::Platform platform;
gd::Project project;
auto &object = SetupProjectWithCustomObject(project, platform);
CheckCustomObjectConfiguration(object);
auto clonedObject = object.Clone();
CheckCustomObjectConfiguration(*(clonedObject.get()));
}
}

View File

@@ -30,6 +30,8 @@
#include "GDCore/Project/Variable.h"
#include "catch.hpp"
// TODO EBO Add a test where a child is removed form the EventsBasedObject
// and check the configuration still gives access to other child configuration.
namespace {
const gd::StandardEvent &EnsureStandardEvent(const gd::BaseEvent &baseEvent) {
@@ -68,6 +70,9 @@ const gd::String &GetEventFirstActionType(const gd::BaseEvent &event) {
enum TestEvent {
FreeFunctionAction,
FreeFunctionWithExpression,
FreeConditionFromExpressionAndCondition,
FreeExpressionFromExpressionAndCondition,
FreeActionWithOperator,
FreeFunctionWithObjects,
FreeFunctionWithObjectExpression,
@@ -79,6 +84,9 @@ enum TestEvent {
IllNamedBehaviorExpression,
NoParameterBehaviorExpression,
NoParameterIllNamedBehaviorExpression,
BehaviorConditionFromExpressionAndCondition,
BehaviorExpressionFromExpressionAndCondition,
BehaviorActionWithOperator,
ObjectAction,
ObjectPropertyAction,
@@ -88,6 +96,9 @@ enum TestEvent {
IllNamedObjectExpression,
NoParameterObjectExpression,
NoParameterIllNamedObjectExpression,
ObjectConditionFromExpressionAndCondition,
ObjectExpressionFromExpressionAndCondition,
ObjectActionWithOperator,
};
const std::vector<const gd::EventsList *> GetEventsLists(gd::Project &project) {
@@ -113,7 +124,7 @@ const void SetupEvents(gd::EventsList &eventList) {
// Add some free functions usages in events
{
if (eventList.GetEventsCount() != FreeFunctionAction) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsFunction
@@ -131,7 +142,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != FreeFunctionWithExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsFunctionExpression
@@ -148,8 +159,86 @@ const void SetupEvents(gd::EventsList &eventList) {
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeConditionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsFunctionExpressionAndCondition
// as a condition.
{
gd::StandardEvent event;
gd::Instruction condition;
condition.SetType("MyEventsExtension::MyEventsFunctionExpressionAndCondition");
condition.SetParametersCount(5);
condition.SetParameter(
0,
gd::Expression("scene"));
condition.SetParameter(
1,
gd::Expression(">"));
condition.SetParameter(
2,
gd::Expression("2"));
condition.SetParameter(
3,
gd::Expression("111"));
condition.SetParameter(
4,
gd::Expression("222"));
event.GetConditions().Insert(condition);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeExpressionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsFunctionExpressionAndCondition
// as an expression.
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0,
gd::Expression(
"2 + MyEventsExtension::MyEventsFunctionExpressionAndCondition(111, 222)"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeActionWithOperator) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsFunctionActionWithOperator
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyEventsExtension::MyEventsFunctionActionWithOperator");
action.SetParametersCount(5);
action.SetParameter(
0,
gd::Expression("scene"));
action.SetParameter(
1,
gd::Expression("+"));
action.SetParameter(
2,
gd::Expression("2"));
action.SetParameter(
3,
gd::Expression("111"));
action.SetParameter(
4,
gd::Expression("222"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeFunctionWithObjects) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to objects
{
@@ -164,7 +253,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != FreeFunctionWithObjectExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to objects in an expression
{
@@ -184,7 +273,7 @@ const void SetupEvents(gd::EventsList &eventList) {
// Add some events based behavior usages in events
{
if (eventList.GetEventsCount() != BehaviorAction) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunction
@@ -204,7 +293,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != BehaviorPropertyAction) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" action
{
@@ -218,7 +307,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != BehaviorPropertyCondition) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" condition
{
@@ -232,7 +321,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != BehaviorPropertyExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" expression
{
@@ -250,7 +339,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != BehaviorExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpression
@@ -269,7 +358,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != IllNamedBehaviorExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event **wrongly** referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpression
@@ -289,7 +378,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != NoParameterBehaviorExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpression
@@ -308,7 +397,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != NoParameterIllNamedBehaviorExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event **wrongly** referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpression
@@ -325,12 +414,99 @@ const void SetupEvents(gd::EventsList &eventList) {
event.GetActions().Insert(instruction);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorConditionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpressionAndCondition
// as a condition.
{
gd::StandardEvent event;
gd::Instruction condition;
condition.SetType("MyEventsExtension::MyEventsBasedBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition");
condition.SetParametersCount(6);
condition.SetParameter(
0,
gd::Expression("ObjectWithMyBehavior"));
condition.SetParameter(
1,
gd::Expression("MyBehavior"));
condition.SetParameter(
2,
gd::Expression(">"));
condition.SetParameter(
3,
gd::Expression("5"));
condition.SetParameter(
4,
gd::Expression("111"));
condition.SetParameter(
5,
gd::Expression("222"));
event.GetConditions().Insert(condition);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorExpressionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionExpressionAndCondition
// as an expression.
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0,
gd::Expression("5 + "
"ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition(111, 222)"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorActionWithOperator) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedBehavior::MyBehaviorEventsFunctionActionWithOperator
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyEventsExtension::MyEventsBasedBehavior::"
"MyBehaviorEventsFunctionActionWithOperator");
action.SetParametersCount(6);
action.SetParameter(
0,
gd::Expression("ObjectWithMyBehavior"));
action.SetParameter(
1,
gd::Expression("MyBehavior"));
action.SetParameter(
2,
gd::Expression("+"));
action.SetParameter(
3,
gd::Expression("5"));
action.SetParameter(
4,
gd::Expression("111"));
action.SetParameter(
5,
gd::Expression("222"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
}
// Add some events based object usages in events
{
if (eventList.GetEventsCount() != ObjectAction) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunction
@@ -349,7 +525,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != ObjectPropertyAction) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" action
{
@@ -363,7 +539,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != ObjectPropertyCondition) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" condition
{
@@ -377,7 +553,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != ObjectPropertyExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" expression
{
@@ -395,7 +571,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != ObjectExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpression
@@ -413,7 +589,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != IllNamedObjectExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event **wrongly** referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpression
@@ -432,7 +608,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != NoParameterObjectExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpression
@@ -451,7 +627,7 @@ const void SetupEvents(gd::EventsList &eventList) {
}
if (eventList.GetEventsCount() != NoParameterIllNamedObjectExpression) {
throw std::logic_error("Invalid events setup");
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event **wrongly** referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpression
@@ -468,6 +644,87 @@ const void SetupEvents(gd::EventsList &eventList) {
event.GetActions().Insert(instruction);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != ObjectConditionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpressionAndCondition
// as a condition.
{
gd::StandardEvent event;
gd::Instruction condition;
condition.SetType("MyEventsExtension::MyEventsBasedObject::"
"MyObjectEventsFunctionExpressionAndCondition");
condition.SetParametersCount(5);
condition.SetParameter(
0,
gd::Expression("MyCustomObject"));
condition.SetParameter(
1,
gd::Expression(">"));
condition.SetParameter(
2,
gd::Expression("5"));
condition.SetParameter(
3,
gd::Expression("111"));
condition.SetParameter(
4,
gd::Expression("222"));
event.GetConditions().Insert(condition);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != ObjectExpressionFromExpressionAndCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionExpressionAndCondition
// as an expression.
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0,
gd::Expression("5 + "
"MyCustomObject."
"MyObjectEventsFunctionExpressionAndCondition(111, 222)"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != ObjectActionWithOperator) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to
// MyEventsExtension::MyEventsBasedObject::MyObjectEventsFunctionActionWithOperator
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyEventsExtension::MyEventsBasedObject::"
"MyObjectEventsFunctionActionWithOperator");
action.SetParametersCount(5);
action.SetParameter(
0,
gd::Expression("MyCustomObject"));
action.SetParameter(
1,
gd::Expression("+"));
action.SetParameter(
2,
gd::Expression("5"));
action.SetParameter(
3,
gd::Expression("111"));
action.SetParameter(
4,
gd::Expression("222"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
}
}
@@ -525,6 +782,31 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
auto &behaviorExpressionAndCondition =
behaviorEventsFunctions
.InsertNewEventsFunction("MyBehaviorEventsFunctionExpressionAndCondition", 2)
.SetFunctionType(gd::EventsFunction::ExpressionAndCondition);
behaviorExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata().SetName("Object").SetType("object"));
behaviorExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
.SetType("behavior")
.SetExtraInfo("MyExtension::MyEventsBasedBehavior"));
behaviorExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value1")
.SetType("expression"));
behaviorExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value2")
.SetType("expression"));
behaviorEventsFunctions
.InsertNewEventsFunction("MyBehaviorEventsFunctionActionWithOperator", 2)
.SetFunctionType(gd::EventsFunction::ActionWithOperator)
.SetGetterName("MyBehaviorEventsFunctionExpressionAndCondition");
// Add property
eventsBasedBehavior.GetPropertyDescriptors()
.InsertNew("MyProperty", 0)
@@ -568,6 +850,26 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
auto &objectExpressionAndCondition =
objectEventsFunctions
.InsertNewEventsFunction("MyObjectEventsFunctionExpressionAndCondition", 2)
.SetFunctionType(gd::EventsFunction::ExpressionAndCondition);
objectExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata().SetName("Object").SetType("object"));
objectExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value1")
.SetType("expression"));
objectExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value2")
.SetType("expression"));
objectEventsFunctions
.InsertNewEventsFunction("MyObjectEventsFunctionActionWithOperator", 2)
.SetFunctionType(gd::EventsFunction::ActionWithOperator)
.SetGetterName("MyObjectEventsFunctionExpressionAndCondition");
// Add a property
eventsBasedObject.GetPropertyDescriptors()
.InsertNew("MyProperty", 0)
@@ -620,6 +922,7 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetName("Behavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
auto &expression =
eventsExtension.InsertNewEventsFunction("MyEventsFunctionExpression", 1)
.SetFunctionType(gd::EventsFunction::Expression);
@@ -627,6 +930,21 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetName("currentScene")
.SetType("")
.SetCodeOnly(true));
auto &freeExpressionAndCondition = eventsExtension.InsertNewEventsFunction("MyEventsFunctionExpressionAndCondition", 2)
.SetFunctionType(gd::EventsFunction::ExpressionAndCondition);
freeExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value1")
.SetType("expression"));
freeExpressionAndCondition.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Value2")
.SetType("expression"));
eventsExtension.InsertNewEventsFunction("MyEventsFunctionActionWithOperator", 2)
.SetFunctionType(gd::EventsFunction::ActionWithOperator)
.SetGetterName("MyEventsFunctionExpressionAndCondition");
}
// Add some usages in events
@@ -1046,6 +1364,21 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
eventsList->GetEvent(FreeFunctionWithExpression)) ==
"1 + MyRenamedExtension::MyEventsFunctionExpression(123, 456)");
// Check that events function calls from an ExpressionAndCondition have
// been renamed.
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(FreeConditionFromExpressionAndCondition)) ==
"MyRenamedExtension::MyEventsFunctionExpressionAndCondition");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(FreeExpressionFromExpressionAndCondition)) ==
"2 + MyRenamedExtension::MyEventsFunctionExpressionAndCondition(111, 222)");
// Check that events function calls from an ActionWithOperator has
// been renamed.
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(FreeActionWithOperator)) ==
"MyRenamedExtension::MyEventsFunctionActionWithOperator");
// Check that the type of the behavior was changed in the behaviors of
// objects. Name is *not* changed.
REQUIRE(project.GetLayout("Scene")
@@ -1082,7 +1415,17 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(GetEventFirstActionType(eventsList->GetEvent(BehaviorAction)) ==
"MyRenamedExtension::MyEventsBasedBehavior::"
"MyBehaviorEventsFunction");
REQUIRE(
GetEventFirstConditionType(
eventsList->GetEvent(BehaviorConditionFromExpressionAndCondition)) ==
"MyRenamedExtension::MyEventsBasedBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition");
REQUIRE(
GetEventFirstActionType(
eventsList->GetEvent(BehaviorActionWithOperator)) ==
"MyRenamedExtension::MyEventsBasedBehavior::"
"MyBehaviorEventsFunctionActionWithOperator");
// Check if events-based behaviors properties have been renamed in
// instructions
REQUIRE(GetEventFirstActionType(
@@ -1094,16 +1437,19 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpression)) ==
"1 + "
"ObjectWithMyBehavior.MyBehavior::"
"1 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpression(123, 456, 789)");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(NoParameterBehaviorExpression)) ==
"3 + "
"ObjectWithMyBehavior.MyBehavior::"
"3 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpression");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpressionFromExpressionAndCondition)) ==
"5 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition(111, 222)");
// Check that the type of the object was changed in the custom
// objects. Name is *not* changed.
REQUIRE(
@@ -1117,6 +1463,16 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(
GetEventFirstActionType(eventsList->GetEvent(ObjectAction)) ==
"MyRenamedExtension::MyEventsBasedObject::MyObjectEventsFunction");
REQUIRE(
GetEventFirstConditionType(
eventsList->GetEvent(ObjectConditionFromExpressionAndCondition)) ==
"MyRenamedExtension::MyEventsBasedObject::"
"MyObjectEventsFunctionExpressionAndCondition");
REQUIRE(
GetEventFirstActionType(
eventsList->GetEvent(ObjectActionWithOperator)) ==
"MyRenamedExtension::MyEventsBasedObject::"
"MyObjectEventsFunctionActionWithOperator");
// Check if events-based object properties have been renamed in
// instructions
@@ -1128,14 +1484,17 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpression)) ==
"1 + "
"MyCustomObject."
"1 + MyCustomObject."
"MyObjectEventsFunctionExpression(123, 456, 789)");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(NoParameterObjectExpression)) ==
"3 + "
"MyCustomObject.MyObjectEventsFunctionExpression");
"3 + MyCustomObject.MyObjectEventsFunctionExpression");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpressionFromExpressionAndCondition)) ==
"5 + MyCustomObject."
"MyObjectEventsFunctionExpressionAndCondition(111, 222)");
}
}
@@ -1237,6 +1596,35 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION("(Free) events expression and condition renamed") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
gd::WholeProjectRefactorer::RenameEventsFunction(
project,
eventsExtension,
"MyEventsFunctionExpressionAndCondition",
"MyRenamedFunctionExpressionAndCondition");
for (auto *eventsList : GetEventsLists(project)) {
// Check that events function calls in expressions have been renamed
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(FreeExpressionFromExpressionAndCondition)) ==
"2 + MyEventsExtension::MyRenamedFunctionExpressionAndCondition(111, 222)");
// Check that events function calls in instructions have been renamed
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(FreeConditionFromExpressionAndCondition)) ==
"MyEventsExtension::MyRenamedFunctionExpressionAndCondition");
// Check that the action still refer to the right ExpressionAndCondition.
REQUIRE(eventsExtension.GetEventsFunction("MyEventsFunctionActionWithOperator")
.GetGetterName() == "MyRenamedFunctionExpressionAndCondition");
}
}
SECTION("(Free) events action parameter moved") {
gd::Project project;
gd::Platform platform;
@@ -1277,6 +1665,35 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION("(Free) events expression and condition parameter moved") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
// The index 0 is reserved for the RuntimeScene.
gd::WholeProjectRefactorer::MoveEventsFunctionParameter(
project, eventsExtension, "MyEventsFunctionExpressionAndCondition", 1, 2);
for (auto *eventsList : GetEventsLists(project)) {
// Check that events function calls in expressions have been updated
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(FreeExpressionFromExpressionAndCondition)) ==
"2 + MyEventsExtension::MyEventsFunctionExpressionAndCondition(222, 111)");
// Check that events function calls in instructions have been updated
auto &condition = static_cast<const gd::StandardEvent &>(
eventsList->GetEvent(FreeConditionFromExpressionAndCondition))
.GetConditions()
.Get(0);
REQUIRE(condition.GetParameter(0).GetPlainString() == "scene");
REQUIRE(condition.GetParameter(1).GetPlainString() == ">");
REQUIRE(condition.GetParameter(2).GetPlainString() == "2");
REQUIRE(condition.GetParameter(3).GetPlainString() == "222");
REQUIRE(condition.GetParameter(4).GetPlainString() == "111");
}
}
SECTION("Events based behavior renamed (instructions update)") {
gd::Project project;
gd::Platform platform;
@@ -1314,6 +1731,14 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(GetEventFirstActionType(eventsList->GetEvent(BehaviorAction)) ==
"MyEventsExtension::MyRenamedEventsBasedBehavior::"
"MyBehaviorEventsFunction");
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(BehaviorConditionFromExpressionAndCondition)) ==
"MyEventsExtension::MyRenamedEventsBasedBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition");
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorActionWithOperator)) ==
"MyEventsExtension::MyRenamedEventsBasedBehavior::"
"MyBehaviorEventsFunctionActionWithOperator");
// Check if events-based behaviors properties have been renamed in
// instructions
@@ -1326,9 +1751,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpression)) ==
"1 + "
"ObjectWithMyBehavior.MyBehavior::"
"1 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpression(123, 456, 789)");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpressionFromExpressionAndCondition)) ==
"5 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition(111, 222)");
}
}
@@ -1405,6 +1833,14 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(GetEventFirstActionType(eventsList->GetEvent(ObjectAction)) ==
"MyEventsExtension::MyRenamedEventsBasedObject::"
"MyObjectEventsFunction");
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(ObjectConditionFromExpressionAndCondition)) ==
"MyEventsExtension::MyRenamedEventsBasedObject::"
"MyObjectEventsFunctionExpressionAndCondition");
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(ObjectActionWithOperator)) ==
"MyEventsExtension::MyRenamedEventsBasedObject::"
"MyObjectEventsFunctionActionWithOperator");
// Check if events-based object properties have been renamed in
// instructions
@@ -1417,9 +1853,12 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpression)) ==
"1 + "
"MyCustomObject."
"1 + MyCustomObject."
"MyObjectEventsFunctionExpression(123, 456, 789)");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpressionFromExpressionAndCondition)) ==
"5 + MyCustomObject."
"MyObjectEventsFunctionExpressionAndCondition(111, 222)");
}
}
@@ -1621,6 +2060,80 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION("(Events based behavior) events expression and condition renamed") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsBasedBehavior =
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
gd::WholeProjectRefactorer::RenameBehaviorEventsFunction(
project,
eventsExtension,
eventsBasedBehavior,
"MyBehaviorEventsFunctionExpressionAndCondition",
"MyRenamedBehaviorEventsFunctionExpressionAndCondition");
for (auto *eventsList : GetEventsLists(project)) {
// Check events-based behavior methods have been renamed in
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpressionFromExpressionAndCondition)) ==
"5 + ObjectWithMyBehavior.MyBehavior::"
"MyRenamedBehaviorEventsFunctionExpressionAndCondition(111, 222)");
// Check if events-based behavior methods have been renamed in
// instructions
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(BehaviorConditionFromExpressionAndCondition)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"MyRenamedBehaviorEventsFunctionExpressionAndCondition");
// Check that the action still refer to the right ExpressionAndCondition.
REQUIRE(eventsBasedBehavior.GetEventsFunctions()
.GetEventsFunction("MyBehaviorEventsFunctionActionWithOperator")
.GetGetterName() == "MyRenamedBehaviorEventsFunctionExpressionAndCondition");
}
}
SECTION("(Events based object) events expression and condition renamed") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsBasedObject =
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
gd::WholeProjectRefactorer::RenameObjectEventsFunction(
project,
eventsExtension,
eventsBasedObject,
"MyObjectEventsFunctionExpressionAndCondition",
"MyRenamedObjectEventsFunctionExpressionAndCondition");
for (auto *eventsList : GetEventsLists(project)) {
// Check events-based behavior methods have been renamed in
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpressionFromExpressionAndCondition)) ==
"5 + MyCustomObject."
"MyRenamedObjectEventsFunctionExpressionAndCondition(111, 222)");
// Check if events-based behavior methods have been renamed in
// instructions
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(ObjectConditionFromExpressionAndCondition)) ==
"MyEventsExtension::MyEventsBasedObject::"
"MyRenamedObjectEventsFunctionExpressionAndCondition");
// Check that the action still refer to the right ExpressionAndCondition.
REQUIRE(eventsBasedObject.GetEventsFunctions()
.GetEventsFunction("MyObjectEventsFunctionActionWithOperator")
.GetGetterName() == "MyRenamedObjectEventsFunctionExpressionAndCondition");
}
}
SECTION("(Events based behavior) events action parameter moved") {
gd::Project project;
gd::Platform platform;
@@ -1737,6 +2250,83 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION("(Events based behavior) events expression and condition parameter moved") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsBasedBehavior =
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
// The first 2 parameters are reserved for the object and behavior.
gd::WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
project,
eventsExtension,
eventsBasedBehavior,
"MyBehaviorEventsFunctionExpressionAndCondition",
2,
3);
for (auto *eventsList : GetEventsLists(project)) {
// Check parameters of events-based behavior methods have been moved in
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorExpressionFromExpressionAndCondition)) ==
"5 + ObjectWithMyBehavior.MyBehavior::"
"MyBehaviorEventsFunctionExpressionAndCondition(222, 111)");
// Check if parameters of events-based behavior methods have been moved in
// instructions
auto &action = static_cast<const gd::StandardEvent &>(
eventsList->GetEvent(BehaviorConditionFromExpressionAndCondition))
.GetConditions()
.Get(0);
REQUIRE(action.GetParameter(0).GetPlainString() == "ObjectWithMyBehavior");
REQUIRE(action.GetParameter(1).GetPlainString() == "MyBehavior");
REQUIRE(action.GetParameter(2).GetPlainString() == ">");
REQUIRE(action.GetParameter(3).GetPlainString() == "5");
REQUIRE(action.GetParameter(4).GetPlainString() == "222");
REQUIRE(action.GetParameter(5).GetPlainString() == "111");
}
}
SECTION("(Events based object) events expression and condition parameter moved") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsBasedObject =
eventsExtension.GetEventsBasedObjects().Get("MyEventsBasedObject");
// The first 2 parameters are reserved for the object and behavior.
gd::WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
project,
eventsExtension,
eventsBasedObject,
"MyObjectEventsFunctionExpressionAndCondition",
1,
2);
for (auto *eventsList : GetEventsLists(project)) {
// Check parameters of events-based behavior methods have been moved in
// expressions
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(ObjectExpressionFromExpressionAndCondition)) ==
"5 + MyCustomObject."
"MyObjectEventsFunctionExpressionAndCondition(222, 111)");
// Check if parameters of events-based behavior methods have been moved in
// instructions
auto &action = static_cast<const gd::StandardEvent &>(
eventsList->GetEvent(ObjectConditionFromExpressionAndCondition))
.GetConditions()
.Get(0);
REQUIRE(action.GetParameter(0).GetPlainString() == "MyCustomObject");
REQUIRE(action.GetParameter(1).GetPlainString() == ">");
REQUIRE(action.GetParameter(2).GetPlainString() == "5");
REQUIRE(action.GetParameter(3).GetPlainString() == "222");
REQUIRE(action.GetParameter(4).GetPlainString() == "111");
}
}
SECTION(
"(Events based behavior) property renamed (not a required behavior)") {
gd::Project project;

View File

@@ -28,7 +28,7 @@ module.exports = {
'Arthur Pacaud (arthuro555)',
'MIT'
)
.setCategory('Device');
.setCategory('User interface');
extension
.addInstructionOrExpressionGroupMetadata(_('Advanced window management'))
.setIcon('res/actions/window24.png');

View File

@@ -105,9 +105,9 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
properties[("useLegacyBottomAndRightAnchors")]
.SetLabel(_(
"Stretch object when anchoring right or bottom ledge (deprecated, "
"it's recommended to let this unchecked and anchor both sides if you "
"want Sprite to stretch instead.)"))
"Stretch object when anchoring right or bottom edge (deprecated, "
"it's recommended to leave this unchecked and anchor both sides if "
"you want Sprite to stretch instead.)"))
.SetGroup(_("Deprecated options (advanced)"))
.SetValue(behaviorContent.GetBoolAttribute(
"useLegacyBottomAndRightAnchors", true)

View File

@@ -17,6 +17,7 @@ void DeclareAnchorBehaviorExtension(gd::PlatformExtension& extension) {
_("Anchor objects to the window's bounds."),
"Victor Levasseur",
"Open source (MIT License)")
.SetCategory("User interface")
.SetExtensionHelpPath("/behaviors/anchor");
gd::BehaviorMetadata& aut = extension.AddBehavior(

View File

@@ -17,8 +17,12 @@ namespace gdjs {
_bottomEdgeDistance: number = 0;
_useLegacyBottomAndRightAnchors: boolean = false;
constructor(runtimeScene, behaviorData, owner) {
super(runtimeScene, behaviorData, owner);
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
owner: gdjs.RuntimeObject
) {
super(instanceContainer, behaviorData, owner);
this._relativeToOriginalWindowSize = !!behaviorData.relativeToOriginalWindowSize;
this._leftEdgeAnchor = behaviorData.leftEdgeAnchor;
this._rightEdgeAnchor = behaviorData.rightEdgeAnchor;
@@ -65,11 +69,15 @@ namespace gdjs {
this._invalidDistances = true;
}
doStepPreEvents(runtimeScene) {
const game = runtimeScene.getGame();
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
const workingPoint: FloatPoint = gdjs.staticArray(
gdjs.AnchorRuntimeBehavior.prototype.doStepPreEvents
) as FloatPoint;
// TODO EBO Make it work with event based objects or hide this behavior for them.
const game = instanceContainer.getGame();
let rendererWidth = game.getGameResolutionWidth();
let rendererHeight = game.getGameResolutionHeight();
const layer = runtimeScene.getLayer(this.owner.getLayer());
const layer = instanceContainer.getLayer(this.owner.getLayer());
if (this._invalidDistances) {
if (this._relativeToOriginalWindowSize) {
rendererWidth = game.getOriginalWidth();
@@ -79,7 +87,9 @@ namespace gdjs {
//Calculate the distances from the window's bounds.
const topLeftPixel = layer.convertCoords(
this.owner.getDrawableX(),
this.owner.getDrawableY()
this.owner.getDrawableY(),
0,
workingPoint
);
//Left edge
@@ -125,9 +135,12 @@ namespace gdjs {
}
}
}
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const bottomRightPixel = layer.convertCoords(
this.owner.getDrawableX() + this.owner.getWidth(),
this.owner.getDrawableY() + this.owner.getHeight()
this.owner.getDrawableY() + this.owner.getHeight(),
0,
workingPoint
);
//Right edge
@@ -268,11 +281,24 @@ namespace gdjs {
}
}
}
const topLeftCoord = layer.convertInverseCoords(leftPixel, topPixel);
// It's fine to reuse workingPoint as topLeftPixel is no longer used.
const topLeftCoord = layer.convertInverseCoords(
leftPixel,
topPixel,
0,
workingPoint
);
const left = topLeftCoord[0];
const top = topLeftCoord[1];
const bottomRightCoord = layer.convertInverseCoords(
rightPixel,
bottomPixel
bottomPixel,
0,
workingPoint
);
const right = bottomRightCoord[0];
const bottom = bottomRightCoord[1];
// Compatibility with GD <= 5.0.133
if (this._useLegacyBottomAndRightAnchors) {
@@ -281,25 +307,25 @@ namespace gdjs {
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
this.owner.setWidth(right - left);
}
if (
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
this.owner.setHeight(bottom - top);
}
if (
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
left + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
top + this.owner.getY() - this.owner.getDrawableY()
);
}
}
@@ -311,15 +337,15 @@ namespace gdjs {
AnchorRuntimeBehavior.HorizontalAnchor.NONE &&
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
this.owner.setX(topLeftCoord[0]);
this.owner.setWidth(right - left);
this.owner.setX(left);
} else {
if (
this._leftEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
left + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
@@ -327,7 +353,7 @@ namespace gdjs {
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
bottomRightCoord[0] +
right +
this.owner.getX() -
this.owner.getDrawableX() -
this.owner.getWidth()
@@ -340,14 +366,14 @@ namespace gdjs {
AnchorRuntimeBehavior.VerticalAnchor.NONE &&
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
this.owner.setY(topLeftCoord[1]);
this.owner.setHeight(bottom - top);
this.owner.setY(top);
} else {
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
top + this.owner.getY() - this.owner.getDrawableY()
);
}
if (
@@ -355,7 +381,7 @@ namespace gdjs {
AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
bottomRightCoord[1] +
bottom +
this.owner.getY() -
this.owner.getDrawableY() -
this.owner.getHeight()
@@ -366,7 +392,7 @@ namespace gdjs {
}
}
doStepPostEvents(runtimeScene) {}
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {}
static HorizontalAnchor = {
NONE: 0,

View File

@@ -33,7 +33,10 @@ module.exports = {
'Todor Imreorov',
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bbtext');
.setExtensionHelpPath('/objects/bbtext')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("BBCode Text Object"))
.setIcon("JsPlatform/Extensions/bbcode32.png");
var objectBBText = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -168,7 +171,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js'
)
.setCategoryFullName(_('Texts'));
.setCategoryFullName(_('User interface'));
/**
* Utility function to add both a setter and a getter to a property from a list.
@@ -289,7 +292,7 @@ module.exports = {
const setterAndGetterProperties = [
{
functionName: 'BBText',
iconPath: 'res/actions/text24.png',
iconPath: 'res/actions/text24_black.png',
type: 'string',
paramLabel: _('BBCode text'),
conditionDescription: _('Compare the value of the BBCode text.'),
@@ -364,7 +367,7 @@ module.exports = {
},
{
functionName: 'WordWrap',
iconPath: 'res/actions/scaleWidth24.png',
iconPath: 'res/actions/scaleWidth24_black.png',
type: 'boolean',
paramLabel: _('Word wrap'),
conditionDescription: _('Check if word wrap is enabled.'),
@@ -376,7 +379,7 @@ module.exports = {
},
{
functionName: 'WrappingWidth',
iconPath: 'res/actions/scaleWidth24.png',
iconPath: 'res/actions/scaleWidth24_black.png',
type: 'number',
paramLabel: _('Wrapping width'),
conditionDescription: _(
@@ -498,7 +501,7 @@ module.exports = {
RenderedBBTextInstance.getThumbnail = function (
project,
resourcesLoader,
object
objectConfiguration
) {
return 'JsPlatform/Extensions/bbcode24.png';
};

View File

@@ -10,11 +10,11 @@ namespace gdjs {
/**
* @param runtimeObject The object to render
* @param runtimeScene The gdjs.RuntimeScene in which the object is
* @param instanceContainer The gdjs.RuntimeInstanceContainer in which the object is
*/
constructor(
runtimeObject: gdjs.BBTextRuntimeObject,
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
) {
this._object = runtimeObject;
@@ -22,7 +22,7 @@ namespace gdjs {
if (this._pixiObject === undefined) {
this._pixiObject = new MultiStyleText(runtimeObject._text, {
default: {
fontFamily: runtimeScene
fontFamily: instanceContainer
.getGame()
.getFontManager()
.getFontFamily(runtimeObject._fontFamily),
@@ -44,7 +44,7 @@ namespace gdjs {
this.updateFontFamily();
this.updateFontSize();
}
runtimeScene
instanceContainer
.getLayer('')
.getRenderer()
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
@@ -95,7 +95,8 @@ namespace gdjs {
}
updateFontFamily(): void {
this._pixiObject.textStyles.default.fontFamily = this._object._runtimeScene
this._pixiObject.textStyles.default.fontFamily = this._object
.getInstanceContainer()
.getGame()
.getFontManager()
.getFontFamily(this._object._fontFamily);

View File

@@ -48,11 +48,14 @@ namespace gdjs {
hidden: boolean;
/**
* @param runtimeScene The scene the object belongs to.
* @param instanceContainer The container the object belongs to.
* @param objectData The object data used to initialize the object
*/
constructor(runtimeScene: gdjs.RuntimeScene, objectData: BBTextObjectData) {
super(runtimeScene, objectData);
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
objectData: BBTextObjectData
) {
super(instanceContainer, objectData);
// @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;
@@ -62,7 +65,10 @@ namespace gdjs {
this._fontSize = parseFloat(objectData.content.fontSize);
this._wordWrap = objectData.content.wordWrap;
this._align = objectData.content.align;
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(this, runtimeScene);
this._renderer = new gdjs.BBTextRuntimeObjectRenderer(
this,
instanceContainer
);
this.hidden = !objectData.content.visible;
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
@@ -122,8 +128,8 @@ namespace gdjs {
}
}
onDestroyFromScene(runtimeScene): void {
super.onDestroyFromScene(runtimeScene);
onDestroyFromScene(instanceContainer: gdjs.RuntimeInstanceContainer): void {
super.onDestroyFromScene(instanceContainer);
}
/**
@@ -239,7 +245,7 @@ namespace gdjs {
this._wrappingWidth = width;
this._renderer.updateWrappingWidth();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
/**
@@ -254,7 +260,7 @@ namespace gdjs {
this._wordWrap = wordWrap;
this._renderer.updateWordWrap();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
getWordWrap() {

View File

@@ -35,7 +35,10 @@ module.exports = {
'Aurélien Vivet',
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bitmap_text');
.setExtensionHelpPath('/objects/bitmap_text')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("Bitmap Text"))
.setIcon("JsPlatform/Extensions/bitmapfont32.png");
const bitmapTextObject = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -171,7 +174,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
)
.setCategoryFullName(_('Texts'));
.setCategoryFullName(_('User interface'));
object
.addExpressionAndConditionAndAction(
@@ -181,7 +184,7 @@ module.exports = {
_('the text'),
_('the text'),
'',
'res/conditions/text24.png'
'res/conditions/text24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('string')
@@ -225,7 +228,7 @@ module.exports = {
_('the scale (1 by default)'),
_('the scale'),
'',
'res/actions/scale24.png'
'res/actions/scale24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
@@ -331,8 +334,8 @@ module.exports = {
_('Check if word wrap is enabled.'),
_('_PARAM0_ word wrap is enabled'),
'',
'res/conditions/wordWrap24.png',
'res/conditions/wordWrap.png'
'res/conditions/wordWrap24_black.png',
'res/conditions/wordWrap_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.getCodeExtraInformation()
@@ -345,8 +348,8 @@ module.exports = {
_('De/activate word wrapping.'),
_('Activate word wrap of _PARAM0_: _PARAM1_'),
'',
'res/actions/wordWrap24.png',
'res/actions/wordWrap.png'
'res/actions/wordWrap24_black.png',
'res/actions/wordWrap_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.addParameter('yesorno', _('Activate word wrap'), '', false)
@@ -361,7 +364,7 @@ module.exports = {
_('the width, in pixels, after which the text is wrapped on next line'),
_('the wrapping width'),
'',
'res/actions/scaleWidth24.png'
'res/actions/scaleWidth24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
@@ -627,7 +630,7 @@ module.exports = {
RenderedBitmapTextInstance.getThumbnail = function (
project,
resourcesLoader,
object
objectConfiguration
) {
return 'JsPlatform/Extensions/bitmapfont24.png';
};

View File

@@ -10,16 +10,16 @@ namespace gdjs {
/**
* @param runtimeObject The object to render
* @param runtimeScene The gdjs.RuntimeScene in which the object is
* @param instanceContainer The container in which the object is
*/
constructor(
runtimeObject: gdjs.BitmapTextRuntimeObject,
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
) {
this._object = runtimeObject;
// Obtain the bitmap font to use in the object.
const bitmapFont = runtimeScene
const bitmapFont = instanceContainer
.getGame()
.getBitmapFontManager()
.obtainBitmapFont(
@@ -32,7 +32,7 @@ namespace gdjs {
});
// Set the object on the scene
runtimeScene
instanceContainer
.getLayer('')
.getRenderer()
.addRendererObject(this._pixiObject, runtimeObject.getZOrder());
@@ -59,7 +59,8 @@ namespace gdjs {
onDestroy() {
// Mark the font from the object as not used anymore.
this._object._runtimeScene
this._object
.getInstanceContainer()
.getGame()
.getBitmapFontManager()
.releaseBitmapFont(this._pixiObject.fontName);
@@ -73,7 +74,8 @@ namespace gdjs {
updateFont(): void {
// Get the new bitmap font to use
const bitmapFont = this._object._runtimeScene
const bitmapFont = this._object
.getInstanceContainer()
.getGame()
.getBitmapFontManager()
.obtainBitmapFont(
@@ -82,7 +84,8 @@ namespace gdjs {
);
// Mark the old font as not used anymore
this._object._runtimeScene
this._object
.getInstanceContainer()
.getGame()
.getBitmapFontManager()
.releaseBitmapFont(this._pixiObject.fontName);

View File

@@ -50,14 +50,14 @@ namespace gdjs {
_renderer: gdjs.BitmapTextRuntimeObjectPixiRenderer;
/**
* @param runtimeScene The scene the object belongs to.
* @param instanceContainer The container the object belongs to.
* @param objectData The object data used to initialize the object
*/
constructor(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
objectData: BitmapTextObjectData
) {
super(runtimeScene, objectData);
super(instanceContainer, objectData);
this._opacity = objectData.content.opacity;
this._text = objectData.content.text;
@@ -73,7 +73,7 @@ namespace gdjs {
this._renderer = new gdjs.BitmapTextRuntimeObjectRenderer(
this,
runtimeScene
instanceContainer
);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
@@ -137,8 +137,8 @@ namespace gdjs {
}
}
onDestroyFromScene(runtimeScene: gdjs.RuntimeScene): void {
super.onDestroyFromScene(runtimeScene);
onDestroyFromScene(instanceContainer: gdjs.RuntimeInstanceContainer): void {
super.onDestroyFromScene(instanceContainer);
this._renderer.onDestroy();
}
@@ -148,7 +148,7 @@ namespace gdjs {
setText(text: string): void {
this._text = text;
this._renderer.updateTextContent();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
/**
@@ -170,7 +170,7 @@ namespace gdjs {
setScale(scale: float): void {
this._scale = scale;
this._renderer.updateScale();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
getScale(): float {
@@ -276,7 +276,7 @@ namespace gdjs {
setWrappingWidth(width: float): void {
this._wrappingWidth = width;
this._renderer.updateWrappingWidth();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
/**
@@ -289,7 +289,7 @@ namespace gdjs {
setWordWrap(wordWrap: boolean): void {
this._wordWrap = wordWrap;
this._renderer.updateWrappingWidth();
this.hitBoxesDirty = true;
this.invalidateHitboxes();
}
getWordWrap(): boolean {

View File

@@ -7,10 +7,12 @@ namespace gdjs {
export namespace debuggerTools {
/**
* Stop the game execution.
* @param runtimeScene - The current scene.
* @param instanceContainer - The current container.
*/
export const pause = function (runtimeScene: gdjs.RuntimeScene) {
runtimeScene.getGame().pause(true);
export const pause = function (
instanceContainer: gdjs.RuntimeInstanceContainer
) {
instanceContainer.getGame().pause(true);
};
/**
@@ -29,20 +31,20 @@ namespace gdjs {
/**
* Enable or disable the debug draw.
* @param runtimeScene - The current scene.
* @param instanceContainer - The current container.
* @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,
instanceContainer: gdjs.RuntimeInstanceContainer,
enableDebugDraw: boolean,
showHiddenInstances: boolean,
showPointsNames: boolean,
showCustomPoints: boolean
) {
runtimeScene.enableDebugDraw(
instanceContainer.enableDebugDraw(
enableDebugDraw,
showHiddenInstances,
showPointsNames,

View File

@@ -20,6 +20,7 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
"or other short-lived objects."),
"Florian Rival",
"Open source (MIT License)")
.SetCategory("Game mechanic")
.SetExtensionHelpPath("/behaviors/destroyoutside");
gd::BehaviorMetadata& aut =

View File

@@ -11,8 +11,12 @@ namespace gdjs {
export class DestroyOutsideRuntimeBehavior extends gdjs.RuntimeBehavior {
_extraBorder: any;
constructor(runtimeScene, behaviorData, owner) {
super(runtimeScene, behaviorData, owner);
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
owner
) {
super(instanceContainer, behaviorData, owner);
this._extraBorder = behaviorData.extraBorder || 0;
}
@@ -23,14 +27,14 @@ namespace gdjs {
return true;
}
doStepPostEvents(runtimeScene) {
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// TODO: This would better be done using the object AABB (getAABB), as (`getCenterX`;`getCenterY`) point
// is not necessarily in the middle of the object (for sprites for example).
const ow = this.owner.getWidth();
const oh = this.owner.getHeight();
const ocx = this.owner.getDrawableX() + this.owner.getCenterX();
const ocy = this.owner.getDrawableY() + this.owner.getCenterY();
const layer = runtimeScene.getLayer(this.owner.getLayer());
const layer = instanceContainer.getLayer(this.owner.getLayer());
const boundingCircleRadius = Math.sqrt(ow * ow + oh * oh) / 2.0;
if (
ocx + boundingCircleRadius + this._extraBorder <
@@ -43,7 +47,7 @@ namespace gdjs {
layer.getCameraY() + layer.getCameraHeight() / 2
) {
//We are outside the camera area.
this.owner.deleteFromScene(runtimeScene);
this.owner.deleteFromScene(instanceContainer);
}
}

View File

@@ -31,7 +31,7 @@ module.exports = {
"Matthias Meike",
"Open source (MIT License)"
).setExtensionHelpPath("/all-features/device-sensors")
.setCategory('Device');
.setCategory('Input');
extension.addInstructionOrExpressionGroupMetadata(_("Device sensors"))
.setIcon("JsPlatform/Extensions/orientation_active32.png");

View File

@@ -35,7 +35,7 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/device-vibration')
.setCategory('Device');
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("Device vibration"))
.setIcon("JsPlatform/Extensions/vibration_start32.png");

View File

@@ -34,7 +34,7 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/dialogue-tree')
.setCategory('Advanced');
.setCategory('Game mechanic');
extension
.addInstructionOrExpressionGroupMetadata(_('Dialogue Tree (experimental)'))
.setIcon('JsPlatform/Extensions/yarn32.png');

View File

@@ -30,16 +30,16 @@ namespace gdjs {
/**
* Load the Dialogue Tree data from a JSON resource.
*
* @param runtimeScene The scene where the dialogue is running.
* @param instanceContainer The scene where the dialogue is running.
* @param jsonResourceName The JSON resource where to load the Dialogue Tree data from. The data is a JSON string usually created with [Yarn Dialogue Editor](https://github.com/InfiniteAmmoInc/Yarn).
* @param startDialogueNode The Dialogue Branch to start the Dialogue Tree from. If left empty, the data will only be loaded, but can later be initialized via another action
*/
gdjs.dialogueTree.loadFromJsonFile = function (
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
jsonResourceName: string,
startDialogueNode: string
) {
runtimeScene
instanceContainer
.getGame()
.getJsonManager()
.loadJson(jsonResourceName, function (error, content) {

View File

@@ -28,13 +28,11 @@ class GD_EXTENSION_API DraggableBehavior : public gd::Behavior {
return new DraggableBehavior(*this);
}
#if defined(GD_IDE_ONLY)
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(
const gd::SerializerElement& behaviorContent) const override;
virtual bool UpdateProperty(gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) override;
#endif
virtual void InitializeContent(
gd::SerializerElement& behaviorContent) override;

View File

@@ -20,6 +20,7 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
"or disable the behavior when needed."),
"Florian Rival",
"Open source (MIT License)")
.SetCategory("User interface")
.SetExtensionHelpPath("/behaviors/draggable");
gd::BehaviorMetadata& aut = extension.AddBehavior(
@@ -33,10 +34,9 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
std::make_shared<DraggableBehavior>(),
std::shared_ptr<gd::BehaviorsSharedData>());
#if defined(GD_IDE_ONLY)
aut.AddCondition("Dragged",
_("Being dragged"),
_("Check if the object is being dragged"),
_("Check if the object is being dragged."),
_("_PARAM0_ is being dragged"),
"",
"CppPlatform/Extensions/draggableicon24.png",
@@ -45,5 +45,16 @@ void DeclareDraggableBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "Draggable")
.SetFunctionName("IsDragged");
#endif
aut.AddCondition("Dropped",
_("Was just dropped"),
_("Check if the object was just dropped after being dragged."),
_("_PARAM0_ was just dropped"),
"",
"CppPlatform/Extensions/draggableicon24.png",
"CppPlatform/Extensions/draggableicon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "Draggable")
.SetFunctionName("WasJustDropped");
}

View File

@@ -4,7 +4,6 @@ GDevelop - Draggable Behavior Extension
Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
@@ -32,6 +31,11 @@ class DraggableBehaviorJsExtension : public gd::PlatformExtension {
.SetFunctionName("isDragged")
.SetIncludeFile(
"Extensions/DraggableBehavior/draggableruntimebehavior.js");
GetAllConditionsForBehavior(
"DraggableBehavior::Draggable")["DraggableBehavior::Dropped"]
.SetFunctionName("wasJustDropped")
.SetIncludeFile(
"Extensions/DraggableBehavior/draggableruntimebehavior.js");
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
};
@@ -49,4 +53,3 @@ extern "C" gd::PlatformExtension* GD_EXTENSION_API CreateGDJSExtension() {
return new DraggableBehaviorJsExtension;
}
#endif
#endif

View File

@@ -15,9 +15,14 @@ namespace gdjs {
*/
_draggedByDraggableManager: DraggableManager | null = null;
_checkCollisionMask: boolean;
_justDropped = false;
constructor(runtimeScene, behaviorData, owner) {
super(runtimeScene, behaviorData, owner);
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
owner
) {
super(instanceContainer, behaviorData, owner);
this._checkCollisionMask = behaviorData.checkCollisionMask ? true : false;
}
@@ -37,6 +42,7 @@ namespace gdjs {
_endDrag() {
if (this._draggedByDraggableManager) {
this._draggedByDraggableManager.endDrag();
this._justDropped = true;
}
this._draggedByDraggableManager = null;
}
@@ -45,21 +51,21 @@ namespace gdjs {
this._draggedByDraggableManager = null;
}
_tryBeginDrag(runtimeScene) {
_tryBeginDrag(instanceContainer: gdjs.RuntimeInstanceContainer) {
if (this._draggedByDraggableManager) {
return false;
}
const inputManager = runtimeScene.getGame().getInputManager();
const inputManager = instanceContainer.getGame().getInputManager();
//Try mouse
const mouseDraggableManager = DraggableManager.getMouseManager(
runtimeScene
instanceContainer
);
if (
inputManager.isMouseButtonPressed(0) &&
!mouseDraggableManager.isDragging(this)
) {
if (mouseDraggableManager.tryAndTakeDragging(runtimeScene, this)) {
if (mouseDraggableManager.tryAndTakeDragging(instanceContainer, this)) {
this._draggedByDraggableManager = mouseDraggableManager;
return true;
}
@@ -68,13 +74,15 @@ namespace gdjs {
const touchIds = inputManager.getStartedTouchIdentifiers();
for (let i = 0; i < touchIds.length; ++i) {
const touchDraggableManager = DraggableManager.getTouchManager(
runtimeScene,
instanceContainer,
touchIds[i]
);
if (touchDraggableManager.isDragging(this)) {
continue;
}
if (touchDraggableManager.tryAndTakeDragging(runtimeScene, this)) {
if (
touchDraggableManager.tryAndTakeDragging(instanceContainer, this)
) {
this._draggedByDraggableManager = touchDraggableManager;
return true;
}
@@ -83,42 +91,54 @@ namespace gdjs {
return false;
}
_shouldEndDrag(runtimeScene) {
_shouldEndDrag(instanceContainer: gdjs.RuntimeInstanceContainer) {
if (!this._draggedByDraggableManager) {
return false;
}
return this._draggedByDraggableManager.shouldEndDrag(runtimeScene, this);
return this._draggedByDraggableManager.shouldEndDrag(
instanceContainer,
this
);
}
_updateObjectPosition(runtimeScene) {
_updateObjectPosition(instanceContainer: gdjs.RuntimeInstanceContainer) {
if (!this._draggedByDraggableManager) {
return false;
}
this._draggedByDraggableManager.updateObjectPosition(runtimeScene, this);
this._draggedByDraggableManager.updateObjectPosition(
instanceContainer,
this
);
return true;
}
doStepPreEvents(runtimeScene) {
this._tryBeginDrag(runtimeScene);
if (this._shouldEndDrag(runtimeScene)) {
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
this._tryBeginDrag(instanceContainer);
if (this._shouldEndDrag(instanceContainer)) {
this._endDrag();
}
this._updateObjectPosition(runtimeScene);
this._updateObjectPosition(instanceContainer);
}
doStepPostEvents(runtimeScene) {
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
const mouseDraggableManager = DraggableManager.getMouseManager(
runtimeScene
instanceContainer
);
mouseDraggableManager.leftPressedLastFrame = runtimeScene
mouseDraggableManager.leftPressedLastFrame = instanceContainer
.getGame()
.getInputManager()
.isMouseButtonPressed(0);
this._justDropped = false;
}
isDragged(runtimeScene): boolean {
isDragged(): boolean {
return !!this._draggedByDraggableManager;
}
wasJustDropped(): boolean {
return this._justDropped;
}
}
/**
@@ -137,53 +157,53 @@ namespace gdjs {
protected _xOffset: number = 0;
protected _yOffset: number = 0;
constructor(runtimeScene: gdjs.RuntimeScene) {}
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {}
/**
* Get the platforms manager of a scene.
* Get the platforms manager of an instance container.
*/
static getMouseManager(
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): MouseDraggableManager {
// @ts-ignore
if (!runtimeScene.mouseDraggableManager) {
if (!instanceContainer.mouseDraggableManager) {
//Create the shared manager if necessary.
// @ts-ignore
runtimeScene.mouseDraggableManager = new MouseDraggableManager(
runtimeScene
instanceContainer.mouseDraggableManager = new MouseDraggableManager(
instanceContainer
);
}
// @ts-ignore
return runtimeScene.mouseDraggableManager;
return instanceContainer.mouseDraggableManager;
}
/**
* Get the platforms manager of a scene.
* Get the platforms manager of an instance container.
*/
static getTouchManager(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
touchId: integer
): DraggableManager {
// @ts-ignore
if (!runtimeScene.touchDraggableManagers) {
if (!instanceContainer.touchDraggableManagers) {
//Create the shared manager if necessary.
// @ts-ignore
runtimeScene.touchDraggableManagers = [];
instanceContainer.touchDraggableManagers = [];
}
// @ts-ignore
if (!runtimeScene.touchDraggableManagers[touchId]) {
if (!instanceContainer.touchDraggableManagers[touchId]) {
//Create the shared manager if necessary.
// @ts-ignore
runtimeScene.touchDraggableManagers[
instanceContainer.touchDraggableManagers[
touchId
] = new TouchDraggableManager(runtimeScene, touchId);
] = new TouchDraggableManager(instanceContainer, touchId);
}
// @ts-ignore
return runtimeScene.touchDraggableManagers[touchId];
return instanceContainer.touchDraggableManagers[touchId];
}
tryAndTakeDragging(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
) {
if (
@@ -193,7 +213,10 @@ namespace gdjs {
) {
return false;
}
const position = this.getPosition(runtimeScene, draggableRuntimeBehavior);
const position = this.getPosition(
instanceContainer,
draggableRuntimeBehavior
);
if (
!draggableRuntimeBehavior.owner.insideObject(position[0], position[1])
) {
@@ -218,10 +241,13 @@ namespace gdjs {
}
updateObjectPosition(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
) {
const position = this.getPosition(runtimeScene, draggableRuntimeBehavior);
const position = this.getPosition(
instanceContainer,
draggableRuntimeBehavior
);
if (
draggableRuntimeBehavior.owner.getX() != position[0] - this._xOffset ||
draggableRuntimeBehavior.owner.getY() != position[1] - this._yOffset
@@ -241,11 +267,11 @@ namespace gdjs {
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean;
abstract shouldEndDrag(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean;
abstract getPosition(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint;
}
@@ -257,8 +283,8 @@ namespace gdjs {
/** Used to only start dragging when clicking. */
leftPressedLastFrame = false;
constructor(runtimeScene: gdjs.RuntimeScene) {
super(runtimeScene);
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {
super(instanceContainer);
}
isDragging(draggableRuntimeBehavior: DraggableRuntimeBehavior): boolean {
@@ -266,20 +292,28 @@ namespace gdjs {
}
getPosition(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint {
const inputManager = runtimeScene.getGame().getInputManager();
return runtimeScene
const workingPoint: FloatPoint = gdjs.staticArray(
MouseDraggableManager.prototype.getPosition
) as FloatPoint;
const inputManager = instanceContainer.getGame().getInputManager();
return instanceContainer
.getLayer(draggableRuntimeBehavior.owner.getLayer())
.convertCoords(inputManager.getMouseX(), inputManager.getMouseY());
.convertCoords(
inputManager.getMouseX(),
inputManager.getMouseY(),
0,
workingPoint
);
}
shouldEndDrag(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean {
const inputManager = runtimeScene.getGame().getInputManager();
const inputManager = instanceContainer.getGame().getInputManager();
return !inputManager.isMouseButtonPressed(0);
}
}
@@ -290,8 +324,11 @@ namespace gdjs {
class TouchDraggableManager extends DraggableManager {
private _touchId: integer;
constructor(runtimeScene: gdjs.RuntimeScene, touchId: integer) {
super(runtimeScene);
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
touchId: integer
) {
super(instanceContainer);
this._touchId = touchId;
}
@@ -300,23 +337,28 @@ namespace gdjs {
}
getPosition(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint {
const inputManager = runtimeScene.getGame().getInputManager();
return runtimeScene
const workingPoint: FloatPoint = gdjs.staticArray(
TouchDraggableManager.prototype.getPosition
) as FloatPoint;
const inputManager = instanceContainer.getGame().getInputManager();
return instanceContainer
.getLayer(draggableRuntimeBehavior.owner.getLayer())
.convertCoords(
inputManager.getTouchX(this._touchId),
inputManager.getTouchY(this._touchId)
inputManager.getTouchY(this._touchId),
0,
workingPoint
);
}
shouldEndDrag(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean {
const inputManager = runtimeScene.getGame().getInputManager();
const inputManager = instanceContainer.getGame().getInputManager();
return (
inputManager.getAllTouchIdentifiers().indexOf(this._touchId) === -1
);

View File

@@ -31,7 +31,9 @@ module.exports = {
'Lots of different effects to be used in your game.',
'Various contributors from PixiJS, PixiJS filters and GDevelop',
'MIT'
).setExtensionHelpPath('/interface/scene-editor/layer-effects');
)
.setCategory('Visual effect')
.setExtensionHelpPath('/interface/scene-editor/layer-effects');
// You can declare an effect here. Please order the effects by alphabetical order.
// This file is for common effects that are well-known/"battle-tested". If you have an

View File

@@ -539,7 +539,7 @@ module.exports = {
RenderedDummyObjectInstance.getThumbnail = function (
project,
resourcesLoader,
object
objectConfiguration
) {
return 'CppPlatform/Extensions/texticon24.png';
};

View File

@@ -11,11 +11,11 @@ namespace gdjs {
_textToSet: string;
constructor(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData: any,
owner: gdjs.RuntimeObject
) {
super(runtimeScene, behaviorData, owner);
super(instanceContainer, behaviorData, owner);
// Here you can access to the behavior data (JSON declared in JsExtension.js)
// using behaviorData:
@@ -37,7 +37,7 @@ namespace gdjs {
onDeActivate() {}
doStepPreEvents(runtimeScene) {
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// This is run at every frame, before events are launched.
this.owner
.getVariables()
@@ -45,7 +45,7 @@ namespace gdjs {
.setString(this._textToSet);
}
doStepPostEvents(runtimeScene) {
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// This is run at every frame, after events are launched.
}
}

View File

@@ -11,11 +11,11 @@ namespace gdjs {
/**
* @param runtimeObject The object to render
* @param runtimeScene The gdjs.RuntimeScene in which the object is
* @param instanceContainer The gdjs.RuntimeScene in which the object is
*/
constructor(
runtimeObject: gdjs.DummyRuntimeObject,
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
) {
this._object = runtimeObject;
@@ -27,12 +27,12 @@ namespace gdjs {
}
// You can also create a PIXI sprite or other PIXI object
// this._imageManager = runtimeScene.getGame().getImageManager();
// this._imageManager = instanceContainer.getGame().getImageManager();
// if ( this._sprite === undefined )
// this._sprite = new PIXI.Sprite(this._imageManager.getInvalidPIXITexture());
this._text.anchor.x = 0.5;
this._text.anchor.y = 0.5;
runtimeScene
instanceContainer
.getLayer('')
.getRenderer()
.addRendererObject(this._text, runtimeObject.getZOrder());

View File

@@ -14,11 +14,14 @@ namespace gdjs {
// @ts-expect-error ts-migrate(2564) FIXME: Property 'opacity' has no initializer and is not d... Remove this comment to see the full error message
opacity: float;
constructor(runtimeScene, objectData) {
constructor(instanceContainer: gdjs.RuntimeInstanceContainer, objectData) {
// *ALWAYS* call the base gdjs.RuntimeObject constructor.
super(runtimeScene, objectData);
super(instanceContainer, objectData);
this._property1 = objectData.content.property1;
this._renderer = new gdjs.DummyRuntimeObjectRenderer(this, runtimeScene);
this._renderer = new gdjs.DummyRuntimeObjectRenderer(
this,
instanceContainer
);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
@@ -40,9 +43,9 @@ namespace gdjs {
/**
* Called once during the game loop, before events and rendering.
* @param runtimeScene The gdjs.RuntimeScene the object belongs to.
* @param instanceContainer The gdjs.RuntimeScene the object belongs to.
*/
update(runtimeScene: gdjs.RuntimeScene): void {
update(instanceContainer: gdjs.RuntimeInstanceContainer): void {
// This is an example: typically you want to make sure the renderer
// is up to date with the object.
this._renderer.ensureUpToDate();

View File

@@ -4,20 +4,20 @@ namespace gdjs {
_textToSet: string;
constructor(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData: any,
owner: gdjs.RuntimeObject
) {
super(runtimeScene, behaviorData, owner);
super(instanceContainer, behaviorData, owner);
// Here you can access to the behavior data (JSON declared in JsExtension.js)
// using behaviorData:
this._textToSet = behaviorData.property1;
// You can also access to the shared data:
const sharedData = runtimeScene.getInitialSharedDataForBehavior(
behaviorData.name
);
const sharedData = instanceContainer
.getScene()
.getInitialSharedDataForBehavior(behaviorData.name);
this._textToSet = (sharedData as any).sharedProperty1;
// You can also run arbitrary code at the creation of the behavior:
@@ -40,7 +40,7 @@ namespace gdjs {
onDeActivate() {}
doStepPreEvents(runtimeScene) {
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// This is run at every frame, before events are launched.
this.owner
.getVariables()
@@ -48,7 +48,7 @@ namespace gdjs {
.setString(this._textToSet);
}
doStepPostEvents(runtimeScene) {
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// This is run at every frame, after events are launched.
}
}

View File

@@ -25,7 +25,9 @@ namespace gdjs {
* In **rare cases** you may want to run code at the start of the scene. You can define a callback
* that will be called at this moment.
*/
gdjs.registerRuntimeSceneLoadedCallback(function (runtimeScene) {
gdjs.registerRuntimeSceneLoadedCallback(function (
runtimeScene: gdjs.RuntimeScene
) {
logger.log('A gdjs.RuntimeScene was loaded:', runtimeScene);
});
@@ -33,7 +35,9 @@ namespace gdjs {
* In **rare cases** you may want to run code at the end of a scene. You can define a callback
* that will be called at this moment.
*/
gdjs.registerRuntimeSceneUnloadedCallback(function (runtimeScene) {
gdjs.registerRuntimeSceneUnloadedCallback(function (
runtimeScene: gdjs.RuntimeScene
) {
logger.log('A gdjs.RuntimeScene was unloaded:', runtimeScene);
});
@@ -41,12 +45,12 @@ namespace gdjs {
* In **very rare cases** you may want to run code whenever an object is deleted.
*/
gdjs.registerObjectDeletedFromSceneCallback(function (
runtimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
runtimeObject
) {
logger.log(
'A gdjs.RuntimeObject was deleted from a gdjs.RuntimeScene:',
runtimeScene,
instanceContainer,
runtimeObject
);
});

View File

@@ -34,7 +34,7 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/filesystem')
.setCategory('Device');
.setCategory('Advanced');
extension
.addInstructionOrExpressionGroupMetadata(_('File system'))
.setIcon('JsPlatform/Extensions/filesystem_create_folder32.png');
@@ -203,6 +203,18 @@ module.exports = {
'',
true
)
.addParameter(
'yesorno',
_('Normalize the file content (recommended)'),
'',
true
)
.setParameterLongDescription(
_(
'This replaces Windows new lines characters ("CRLF") by a single new line character.'
)
)
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadStringFromFileAsync');
@@ -229,6 +241,18 @@ module.exports = {
'',
true
)
.addParameter(
'yesorno',
_('Normalize the file content (recommended)'),
'',
true
)
.setParameterLongDescription(
_(
'This replaces Windows new lines characters ("CRLF") by a single new line character.'
)
)
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadStringFromFile');
@@ -255,6 +279,18 @@ module.exports = {
'',
true
)
.addParameter(
'yesorno',
_('Normalize the file content (recommended)'),
'',
true
)
.setParameterLongDescription(
_(
'This replaces Windows new lines characters ("CRLF") by a single new line character.'
)
)
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadVariableFromJSONFile');
@@ -281,6 +317,18 @@ module.exports = {
'',
true
)
.addParameter(
'yesorno',
_('Normalize the file content (recommended)'),
'',
true
)
.setParameterLongDescription(
_(
'This replaces Windows new lines characters ("CRLF") by a single new line character.'
)
)
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadVariableFromJSONFileAsync');

View File

@@ -48,13 +48,16 @@ namespace gdjs {
/**
* Get the path to 'Desktop' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to the desktop folder
*/
export const getDesktopPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('desktop') || '';
@@ -65,13 +68,16 @@ namespace gdjs {
/**
* Get the path to 'Documents' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to the documents folder
*/
export const getDocumentsPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('documents') || '';
@@ -82,13 +88,16 @@ namespace gdjs {
/**
* Get the path to 'Pictures' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to the pictures folder
*/
export const getPicturesPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('pictures') || '';
@@ -99,13 +108,16 @@ namespace gdjs {
/**
* Get the path to this application 'Executable' file.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to this applications executable file
*/
export const getExecutablePath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('exe') || '';
@@ -116,14 +128,16 @@ namespace gdjs {
/**
* Get the path to this application 'Executable' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to this applications executable folder
*/
export const getExecutableFolderPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const path = gdjs.fileSystem._getPath();
const executablePath = gdjs.fileSystem.getExecutablePath(runtimeScene);
const executablePath = gdjs.fileSystem.getExecutablePath(
instanceContainer
);
if (!path) {
return '';
}
@@ -132,13 +146,16 @@ namespace gdjs {
/**
* Get the path to 'UserData' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to userdata folder
*/
export const getUserdataPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('userData') || '';
@@ -152,9 +169,12 @@ namespace gdjs {
* @return The path to user's "home" folder
*/
export const getUserHomePath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('home') || '';
@@ -165,13 +185,16 @@ namespace gdjs {
/**
* Get the path to 'Temp' folder.
* @param runtimeScene The current scene
* @param instanceContainer The current container
* @return The path to temp folder
*/
export const getTempPath = function (
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): string {
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const remote = instanceContainer
.getGame()
.getRenderer()
.getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('temp') || '';
@@ -338,11 +361,13 @@ namespace gdjs {
* @param stringVar Variable where to store the content
* @param loadPath Path to the file
* @param resultVar The variable where to store the result of the operation
* @param removeCRCharacters If true, will remove \r characters usually added by Windows when editing files
*/
export const loadStringFromFile = function (
stringVar: gdjs.Variable,
loadPath: string,
resultVar: gdjs.Variable
resultVar: gdjs.Variable,
removeCRCharacters: boolean
) {
const fileSystem = gdjs.fileSystem._getFs();
let result = 'error';
@@ -350,7 +375,9 @@ namespace gdjs {
try {
const data = fileSystem.readFileSync(loadPath, 'utf8');
if (data) {
stringVar.setString(data);
stringVar.setString(
removeCRCharacters ? data.replace(/\r/g, '') : data
);
result = 'ok';
}
} catch (err) {
@@ -368,11 +395,13 @@ namespace gdjs {
* @param variable Variable to store the variable
* @param loadPath Path to the file
* @param resultVar The variable where to store the result of the operation
* @param removeCRCharacters If true, will remove \r characters usually added by Windows when editing files
*/
export const loadVariableFromJSONFile = function (
variable: gdjs.Variable,
loadPath: string,
resultVar: gdjs.Variable
resultVar: gdjs.Variable,
removeCRCharacters: boolean
) {
const fileSystem = gdjs.fileSystem._getFs();
let result = 'error';
@@ -380,7 +409,9 @@ namespace gdjs {
try {
const data = fileSystem.readFileSync(loadPath, 'utf8');
if (data) {
variable.fromJSON(data);
variable.fromJSON(
removeCRCharacters ? data.replace(/\r/g, '') : data
);
result = 'ok';
}
} catch (err) {
@@ -400,17 +431,21 @@ namespace gdjs {
* @param variable Variable to store the variable
* @param loadPath Path to the file
* @param resultVar The variable where to store the result of the operation
* @param removeCRCharacters If true, will remove \r characters usually added by Windows when editing files
*/
export const loadVariableFromJSONFileAsync = function (
variable: gdjs.Variable,
loadPath: string,
resultVar: gdjs.Variable
resultVar: gdjs.Variable,
removeCRCharacters: boolean
) {
const fileSystem = gdjs.fileSystem._getFs();
if (fileSystem) {
fileSystem.readFile(loadPath, 'utf8', (err, data) => {
if (data) {
variable.fromJSON(data);
variable.fromJSON(
removeCRCharacters ? data.replace(/\r/g, '') : data
);
resultVar.setString('ok');
}
if (err) {
@@ -431,17 +466,21 @@ namespace gdjs {
* @param stringVar Variable where to store the content
* @param loadPath Path to the file
* @param resultVar The variable where to store the result of the operation
* @param removeCRCharacters If true, will remove \r characters usually added by Windows when editing files
*/
export const loadStringFromFileAsync = function (
stringVar: gdjs.Variable,
loadPath: string,
resultVar: gdjs.Variable
resultVar: gdjs.Variable,
removeCRCharacters: boolean
) {
const fileSystem = gdjs.fileSystem._getFs();
if (fileSystem) {
fileSystem.readFile(loadPath, 'utf8', (err, data) => {
if (data) {
stringVar.setString(data);
stringVar.setString(
removeCRCharacters ? data.replace(/\r/g, '') : data
);
resultVar.setString('ok');
}
if (err) {

View File

@@ -19,7 +19,7 @@ void DeclareInventoryExtension(gd::PlatformExtension& extension) {
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/inventory")
.SetCategory("Advanced");
.SetCategory("Game mechanic");
extension
.AddInstructionOrExpressionGroupMetadata(_("Inventories"))
.SetIcon("CppPlatform/Extensions/Inventoryicon.png");

View File

@@ -1,7 +1,13 @@
namespace gdjs {
export interface RuntimeGame {
inventories: { [name: string]: gdjs.Inventory };
}
export class InventoryManager {
static get(runtimeScene, name): gdjs.Inventory {
const game = runtimeScene.getGame();
static get(
instanceContainer: gdjs.RuntimeInstanceContainer,
name: string
): gdjs.Inventory {
const game = instanceContainer.getGame();
if (!game.inventories) {
game.inventories = {};
}
@@ -15,70 +21,106 @@ namespace gdjs {
export namespace evtTools {
export namespace inventory {
export const add = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).add(name);
export const add = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(instanceContainer, inventoryName).add(name);
};
export const remove = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).remove(name);
export const remove = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(instanceContainer, inventoryName).remove(
name
);
};
export const count = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).count(name);
export const count = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(instanceContainer, inventoryName).count(
name
);
};
export const has = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).has(name);
export const has = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(instanceContainer, inventoryName).has(name);
};
export const setMaximum = function (
runtimeScene,
inventoryName,
name,
maxCount
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string,
maxCount: number
) {
return InventoryManager.get(runtimeScene, inventoryName).setMaximum(
name,
maxCount
);
return InventoryManager.get(
instanceContainer,
inventoryName
).setMaximum(name, maxCount);
};
export const setUnlimited = function (
runtimeScene,
inventoryName,
name,
enable
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string,
enable: boolean
) {
return InventoryManager.get(runtimeScene, inventoryName).setUnlimited(
name,
enable
return InventoryManager.get(
instanceContainer,
inventoryName
).setUnlimited(name, enable);
};
export const isFull = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(instanceContainer, inventoryName).isFull(
name
);
};
export const isFull = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).isFull(name);
};
export const equip = function (runtimeScene, inventoryName, name, equip) {
return InventoryManager.get(runtimeScene, inventoryName).equip(
export const equip = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string,
equip: boolean
) {
return InventoryManager.get(instanceContainer, inventoryName).equip(
name,
equip
);
};
export const isEquipped = function (runtimeScene, inventoryName, name) {
return InventoryManager.get(runtimeScene, inventoryName).isEquipped(
name
);
export const isEquipped = function (
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
name: string
) {
return InventoryManager.get(
instanceContainer,
inventoryName
).isEquipped(name);
};
export const serializeToVariable = function (
runtimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
variable: gdjs.Variable
) {
const allItems = gdjs.InventoryManager.get(
runtimeScene,
instanceContainer,
inventoryName
).getAllItems();
for (const name in allItems) {
@@ -92,12 +134,12 @@ namespace gdjs {
};
export const unserializeFromVariable = function (
runtimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
inventoryName: string,
variable: gdjs.Variable
) {
const inventory = gdjs.InventoryManager.get(
runtimeScene,
instanceContainer,
inventoryName
);
inventory.clear();

View File

@@ -20,7 +20,7 @@ export type ObjectsRenderingService = {
RenderedInstance: any,
registerInstanceRenderer: (objectType: string, renderer: any) => void,
requireModule: (dirname: string, moduleName: string) => any,
getThumbnail: (project: gdProject, object: gdObject) => string,
getThumbnail: (project: gdProject, objectConfiguration: gdObjectConfiguration) => string,
rgbOrHexToHexNumber: (value: string) => number,
};
export type ObjectsEditorService = {

View File

@@ -34,7 +34,7 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/leaderboards')
.setCategory('Leaderboards')
.setCategory('Players')
.addInstructionOrExpressionGroupMetadata(_('Leaderboards (experimental)'))
.setIcon('JsPlatform/Extensions/leaderboard.svg');
@@ -65,6 +65,32 @@ module.exports = {
.addIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.savePlayerScore');
extension
.addAction(
'SaveConnectedPlayerScore',
_('Save connected player score'),
_("Save the connected player's score to the given leaderboard."),
_(
'Send to leaderboard _PARAM1_ the score _PARAM2_ for the connected player'
),
_('Save score'),
'JsPlatform/Extensions/leaderboard.svg',
'JsPlatform/Extensions/leaderboard.svg'
)
.addCodeOnlyParameter('currentScene', '')
.addParameter('leaderboardId', _('Leaderboard'), '', false)
.addParameter(
'expression',
_('Score to register for the player'),
'',
false
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/sha256.js')
.addIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.saveConnectedPlayerScore');
extension
.addCondition(
'HasLastSaveErrored',

View File

@@ -1,5 +1,6 @@
/// <reference path="sha256.d.ts" />
// TODO EBO Replace runtimeScene to instanceContainer.
namespace gdjs {
const logger = new gdjs.Logger('Leaderboards');
export namespace evtTools {
@@ -16,8 +17,10 @@ namespace gdjs {
lastScoreSavingSucceededAt: number | null;
currentlySavingScore: number | null;
currentlySavingPlayerName: string | null;
currentlySavingPlayerId: string | null;
lastSavedScore: number | null;
lastSavedPlayerName: string | null;
lastSavedPlayerId: string | null;
lastSaveError: string | null;
isScoreSaving: boolean;
hasScoreBeenSaved: boolean;
@@ -28,49 +31,79 @@ namespace gdjs {
this.lastScoreSavingSucceededAt = null;
this.currentlySavingScore = null;
this.currentlySavingPlayerName = null;
this.currentlySavingPlayerId = null;
this.lastSavedScore = null;
this.lastSavedPlayerName = null;
this.lastSavedPlayerId = null;
this.lastSaveError = null;
this.isScoreSaving = false;
this.hasScoreBeenSaved = false;
this.hasScoreSavingErrored = false;
}
isSameAsLastScore(playerName: string, score: number): boolean {
isSameAsLastScore({
playerName,
playerId,
score,
}: {
playerName?: string;
playerId?: string;
score: number;
}): boolean {
return (
this.lastSavedPlayerName === playerName &&
((!!playerName && this.lastSavedPlayerName === playerName) ||
(!!playerId && this.lastSavedPlayerId === playerId)) &&
this.lastSavedScore === score
);
}
isAlreadySavingThisScore(playerName: string, score: number): boolean {
isAlreadySavingThisScore({
playerName,
playerId,
score,
}: {
playerName?: string;
playerId?: string;
score: number;
}): boolean {
return (
((!!playerName && this.currentlySavingPlayerName === playerName) ||
(!!playerId && this.currentlySavingPlayerId === playerId)) &&
this.isScoreSaving &&
this.currentlySavingPlayerName === playerName &&
this.currentlySavingScore === score
);
}
isTooSoonToSaveAnotherScore(): boolean {
return (
!!this.lastScoreSavingSucceededAt &&
Date.now() - this.lastScoreSavingSucceededAt < 500
!!this.lastScoreSavingStartedAt &&
Date.now() - this.lastScoreSavingStartedAt < 500
);
}
startSaving(playerName: string, score: number): void {
startSaving({
playerName,
playerId,
score,
}: {
playerName?: string;
playerId?: string;
score: number;
}): void {
this.lastScoreSavingStartedAt = Date.now();
this.isScoreSaving = true;
this.hasScoreBeenSaved = false;
this.hasScoreSavingErrored = false;
this.currentlySavingScore = score;
this.currentlySavingPlayerName = playerName;
if (playerName) this.currentlySavingPlayerName = playerName;
if (playerId) this.currentlySavingPlayerId = playerId;
}
closeSaving(): void {
this.lastScoreSavingSucceededAt = Date.now();
this.lastSavedScore = this.currentlySavingScore;
this.lastSavedPlayerName = this.currentlySavingPlayerName;
this.lastSavedPlayerId = this.currentlySavingPlayerId;
this.isScoreSaving = false;
this.hasScoreBeenSaved = true;
}
@@ -155,50 +188,29 @@ namespace gdjs {
return lastScoreSavingState;
};
export const savePlayerScore = function (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float,
playerName: string
) {
let scoreSavingState: ScoreSavingState;
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
if (scoreSavingState.isAlreadySavingThisScore(playerName, score)) {
logger.warn(
'There is already a request to save with this player name and this score. Ignoring this one.'
);
return;
}
if (scoreSavingState.isSameAsLastScore(playerName, score)) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
const errorCode = 'SAME_AS_PREVIOUS';
scoreSavingState.setError(errorCode);
return;
}
if (scoreSavingState.isTooSoonToSaveAnotherScore()) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
const errorCode = 'TOO_FAST';
scoreSavingState.setError(errorCode);
return;
}
} else {
scoreSavingState = new ScoreSavingState();
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
scoreSavingState.startSaving(playerName, score);
const baseUrl = 'https://api.gdevelop-app.com/play';
const saveScore = function ({
leaderboardId,
playerName,
authenticatedPlayerData,
score,
scoreSavingState,
runtimeScene,
}: {
leaderboardId: string;
playerName?: string | null;
authenticatedPlayerData?: { playerId: string; playerToken: string };
score: number;
scoreSavingState: ScoreSavingState;
runtimeScene: gdjs.RuntimeScene;
}) {
const rootApi = runtimeScene
.getGame()
.isUsingGDevelopDevelopmentEnvironment()
? 'https://api-dev.gdevelop.io'
: 'https://api.gdevelop.io';
const baseUrl = `${rootApi}/play`;
const game = runtimeScene.getGame();
const payload = JSON.stringify({
playerName: formatPlayerName(playerName),
const payloadObject = {
score: score,
sessionId: game.getSessionId(),
clientPlayerId: game.getPlayerId(),
@@ -206,18 +218,28 @@ namespace gdjs {
typeof window !== 'undefined' && (window as any).location
? (window as any).location.href
: '',
});
fetch(
`${baseUrl}/game/${gdjs.projectData.properties.projectUuid}/leaderboard/${leaderboardId}/entry`,
{
body: payload,
method: 'POST',
headers: {
'Content-Type': 'application/json',
Digest: computeDigest(payload),
},
}
).then(
};
const headers = {
'Content-Type': 'application/json',
};
let leaderboardEntryCreationUrl = `${baseUrl}/game/${gdjs.projectData.properties.projectUuid}/leaderboard/${leaderboardId}/entry`;
if (authenticatedPlayerData) {
headers[
'Authorization'
] = `player-game-token ${authenticatedPlayerData.playerToken}`;
leaderboardEntryCreationUrl += `?playerId=${authenticatedPlayerData.playerId}`;
} else {
// In case playerName is empty or undefined, the formatting will generate a random name.
payloadObject['playerName'] = formatPlayerName(playerName);
}
const payload = JSON.stringify(payloadObject);
headers['Digest'] = computeDigest(payload);
fetch(leaderboardEntryCreationUrl, {
body: payload,
method: 'POST',
headers: headers,
}).then(
(response) => {
if (!response.ok) {
const errorCode = response.status.toString();
@@ -250,6 +272,139 @@ namespace gdjs {
);
};
export const savePlayerScore = function (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float,
playerName: string
) {
let scoreSavingState: ScoreSavingState;
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
let shouldStartSaving = true;
if (
shouldStartSaving &&
scoreSavingState.isAlreadySavingThisScore({ playerName, score })
) {
logger.warn(
'There is already a request to save with this player name and this score. Ignoring this one.'
);
shouldStartSaving = false;
}
if (
shouldStartSaving &&
scoreSavingState.isSameAsLastScore({ playerName, score })
) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
scoreSavingState.setError('SAME_AS_PREVIOUS');
shouldStartSaving = false;
}
if (
shouldStartSaving &&
scoreSavingState.isTooSoonToSaveAnotherScore()
) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
scoreSavingState.setError('TOO_FAST');
shouldStartSaving = false;
// Set the starting time to cancel all the following attempts that
// are started too early after this one.
scoreSavingState.lastScoreSavingStartedAt = Date.now();
}
if (!shouldStartSaving) {
return;
}
} else {
scoreSavingState = new ScoreSavingState();
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
scoreSavingState.startSaving({ playerName, score });
saveScore({
leaderboardId,
playerName,
score,
scoreSavingState,
runtimeScene,
});
};
export const saveConnectedPlayerScore = function (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float
) {
let scoreSavingState: ScoreSavingState;
const playerId = gdjs.playerAuthentication.getUserId();
const playerToken = gdjs.playerAuthentication.getUserToken();
if (!playerId || !playerToken) {
logger.warn(
'Cannot save a score for a connected player if the player is not connected.'
);
return;
}
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
scoreSavingState = _scoreSavingStateByLeaderboard[leaderboardId];
let shouldStartSaving = true;
if (
shouldStartSaving &&
scoreSavingState.isAlreadySavingThisScore({ playerId, score })
) {
logger.warn(
'There is already a request to save with this player ID and this score. Ignoring this one.'
);
shouldStartSaving = false;
}
if (
shouldStartSaving &&
scoreSavingState.isSameAsLastScore({ playerId, score })
) {
logger.warn(
'The player and score to be sent are the same as previous one. Ignoring this one.'
);
scoreSavingState.setError('SAME_AS_PREVIOUS');
shouldStartSaving = false;
}
if (
shouldStartSaving &&
scoreSavingState.isTooSoonToSaveAnotherScore()
) {
logger.warn(
'Last entry was sent too little time ago. Ignoring this one.'
);
scoreSavingState.setError('TOO_FAST');
shouldStartSaving = false;
// Set the starting time to cancel all the following attempts that
// are started too early after this one.
scoreSavingState.lastScoreSavingStartedAt = Date.now();
}
if (!shouldStartSaving) {
return;
}
} else {
scoreSavingState = new ScoreSavingState();
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
scoreSavingState.startSaving({ playerId, score });
saveScore({
leaderboardId,
authenticatedPlayerData: { playerId, playerToken },
score,
scoreSavingState,
runtimeScene,
});
};
export const isSaving = function (leaderboardId?: string): boolean {
if (leaderboardId) {
return _scoreSavingStateByLeaderboard[leaderboardId]
@@ -315,7 +470,9 @@ namespace gdjs {
: 'NO_DATA_ERROR';
};
export const formatPlayerName = function (rawName: string): string {
export const formatPlayerName = function (
rawName?: string | null
): string {
if (
!rawName ||
typeof rawName !== 'string' ||
@@ -512,7 +669,12 @@ namespace gdjs {
}
const gameId = gdjs.projectData.properties.projectUuid;
const targetUrl = `https://liluo.io/games/${gameId}/leaderboard/${leaderboardId}?inGameEmbedded=true`;
const isDev = runtimeScene
.getGame()
.isUsingGDevelopDevelopmentEnvironment();
const targetUrl = `https://liluo.io/games/${gameId}/leaderboard/${leaderboardId}?inGameEmbedded=true${
isDev ? '&dev=true' : ''
}`;
checkLeaderboardAvailability(targetUrl).then(
(isAvailable) => {
if (leaderboardId !== _requestedLeaderboardId) {

View File

@@ -32,7 +32,8 @@ module.exports = {
'This provides a light object, and a behavior to mark other objects as being obstacles for the lights. This is a great way to create a special atmosphere to your game, along with effects, make it more realistic or to create gameplays based on lights.',
'Harsimran Virk',
'MIT'
);
)
.setCategory('Visual effect');
const lightObstacleBehavior = new gd.BehaviorJsImplementation();
// $FlowExpectedError - ignore Flow warning as we're creating a behavior
@@ -195,7 +196,7 @@ module.exports = {
.setIncludeFile('Extensions/Lighting/lightruntimeobject.js')
.addIncludeFile('Extensions/Lighting/lightruntimeobject-pixi-renderer.js')
.addIncludeFile('Extensions/Lighting/lightobstacleruntimebehavior.js')
.setCategoryFullName(_('Lights'));
.setCategoryFullName(_('Visual effect'));
object
.addAction(
@@ -370,7 +371,7 @@ module.exports = {
RenderedLightObjectInstance.getThumbnail = function (
project,
resourcesLoader,
object
objectConfiguration
) {
return 'CppPlatform/Extensions/lightIcon32.png';
};

View File

@@ -4,26 +4,26 @@ namespace gdjs {
export class LightObstaclesManager {
_obstacleRBush: any;
constructor(runtimeScene: gdjs.RuntimeScene) {
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {
this._obstacleRBush = new rbush();
}
/**
* Get the light obstacles manager of a scene.
* Get the light obstacles manager of an instance container.
*/
static getManager(
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
): gdjs.LightObstaclesManager {
// @ts-ignore
if (!runtimeScene._lightObstaclesManager) {
if (!instanceContainer._lightObstaclesManager) {
// Create the shared manager if necessary.
// @ts-ignore
runtimeScene._lightObstaclesManager = new gdjs.LightObstaclesManager(
runtimeScene
instanceContainer._lightObstaclesManager = new gdjs.LightObstaclesManager(
instanceContainer
);
}
// @ts-ignore
return runtimeScene._lightObstaclesManager;
return instanceContainer._lightObstaclesManager;
}
/**
@@ -92,15 +92,15 @@ namespace gdjs {
_registeredInManager: boolean = false;
constructor(
runtimeScene: gdjs.RuntimeScene,
instanceContainer: gdjs.RuntimeInstanceContainer,
behaviorData,
owner: gdjs.RuntimeObject
) {
super(runtimeScene, behaviorData, owner);
this._manager = LightObstaclesManager.getManager(runtimeScene);
super(instanceContainer, behaviorData, owner);
this._manager = LightObstaclesManager.getManager(instanceContainer);
}
doStepPreEvents(runtimeScene: gdjs.RuntimeScene) {
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// Make sure the obstacle is or is not in the obstacles manager.
if (!this.activated() && this._registeredInManager) {
this._manager.removeObstacle(this);

View File

@@ -7,7 +7,7 @@ namespace gdjs {
*/
export class LightRuntimeObjectPixiRenderer {
_object: gdjs.LightRuntimeObject;
_runtimeScene: gdjs.RuntimeScene;
_instanceContainer: gdjs.RuntimeInstanceContainer;
_manager: gdjs.LightObstaclesManager;
_radius: number;
_color: [number, number, number];
@@ -30,10 +30,10 @@ namespace gdjs {
constructor(
runtimeObject: gdjs.LightRuntimeObject,
runtimeScene: gdjs.RuntimeScene
instanceContainer: gdjs.RuntimeInstanceContainer
) {
this._object = runtimeObject;
this._runtimeScene = runtimeScene;
this._instanceContainer = instanceContainer;
this._manager = runtimeObject.getObstaclesManager();
this._radius = runtimeObject.getRadius();
const objectColor = runtimeObject._color;
@@ -57,14 +57,14 @@ namespace gdjs {
]);
this._indexBuffer = new Uint16Array([0, 1, 2, 0, 2, 3]);
this.updateMesh();
this._isPreview = runtimeScene.getGame().isPreview();
this._isPreview = instanceContainer.getGame().isPreview();
this._lightBoundingPoly = gdjs.Polygon.createRectangle(0, 0);
this.updateDebugMode();
// Objects will be added in lighting layer, this is just to maintain consistency.
if (this._light) {
runtimeScene
instanceContainer
.getLayer('')
.getRenderer()
.addRendererObject(
@@ -198,7 +198,7 @@ namespace gdjs {
const texture = this._object.getTexture();
this._texture =
texture !== ''
? (this._runtimeScene
? (this._instanceContainer
.getGame()
.getImageManager() as gdjs.PixiImageManager).getPIXITexture(
texture

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