Compare commits

..

105 Commits

Author SHA1 Message Date
Florian Rival
124079c50f Fix formatting 2020-04-16 18:46:44 +02:00
Arthur Pacaud
2e42fc01be Fix gdjs.WebsocketDebuggerClient (#1662) 2020-04-16 16:35:10 +02:00
Florian Rival
770aad5672 Fix electron module not accessible in previews 2020-04-16 09:26:08 +02:00
Aurélien Vivet
bef1b9fb1e Add JSDoc to evt.common functions (#1640) 2020-04-15 22:14:17 +02:00
Florian Rival
831dce0f51 Bump newIDE version 2020-04-15 09:58:22 +02:00
Florian Rival
2da4e79d06 Upgrade material-ui to 4.9.10 to avoid infinite rerender of text areas (#1656) 2020-04-14 23:03:55 +02:00
Florian Rival
804a07c56e Add "Jump sustain time" to Platformer Object behavior (#1650) 2020-04-14 11:24:45 +02:00
Florian Rival
b367f13116 Fix popovers in ForEach/JsCode/Link/Repeat events
Also ensure the fields are focused when opened.
Fix #1653.
2020-04-14 10:04:33 +02:00
Florian Rival
581d7716f7 Fix imports 2020-04-14 10:01:27 +02:00
Nilay Majorwar
19de7aefbc Fix confirmation dialogs making the app lose the focus on Windows (#1649)
Fix #1646

Electron default confirm and alert dialogs don't play nicely with the focus on Windows.
2020-04-14 09:57:22 +02:00
Florian Rival
57759aa1b8 Run auto formatting on platformerobjectruntimebehavior.spec.js 2020-04-13 21:39:38 +02:00
Todor Imreorov
07876afc28 fix "Select option by number" in Dialogue Tree (#1648) 2020-04-13 19:17:06 +02:00
Aurélien Vivet
b9029fba4d Fix help button for BBText objects (#1647) 2020-04-13 14:46:13 +02:00
Florian Rival
c4ba357296 Bump newIDE version 2020-04-13 11:16:06 +02:00
Florian Rival
a47acbb82a Fix deploy script for web-app 2020-04-12 20:05:58 +02:00
Florian Rival
f1f93c9be0 Update translations 2020-04-12 19:54:05 +02:00
Florian Rival
f56d864efb Add cannon-ball-with-physics example 2020-04-12 19:29:19 +02:00
Florian Rival
017f8cf554 Update flappy bird example 2020-04-12 19:19:12 +02:00
Arthur Pacaud
d8546c5547 Add doc and type annotations to gdjs.WebsocketDebuggerClient (#1637) 2020-04-11 18:37:28 +02:00
Florian Rival
0bc6e41709 Remove extra console.log and close confirm dialog in development 2020-04-11 16:28:55 +02:00
Florian Rival
943fac772d Fix translation and warn about unsaved changes in CloseConfirmDialog 2020-04-10 23:24:34 +02:00
Florian Rival
327e4cb6a3 Fix horizontal scrollbar in ExpressionAutocompletionsDisplayer 2020-04-10 19:58:12 +02:00
Florian Rival
277989f329 Fix ExpressionSelector positioning when errors shown in an expression 2020-04-10 19:58:12 +02:00
Florian Rival
2bdae4ed14 Display autocompletions at the bottom of the input 2020-04-10 19:58:12 +02:00
Florian Rival
4bfbd7c78f Add autocompletions when typing an expression
Add ExpressionAutocompletion, ExpressionAutocompletionsDisplayer, ExpressionAutocompletionsHandler.
2020-04-10 19:58:12 +02:00
Harsimran Singh Virk
7b76564dda Fix for redundant scrollbar in Project Manager (#1635) 2020-04-10 14:35:50 +02:00
Florian Rival
41a2b87dd0 Fix unsaved changes not triggered when editing an object 2020-04-09 22:56:52 +02:00
Nilay Majorwar
397781bb98 Disable some menu items if no project is opened (#1626) 2020-04-09 22:25:23 +02:00
Florian Rival
b4fa741717 Upgrade to electron-builder 21.2.0
* Use new entitlement to avoid the packaged and signed macOS app to crash when launched.
* Don't upgrade to a newer version of electron-builder because not compatible with macOS 10.13 it seems
2020-04-09 21:47:14 +02:00
Nilay Majorwar
6e16bd764f Upgrade IDE to Electron v8.2.1 (#1589) 2020-04-09 21:34:51 +02:00
Florian Rival
1071b66c92 Enhance typing of MenuItemTemplate in the whole app 2020-04-08 19:42:02 +02:00
Florian Rival
9ff6d91717 Simplify a bit extra menu item handling in ProjectManager 2020-04-08 19:24:35 +02:00
Nilay Majorwar
bda1eb01d2 Add menu items to scene context menu to edit properties or variables (#1607) 2020-04-08 18:43:32 +02:00
Florian Rival
dfcaf472c7 Fix tests 2020-04-07 16:26:06 +02:00
Florian Rival
c8a9da6aea Fix some bad characters in results of HelpFinder 2020-04-05 19:26:23 +02:00
Florian Rival
daa50931ae Fix formatting 2020-04-05 17:31:01 +02:00
Florian Rival
f84a97a4f2 Move Cursor/touch on object condition to an "object" condition
See #1611
2020-04-05 17:25:09 +02:00
Aurélien Vivet
10d5c403a7 Add preload auto to fix video in electron 8+ and Chrome 76+ (#1624) 2020-04-05 17:14:28 +02:00
Florian Rival
15471e6e28 Move EventsScope to InstructionOrExpression folder 2020-04-05 14:21:35 +02:00
Florian Rival
7ccebc69fa Fix warnings in Storybook 2020-04-05 12:12:03 +02:00
Florian Rival
4c57fbc01f Rename enumerateInstructions to enumerateAllInstructions 2020-04-05 12:02:45 +02:00
Florian Rival
ed58ebd3be Add imperative methods to SemiControlledTextField 2020-04-05 11:40:08 +02:00
dependabot[bot]
9cae4fb264 Bump minimist from 1.2.0 to 1.2.3 in /newIDE/web-app (#1623)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.3.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.0...1.2.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-04-05 10:49:51 +02:00
Florian Rival
83e7314863 Clean the GDJS runtime folder only when starting the development app
Potential fix for filesystem issue like #1528
2020-04-04 22:36:03 +02:00
Florian Rival
8ec56164af Update GDevelop-services urls to use proper subdomains 2020-04-04 15:56:39 +02:00
Aurélien Vivet
ba0c4a9bc4 Improve bug reports with system details (#1612) 2020-04-04 15:51:24 +02:00
dependabot[bot]
8706dc727d Bump minimist from 1.2.0 to 1.2.3 in /newIDE/electron-app/app (#1619)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.3.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.0...1.2.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-04-04 13:53:15 +02:00
dependabot[bot]
7ee9facb34 Bump minimist from 1.2.0 to 1.2.3 in /newIDE/electron-app (#1620)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.0 to 1.2.3.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.0...1.2.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-04-04 13:52:58 +02:00
gautamv95
4190cbda88 Rationalise dismissing of dialogs with click outside/escape key (#1522)
Fix #1517
2020-04-01 10:05:03 +02:00
Florian Rival
aa73b01bbc Fix warning in ContextMenu 2020-04-01 09:54:43 +02:00
Florian Rival
b242c7863f Add asterisk in titlebar when the file is modified 2020-04-01 09:51:20 +02:00
Apostoles
41550ee10f Track changes to display a smart unsaved changes warning (#1523) 2020-03-31 22:35:08 +02:00
Florian Rival
7af0999f59 Remove obsolete ExternalEditor in LocalApp (#1604) 2020-03-31 09:45:15 +02:00
Nilay Majorwar
93e0ccc163 Add Prettier to electron-app and autoformat files (#1602) 2020-03-30 20:25:08 +02:00
Aurélien Vivet
94303fccc2 Update required CMake version for GDevelop.js (#1600) 2020-03-30 16:05:24 +02:00
Aurélien Vivet
33949fd93c Add option to use MinGW instead ninja for GDevelop.js (#1599) 2020-03-29 23:21:55 +02:00
Harsimran Singh Virk
bd40bb892c Fix selection issues in the Autocomplete lists (#1586) 2020-03-29 21:11:20 +02:00
Florian Rival
c2cf935bd9 Fix typo 2020-03-28 18:24:06 +01:00
Quarkstar
c7d5ab8013 Update Twist/ZoomBlur/RadialBlur to be centered by default (#1564)
Remove dependency on window size, preparing for object effects support
2020-03-25 23:33:55 +01:00
Florian Rival
e8c93a5622 Add autoHideScrollbar and fix scrolling in ScrollView 2020-03-25 22:36:03 +01:00
Garett Tok Ern Liang
348459481a Fix Left/Right Ctrl/Shift/Alt/Meta not recognised as separate keys (#1553) 2020-03-25 21:13:08 +01:00
Florian Rival
e7348f08c4 Update bouncing-ball-and-rope example 2020-03-24 21:46:35 +01:00
Harsimran Singh Virk
ef96adee92 Close InlinePopover after selection in an autocomplete field (#1568)
Also if Escape key is pressed
2020-03-24 08:55:40 +01:00
Florian Rival
66b3ec1686 Rename IsInformative to IsExact in ExpressionCompletionFinder 2020-03-23 23:32:33 +01:00
Arthur Pacaud
b77eb123e8 Move loadObject to registerObject method in gdjs.RuntimeScene (#1572) 2020-03-22 21:32:43 +01:00
Florian Rival
dcba4272e0 Fix description in CRT 2020-03-22 17:16:24 +01:00
Quarkstar
c2dd5a0a09 Allow to change the animation speed/frequency of effects (#1554) 2020-03-22 17:13:05 +01:00
Aurélien Vivet
a6ae265705 Improve visibility of parameter for checkbox in effects list (#1575) 2020-03-22 15:42:51 +01:00
Florian Rival
94fb2fede6 Remove dead code 2020-03-22 15:41:13 +01:00
Jimil Desai
7bcaf55342 Fix warning not showing when using a digit as first character for a name (#1560) 2020-03-22 15:24:28 +01:00
Geetesh Gupta
cc9632e7c1 Remember the directory previously chosen when selecting a resource (#1494) 2020-03-21 13:29:00 +01:00
Aurélien Vivet
3ff5dd7cd2 Add duplicate menu option in Project Manager (#1556) 2020-03-20 09:45:18 +01:00
Florian Rival
1193e1bbd0 Run Prettier autoformatting on some files 2020-03-19 23:17:38 +01:00
Harsimran Singh Virk
9c55b0acc6 Replace Downshift with material-ui Autocomplete. (#1453) 2020-03-19 22:45:21 +01:00
Jimil Desai
d03c1964cb Fix global objects not updated in other editors after modifying them in an editor (#1545) 2020-03-19 19:17:54 +01:00
Aurélien Vivet
e5695aacf6 Fix sentences for video object actions & clean whitespace (#1552) 2020-03-18 21:50:09 +01:00
Florian Rival
8e6d2da9f7 Fix crash in external events 2020-03-18 21:46:32 +01:00
Aurélien Vivet
5c043fd04a Add context menu to select the scene to start the preview with (#1429) 2020-03-18 21:28:18 +01:00
Pranav Shridhar
4edbd9d377 Added shortcut to export project (#1548) 2020-03-18 15:23:08 +01:00
Quarkstar
c6f21955a3 Add BulgePinch, Glitch, RadialBlur and Twist effects (#1531) 2020-03-18 15:20:01 +01:00
Florian Rival
03cc406459 Fix tests 2020-03-18 15:03:11 +01:00
Ferry Pie
c5d855b768 Make table headers bolder (#1512) 2020-03-17 15:03:40 +01:00
Pranav Shridhar
2aba1c57c4 Fix spinner shown in "See all my builds" when not logged in (#1542)
Fix #1541
2020-03-17 14:54:53 +01:00
Minisonny
9614549436 Fix ContextMenu positioning in the web-app (#1527)
Fix #1492
2020-03-17 09:36:26 +01:00
Florian Rival
f1730c239d Add type to ExpressionCompletionDescription::ForObject 2020-03-16 23:08:05 +01:00
Pranav Shridhar
acb19bf8ed Fix typos (#1535) 2020-03-16 19:03:58 +01:00
Florian Rival
4d63fbcca0 Fix Flow typing of components with useImperativeHandle 2020-03-15 13:12:30 +01:00
Florian Rival
eb19b6ba21 Remove Fullstory analytics 2020-03-14 18:48:45 +01:00
Florian Rival
d2747782b4 Remove mention to babel-loader in package.json.README.md 2020-03-14 17:24:20 +01:00
Nilay Majorwar
8202e6b38e Update react-scripts to v3.4.0 (#1526) 2020-03-14 17:22:08 +01:00
Florian Rival
6deb4fa122 Merge branch 'master' of github.com:4ian/GDevelop 2020-03-14 13:58:58 +01:00
Nilay Majorwar
3990064da9 Add Exit GDevelop option to File menu (#1524)
Closes #1498
2020-03-14 12:45:04 +01:00
Quarkstar
a315eabdce Reorder Effects/JsExtension.js (#1519) 2020-03-12 14:57:34 +01:00
Florian Rival
faa02d4459 Add proper handling of closing parenthesis in ExpressionCompletionFinder 2020-03-11 17:41:52 +00:00
Harsimran Singh Virk
8b294ae369 Fix tooltip content for editor titles (#1495)
Fix #1484
2020-03-10 22:21:26 +00:00
Florian Rival
cb43eb7780 Upgrade to Flow 0.120.1 2020-03-10 21:15:48 +00:00
Geetesh Gupta
765295fc5d Add Escape (and Enter) key to finish renaming groups and comments (#1488) 2020-03-09 20:51:42 +00:00
A.Dilshaad
beb3bde4a8 Make New scene naming convention more consistent (#1508) 2020-03-09 10:01:00 +00:00
Aurélien Vivet
fe5b519917 Add blending mode effect (#1499) 2020-03-08 23:34:53 +00:00
Geetesh Gupta
8661fbef07 Fix object name not selectable when renaming an object (#1477)
Fix #1440
2020-03-08 23:09:10 +00:00
Quarkstar
afd11d2480 Add old film, dot and color replace effects (#1497) 2020-03-08 17:44:06 +00:00
Florian Rival
c5ad9715df Fix project name not escaped in Cordova generated config.xml 2020-03-05 21:21:27 +00:00
Florian Rival
4362e8dd42 Add check for libGD.js size in electron app build and fix failure reports 2020-03-05 07:57:31 +00:00
Florian Rival
372fa46709 Fix yarn command wrongly removing space between words (#1491) 2020-03-04 22:39:17 +00:00
Florian Rival
c43cfcd49e Display human readable names for builds in the Builds list (#1489)
Fix #1421
2020-03-04 20:27:14 +00:00
384 changed files with 30896 additions and 23969 deletions

View File

@@ -348,7 +348,8 @@ class GD_CORE_API ExpressionParser2 {
return std::move(child);
}
return std::move(std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>());
return std::move(
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>());
}
std::unique_ptr<FunctionCallNode> FreeFunction(
@@ -367,10 +368,10 @@ class GD_CORE_API ExpressionParser2 {
: MetadataProvider::GetStrExpressionMetadata(
platform, functionFullName);
auto parametersAndError = Parameters(metadata.parameters);
auto parametersNode = Parameters(metadata.parameters);
auto function = gd::make_unique<FunctionCallNode>(
type, std::move(parametersAndError.first), metadata, functionFullName);
function->diagnostic = std::move(parametersAndError.second);
type, std::move(parametersNode.parameters), metadata, functionFullName);
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic)
function->diagnostic =
ValidateFunction(*function, identifierLocation.GetStartPosition());
@@ -379,6 +380,8 @@ class GD_CORE_API ExpressionParser2 {
identifierLocation.GetStartPosition(), GetCurrentPosition());
function->functionNameLocation = identifierLocation;
function->openingParenthesisLocation = openingParenthesisLocation;
function->closingParenthesisLocation =
parametersNode.closingParenthesisLocation;
return std::move(function);
}
@@ -421,14 +424,14 @@ class GD_CORE_API ExpressionParser2 {
: MetadataProvider::GetObjectStrExpressionMetadata(
platform, objectType, objectFunctionOrBehaviorName);
auto parametersAndError = Parameters(metadata.parameters, objectName);
auto function =
gd::make_unique<FunctionCallNode>(type,
objectName,
std::move(parametersAndError.first),
metadata,
objectFunctionOrBehaviorName);
function->diagnostic = std::move(parametersAndError.second);
auto parametersNode = Parameters(metadata.parameters, objectName);
auto function = gd::make_unique<FunctionCallNode>(
type,
objectName,
std::move(parametersNode.parameters),
metadata,
objectFunctionOrBehaviorName);
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic)
function->diagnostic =
ValidateFunction(*function, objectNameLocation.GetStartPosition());
@@ -439,6 +442,8 @@ class GD_CORE_API ExpressionParser2 {
function->objectNameDotLocation = objectNameDotLocation;
function->functionNameLocation = objectFunctionOrBehaviorNameLocation;
function->openingParenthesisLocation = openingParenthesisLocation;
function->closingParenthesisLocation =
parametersNode.closingParenthesisLocation;
return std::move(function);
}
@@ -485,16 +490,16 @@ class GD_CORE_API ExpressionParser2 {
: MetadataProvider::GetBehaviorStrExpressionMetadata(
platform, behaviorType, functionName);
auto parametersAndError =
auto parametersNode =
Parameters(metadata.parameters, objectName, behaviorName);
auto function =
gd::make_unique<FunctionCallNode>(type,
objectName,
behaviorName,
std::move(parametersAndError.first),
metadata,
functionName);
function->diagnostic = std::move(parametersAndError.second);
auto function = gd::make_unique<FunctionCallNode>(
type,
objectName,
behaviorName,
std::move(parametersNode.parameters),
metadata,
functionName);
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic)
function->diagnostic =
ValidateFunction(*function, objectNameLocation.GetStartPosition());
@@ -507,6 +512,8 @@ class GD_CORE_API ExpressionParser2 {
function->behaviorNameNamespaceSeparatorLocation =
behaviorNameNamespaceSeparatorLocation;
function->openingParenthesisLocation = openingParenthesisLocation;
function->closingParenthesisLocation =
parametersNode.closingParenthesisLocation;
function->functionNameLocation = functionNameLocation;
return std::move(function);
} else {
@@ -527,11 +534,17 @@ class GD_CORE_API ExpressionParser2 {
}
}
std::pair<std::vector<std::unique_ptr<ExpressionNode>>,
std::unique_ptr<gd::ExpressionParserError>>
Parameters(std::vector<gd::ParameterMetadata> parameterMetadata,
const gd::String &objectName = "",
const gd::String &behaviorName = "") {
// A temporary node that will be integrated into function nodes.
struct ParametersNode {
std::vector<std::unique_ptr<ExpressionNode>> parameters;
std::unique_ptr<gd::ExpressionParserError> diagnostic;
ExpressionParserLocation closingParenthesisLocation;
};
ParametersNode Parameters(
std::vector<gd::ParameterMetadata> parameterMetadata,
const gd::String &objectName = "",
const gd::String &behaviorName = "") {
std::vector<std::unique_ptr<ExpressionNode>> parameters;
// By convention, object is always the first parameter, and behavior the
@@ -543,8 +556,9 @@ class GD_CORE_API ExpressionParser2 {
SkipAllWhitespaces();
if (CheckIfChar(IsClosingParenthesis)) {
SkipChar();
return std::make_pair(std::move(parameters), nullptr);
auto closingParenthesisLocation = SkipChar();
return ParametersNode{
std::move(parameters), nullptr, closingParenthesisLocation};
} else {
if (parameterIndex < parameterMetadata.size()) {
const gd::String &type = parameterMetadata[parameterIndex].GetType();
@@ -588,10 +602,12 @@ class GD_CORE_API ExpressionParser2 {
}
}
return std::make_pair(
ExpressionParserLocation invalidClosingParenthesisLocation;
return ParametersNode{
std::move(parameters),
RaiseSyntaxError(_("The list of parameters is not terminated. Add a "
"closing parenthesis to end the parameters.")));
"closing parenthesis to end the parameters.")),
invalidClosingParenthesisLocation};
}
///@}
@@ -821,6 +837,7 @@ class GD_CORE_API ExpressionParser2 {
bool IsEndReached() { return currentPosition >= expression.size(); }
// A temporary node used when reading an identifier
struct IdentifierAndLocation {
gd::String name;
ExpressionParserLocation location;

View File

@@ -385,6 +385,8 @@ struct FunctionCallNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
///separator, if any.
ExpressionParserLocation
openingParenthesisLocation; ///< Location of the "(".
ExpressionParserLocation
closingParenthesisLocation; ///< Location of the ")".
};
/**

View File

@@ -13,11 +13,12 @@ namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("BuiltinObject",
_("Features for all objects"),
_("Common features that can be used for all objects in GDevelop."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionInformation(
"BuiltinObject",
_("Features for all objects"),
_("Common features that can be used for all objects in GDevelop."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/base_object/events");
gd::ObjectMetadata& obj = extension.AddObject<gd::Object>(
@@ -72,14 +73,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.UseStandardOperatorParameters("number")
.MarkAsSimple();
obj.AddAction(
"MettreXY",
_("Position of an object"),
_("Change the position of an object."),
_("Change the position of _PARAM0_: _PARAM1_ _PARAM2_ (x axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
obj.AddAction("MettreXY",
_("Position of an object"),
_("Change the position of an object."),
_("Change the position of _PARAM0_: _PARAM1_ _PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"))
@@ -294,14 +295,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("number");
obj.AddAction(
"ModVarObjetTxt",
_("Modify the text of a variable of an object"),
_("Modify the text of a variable of an object"),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
"res/actions/var.png")
obj.AddAction("ModVarObjetTxt",
_("Modify the text of a variable of an object"),
_("Modify the text of a variable of an object"),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
@@ -473,14 +473,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters("number");
obj.AddCondition(
"VarObjetTxt",
_("Text of an object's variable"),
_("Compare the text of a variable of an object."),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
obj.AddCondition("VarObjetTxt",
_("Text of an object's variable"),
_("Compare the text of a variable of an object."),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
@@ -634,6 +633,23 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Y position of the point"))
.MarkAsSimple();
extension
.AddCondition("SourisSurObjet",
_("The cursor/touch is on an object"),
_("Test if the cursor is over an object, or if the object "
"is being touched."),
_("The cursor/touch is on _PARAM0_"),
_("Mouse and touch"),
"res/conditions/surObjet24.png",
"res/conditions/surObjet.png")
.AddParameter("objectList", _("Object"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Accurate test (yes by default)"), "", true)
.SetDefaultValue("yes")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsSimple();
obj.AddCondition(
"ObjectTimer",
_("Value of a timer"),

View File

@@ -21,23 +21,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetExtensionHelpPath("/all-features/mouse-touch");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("SourisSurObjet",
_("The cursor/touch is on an object"),
_("Test if the cursor is over an object, or if the object "
"is being touched."),
_("The cursor/touch is on _PARAM0_"),
_("Mouse and touch"),
"res/conditions/surObjet24.png",
"res/conditions/surObjet.png")
.AddParameter("objectList", _("Object"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Accurate test (yes by default)"), "", true)
.SetDefaultValue("yes")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsSimple();
extension
.AddCondition(
"IsMouseWheelScrollingUp",

View File

@@ -380,7 +380,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
obj.AddAction("ChangeBlendMode",
_("Blend mode"),
_("Change the number of the blend mode of an object.\nThe "
"default blend mode is 0 (Alpha)."),
"default blend mode is 0 (Normal)."),
_("Change Blend mode of _PARAM0_ to _PARAM1_"),
_("Effects"),
"res/actions/color24.png",
@@ -388,7 +388,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("expression",
_("Mode (0 : Alpha, 1 : Add, 2 : Multiply, 3 : None)"))
_("Mode (0: Normal, 1: Add, 2: Multiply, 3: Screen)"))
.MarkAsSimple();
obj.AddAction("FlipX",

View File

@@ -43,8 +43,9 @@ struct ExpressionCompletionDescription {
/**
* \brief Create a completion for an object with the given prefix
*/
static ExpressionCompletionDescription ForObject(const gd::String& prefix_) {
return ExpressionCompletionDescription(Object, "", prefix_);
static ExpressionCompletionDescription ForObject(const gd::String& type_,
const gd::String& prefix_) {
return ExpressionCompletionDescription(Object, type_, prefix_);
}
/**
@@ -114,23 +115,21 @@ struct ExpressionCompletionDescription {
const gd::String& GetBehaviorName() const { return behaviorName; }
/**
* \brief Set if the completion description is informative, i.e: it's not used
* to
* complete anything. Rather, it should display information about what is
* \brief Set if the completion description is exact, i.e: it's not used
* to complete anything. Rather, it should display information about what is
* described by the completion.
*/
ExpressionCompletionDescription& SetIsInformative(bool isInformative_) {
isInformative = isInformative_;
ExpressionCompletionDescription& SetIsExact(bool isExact_) {
isExact = isExact_;
return *this;
}
/**
* \brief Check if the completion description is informative, i.e: it's not
* used to
* complete anything. Rather, it should display information about what is
* described by the completion.
* \brief Check if the completion description is exact, i.e: it's not
* used to complete anything. Rather, it should display information
* about what is described by the completion.
*/
bool IsInformative() const { return isInformative; }
bool IsExact() const { return isExact; }
/** Default constructor, only to be used by Emscripten bindings. */
ExpressionCompletionDescription() : completionKind(Object){};
@@ -146,14 +145,14 @@ struct ExpressionCompletionDescription {
prefix(prefix_),
objectName(objectName_),
behaviorName(behaviorName_),
isInformative(false) {}
isExact(false) {}
CompletionKind completionKind;
gd::String type;
gd::String prefix;
gd::String objectName;
gd::String behaviorName;
bool isInformative;
bool isExact;
};
/**
@@ -164,7 +163,7 @@ std::ostream& operator<<(std::ostream& os,
os << "{ " << value.GetCompletionKind() << ", " << value.GetType() << ", "
<< value.GetPrefix() << ", " << value.GetObjectName() << ", "
<< value.GetBehaviorName() << ", "
<< (value.IsInformative() ? "informative" : "non-informative") << " }";
<< (value.IsExact() ? "exact" : "non-exact") << " }";
return os;
}
@@ -209,17 +208,20 @@ class GD_CORE_API ExpressionCompletionFinder
protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
completions.push_back(ExpressionCompletionDescription::ForObject(""));
completions.push_back(
ExpressionCompletionDescription::ForObject(node.type, ""));
completions.push_back(
ExpressionCompletionDescription::ForExpression(node.type, ""));
}
void OnVisitOperatorNode(OperatorNode& node) override {
completions.push_back(ExpressionCompletionDescription::ForObject(""));
completions.push_back(
ExpressionCompletionDescription::ForObject(node.type, ""));
completions.push_back(
ExpressionCompletionDescription::ForExpression(node.type, ""));
}
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
completions.push_back(ExpressionCompletionDescription::ForObject(""));
completions.push_back(
ExpressionCompletionDescription::ForObject(node.type, ""));
completions.push_back(
ExpressionCompletionDescription::ForExpression(node.type, ""));
}
@@ -243,12 +245,12 @@ class GD_CORE_API ExpressionCompletionFinder
void OnVisitIdentifierNode(IdentifierNode& node) override {
if (gd::ParameterMetadata::IsObject(node.type)) {
// Only show completions of objects if an object is required
completions.push_back(
ExpressionCompletionDescription::ForObject(node.identifierName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.identifierName));
} else {
// Show completions for expressions and objects otherwise.
completions.push_back(
ExpressionCompletionDescription::ForObject(node.identifierName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.identifierName));
completions.push_back(ExpressionCompletionDescription::ForExpression(
node.type, node.identifierName));
}
@@ -259,8 +261,8 @@ class GD_CORE_API ExpressionCompletionFinder
// Behavior function (or behavior function being written, with the
// function name missing)
if (IsCaretOn(node.objectNameLocation)) {
completions.push_back(
ExpressionCompletionDescription::ForObject(node.objectName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.objectName));
} else if (IsCaretOn(node.objectNameDotLocation) ||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
completions.push_back(ExpressionCompletionDescription::ForBehavior(
@@ -276,8 +278,8 @@ class GD_CORE_API ExpressionCompletionFinder
} else {
// Object function or behavior name
if (IsCaretOn(node.objectNameLocation)) {
completions.push_back(
ExpressionCompletionDescription::ForObject(node.objectName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.objectName));
} else if (IsCaretOn(node.objectNameDotLocation) ||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
completions.push_back(ExpressionCompletionDescription::ForBehavior(
@@ -288,11 +290,14 @@ class GD_CORE_API ExpressionCompletionFinder
}
}
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
bool isCaretOnParenthesis = IsCaretOn(node.openingParenthesisLocation) ||
IsCaretOn(node.closingParenthesisLocation);
if (!node.behaviorName.empty()) {
// Behavior function
if (IsCaretOn(node.objectNameLocation)) {
completions.push_back(
ExpressionCompletionDescription::ForObject(node.objectName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.objectName));
} else if (IsCaretOn(node.objectNameDotLocation) ||
IsCaretOn(node.behaviorNameLocation)) {
completions.push_back(ExpressionCompletionDescription::ForBehavior(
@@ -303,40 +308,38 @@ class GD_CORE_API ExpressionCompletionFinder
node.functionName,
node.objectName,
node.behaviorName)
.SetIsInformative(IsCaretOn(node.openingParenthesisLocation)));
.SetIsExact(isCaretOnParenthesis));
}
} else if (!node.objectName.empty()) {
// Object function
if (IsCaretOn(node.objectNameLocation)) {
completions.push_back(
ExpressionCompletionDescription::ForObject(node.objectName));
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, node.objectName));
} else {
// Add completions for behaviors, because we could imagine that the user
// wants to move from an object function to a behavior function, and so
// need behavior completions. Do this unless we're on the parenthesis
// (at which point we're only showing informative message about the
// function).
if (!IsCaretOn(node.openingParenthesisLocation)) {
if (!isCaretOnParenthesis) {
completions.push_back(ExpressionCompletionDescription::ForBehavior(
node.functionName, node.objectName));
}
completions.push_back(
ExpressionCompletionDescription::ForExpression(
node.type, node.functionName, node.objectName)
.SetIsInformative(IsCaretOn(node.openingParenthesisLocation)));
completions.push_back(ExpressionCompletionDescription::ForExpression(
node.type, node.functionName, node.objectName)
.SetIsExact(isCaretOnParenthesis));
}
} else {
// Free function
completions.push_back(
ExpressionCompletionDescription::ForExpression(node.type,
node.functionName)
.SetIsInformative(IsCaretOn(node.openingParenthesisLocation)));
completions.push_back(ExpressionCompletionDescription::ForExpression(
node.type, node.functionName)
.SetIsExact(isCaretOnParenthesis));
}
}
void OnVisitEmptyNode(EmptyNode& node) override {
completions.push_back(
ExpressionCompletionDescription::ForObject(node.text));
ExpressionCompletionDescription::ForObject(node.type, node.text));
completions.push_back(
ExpressionCompletionDescription::ForExpression(node.type, node.text));
}
@@ -344,6 +347,8 @@ class GD_CORE_API ExpressionCompletionFinder
private:
bool IsCaretOn(const ExpressionParserLocation& location,
bool inclusive = false) {
if (!location.IsValid()) return false;
return (location.GetStartPosition() <= searchedPosition &&
((!inclusive && searchedPosition < location.GetEndPosition()) ||
(inclusive && searchedPosition <= location.GetEndPosition())));

View File

@@ -7,6 +7,7 @@
#include "Project.h"
#include <stdio.h>
#include <stdlib.h>
#include <cctype>
#include <SFML/System/Utf.hpp>
#include <fstream>
#include <map>
@@ -945,18 +946,16 @@ void Project::SerializeTo(SerializerElement& element) const {
#endif
}
bool Project::ValidateObjectName(const gd::String& name) {
bool Project::ValidateName(const gd::String& name) {
if (name.empty()) return false;
if (isdigit(name[0])) return false;
gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
return !(name.find_first_not_of(allowedCharacters) != gd::String::npos);
}
gd::String Project::GetBadObjectNameWarning() {
return _("Please use only letters, digits\nand underscores ( _ ).");
}
void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
// See also gd::WholeProjectRefactorer::ExposeProjectEvents for a method that
// traverse the whole project (this time for events) and ExposeProjectEffects

View File

@@ -843,21 +843,10 @@ class GD_CORE_API Project : public ObjectsContainer {
///@{
/**
* Return true if \a objectName can be used as name for an object.
*
* Default implementation check if objectName is only composed of a-z,A-Z,0-9
* or _ characters an if does not conflict with an expression.
* Return true if \a name is valid (can be used safely for an object,
* behavior, events function name, etc...).
*/
static bool ValidateObjectName(const gd::String& objectName);
/**
* Return a message that will be displayed when an invalid object name has
* been entered.
*
* \note This message will be displayed by the IDE into a tooltip.
*/
static gd::String GetBadObjectNameWarning();
static bool ValidateName(const gd::String& name);
///@}
/** \name External source files

View File

@@ -95,6 +95,14 @@ void Serializer::FromXML(SerializerElement& element,
}
#endif
gd::String Serializer::ToEscapedXMLString(const gd::String& str) {
return str.FindAndReplace("&", "&amp;")
.FindAndReplace("'", "&apos;")
.FindAndReplace("\"", "&quot;")
.FindAndReplace("<", "&lt;")
.FindAndReplace(">", "&gt;");
}
namespace {
/**

View File

@@ -27,14 +27,26 @@ class GD_CORE_API Serializer {
static void FromXML(SerializerElement& element,
const TiXmlElement* xmlElement);
#endif
/**
* \brief Escape a string for inclusion in a XML tag
*/
static gd::String ToEscapedXMLString(const gd::String& str);
///@}
/** \name JSON serialization.
* Serialize a SerializerElement from/to JSON.
*/
///@{
/**
* \brief Serialize a gd::SerializerElement to a JSON string.
*/
static gd::String ToJSON(const SerializerElement& element);
static SerializerElement FromJSON(const std::string& json);
/**
* \brief Parse a JSON string and returns a gd::SerializerElement for it.
*/
static SerializerElement FromJSON(const gd::String& json) {
return FromJSON(json.ToUTF8());
}

View File

@@ -34,7 +34,7 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Identifier") {
SECTION("Object or expression completions when type is string") {
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject("My"),
gd::ExpressionCompletionDescription::ForObject("string", "My"),
gd::ExpressionCompletionDescription::ForExpression("string", "My")};
REQUIRE(getCompletionsFor("string", "My", 0) == expectedCompletions);
REQUIRE(getCompletionsFor("string", "My", 1) == expectedCompletions);
@@ -42,7 +42,7 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
}
SECTION("Object or expression completions when type is number") {
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject("My"),
gd::ExpressionCompletionDescription::ForObject("number", "My"),
gd::ExpressionCompletionDescription::ForExpression("number", "My")};
REQUIRE(getCompletionsFor("number", "My", 0) == expectedCompletions);
REQUIRE(getCompletionsFor("number", "My", 1) == expectedCompletions);
@@ -50,14 +50,17 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
}
SECTION("Object when type is an object") {
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject("My")};
gd::ExpressionCompletionDescription::ForObject("object", "My")};
REQUIRE(getCompletionsFor("object", "My", 0) == expectedCompletions);
REQUIRE(getCompletionsFor("object", "My", 1) == expectedCompletions);
REQUIRE(getCompletionsFor("object", "My", 2) == expectedEmptyCompletions);
}
SECTION("Object when type is an object (alternate type)") {
// Also test alternate types also considered as objects (but that can
// result
// in different code generation):
// result in different code generation):
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject("objectPtr", "My")};
REQUIRE(getCompletionsFor("objectPtr", "My", 0) == expectedCompletions);
REQUIRE(getCompletionsFor("objectPtr", "My", 1) == expectedCompletions);
REQUIRE(getCompletionsFor("objectPtr", "My", 2) ==
@@ -66,7 +69,7 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
}
SECTION("Operator (number)") {
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject(""),
gd::ExpressionCompletionDescription::ForObject("number", ""),
gd::ExpressionCompletionDescription::ForExpression("number", "")};
REQUIRE(getCompletionsFor("number", "1 + ", 1) == expectedCompletions);
REQUIRE(getCompletionsFor("number", "1 + ", 2) == expectedCompletions);
@@ -74,7 +77,7 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
}
SECTION("Operator (string)") {
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject(""),
gd::ExpressionCompletionDescription::ForObject("string", ""),
gd::ExpressionCompletionDescription::ForExpression("string", "")};
REQUIRE(getCompletionsFor("string", "\"a\" + ", 3) == expectedCompletions);
REQUIRE(getCompletionsFor("string", "\"a\" + ", 4) == expectedCompletions);
@@ -87,10 +90,10 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
gd::ExpressionCompletionDescription::ForExpression("string",
"Function")};
std::vector<gd::ExpressionCompletionDescription>
expectedInformativeCompletions{
expectedExactCompletions{
gd::ExpressionCompletionDescription::ForExpression("string",
"Function")
.SetIsInformative(true)};
.SetIsExact(true)};
REQUIRE(getCompletionsFor("string", "Function(", 0) ==
expectedCompletions);
REQUIRE(getCompletionsFor("string", "Function(", 1) ==
@@ -98,9 +101,11 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
REQUIRE(getCompletionsFor("string", "Function(", 7) ==
expectedCompletions);
REQUIRE(getCompletionsFor("string", "Function(", 8) ==
expectedInformativeCompletions);
expectedExactCompletions);
REQUIRE(getCompletionsFor("string", "Function(", 9) ==
expectedEmptyCompletions);
REQUIRE(getCompletionsFor("string", "Function()", 9) ==
expectedExactCompletions);
}
SECTION("Unknown function, test with arguments") {
REQUIRE(getCompletionsFor("string", "Function(1", 9) ==
@@ -109,7 +114,7 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
expectedEmptyCompletions);
std::vector<gd::ExpressionCompletionDescription> expectedCompletions{
gd::ExpressionCompletionDescription::ForObject("a"),
gd::ExpressionCompletionDescription::ForObject("unknown", "a"),
gd::ExpressionCompletionDescription::ForExpression("unknown", "a")};
REQUIRE(getCompletionsFor("string", "Function(a", 9) ==
expectedCompletions);
@@ -128,7 +133,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Test 1") {
std::vector<gd::ExpressionCompletionDescription>
expectedObjectCompletions{
gd::ExpressionCompletionDescription::ForObject("MyObject")};
gd::ExpressionCompletionDescription::ForObject("string",
"MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedBehaviorOrFunctionCompletions{
gd::ExpressionCompletionDescription::ForBehavior("Func",
@@ -154,7 +160,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Test 1") {
std::vector<gd::ExpressionCompletionDescription>
expectedObjectCompletions{
gd::ExpressionCompletionDescription::ForObject("MyObject")};
gd::ExpressionCompletionDescription::ForObject("string",
"MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedBehaviorOrFunctionCompletions{
gd::ExpressionCompletionDescription::ForBehavior("Func",
@@ -162,10 +169,10 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
gd::ExpressionCompletionDescription::ForExpression(
"string", "Func", "MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedInformativeFunctionCompletions{
expectedExactFunctionCompletions{
gd::ExpressionCompletionDescription::ForExpression(
"string", "Func", "MyObject")
.SetIsInformative(true)};
.SetIsExact(true)};
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 0) ==
expectedObjectCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 7) ==
@@ -177,9 +184,11 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 12) ==
expectedBehaviorOrFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 13) ==
expectedInformativeFunctionCompletions);
expectedExactFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.Func(", 14) ==
expectedEmptyCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.Func()", 14) ==
expectedExactFunctionCompletions);
}
}
@@ -187,7 +196,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Test 1") {
std::vector<gd::ExpressionCompletionDescription>
expectedObjectCompletions{
gd::ExpressionCompletionDescription::ForObject("MyObject")};
gd::ExpressionCompletionDescription::ForObject("string",
"MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedBehaviorCompletions{
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
@@ -218,7 +228,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Test 2") {
std::vector<gd::ExpressionCompletionDescription>
expectedObjectCompletions{
gd::ExpressionCompletionDescription::ForObject("MyObject")};
gd::ExpressionCompletionDescription::ForObject("string",
"MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedBehaviorCompletions{
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
@@ -248,7 +259,8 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
SECTION("Test 1") {
std::vector<gd::ExpressionCompletionDescription>
expectedObjectCompletions{
gd::ExpressionCompletionDescription::ForObject("MyObject")};
gd::ExpressionCompletionDescription::ForObject("string",
"MyObject")};
std::vector<gd::ExpressionCompletionDescription>
expectedBehaviorCompletions{
gd::ExpressionCompletionDescription::ForBehavior("MyBehavior",
@@ -258,10 +270,10 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
gd::ExpressionCompletionDescription::ForExpression(
"string", "Func", "MyObject", "MyBehavior")};
std::vector<gd::ExpressionCompletionDescription>
expectedInformativeFunctionCompletions{
expectedExactFunctionCompletions{
gd::ExpressionCompletionDescription::ForExpression(
"string", "Func", "MyObject", "MyBehavior")
.SetIsInformative(true)};
.SetIsExact(true)};
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 0) ==
expectedObjectCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 7) ==
@@ -282,6 +294,14 @@ TEST_CASE("ExpressionCompletionFinder", "[common][events]") {
expectedFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 23) ==
expectedFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 24) ==
expectedFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 25) ==
expectedExactFunctionCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func(", 26) ==
expectedEmptyCompletions);
REQUIRE(getCompletionsFor("string", "MyObject.MyBehavior::Func()", 26) ==
expectedExactFunctionCompletions);
}
}
}

View File

@@ -1172,6 +1172,8 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
REQUIRE(textNode.location.GetEndPosition() == 23);
REQUIRE(identifierNode.location.GetStartPosition() == 25);
REQUIRE(identifierNode.location.GetEndPosition() == 30);
REQUIRE(functionNode.closingParenthesisLocation.GetStartPosition() == 30);
REQUIRE(functionNode.closingParenthesisLocation.GetEndPosition() == 31);
}
SECTION("Free function locations (with whitespaces)") {
auto node = parser.ParseExpression("number",
@@ -1192,6 +1194,8 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
REQUIRE(functionNode.functionNameLocation.GetEndPosition() == 16);
REQUIRE(functionNode.openingParenthesisLocation.GetStartPosition() == 18);
REQUIRE(functionNode.openingParenthesisLocation.GetEndPosition() == 19);
REQUIRE(functionNode.closingParenthesisLocation.GetStartPosition() == 32);
REQUIRE(functionNode.closingParenthesisLocation.GetEndPosition() == 33);
}
SECTION("Object function locations") {
auto node = parser.ParseExpression(
@@ -1231,6 +1235,8 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
REQUIRE(textNode.location.GetEndPosition() == 38);
REQUIRE(identifierNode.location.GetStartPosition() == 40);
REQUIRE(identifierNode.location.GetEndPosition() == 45);
REQUIRE(functionNode.closingParenthesisLocation.GetStartPosition() == 45);
REQUIRE(functionNode.closingParenthesisLocation.GetEndPosition() == 46);
}
SECTION("Object function name locations") {
auto node =
@@ -1306,6 +1312,8 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
REQUIRE(functionNode.functionNameLocation.GetEndPosition() == 33);
REQUIRE(functionNode.openingParenthesisLocation.GetStartPosition() == 34);
REQUIRE(functionNode.openingParenthesisLocation.GetEndPosition() == 35);
REQUIRE(functionNode.closingParenthesisLocation.GetStartPosition() == 48);
REQUIRE(functionNode.closingParenthesisLocation.GetEndPosition() == 49);
}
SECTION("Behavior function locations") {
auto node = parser.ParseExpression(
@@ -1350,6 +1358,8 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
REQUIRE(textNode.location.GetEndPosition() == 56);
REQUIRE(identifierNode.location.GetStartPosition() == 58);
REQUIRE(identifierNode.location.GetEndPosition() == 63);
REQUIRE(functionNode.closingParenthesisLocation.GetStartPosition() == 63);
REQUIRE(functionNode.closingParenthesisLocation.GetEndPosition() == 64);
}
SECTION("Behavior function name locations (with whitespace)") {
auto node = parser.ParseExpression(

View File

@@ -410,7 +410,7 @@ module.exports = {
objectsEditorService.registerEditorConfiguration(
'BBText::BBText',
objectsEditorService.getDefaultObjectJsImplementationPropertiesEditor({
helpPagePath: '/objects/bbtext_object',
helpPagePath: '/objects/bbtext',
})
);
},

View File

@@ -168,15 +168,14 @@ module.exports = {
_(
'Select option by number. Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'
),
_('Select option by number'),
_('Select option at index _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Option index number'), '', false)
.setDefaultValue('0')
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectPreviousOption');
.setFunctionName('gdjs.dialogueTree.selectOption');
extension
.addAction(

View File

@@ -339,7 +339,7 @@ gdjs.dialogueTree.selectOption = function(optionIndex) {
if (!this.dialogueIsRunning) return;
if (this.dialogueData.select) {
this.selectedOption = gdjs.dialogueTree._normalizedOptionIndex(
this.selectedOption
optionIndex
);
this.selectedOptionUpdated = true;
}
@@ -472,7 +472,8 @@ gdjs.dialogueTree.goToNextDialogueLine = function() {
this.dialogueText = this.dialogueData.text;
this.commandCalls = [];
} else {
this.dialogueText += this.dialogueData.text;
this.dialogueText +=
(this.dialogueText === '' ? '' : ' ') + this.dialogueData.text;
}
this.dialogueDataType = 'text';
@@ -482,11 +483,14 @@ gdjs.dialogueTree.goToNextDialogueLine = function() {
this.dialogueData = this.dialogue.next().value;
} else if (gdjs.dialogueTree._isLineTypeOptions()) {
this.dialogueDataType = 'options';
this.dialogueText = '';
this.clipTextEnd = 0;
this.optionsCount = this.dialogueData.options.length;
this.options = this.dialogueData.options;
this.selectedOptionUpdated = true;
} else if (gdjs.dialogueTree._isLineTypeCommand()) {
this.dialogueDataType = 'command';
this.clipTextEnd = 0;
var command = this.dialogueData.text.split(' ');
// If last command was to wait, increase time by one

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
gdjs.PixiFiltersTools.registerFilterCreator('BlendingMode', {
makePIXIFilter: function(layer, effectData) {
var blendingModeFilter = new PIXI.filters.AlphaFilter();
return blendingModeFilter;
},
update: function(filter, layer) {},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'alpha') {
filter.alpha = value;
}
if (parameterName === 'blendmode') {
filter.blendMode = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
updateBooleanParameter: function(filter, parameterName, value) {},
});

View File

@@ -14,7 +14,7 @@ gdjs.PixiFiltersTools.registerFilterCreator('Blur', {
return;
if (parameterName === 'kernelSize') {
value = gdjs.PixiFiltersTools.clampKernelSize(value);
value = gdjs.PixiFiltersTools.clampKernelSize(value, 5, 15);
}
filter[parameterName] = value;

View File

@@ -0,0 +1,27 @@
gdjs.PixiFiltersTools.registerFilterCreator('BulgePinch', {
makePIXIFilter: function(layer, effectData) {
var bulgePinchFilter = new PIXI.filters.BulgePinchFilter();
return bulgePinchFilter;
},
update: function(filter, layer) {
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'centerX') {
filter.center[0] = value;
}
else if (parameterName === 'centerY') {
filter.center[1] = value;
}
else if (parameterName === 'radius') {
filter.radius = value;
}
else if (parameterName === 'strength') {
filter.strength = gdjs.PixiFiltersTools.clampValue(value, -1, 1);
}
},
updateStringParameter: function(filter, parameterName, value) {
},
updateBooleanParameter: function(filter, parameterName, value) {
},
});

View File

@@ -0,0 +1,22 @@
gdjs.PixiFiltersTools.registerFilterCreator('ColorReplace', {
makePIXIFilter: function(layer, effectData) {
var colorReplaceFilter = new PIXI.filters.ColorReplaceFilter();
return colorReplaceFilter;
},
update: function(filter, layer) {},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'epsilon') {
filter.epsilon = value;
}
},
updateStringParameter: function(filter, parameterName, value) {
if (parameterName === 'originalColor') {
filter.originalColor = parseInt(value.replace('#', '0x'), 16);
}
else if (parameterName === 'newColor') {
filter.newColor = parseInt(value.replace('#', '0x'), 16);
}
},
updateBooleanParameter: function(filter, parameterName, value) {},
});

View File

@@ -1,13 +1,20 @@
gdjs.PixiFiltersTools.registerFilterCreator('CRT', {
makePIXIFilter: function(layer, effectData) {
var crtFilter = new PIXI.filters.CRTFilter();
crtFilter._animationTimer = 0;
return crtFilter;
},
update: function(filter, layer) {
if (filter.animated) {
filter.time += layer.getElapsedTime() / 1000;
filter.seed = Math.random();
if (filter.animationSpeed !== 0) {
// Multiply by 10 so that the default value is a sensible speed
filter.time += layer.getElapsedTime() / 1000 * 10 * filter.animationSpeed;
}
if (filter.animationFrequency !== 0) {
filter._animationTimer += layer.getElapsedTime() / 1000;
if (filter._animationTimer >= 1 / filter.animationFrequency) {
filter.seed = Math.random();
filter._animationTimer = 0;
}
}
},
updateDoubleParameter: function(filter, parameterName, value) {
@@ -27,6 +34,10 @@ gdjs.PixiFiltersTools.registerFilterCreator('CRT', {
filter.vignettingAlpha = value;
} else if (parameterName === 'vignettingBlur') {
filter.vignettingBlur = value;
} else if (parameterName === 'animationSpeed') {
filter.animationSpeed = value;
} else if (parameterName === 'animationFrequency') {
filter.animationFrequency = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
@@ -34,8 +45,5 @@ gdjs.PixiFiltersTools.registerFilterCreator('CRT', {
if (parameterName === 'verticalLine') {
filter.verticalLine = value;
}
if (parameterName === 'animated') {
filter.animated = value;
}
},
});

View File

@@ -0,0 +1,18 @@
gdjs.PixiFiltersTools.registerFilterCreator('Dot', {
makePIXIFilter: function(layer, effectData) {
var dotFilter = new PIXI.filters.DotFilter();
return dotFilter;
},
update: function(filter, layer) {},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'scale') {
filter.scale = value;
}
else if (parameterName === 'angle') {
filter.angle = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
updateBooleanParameter: function(filter, parameterName, value) {},
});

View File

@@ -0,0 +1,64 @@
gdjs.PixiFiltersTools.registerFilterCreator('Glitch', {
makePIXIFilter: function(layer, effectData) {
var glitchFilter = new PIXI.filters.GlitchFilter();
glitchFilter._animationTimer = 0;
return glitchFilter;
},
update: function(filter, layer) {
if (filter.animationFrequency !== 0) {
filter._animationTimer += layer.getElapsedTime() / 1000;
if (filter._animationTimer >= 1 / filter.animationFrequency) {
filter.seed = Math.random();
filter._animationTimer = 0;
}
}
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'slices') {
filter.slices = value;
}
else if (parameterName === 'offset') {
filter.offset = value;
}
else if (parameterName === 'direction') {
filter.direction = value;
}
else if (parameterName === 'fillMode') {
filter.fillMode = value;
}
else if (parameterName === 'minSize') {
filter.minSize = value;
}
else if (parameterName === 'sampleSize') {
filter.sampleSize = value;
}
else if (parameterName === 'redX') {
filter.red.x = value;
}
else if (parameterName === 'redY') {
filter.red.y = value;
}
else if (parameterName === 'greenX') {
filter.green.x = value;
}
else if (parameterName === 'greenY') {
filter.green.y = value;
}
else if (parameterName === 'blueX') {
filter.blue.x = value;
}
else if (parameterName === 'blueY') {
filter.blue.y = value;
}
else if (parameterName === 'animationFrequency') {
filter.animationFrequency = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
updateBooleanParameter: function(filter, parameterName, value) {
if (parameterName === 'average') {
filter.average = value;
}
},
});

View File

@@ -5,8 +5,8 @@ gdjs.PixiFiltersTools.registerFilterCreator('Godray', {
return godrayFilter;
},
update: function(filter, layer) {
if (filter.animated) {
filter.time += layer.getElapsedTime() / 1000;
if (filter.animationSpeed !== 0) {
filter.time += layer.getElapsedTime() / 1000 * filter.animationSpeed;
}
},
updateDoubleParameter: function(filter, parameterName, value) {
@@ -22,6 +22,8 @@ gdjs.PixiFiltersTools.registerFilterCreator('Godray', {
filter.x = value;
} else if (parameterName === 'y') {
filter.y = value;
} else if (parameterName === 'animationSpeed') {
filter.animationSpeed = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
@@ -29,8 +31,5 @@ gdjs.PixiFiltersTools.registerFilterCreator('Godray', {
if (parameterName === 'parallel') {
filter.parallel = value;
}
if (parameterName === 'animated') {
filter.animated = value;
}
},
});

View File

@@ -0,0 +1,50 @@
gdjs.PixiFiltersTools.registerFilterCreator('OldFilm', {
makePIXIFilter: function(layer, effectData) {
var oldFilmFilter = new PIXI.filters.OldFilmFilter();
oldFilmFilter._animationTimer = 0;
return oldFilmFilter;
},
update: function(filter, layer) {
if (filter.animationFrequency !== 0) {
filter._animationTimer += layer.getElapsedTime() / 1000;
if (filter._animationTimer >= 1 / filter.animationFrequency) {
filter.seed = Math.random();
filter._animationTimer = 0;
}
}
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'sepia') {
filter.sepia = value;
}
else if (parameterName === 'noise') {
filter.noise = value;
}
else if (parameterName === 'noiseSize') {
filter.noiseSize = value;
}
else if (parameterName === 'scratch') {
filter.scratch = value;
}
else if (parameterName === 'scratchDensity') {
filter.scratchDensity = value;
}
else if (parameterName === 'scratchWidth') {
filter.scratchWidth = value;
}
else if (parameterName === 'vignetting') {
filter.vignetting = value;
}
else if (parameterName === 'vignettingAlpha') {
filter.vignettingAlpha = value;
}
else if (parameterName === 'vignettingBlur') {
filter.vignettingBlur = value;
}
else if (parameterName === 'animationFrequency') {
filter.animationFrequency = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
updateBooleanParameter: function(filter, parameterName, value) {},
});

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-alpha - v5.2.1
* Compiled Tue, 28 Jan 2020 23:33:11 UTC
*
* @pixi/filter-alpha is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
this.PIXI=this.PIXI||{},this.PIXI.filters=this.PIXI.filters||{};var _pixi_filter_alpha=function(t,r){"use strict";var e="varying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float uAlpha;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord) * uAlpha;\n}\n",i=function(t){function i(i){void 0===i&&(i=1),t.call(this,r.defaultVertex,e,{uAlpha:1}),this.alpha=i}t&&(i.__proto__=t),i.prototype=Object.create(t&&t.prototype),i.prototype.constructor=i;var a={alpha:{configurable:!0}};return a.alpha.get=function(){return this.uniforms.uAlpha},a.alpha.set=function(t){this.uniforms.uAlpha=t},Object.defineProperties(i.prototype,a),i}(r.Filter);return t.AlphaFilter=i,t}({},PIXI);Object.assign(this.PIXI.filters,_pixi_filter_alpha);
//# sourceMappingURL=filter-alpha.min.js.map

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-bulge-pinch - v2.7.0
* Compiled Sun, 13 Jan 2019 22:51:52 UTC
*
* @pixi/filter-bulge-pinch is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("pixi.js")):"function"==typeof define&&define.amd?define(["exports","pixi.js"],n):n((e=e||self).__filters={},e.PIXI)}(this,function(e,n){"use strict";var t="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",r="uniform float radius;\nuniform float strength;\nuniform vec2 center;\nuniform sampler2D uSampler;\nvarying vec2 vTextureCoord;\n\nuniform vec4 filterArea;\nuniform vec4 filterClamp;\nuniform vec2 dimensions;\n\nvoid main()\n{\n vec2 coord = vTextureCoord * filterArea.xy;\n coord -= center * dimensions.xy;\n float distance = length(coord);\n if (distance < radius) {\n float percent = distance / radius;\n if (strength > 0.0) {\n coord *= mix(1.0, smoothstep(0.0, radius / distance, percent), strength * 0.75);\n } else {\n coord *= mix(1.0, pow(percent, 1.0 + strength * 0.75) * radius / distance, 1.0 - percent);\n }\n }\n coord += center * dimensions.xy;\n coord /= filterArea.xy;\n vec2 clampedCoord = clamp(coord, filterClamp.xy, filterClamp.zw);\n vec4 color = texture2D(uSampler, clampedCoord);\n if (coord != clampedCoord) {\n color *= max(0.0, 1.0 - length(coord - clampedCoord));\n }\n\n gl_FragColor = color;\n}\n",o=function(e){function n(n,o,i){e.call(this,t,r),this.uniforms.dimensions=new Float32Array(2),this.center=n||[.5,.5],this.radius="number"==typeof o?o:100,this.strength="number"==typeof i?i:1}e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n;var o={radius:{configurable:!0},strength:{configurable:!0},center:{configurable:!0}};return n.prototype.apply=function(e,n,t,r){this.uniforms.dimensions[0]=n.sourceFrame.width,this.uniforms.dimensions[1]=n.sourceFrame.height,e.applyFilter(this,n,t,r)},o.radius.get=function(){return this.uniforms.radius},o.radius.set=function(e){this.uniforms.radius=e},o.strength.get=function(){return this.uniforms.strength},o.strength.set=function(e){this.uniforms.strength=e},o.center.get=function(){return this.uniforms.center},o.center.set=function(e){this.uniforms.center=e},Object.defineProperties(n.prototype,o),n}(n.Filter);e.BulgePinchFilter=o,Object.defineProperty(e,"__esModule",{value:!0})}),Object.assign(PIXI.filters,this?this.__filters:__filters);
//# sourceMappingURL=filter-bulge-pinch.js.map

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-color-replace - v2.7.0
* Compiled Sun, 13 Jan 2019 22:51:52 UTC
*
* @pixi/filter-color-replace is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
!function(o,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("pixi.js")):"function"==typeof define&&define.amd?define(["exports","pixi.js"],r):r((o=o||self).__filters={},o.PIXI)}(this,function(o,r){"use strict";var e="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",i="varying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform vec3 originalColor;\nuniform vec3 newColor;\nuniform float epsilon;\nvoid main(void) {\n vec4 currentColor = texture2D(uSampler, vTextureCoord);\n vec3 colorDiff = originalColor - (currentColor.rgb / max(currentColor.a, 0.0000000001));\n float colorDistance = length(colorDiff);\n float doReplace = step(colorDistance, epsilon);\n gl_FragColor = vec4(mix(currentColor.rgb, (newColor + colorDiff) * currentColor.a, doReplace), currentColor.a);\n}\n",n=function(o){function n(r,n,t){void 0===r&&(r=16711680),void 0===n&&(n=0),void 0===t&&(t=.4),o.call(this,e,i),this.uniforms.originalColor=new Float32Array(3),this.uniforms.newColor=new Float32Array(3),this.originalColor=r,this.newColor=n,this.epsilon=t}o&&(n.__proto__=o),n.prototype=Object.create(o&&o.prototype),n.prototype.constructor=n;var t={originalColor:{configurable:!0},newColor:{configurable:!0},epsilon:{configurable:!0}};return t.originalColor.set=function(o){var e=this.uniforms.originalColor;"number"==typeof o?(r.utils.hex2rgb(o,e),this._originalColor=o):(e[0]=o[0],e[1]=o[1],e[2]=o[2],this._originalColor=r.utils.rgb2hex(e))},t.originalColor.get=function(){return this._originalColor},t.newColor.set=function(o){var e=this.uniforms.newColor;"number"==typeof o?(r.utils.hex2rgb(o,e),this._newColor=o):(e[0]=o[0],e[1]=o[1],e[2]=o[2],this._newColor=r.utils.rgb2hex(e))},t.newColor.get=function(){return this._newColor},t.epsilon.set=function(o){this.uniforms.epsilon=o},t.epsilon.get=function(){return this.uniforms.epsilon},Object.defineProperties(n.prototype,t),n}(r.Filter);o.ColorReplaceFilter=n,Object.defineProperty(o,"__esModule",{value:!0})}),Object.assign(PIXI.filters,this?this.__filters:__filters);
//# sourceMappingURL=filter-color-replace.js.map

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-dot - v2.7.0
* Compiled Sun, 13 Jan 2019 22:51:52 UTC
*
* @pixi/filter-dot is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("pixi.js")):"function"==typeof define&&define.amd?define(["exports","pixi.js"],n):n((e=e||self).__filters={},e.PIXI)}(this,function(e,n){"use strict";var t="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",o="precision mediump float;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec4 filterArea;\nuniform sampler2D uSampler;\n\nuniform float angle;\nuniform float scale;\n\nfloat pattern()\n{\n float s = sin(angle), c = cos(angle);\n vec2 tex = vTextureCoord * filterArea.xy;\n vec2 point = vec2(\n c * tex.x - s * tex.y,\n s * tex.x + c * tex.y\n ) * scale;\n return (sin(point.x) * sin(point.y)) * 4.0;\n}\n\nvoid main()\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n float average = (color.r + color.g + color.b) / 3.0;\n gl_FragColor = vec4(vec3(average * 10.0 - 5.0 + pattern()), color.a);\n}\n",r=function(e){function n(n,r){void 0===n&&(n=1),void 0===r&&(r=5),e.call(this,t,o),this.scale=n,this.angle=r}e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n;var r={scale:{configurable:!0},angle:{configurable:!0}};return r.scale.get=function(){return this.uniforms.scale},r.scale.set=function(e){this.uniforms.scale=e},r.angle.get=function(){return this.uniforms.angle},r.angle.set=function(e){this.uniforms.angle=e},Object.defineProperties(n.prototype,r),n}(n.Filter);e.DotFilter=r,Object.defineProperty(e,"__esModule",{value:!0})}),Object.assign(PIXI.filters,this?this.__filters:__filters);
//# sourceMappingURL=filter-dot.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-radial-blur - v2.7.0
* Compiled Sun, 13 Jan 2019 22:51:52 UTC
*
* @pixi/filter-radial-blur is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("pixi.js")):"function"==typeof define&&define.amd?define(["exports","pixi.js"],n):n((e=e||self).__filters={},e.PIXI)}(this,function(e,n){"use strict";var t="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",r="varying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform vec4 filterArea;\n\nuniform float uRadian;\nuniform vec2 uCenter;\nuniform float uRadius;\nuniform int uKernelSize;\n\nconst int MAX_KERNEL_SIZE = 2048;\n\nvoid main(void)\n{\n vec4 color = texture2D(uSampler, vTextureCoord);\n\n if (uKernelSize == 0)\n {\n gl_FragColor = color;\n return;\n }\n\n float aspect = filterArea.y / filterArea.x;\n vec2 center = uCenter.xy / filterArea.xy;\n float gradient = uRadius / filterArea.x * 0.3;\n float radius = uRadius / filterArea.x - gradient * 0.5;\n int k = uKernelSize - 1;\n\n vec2 coord = vTextureCoord;\n vec2 dir = vec2(center - coord);\n float dist = length(vec2(dir.x, dir.y * aspect));\n\n float radianStep = uRadian;\n if (radius >= 0.0 && dist > radius) {\n float delta = dist - radius;\n float gap = gradient;\n float scale = 1.0 - abs(delta / gap);\n if (scale <= 0.0) {\n gl_FragColor = color;\n return;\n }\n radianStep *= scale;\n }\n radianStep /= float(k);\n\n float s = sin(radianStep);\n float c = cos(radianStep);\n mat2 rotationMatrix = mat2(vec2(c, -s), vec2(s, c));\n\n for(int i = 0; i < MAX_KERNEL_SIZE - 1; i++) {\n if (i == k) {\n break;\n }\n\n coord -= center;\n coord.y *= aspect;\n coord = rotationMatrix * coord;\n coord.y /= aspect;\n coord += center;\n\n vec4 sample = texture2D(uSampler, coord);\n\n // switch to pre-multiplied alpha to correctly blur transparent images\n // sample.rgb *= sample.a;\n\n color += sample;\n }\n\n gl_FragColor = color / float(uKernelSize);\n}\n",i=function(e){function n(n,i,o,a){void 0===n&&(n=0),void 0===i&&(i=[0,0]),void 0===o&&(o=5),void 0===a&&(a=-1),e.call(this,t,r),this._angle=0,this.angle=n,this.center=i,this.kernelSize=o,this.radius=a}e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n;var i={angle:{configurable:!0},center:{configurable:!0},radius:{configurable:!0}};return n.prototype.apply=function(e,n,t,r){this.uniforms.uKernelSize=0!==this._angle?this.kernelSize:0,e.applyFilter(this,n,t,r)},i.angle.set=function(e){this._angle=e,this.uniforms.uRadian=e*Math.PI/180},i.angle.get=function(){return this._angle},i.center.get=function(){return this.uniforms.uCenter},i.center.set=function(e){this.uniforms.uCenter=e},i.radius.get=function(){return this.uniforms.uRadius},i.radius.set=function(e){(e<0||e===1/0)&&(e=-1),this.uniforms.uRadius=e},Object.defineProperties(n.prototype,i),n}(n.Filter);e.RadialBlurFilter=i,Object.defineProperty(e,"__esModule",{value:!0})}),Object.assign(PIXI.filters,this?this.__filters:__filters);
//# sourceMappingURL=filter-radial-blur.js.map

View File

@@ -0,0 +1,9 @@
/*!
* @pixi/filter-twist - v2.7.0
* Compiled Sun, 13 Jan 2019 22:51:52 UTC
*
* @pixi/filter-twist is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license
*/
!function(o,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports,require("pixi.js")):"function"==typeof define&&define.amd?define(["exports","pixi.js"],n):n((o=o||self).__filters={},o.PIXI)}(this,function(o,n){"use strict";var r="attribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}",e="varying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n",t=function(o){function n(n,t,i){void 0===n&&(n=200),void 0===t&&(t=4),void 0===i&&(i=20),o.call(this,r,e),this.radius=n,this.angle=t,this.padding=i}o&&(n.__proto__=o),n.prototype=Object.create(o&&o.prototype),n.prototype.constructor=n;var t={offset:{configurable:!0},radius:{configurable:!0},angle:{configurable:!0}};return t.offset.get=function(){return this.uniforms.offset},t.offset.set=function(o){this.uniforms.offset=o},t.radius.get=function(){return this.uniforms.radius},t.radius.set=function(o){this.uniforms.radius=o},t.angle.get=function(){return this.uniforms.angle},t.angle.set=function(o){this.uniforms.angle=o},Object.defineProperties(n.prototype,t),n}(n.Filter);o.TwistFilter=t,Object.defineProperty(o,"__esModule",{value:!0})}),Object.assign(PIXI.filters,this?this.__filters:__filters);
//# sourceMappingURL=filter-twist.js.map

View File

@@ -0,0 +1,32 @@
gdjs.PixiFiltersTools.registerFilterCreator('RadialBlur', {
makePIXIFilter: function(layer, effectData) {
var radialBlurFilter = new PIXI.filters.RadialBlurFilter();
return radialBlurFilter;
},
update: function(filter, layer) {
filter.center[0] = Math.round(filter._centerX * layer.getWidth());
filter.center[1] = Math.round(filter._centerY * layer.getHeight());
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'radius') {
filter.radius = (value < 0 ? -1 : value);
}
else if (parameterName === 'angle') {
filter.angle = value;
}
else if (parameterName === 'kernelSize') {
filter.kernelSize = gdjs.PixiFiltersTools.clampKernelSize(value, 3, 25);
}
else if (parameterName === 'centerX') {
filter._centerX = value;
}
else if (parameterName === 'centerY') {
filter._centerY = value;
}
},
updateStringParameter: function(filter, parameterName, value) {
},
updateBooleanParameter: function(filter, parameterName, value) {
},
});

View File

@@ -23,8 +23,8 @@ gdjs.PixiFiltersTools.registerFilterCreator("Reflection", {
return reflectionFilter;
},
update: function(filter, layer) {
if (filter.animated) {
filter.time -= layer.getElapsedTime() / 1000;
if (filter.animationSpeed !== 0) {
filter.time += layer.getElapsedTime() / 1000 * filter.animationSpeed;
}
},
updateDoubleParameter: function(filter, parameterName, value) {
@@ -55,14 +55,15 @@ gdjs.PixiFiltersTools.registerFilterCreator("Reflection", {
if (parameterName === "alphaEnding") {
filter.alpha[1] = value;
}
if (parameterName === "animationSpeed") {
filter.animationSpeed = value;
}
},
updateStringParameter: function(filter, parameterName, value) {},
updateBooleanParameter: function(filter, parameterName, value) {
if (parameterName === "mirror") {
filter.mirror = value;
}
if (parameterName === "animated") {
filter.animated = value;
}
}
});

View File

@@ -0,0 +1,32 @@
gdjs.PixiFiltersTools.registerFilterCreator('Twist', {
makePIXIFilter: function(layer, effectData) {
var twistFilter = new PIXI.filters.TwistFilter();
return twistFilter;
},
update: function(filter, layer) {
filter.offset[0] = Math.round(filter._offsetX * layer.getWidth());
filter.offset[1] = Math.round(filter._offsetY * layer.getHeight());
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'radius') {
filter.radius = value;
}
else if (parameterName === 'angle') {
filter.angle = value;
}
else if (parameterName === 'padding') {
filter.padding = value;
}
else if (parameterName === 'offsetX') {
filter._offsetX = value;
}
else if (parameterName === 'offsetY') {
filter._offsetY = value;
}
},
updateStringParameter: function(filter, parameterName, value) {
},
updateBooleanParameter: function(filter, parameterName, value) {
},
});

View File

@@ -5,16 +5,18 @@ gdjs.PixiFiltersTools.registerFilterCreator('ZoomBlur', {
return zoomBlurFilter;
},
update: function(filter, layer) {
filter.center[0] = Math.round(filter._centerX * layer.getWidth());
filter.center[1] = Math.round(filter._centerY * layer.getHeight());
},
updateDoubleParameter: function(filter, parameterName, value) {
if (parameterName === 'centerX') {
filter.center[0]= Math.round(window.innerWidth * value);
filter._centerX = value;
}
else if (parameterName === 'centerY') {
filter.center[1] = Math.round(window.innerHeight * value);
filter._centerY = value;
}
else if (parameterName === 'innerRadius') {
filter.innerRadius = Math.round(window.innerWidth * value);
filter.innerRadius = value;
}
else if (parameterName === 'strength') {
filter.strength = gdjs.PixiFiltersTools.clampValue(value / 10, 0, 20);

View File

@@ -754,8 +754,7 @@ module.exports = {
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setShapeScale')
.setFunctionName('setShapeScale')
.setGetter('getShapeScale');
aut
@@ -790,8 +789,7 @@ module.exports = {
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setDensity')
.setFunctionName('setDensity')
.setGetter('getDensity');
aut
@@ -840,7 +838,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setFriction')
.setGetter('getFriction');
aut
@@ -889,7 +886,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setRestitution')
.setGetter('getRestitution');
aut
@@ -938,7 +934,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setLinearDamping')
.setGetter('getLinearDamping');
aut
@@ -987,7 +982,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setAngularDamping')
.setGetter('getAngularDamping');
aut
@@ -1036,7 +1030,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setGravityScale')
.setGetter('getGravityScale');
aut
@@ -1157,7 +1150,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setLinearVelocityX')
.setGetter('getLinearVelocityX');
aut
@@ -1204,7 +1196,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setLinearVelocityY')
.setGetter('getLinearVelocityY');
aut
@@ -1280,7 +1271,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setAngularVelocity')
.setGetter('getAngularVelocity');
aut
@@ -1729,7 +1719,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setDistanceJointLength')
.setGetter('getDistanceJointLength');
aut
@@ -1762,7 +1751,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setDistanceJointFrequency')
.setGetter('getDistanceJointFrequency');
aut
@@ -1795,7 +1783,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setDistanceJointDampingRatio')
.setGetter('getDistanceJointDampingRatio');
aut
@@ -2091,7 +2078,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setRevoluteJointMotorSpeed')
.setGetter('getRevoluteJointMotorSpeed');
aut
@@ -2124,7 +2110,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setRevoluteJointMaxMotorTorque')
.setGetter('getRevoluteJointMaxMotorTorque');
aut
@@ -2405,7 +2390,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setPrismaticJointMotorSpeed')
.setGetter('getPrismaticJointMotorSpeed');
aut
@@ -2438,7 +2422,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setPrismaticJointMaxMotorForce')
.setGetter('getPrismaticJointMaxMotorForce');
aut
@@ -2709,7 +2692,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setGearJointRatio')
.setGetter('getGearJointRatio');
aut
@@ -2835,7 +2817,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMouseJointMaxForce')
.setGetter('getMouseJointMaxForce');
aut
@@ -2868,7 +2849,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMouseJointFrequency')
.setGetter('getMouseJointFrequency');
aut
@@ -2901,7 +2881,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMouseJointDampingRatio')
.setGetter('getMouseJointDampingRatio');
aut
@@ -3071,7 +3050,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWheelJointMotorSpeed')
.setGetter('getWheelJointMotorSpeed');
aut
@@ -3104,7 +3082,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWheelJointMaxMotorTorque')
.setGetter('getWheelJointMaxMotorTorque');
aut
@@ -3151,7 +3128,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWheelJointFrequency')
.setGetter('getWheelJointFrequency');
aut
@@ -3184,7 +3160,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWheelJointDampingRatio')
.setGetter('getWheelJointDampingRatio');
aut
@@ -3281,7 +3256,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWeldJointFrequency')
.setGetter('getWeldJointFrequency');
aut
@@ -3314,7 +3288,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setWeldJointDampingRatio')
.setGetter('getWeldJointDampingRatio');
aut
@@ -3390,7 +3363,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setRopeJointMaxLength')
.setGetter('getRopeJointMaxLength');
aut
@@ -3459,7 +3431,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setFrictionJointMaxForce')
.setGetter('getFrictionJointMaxForce');
aut
@@ -3492,7 +3463,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setFrictionJointMaxTorque')
.setGetter('getFrictionJointMaxTorque');
aut
@@ -3610,7 +3580,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMotorJointAngularOffset')
.setGetter('getMotorJointAngularOffset');
aut
@@ -3643,7 +3612,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMotorJointMaxForce')
.setGetter('getMotorJointMaxForce');
aut
@@ -3676,7 +3644,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMotorJointMaxTorque')
.setGetter('getMotorJointMaxTorque');
aut
@@ -3709,7 +3676,6 @@ module.exports = {
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName('setMotorJointCorrectionFactor')
.setGetter('getMotorJointCorrectionFactor');
aut

View File

@@ -303,6 +303,31 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
.SetGetter("GetJumpSpeed")
.SetIncludeFile("PlatformBehavior/PlatformerObjectRuntimeBehavior.h");
aut.AddCondition(
"JumpSustainTime",
_("Jump sustain time"),
_("Compare the jump sustain time of the object (in seconds)."),
_("the jump sustain time"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon24.png",
"CppPlatform/Extensions/platformerobjecticon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.MarkAsAdvanced();
aut.AddAction(
"JumpSustainTime",
_("Jump sustain time"),
_("Change the jump sustain time of an object (in seconds)."),
_("the jump sustain time"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon24.png",
"CppPlatform/Extensions/platformerobjecticon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number");
aut.AddAction(
"SetCanJump",
_("Allow again jumping"),
@@ -502,6 +527,14 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.SetFunctionName("GetJumpSpeed")
.SetIncludeFile("PlatformBehavior/PlatformerObjectRuntimeBehavior.h");
aut.AddExpression("JumpSustainTime",
_("Jump sustain time"),
_("The time during which keeping the jump button held allow the initial jump speed to be maintained."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior");
#endif
}
{

View File

@@ -92,6 +92,12 @@ class PlatformBehaviorJsExtension : public gd::PlatformExtension {
.SetFunctionName("setJumpSpeed")
.SetGetter("getJumpSpeed");
autExpressions["JumpSpeed"].SetFunctionName("getJumpSpeed");
autConditions["PlatformBehavior::JumpSustainTime"].SetFunctionName(
"getJumpSustainTime");
autActions["PlatformBehavior::JumpSustainTime"]
.SetFunctionName("setJumpSustainTime")
.SetGetter("getJumpSustainTime");
autExpressions["JumpSustainTime"].SetFunctionName("getJumpSustainTime");
autActions["PlatformBehavior::SetCanJump"].SetFunctionName("setCanJump");
autActions["PlatformBehavior::SimulateLeftKey"].SetFunctionName(

View File

@@ -6,11 +6,13 @@ This project is released under the MIT License.
*/
#include "PlatformerObjectBehavior.h"
#include <SFML/Window.hpp>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <memory>
#include "GDCore/Tools/Localization.h"
#include "GDCpp/Runtime/CommonTools.h"
#include "GDCpp/Runtime/Project/Layout.h"
@@ -22,6 +24,7 @@ This project is released under the MIT License.
#if defined(GD_IDE_ONLY)
#include <iostream>
#include <map>
#include "GDCore/Project/PropertyDescriptor.h"
#endif
@@ -34,6 +37,7 @@ void PlatformerObjectBehavior::InitializeContent(
behaviorContent.SetAttribute("deceleration", 1500);
behaviorContent.SetAttribute("maxSpeed", 250);
behaviorContent.SetAttribute("jumpSpeed", 600);
behaviorContent.SetAttribute("jumpSustainTime", 0.2);
behaviorContent.SetAttribute("ignoreDefaultControls", false);
behaviorContent.SetAttribute("slopeMaxAngle", 60);
behaviorContent.SetAttribute("canGrabPlatforms", false);
@@ -51,6 +55,14 @@ PlatformerObjectBehavior::GetProperties(
gd::String::From(behaviorContent.GetDoubleAttribute("gravity")));
properties[_("Jump speed")].SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("jumpSpeed")));
properties[_("jumpSustainTime")]
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("jumpSustainTime", 0)))
.SetLabel(_("Jump sustain time"))
.SetDescription(
_("Maximum time (in seconds) during which the jump strength is "
"sustained if the jump key is held - allowing variable height "
"jumps."));
properties[_("Max. falling speed")].SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("maxFallingSpeed")));
properties[_("Acceleration")].SetValue(
@@ -91,7 +103,7 @@ bool PlatformerObjectBehavior::UpdateProperty(
gd::Project& project) {
if (name == _("Default controls"))
behaviorContent.SetAttribute("ignoreDefaultControls", (value == "0"));
if (name == _("Round coordinates"))
else if (name == _("Round coordinates"))
behaviorContent.SetAttribute("roundCoordinates", (value == "1"));
else if (name == _("Can grab platform ledges"))
behaviorContent.SetAttribute("canGrabPlatforms", (value == "1"));
@@ -112,6 +124,8 @@ bool PlatformerObjectBehavior::UpdateProperty(
behaviorContent.SetAttribute("maxSpeed", value.To<double>());
else if (name == _("Jump speed"))
behaviorContent.SetAttribute("jumpSpeed", value.To<double>());
else if (name == _("jumpSustainTime"))
behaviorContent.SetAttribute("jumpSustainTime", value.To<double>());
else if (name == _("Slope max. angle")) {
double newMaxAngle = value.To<double>();
if (newMaxAngle < 0 || newMaxAngle >= 90) return false;

View File

@@ -323,6 +323,7 @@ void PlatformerObjectRuntimeBehavior::DoStepPreEvents(RuntimeScene& scene) {
}
if (jumping) {
// TODO: Port the jump sustain feature
requestedDeltaY -= currentJumpSpeed * timeDelta;
currentJumpSpeed -= gravity * timeDelta;
if (currentJumpSpeed < 0) {

File diff suppressed because it is too large Load Diff

View File

@@ -1,282 +1,480 @@
const makeTestRuntimeScene = () => {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
properties: { windowWidth: 800, windowHeight: 600 },
});
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{ name: '', visibility: true }],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: [],
});
runtimeScene._timeManager.getElapsedTime = function() {
return (1 / 60) * 1000;
};
return runtimeScene;
};
const addPlatformObject = runtimeScene => {
var platform = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj2',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformBehavior',
canBeGrabbed: true,
},
],
});
platform.getWidth = function() {
return 60;
};
platform.getHeight = function() {
return 32;
};
runtimeScene.addObject(platform);
return platform;
};
describe('gdjs.PlatformerObjectRuntimeBehavior', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{name: "", visibility: true}],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: []
});
runtimeScene._timeManager.getElapsedTime = function() { return 1 / 60 * 1000; };
const runtimeScene = makeTestRuntimeScene();
//Put a platformer object in the air.
var object = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", behaviors: [{
type: "PlatformBehavior::PlatformerObjectBehavior",
name: "auto1",
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 1500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60
}]});
object.getWidth = function() { return 10; };
object.getHeight = function() { return 20; };
runtimeScene.addObject(object);
object.setPosition(0, -100);
//Put a platformer object in the air.
var object = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformerObjectBehavior',
name: 'auto1',
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 1500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60,
},
],
});
object.getWidth = function() {
return 10;
};
object.getHeight = function() {
return 20;
};
runtimeScene.addObject(object);
object.setPosition(0, -100);
//Put a platform
var platform = new gdjs.RuntimeObject(runtimeScene, {name: "obj2", type: "", behaviors: [{
type: "PlatformBehavior::PlatformBehavior",
canBeGrabbed: true,
}]});
platform.getWidth = function() { return 60; };
platform.getHeight = function() { return 32; };
runtimeScene.addObject(platform);
platform.setPosition(0, -10);
//Put a platform
const platform = addPlatformObject(runtimeScene);
platform.setPosition(0, -10);
it('can fall when in the air', function() {
for(var i = 0; i<30; ++i) {
runtimeScene.renderAndStep();
if (i < 10) expect(object.getBehavior("auto1").isFalling()).to.be(true);
}
it('can fall when in the air', function() {
for (var i = 0; i < 30; ++i) {
runtimeScene.renderAndStep();
if (i < 10) expect(object.getBehavior('auto1').isFalling()).to.be(true);
}
//Check the platform stopped the platformer object.
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior("auto1").isFalling()).to.be(false);
expect(object.getBehavior("auto1").isMoving()).to.be(false);
//Check the platform stopped the platformer object.
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
for(var i = 0; i<35; ++i) { //Check that the platformer object can fall.
object.getBehavior("auto1").simulateRightKey();
runtimeScene.renderAndStep();
}
expect(object.getX()).to.be.within(87.50, 87.51);
expect(object.getY()).to.be(-24.75);
expect(object.getBehavior("auto1").isFalling()).to.be(true);
for (var i = 0; i < 35; ++i) {
//Check that the platformer object can fall.
object.getBehavior('auto1').simulateRightKey();
runtimeScene.renderAndStep();
}
expect(object.getX()).to.be.within(87.5, 87.51);
expect(object.getY()).to.be(-24.75);
expect(object.getBehavior('auto1').isFalling()).to.be(true);
for(var i = 0; i<100; ++i) { //Let the speed on X axis go back to 0.
runtimeScene.renderAndStep();
}
});
for (var i = 0; i < 100; ++i) {
//Let the speed on X axis go back to 0.
runtimeScene.renderAndStep();
}
});
it('can grab, and release, a platform', function() {
//Put the object near the right ledge of the platform.
object.setPosition(platform.getX() + platform.getWidth() + 2, platform.getY() - 10);
it('can grab, and release, a platform', function() {
//Put the object near the right ledge of the platform.
object.setPosition(
platform.getX() + platform.getWidth() + 2,
platform.getY() - 10
);
for(var i = 0; i<35; ++i) {
object.getBehavior("auto1").simulateLeftKey();
runtimeScene.renderAndStep();
}
for (var i = 0; i < 35; ++i) {
object.getBehavior('auto1').simulateLeftKey();
runtimeScene.renderAndStep();
}
//Check that the object grabbed the platform
expect(object.getX()).to.be.within(
platform.getX() + platform.getWidth() + 1,
platform.getX() + platform.getWidth() + 2
);
expect(object.getY()).to.be(platform.getY());
//Check that the object grabbed the platform
expect(object.getX()).to.be.within(
platform.getX() + platform.getWidth() + 1,
platform.getX() + platform.getWidth() + 2
);
expect(object.getY()).to.be(platform.getY());
object.getBehavior("auto1").simulateReleaseKey();
for(var i = 0; i<10; ++i) {
runtimeScene.renderAndStep();
}
object.getBehavior('auto1').simulateReleaseKey();
for (var i = 0; i < 10; ++i) {
runtimeScene.renderAndStep();
}
//Check that the object is falling
expect(object.getY()).to.be(1.25);
});
//Check that the object is falling
expect(object.getY()).to.be(1.25);
});
it('can track object height changes', function() {
//Put the object near the right ledge of the platform.
object.setPosition(platform.getX() + 10, platform.getY() - object.getHeight() - 1);
it('can track object height changes', function() {
//Put the object near the right ledge of the platform.
object.setPosition(
platform.getX() + 10,
platform.getY() - object.getHeight() - 1
);
for(var i = 0; i<15; ++i) {
runtimeScene.renderAndStep();
}
for (var i = 0; i < 15; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getBehavior("auto1").isFalling()).to.be(false);
expect(object.getX()).to.be(10);
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getX()).to.be(10);
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
object.getHeight = function() { return 9; }
runtimeScene.renderAndStep();
expect(object.getBehavior("auto1").isFalling()).to.be(false);
expect(object.getY()).to.be(-19); // -19 = -10 (platform y) + -9 (object height)
object.getHeight = function() {
return 9;
};
runtimeScene.renderAndStep();
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getY()).to.be(-19); // -19 = -10 (platform y) + -9 (object height)
for(var i = 0; i<10; ++i) {
object.getBehavior("auto1").simulateRightKey();
runtimeScene.renderAndStep();
expect(object.getBehavior("auto1").isFalling()).to.be(false);
}
expect(object.getY()).to.be(-19);
expect(object.getX()).to.be.within(17.638, 17.639);
for (var i = 0; i < 10; ++i) {
object.getBehavior('auto1').simulateRightKey();
runtimeScene.renderAndStep();
expect(object.getBehavior('auto1').isFalling()).to.be(false);
}
expect(object.getY()).to.be(-19);
expect(object.getX()).to.be.within(17.638, 17.639);
object.getHeight = function() { return 20; }
runtimeScene.renderAndStep();
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
});
object.getHeight = function() {
return 20;
};
runtimeScene.renderAndStep();
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
});
});
describe('gdjs.PlatformerObjectRuntimeBehavior, jump and jump sustain (round coordinates on)', function() {
const runtimeScene = makeTestRuntimeScene();
//Put a platformer object on a platform
var object = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformerObjectBehavior',
name: 'auto1',
gravity: 1500,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 900,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60,
jumpSustainTime: 0.2,
roundCoordinates: true,
},
],
});
object.getWidth = function() {
return 10;
};
object.getHeight = function() {
return 20;
};
runtimeScene.addObject(object);
object.setPosition(0, -32);
//Put a platform
const platform = addPlatformObject(runtimeScene);
platform.setPosition(0, -10);
it('can jump', function() {
// Ensure the object falls on the platform
for (var i = 0; i < 10; ++i) {
runtimeScene.renderAndStep();
}
//Check the object is on the platform
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// Jump without sustaining
object.getBehavior('auto1').simulateJumpKey();
for (var i = 0; i < 18; ++i) {
runtimeScene.renderAndStep();
}
// Check that we reached the maximum height
expect(object.getY()).to.be.within(-180, -179);
runtimeScene.renderAndStep();
expect(object.getY()).to.be(-180);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-180, -179);
// Then let the object fall
for (var i = 0; i < 60; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be(-30);
});
it('can jump, sustaining the jump', function() {
//Check the object is on the platform
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// Jump with sustaining as much as possible, and
// even more (18 frames at 60fps is greater than 0.2s)
for (var i = 0; i < 18; ++i) {
object.getBehavior('auto1').simulateJumpKey();
runtimeScene.renderAndStep();
}
// Check the height reached
expect(object.getY()).to.be(-230);
runtimeScene.renderAndStep();
expect(object.getY()).to.be(-235);
for (var i = 0; i < 5; ++i) {
// Verify that pressing the jump key does not change anything
object.getBehavior('auto1').simulateJumpKey();
runtimeScene.renderAndStep();
}
// Check that we reached the maximum height
expect(object.getY()).to.be(-247.5);
runtimeScene.renderAndStep();
expect(object.getY()).to.be(-247.5);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-247, -246);
// Then let the object fall
for (var i = 0; i < 60; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be(-30);
});
it('can jump, and only sustain the jump while key held', function() {
//Check the object is on the platform
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// Jump with sustaining a bit (5 frames at 60fps = 0.08s), then stop
for (var i = 0; i < 5; ++i) {
object.getBehavior('auto1').simulateJumpKey();
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be.within(-101, -100);
// Stop holding the jump key
runtimeScene.renderAndStep();
for (var i = 0; i < 13; ++i) {
// then hold it again (but it's too late, jump sustain is gone for this jump)
object.getBehavior('auto1').simulateJumpKey();
runtimeScene.renderAndStep();
}
// Check that we reached the maximum height
expect(object.getY()).to.be.within(-206, -205);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-208, -207);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-208, -207);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-208, -207);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-206, -205);
runtimeScene.renderAndStep();
// Then let the object fall
for (var i = 0; i < 60; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be(-30);
});
});
describe('gdjs.PlatformerObjectRuntimeBehavior, jumpthru', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{name: "", visibility: true}],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: []
});
runtimeScene._timeManager.getElapsedTime = function() { return 1 / 60 * 1000; };
const runtimeScene = makeTestRuntimeScene();
//Put a platformer object in a platform.
var object = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", behaviors: [{
type: "PlatformBehavior::PlatformerObjectBehavior",
name: "auto1",
roundCoordinates: true,
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60
}]});
object.getWidth = function() { return 10; };
object.getHeight = function() { return 20; };
runtimeScene.addObject(object);
object.setPosition(0, -30);
//Put a platformer object in a platform.
var object = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformerObjectBehavior',
name: 'auto1',
roundCoordinates: true,
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60,
},
],
});
object.getWidth = function() {
return 10;
};
object.getHeight = function() {
return 20;
};
runtimeScene.addObject(object);
object.setPosition(0, -30);
//Put a platform
var platform = new gdjs.RuntimeObject(runtimeScene, {name: "obj2", type: "", behaviors: [{
type: "PlatformBehavior::PlatformBehavior",
canBeGrabbed: true,
platformType: "Platform",
}]});
platform.getWidth = function() { return 60; };
platform.getHeight = function() { return 32; };
runtimeScene.addObject(platform);
platform.setPosition(0, -10);
//Put a platform
const platform = addPlatformObject(runtimeScene);
platform.setPosition(0, -10);
// Put a jump thru, higher than the platform so that the object jump from under it
// and will land on it at the end of the jump.
var jumpthru = new gdjs.RuntimeObject(runtimeScene, {name: "obj2", type: "", behaviors: [{
type: "PlatformBehavior::PlatformBehavior",
canBeGrabbed: true,
platformType: "Jumpthru",
}]});
jumpthru.getWidth = function() { return 60; };
jumpthru.getHeight = function() { return 5; };
runtimeScene.addObject(jumpthru);
jumpthru.setPosition(0, -33);
// Put a jump thru, higher than the platform so that the object jump from under it
// and will land on it at the end of the jump.
var jumpthru = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj2',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformBehavior',
canBeGrabbed: true,
platformType: 'Jumpthru',
},
],
});
jumpthru.getWidth = function() {
return 60;
};
jumpthru.getHeight = function() {
return 5;
};
runtimeScene.addObject(jumpthru);
jumpthru.setPosition(0, -33);
it('can jump through the jumpthru', function() {
//Check the platform stopped the platformer object.
for(var i = 0; i<5; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior("auto1").isFalling()).to.be(false);
expect(object.getBehavior("auto1").isMoving()).to.be(false);
it('can jump through the jumpthru', function() {
//Check the platform stopped the platformer object.
for (var i = 0; i < 5; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be(-30); // -30 = -10 (platform y) + -20 (object height)
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// Check that the jump starts properly, and is not stopped on the jumpthru
object.getBehavior("auto1").simulateJumpKey();
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-39, -38);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-47, -46);
runtimeScene.renderAndStep();
// At this step, the object is almost on the jumpthru (-53 + 20 (object height) = -33 (jump thru Y position)),
// but the object should not stop.
expect(object.getY()).to.be.within(-54, -53);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-61, -60);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-67, -66);
expect(object.getBehavior("auto1").isJumping()).to.be(true);
// Check that the jump starts properly, and is not stopped on the jumpthru
object.getBehavior('auto1').simulateJumpKey();
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-39, -38);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-47, -46);
runtimeScene.renderAndStep();
// At this step, the object is almost on the jumpthru (-53 + 20 (object height) = -33 (jump thru Y position)),
// but the object should not stop.
expect(object.getY()).to.be.within(-54, -53);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-61, -60);
runtimeScene.renderAndStep();
expect(object.getY()).to.be.within(-67, -66);
expect(object.getBehavior('auto1').isJumping()).to.be(true);
// Continue the simulation and check that position is correct in the middle of the jump
for(var i = 0; i<20; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be.within(-89, -88);
// Continue the simulation and check that position is correct in the middle of the jump
for (var i = 0; i < 20; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be.within(-89, -88);
// Continue simulation and check that we arrive on the jumpthru
for(var i = 0; i<10; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be.within(jumpthru.getY() - object.getHeight(), jumpthru.getY() - object.getHeight() + 1);
expect(object.getBehavior("auto1").isFalling()).to.be(false);
});
// Continue simulation and check that we arrive on the jumpthru
for (var i = 0; i < 10; ++i) {
runtimeScene.renderAndStep();
}
expect(object.getY()).to.be.within(
jumpthru.getY() - object.getHeight(),
jumpthru.getY() - object.getHeight() + 1
);
expect(object.getBehavior('auto1').isFalling()).to.be(false);
});
});
describe('gdjs.PlatformerObjectRuntimeBehavior, rounded coordinates (moving platforms)', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{name: "", visibility: true}],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: []
});
runtimeScene._timeManager.getElapsedTime = function() { return 1 / 60 * 1000; };
const runtimeScene = makeTestRuntimeScene();
//Put a platformer object on a platform.
var object = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", behaviors: [{
type: "PlatformBehavior::PlatformerObjectBehavior",
name: "auto1",
roundCoordinates: true,
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 1500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60
}]});
object.getWidth = function() { return 10; };
object.getHeight = function() { return 20; };
runtimeScene.addObject(object);
object.setPosition(0, -30);
//Put a platformer object on a platform.
var object = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
type: 'PlatformBehavior::PlatformerObjectBehavior',
name: 'auto1',
roundCoordinates: true,
gravity: 900,
maxFallingSpeed: 1500,
acceleration: 500,
deceleration: 1500,
maxSpeed: 500,
jumpSpeed: 1500,
canGrabPlatforms: true,
ignoreDefaultControls: true,
slopeMaxAngle: 60,
},
],
});
object.getWidth = function() {
return 10;
};
object.getHeight = function() {
return 20;
};
runtimeScene.addObject(object);
object.setPosition(0, -30);
//Put a platform
var platform = new gdjs.RuntimeObject(runtimeScene, {name: "obj2", type: "", behaviors: [{
type: "PlatformBehavior::PlatformBehavior",
canBeGrabbed: true,
}]});
platform.getWidth = function() { return 60; };
platform.getHeight = function() { return 32; };
runtimeScene.addObject(platform);
platform.setPosition(0, -10);
//Put a platform
const platform = addPlatformObject(runtimeScene);
platform.setPosition(0, -10);
it('follows the platform', function() {
for(var i = 0; i<30; ++i) {
runtimeScene.renderAndStep();
}
it('follows the platform', function() {
for (var i = 0; i < 30; ++i) {
runtimeScene.renderAndStep();
}
// Check the object has not moved.
expect(object.getY()).to.be(-30);
expect(object.getX()).to.be(0);
expect(object.getBehavior("auto1").isOnFloor()).to.be(true);
expect(object.getBehavior("auto1").isFalling()).to.be(false);
expect(object.getBehavior("auto1").isMoving()).to.be(false);
// Check the object has not moved.
expect(object.getY()).to.be(-30);
expect(object.getX()).to.be(0);
expect(object.getBehavior('auto1').isOnFloor()).to.be(true);
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// Check that the object follow the platform, even if the
// movement is less than one pixel.
platform.setX(platform.getX()+0.12);
runtimeScene.renderAndStep();
platform.setX(platform.getX()+0.12);
runtimeScene.renderAndStep();
platform.setX(platform.getX()+0.12);
runtimeScene.renderAndStep();
// Check that the object follow the platform, even if the
// movement is less than one pixel.
platform.setX(platform.getX() + 0.12);
runtimeScene.renderAndStep();
platform.setX(platform.getX() + 0.12);
runtimeScene.renderAndStep();
platform.setX(platform.getX() + 0.12);
runtimeScene.renderAndStep();
expect(object.getX()).to.be(0.36);
});
expect(object.getX()).to.be(0.36);
});
});

View File

@@ -10,203 +10,253 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
* @class TopDownMovementRuntimeBehavior
* @constructor
*/
gdjs.TopDownMovementRuntimeBehavior = function(runtimeScene, behaviorData, owner)
{
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
gdjs.TopDownMovementRuntimeBehavior = function(
runtimeScene,
behaviorData,
owner
) {
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
//Behavior configuration:
this._allowDiagonals = behaviorData.allowDiagonals;
this._acceleration = behaviorData.acceleration;
this._deceleration = behaviorData.deceleration;
this._maxSpeed = behaviorData.maxSpeed;
this._angularMaxSpeed = behaviorData.angularMaxSpeed;
this._rotateObject = behaviorData.rotateObject;
this._angleOffset = behaviorData.angleOffset;
this._ignoreDefaultControls = behaviorData.ignoreDefaultControls;
this._angle = 0; // The latest angle of movement, in degrees.
//Behavior configuration:
this._allowDiagonals = behaviorData.allowDiagonals;
this._acceleration = behaviorData.acceleration;
this._deceleration = behaviorData.deceleration;
this._maxSpeed = behaviorData.maxSpeed;
this._angularMaxSpeed = behaviorData.angularMaxSpeed;
this._rotateObject = behaviorData.rotateObject;
this._angleOffset = behaviorData.angleOffset;
this._ignoreDefaultControls = behaviorData.ignoreDefaultControls;
this._angle = 0; // The latest angle of movement, in degrees.
//Attributes used when moving
this._xVelocity = 0;
this._yVelocity = 0;
this._angularSpeed = 0;
this._leftKey = false;
this._rightKey = false;
this._upKey = false;
this._downKey = false;
//Attributes used when moving
this._xVelocity = 0;
this._yVelocity = 0;
this._angularSpeed = 0;
this._leftKey = false;
this._rightKey = false;
this._upKey = false;
this._downKey = false;
};
gdjs.TopDownMovementRuntimeBehavior.prototype = Object.create( gdjs.RuntimeBehavior.prototype );
gdjs.registerBehavior("TopDownMovementBehavior::TopDownMovementBehavior", gdjs.TopDownMovementRuntimeBehavior);
gdjs.TopDownMovementRuntimeBehavior.prototype = Object.create(
gdjs.RuntimeBehavior.prototype
);
gdjs.registerBehavior(
'TopDownMovementBehavior::TopDownMovementBehavior',
gdjs.TopDownMovementRuntimeBehavior
);
gdjs.TopDownMovementRuntimeBehavior.prototype.setAcceleration = function(acceleration) {
this._acceleration = acceleration;
gdjs.TopDownMovementRuntimeBehavior.prototype.setAcceleration = function(
acceleration
) {
this._acceleration = acceleration;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getAcceleration = function() {
return this._acceleration;
return this._acceleration;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.setDeceleration = function(deceleration) {
this._deceleration = deceleration;
gdjs.TopDownMovementRuntimeBehavior.prototype.setDeceleration = function(
deceleration
) {
this._deceleration = deceleration;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getDeceleration = function() {
return this._deceleration;
return this._deceleration;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.setMaxSpeed = function(maxSpeed) {
this._maxSpeed = maxSpeed;
this._maxSpeed = maxSpeed;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getMaxSpeed = function() {
return this._maxSpeed;
return this._maxSpeed;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.setAngularMaxSpeed = function(angularMaxSpeed) {
this._angularMaxSpeed = angularMaxSpeed;
gdjs.TopDownMovementRuntimeBehavior.prototype.setAngularMaxSpeed = function(
angularMaxSpeed
) {
this._angularMaxSpeed = angularMaxSpeed;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getAngularMaxSpeed = function() {
return this._angularMaxSpeed;
return this._angularMaxSpeed;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.setAngleOffset = function(angleOffset) {
this._angleOffset = angleOffset;
gdjs.TopDownMovementRuntimeBehavior.prototype.setAngleOffset = function(
angleOffset
) {
this._angleOffset = angleOffset;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getAngleOffset = function() {
return this._angleOffset;
return this._angleOffset;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.allowDiagonals = function(allow) {
this._allowDiagonals = allow;
this._allowDiagonals = allow;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.diagonalsAllowed = function() {
return this._allowDiagonals;
return this._allowDiagonals;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.setRotateObject = function(allow) {
this._rotateObject = allow;
gdjs.TopDownMovementRuntimeBehavior.prototype.setRotateObject = function(
allow
) {
this._rotateObject = allow;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.isObjectRotated = function() {
return this._rotateObject;
return this._rotateObject;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.isMoving = function() {
return this._xVelocity !== 0 || this._yVelocity !== 0;
return this._xVelocity !== 0 || this._yVelocity !== 0;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getSpeed = function() {
return Math.sqrt(this._xVelocity*this._xVelocity+this._yVelocity*this._yVelocity);
return Math.sqrt(
this._xVelocity * this._xVelocity + this._yVelocity * this._yVelocity
);
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getXVelocity = function() {
return this._xVelocity;
return this._xVelocity;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getYVelocity = function() {
return this._yVelocity;
return this._yVelocity;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.getAngle = function() {
return this._angle;
return this._angle;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.doStepPreEvents = function(runtimeScene)
{
var LEFTKEY = 37;
var UPKEY = 38;
var RIGHTKEY = 39;
var DOWNKEY = 40;
var SHIFTKEY = 16;
var object = this.owner;
var timeDelta = this.owner.getElapsedTime(runtimeScene)/1000;
gdjs.TopDownMovementRuntimeBehavior.prototype.doStepPreEvents = function(
runtimeScene
) {
var LEFTKEY = 37;
var UPKEY = 38;
var RIGHTKEY = 39;
var DOWNKEY = 40;
var object = this.owner;
var timeDelta = this.owner.getElapsedTime(runtimeScene) / 1000;
//Get the player input:
this._leftKey |= !this._ignoreDefaultControls && runtimeScene.getGame().getInputManager().isKeyPressed(LEFTKEY);
this._rightKey |= !this._ignoreDefaultControls && runtimeScene.getGame().getInputManager().isKeyPressed(RIGHTKEY);
this._downKey |= !this._ignoreDefaultControls && runtimeScene.getGame().getInputManager().isKeyPressed(DOWNKEY);
this._upKey |= !this._ignoreDefaultControls && runtimeScene.getGame().getInputManager().isKeyPressed(UPKEY);
//Get the player input:
this._leftKey |=
!this._ignoreDefaultControls &&
runtimeScene
.getGame()
.getInputManager()
.isKeyPressed(LEFTKEY);
this._rightKey |=
!this._ignoreDefaultControls &&
runtimeScene
.getGame()
.getInputManager()
.isKeyPressed(RIGHTKEY);
this._downKey |=
!this._ignoreDefaultControls &&
runtimeScene
.getGame()
.getInputManager()
.isKeyPressed(DOWNKEY);
this._upKey |=
!this._ignoreDefaultControls &&
runtimeScene
.getGame()
.getInputManager()
.isKeyPressed(UPKEY);
var direction = -1;
var directionInRad = 0;
var directionInDeg = 0;
if (!this._allowDiagonals) {
if (this._upKey && !this._downKey) direction = 6;
else if (!this._upKey && this._downKey) direction = 2;
var direction = -1;
var directionInRad = 0;
var directionInDeg = 0;
if (!this._allowDiagonals) {
if (this._upKey && !this._downKey) direction = 6;
else if (!this._upKey && this._downKey) direction = 2;
if (!this._upKey && !this._downKey) {
if (this._leftKey && !this._rightKey) direction = 4;
else if (!this._leftKey && this._rightKey) direction = 0;
}
if (!this._upKey && !this._downKey) {
if (this._leftKey && !this._rightKey) direction = 4;
else if (!this._leftKey && this._rightKey) direction = 0;
}
} else {
if (this._upKey && !this._downKey) {
if (this._leftKey && !this._rightKey) direction = 5;
else if (!this._leftKey && this._rightKey) direction = 7;
else direction = 6;
} else if (!this._upKey && this._downKey) {
if (this._leftKey && !this._rightKey) direction = 3;
else if (!this._leftKey && this._rightKey) direction = 1;
else direction = 2;
} else {
if (this._upKey && !this._downKey) {
if (this._leftKey && !this._rightKey) direction = 5;
else if (!this._leftKey && this._rightKey) direction = 7;
else direction = 6;
} else if (!this._upKey && this._downKey) {
if (this._leftKey && !this._rightKey) direction = 3;
else if (!this._leftKey && this._rightKey) direction = 1;
else direction = 2;
} else {
if (this._leftKey && !this._rightKey) direction = 4;
else if (!this._leftKey && this._rightKey) direction = 0;
}
if (this._leftKey && !this._rightKey) direction = 4;
else if (!this._leftKey && this._rightKey) direction = 0;
}
}
//Update the speed of the object
if (direction != -1) {
directionInRad = direction*Math.PI/4.0;
directionInDeg = direction*45;
//Update the speed of the object
if (direction != -1) {
directionInRad = (direction * Math.PI) / 4.0;
directionInDeg = direction * 45;
this._xVelocity += this._acceleration*timeDelta*Math.cos(directionInRad);
this._yVelocity += this._acceleration*timeDelta*Math.sin(directionInRad);
} else {
directionInRad = Math.atan2(this._yVelocity, this._xVelocity);
directionInDeg = Math.atan2(this._yVelocity, this._xVelocity)*180.0/Math.PI;
this._xVelocity +=
this._acceleration * timeDelta * Math.cos(directionInRad);
this._yVelocity +=
this._acceleration * timeDelta * Math.sin(directionInRad);
} else {
directionInRad = Math.atan2(this._yVelocity, this._xVelocity);
directionInDeg =
(Math.atan2(this._yVelocity, this._xVelocity) * 180.0) / Math.PI;
var xVelocityWasPositive = this._xVelocity >= 0;
var yVelocityWasPositive = this._yVelocity >= 0;
this._xVelocity -= this._deceleration*timeDelta*Math.cos(directionInRad);
this._yVelocity -= this._deceleration*timeDelta*Math.sin(directionInRad);
if ( this._xVelocity > 0 ^ xVelocityWasPositive ) this._xVelocity = 0;
if ( this._yVelocity > 0 ^ yVelocityWasPositive ) this._yVelocity = 0;
var xVelocityWasPositive = this._xVelocity >= 0;
var yVelocityWasPositive = this._yVelocity >= 0;
this._xVelocity -=
this._deceleration * timeDelta * Math.cos(directionInRad);
this._yVelocity -=
this._deceleration * timeDelta * Math.sin(directionInRad);
if ((this._xVelocity > 0) ^ xVelocityWasPositive) this._xVelocity = 0;
if ((this._yVelocity > 0) ^ yVelocityWasPositive) this._yVelocity = 0;
}
var speed = Math.sqrt(
this._xVelocity * this._xVelocity + this._yVelocity * this._yVelocity
);
if (speed > this._maxSpeed) {
this._xVelocity = this._maxSpeed * Math.cos(directionInRad);
this._yVelocity = this._maxSpeed * Math.sin(directionInRad);
}
this._angularSpeed = this._angularMaxSpeed; //No acceleration for angular speed for now
//Position object
object.setX(object.getX() + this._xVelocity * timeDelta);
object.setY(object.getY() + this._yVelocity * timeDelta);
//Also update angle if needed
if (this._xVelocity !== 0 || this._yVelocity !== 0) {
this._angle = directionInDeg;
if (this._rotateObject) {
object.rotateTowardAngle(
directionInDeg + this._angleOffset,
this._angularSpeed,
runtimeScene
);
}
}
var speed = Math.sqrt(this._xVelocity*this._xVelocity+this._yVelocity*this._yVelocity);
if ( speed > this._maxSpeed ) {
this._xVelocity = this._maxSpeed*Math.cos(directionInRad);
this._yVelocity = this._maxSpeed*Math.sin(directionInRad);
}
this._angularSpeed = this._angularMaxSpeed; //No acceleration for angular speed for now
//Position object
object.setX(object.getX()+this._xVelocity*timeDelta);
object.setY(object.getY()+this._yVelocity*timeDelta);
//Also update angle if needed
if ( (this._xVelocity !== 0 || this._yVelocity !== 0) ) {
this._angle = directionInDeg;
if (this._rotateObject) {
object.rotateTowardAngle(directionInDeg+this._angleOffset, this._angularSpeed, runtimeScene);
}
}
this._leftKey = false;
this._rightKey = false;
this._upKey = false;
this._downKey = false;
this._leftKey = false;
this._rightKey = false;
this._upKey = false;
this._downKey = false;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateControl = function(input) {
if ( input === "Left" ) this._leftKey = true;
else if ( input === "Right" ) this._rightKey = true;
else if ( input === "Up" ) this._upKey = true;
else if ( input === "Down" ) this._downKey = true;
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateControl = function(
input
) {
if (input === 'Left') this._leftKey = true;
else if (input === 'Right') this._rightKey = true;
else if (input === 'Up') this._upKey = true;
else if (input === 'Down') this._downKey = true;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.ignoreDefaultControls = function(ignore)
{
this._ignoreDefaultControls = ignore;
gdjs.TopDownMovementRuntimeBehavior.prototype.ignoreDefaultControls = function(
ignore
) {
this._ignoreDefaultControls = ignore;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateLeftKey = function()
{
this._leftKey = true;
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateLeftKey = function() {
this._leftKey = true;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateRightKey = function()
{
this._rightKey = true;
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateRightKey = function() {
this._rightKey = true;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateUpKey = function()
{
this._upKey = true;
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateUpKey = function() {
this._upKey = true;
};
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateDownKey = function()
{
this._downKey = true;
gdjs.TopDownMovementRuntimeBehavior.prototype.simulateDownKey = function() {
this._downKey = true;
};

View File

@@ -180,22 +180,20 @@ module.exports = {
.getCodeExtraInformation()
.setFunctionName("mute");
object
object
.addAction(
"SetTime",
_("Set time"),
_("Set the time of the video object in seconds"),
_("Set time of _PARAM0_: _PARAM1__PARAM2_ seconds"),
_("the time"),
"",
"JsPlatform/Extensions/videoicon24.png",
"JsPlatform/Extensions/videoicon16.png"
)
.addParameter("object", _("Video object"), "VideoObject", false)
.addParameter("operator", _("Modification's sign"), "", false)
.addParameter("expression", _("Time in seconds"), "", false)
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName("setCurrentTime")
.setManipulatedType("number")
.setGetter("getCurrentTime");
object
@@ -211,11 +209,9 @@ module.exports = {
"JsPlatform/Extensions/videoicon16.png"
)
.addParameter("object", _("Video object"), "VideoObject", false)
.addParameter("operator", _("Modification's sign"), "", false)
.addParameter("expression", _("Value"), "", false)
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName("setVolume")
.setManipulatedType("number")
.setGetter("getVolume");
object
@@ -384,11 +380,9 @@ module.exports = {
"JsPlatform/Extensions/videoicon16.png"
)
.addParameter("object", _("Video object"), "VideoObject", false)
.addParameter("operator", _("Modification's sign"), "", false)
.addParameter("expression", _("Opacity (0-255)"), "", false)
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName("setOpacity")
.setManipulatedType("number")
.setGetter("getOpacity");
object
@@ -431,11 +425,9 @@ module.exports = {
"JsPlatform/Extensions/videoicon16.png"
)
.addParameter("object", _("Video object"), "VideoObject", false)
.addParameter("operator", _("Modification's sign"), "", false)
.addParameter("expression", _("Speed "), "", false)
.useStandardOperatorParameters("number")
.getCodeExtraInformation()
.setFunctionName("setPlaybackSpeed")
.setManipulatedType("number")
.setGetter("getPlaybackSpeed");
object

View File

@@ -186,6 +186,9 @@ BaseObjectExtension::BaseObjectExtension() {
GetAllConditions()["RaycastToPosition"]
.SetFunctionName("RaycastObjectToPosition")
.SetIncludeFile("GDCpp/Extensions/Builtin/RuntimeSceneTools.h");
GetAllConditions()["SourisSurObjet"]
.SetFunctionName("CursorOnObject")
.SetIncludeFile("GDCpp/Extensions/Builtin/ObjectTools.h");
GetAllExpressions()["Count"]
.SetFunctionName("PickedObjectsCount")

View File

@@ -48,17 +48,13 @@ MouseExtension::MouseExtension() {
GetAllConditions()["MouseButtonReleased"]
.SetFunctionName("MouseButtonReleased")
.SetIncludeFile("GDCpp/Extensions/Builtin/MouseTools.h");
GetAllConditions()["IsMouseWheelScrollingUp"]
GetAllConditions()["IsMouseWheelScrollingUp"]
.SetFunctionName("IsMouseWheelScrollingUp")
.SetIncludeFile("GDCpp/Extensions/Builtin/MouseTools.h");
GetAllConditions()["IsMouseWheelScrollingDown"]
GetAllConditions()["IsMouseWheelScrollingDown"]
.SetFunctionName("IsMouseWheelScrollingDown")
.SetIncludeFile("GDCpp/Extensions/Builtin/MouseTools.h");
GetAllConditions()["SourisSurObjet"]
.SetFunctionName("CursorOnObject")
.SetIncludeFile("GDCpp/Extensions/Builtin/MouseTools.h");
GetAllExpressions()["MouseX"]
.SetFunctionName("GetCursorXPosition")
.SetIncludeFile("GDCpp/Extensions/Builtin/MouseTools.h");

View File

@@ -1,7 +1,6 @@
#include "GDCpp/Extensions/Builtin/MouseTools.h"
#include <SFML/Graphics.hpp>
#include "GDCpp/Runtime/RuntimeLayer.h"
#include "GDCpp/Runtime/RuntimeObjectsListsTools.h"
#include "GDCpp/Runtime/RuntimeScene.h"
void GD_API CenterCursor(RuntimeScene &scene) {
@@ -83,14 +82,3 @@ bool GD_API IsMouseWheelScrollingUp(RuntimeScene &scene) {
bool GD_API IsMouseWheelScrollingDown(RuntimeScene &scene) {
return scene.GetInputManager().IsScrollingDown();
}
bool GD_API CursorOnObject(
std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists,
RuntimeScene &scene,
bool precise,
bool conditionInverted) {
return PickObjectsIf(
objectsLists, conditionInverted, [&scene, precise](RuntimeObject *obj) {
return obj->CursorOnObject(scene, precise);
});
}

View File

@@ -26,10 +26,5 @@ bool GD_API MouseButtonReleased(RuntimeScene &scene, const gd::String &key);
int GD_API GetMouseWheelDelta(RuntimeScene &scene);
bool GD_API IsMouseWheelScrollingUp(RuntimeScene &scene);
bool GD_API IsMouseWheelScrollingDown(RuntimeScene &scene);
bool GD_API CursorOnObject(
std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists,
RuntimeScene &scene,
bool precise,
bool conditionInverted);
#endif // MOUSETOOLS_H

View File

@@ -108,3 +108,14 @@ MovesToward(std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists1,
obj1->TotalForceAngle(), objAngle)) <= tolerance / 2;
});
}
bool GD_API CursorOnObject(
std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists,
RuntimeScene &scene,
bool precise,
bool conditionInverted) {
return PickObjectsIf(
objectsLists, conditionInverted, [&scene, precise](RuntimeObject *obj) {
return obj->CursorOnObject(scene, precise);
});
}

View File

@@ -57,4 +57,13 @@ MovesToward(std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists1,
float tolerance,
bool conditionInverted);
/**
* Only used internally by GD events generated code.
*/
bool GD_API CursorOnObject(
std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists,
RuntimeScene &scene,
bool precise,
bool conditionInverted);
#endif // OBJECTTOOLS_H

View File

@@ -214,6 +214,8 @@ BaseObjectExtension::BaseObjectExtension() {
"gdjs.evtTools.object.movesTowardTest");
GetAllConditions()["EstTourne"].SetFunctionName(
"gdjs.evtTools.object.turnedTowardTest");
GetAllConditions()["SourisSurObjet"].SetFunctionName(
"gdjs.evtTools.input.cursorOnObject");
GetAllActions()["AjoutObjConcern"].SetFunctionName(
"gdjs.evtTools.object.pickAllObjects");

View File

@@ -33,9 +33,6 @@ MouseExtension::MouseExtension() {
GetAllConditions()["IsMouseWheelScrollingDown"].SetFunctionName(
"gdjs.evtTools.input.isScrollingDown");
GetAllConditions()["SourisSurObjet"].SetFunctionName(
"gdjs.evtTools.input.cursorOnObject");
GetAllExpressions()["MouseX"].SetFunctionName(
"gdjs.evtTools.input.getMouseX");
GetAllExpressions()["SourisX"].SetFunctionName(

View File

@@ -267,8 +267,11 @@ bool ExporterHelper::ExportCordovaFiles(const gd::Project &project,
gd::String str =
fs.ReadFile(gdjsRoot + "/Runtime/Cordova/config.xml")
.FindAndReplace("GDJS_PROJECTNAME", project.GetName())
.FindAndReplace("GDJS_PACKAGENAME", project.GetPackageName())
.FindAndReplace("GDJS_PROJECTNAME",
gd::Serializer::ToEscapedXMLString(project.GetName()))
.FindAndReplace(
"GDJS_PACKAGENAME",
gd::Serializer::ToEscapedXMLString(project.GetPackageName()))
.FindAndReplace("GDJS_ORIENTATION", project.GetOrientation())
.FindAndReplace("GDJS_PROJECTVERSION", project.GetVersion())
.FindAndReplace("<!-- GDJS_ICONS_ANDROID -->", makeIconsAndroid())

View File

@@ -17,6 +17,12 @@ function createWindow() {
useContentSize: true,
title: "GDJS_GAME_NAME",
backgroundColor: '#000000'
// To be added once upgraded to Electron 8+
// (or custom events to be written for each usage of electron
// in the game engine):
// ,webPreferences: {
// nodeIntegration: true,
// }
});
// Open external link in the OS default browser

View File

@@ -5,15 +5,16 @@
*/
/**
* @memberof gdjs.evtTools
* @class common
* @namespace common
* @static
* @private
*/
gdjs.evtTools.common = gdjs.evtTools.common || {};
/**
* Get the value of a variable. Equivalent of variable.getAsNumber().
* Get the value of a variable. Equivalent to `variable.getAsNumber()`.
* @param {gdjs.Variable} variable Variable.
* @returns {number} The content of the variable, as a number.
* @private
*/
gdjs.evtTools.common.getVariableNumber = function(variable) {
@@ -21,7 +22,9 @@ gdjs.evtTools.common.getVariableNumber = function(variable) {
};
/**
* Get the string of a variable. Equivalent of variable.getAsString().
* Get the string of a variable. Equivalent to `variable.getAsString()`.
* @param {gdjs.Variable} variable Variable.
* @returns {string} The content of the variable, as a string.
* @private
*/
gdjs.evtTools.common.getVariableString = function(variable) {
@@ -29,29 +32,32 @@ gdjs.evtTools.common.getVariableString = function(variable) {
};
/**
* Check if a scene variable exists.
* @param {gdjs.RuntimeScene} runtimeScene The scene.
* @param {string} variableName Name of the scene variable.
* @returns {boolean} true if the scene variable exits, false otherwise.
* @private
*/
gdjs.evtTools.common.sceneVariableExists = function(
runtimeScene,
variableName
) {
gdjs.evtTools.common.sceneVariableExists = function(runtimeScene, variableName) {
return runtimeScene.getVariables().has(variableName);
};
/**
* Check if a global variable exists.
* @param {gdjs.RuntimeScene} runtimeScene The scene.
* @param {string} variableName Name of the global variable.
* @returns {boolean} true if the global variable exits, false otherwise.
* @private
*/
gdjs.evtTools.common.globalVariableExists = function(
runtimeScene,
variableName
) {
return runtimeScene
.getGame()
.getVariables()
.has(variableName);
gdjs.evtTools.common.globalVariableExists = function(runtimeScene, variableName) {
return runtimeScene.getGame().getVariables().has(variableName);
};
/**
* Check if a child exists in a variable.
* @param {gdjs.Variable} variable Variable.
* @param {string} childName Name of the child.
* @returns {boolean} true if child exist in the variable, false otherwise.
* @private
*/
gdjs.evtTools.common.variableChildExists = function(variable, childName) {
@@ -59,6 +65,10 @@ gdjs.evtTools.common.variableChildExists = function(variable, childName) {
};
/**
* Remove the child with the given name in a variable.
* @param {gdjs.Variable} variable Variable.
* @param {string} childName Name of the child.
* @returns {gdjs.Variable} The new variable, with the child removed.
* @private
*/
gdjs.evtTools.common.variableRemoveChild = function(variable, childName) {
@@ -66,6 +76,8 @@ gdjs.evtTools.common.variableRemoveChild = function(variable, childName) {
};
/**
* Clear the children in a variable.
* @param {gdjs.Variable} variable Variable.
* @private
*/
gdjs.evtTools.common.variableClearChildren = function(variable) {
@@ -73,6 +85,9 @@ gdjs.evtTools.common.variableClearChildren = function(variable) {
};
/**
* Get the number of children in a variable.
* @param {gdjs.Variable} variable Variable.
* @returns {number} The number of children in the variable.
* @private
*/
gdjs.evtTools.common.getVariableChildCount = function(variable) {
@@ -81,7 +96,9 @@ gdjs.evtTools.common.getVariableChildCount = function(variable) {
};
/**
* Convert a string to a float.
* Convert a string to a number.
* @param {boolean} str String to convert.
* @returns {number} The parsed number, or NaN if invalid.
* @private
*/
gdjs.evtTools.common.toNumber = function(str) {
@@ -90,6 +107,8 @@ gdjs.evtTools.common.toNumber = function(str) {
/**
* Convert a number to a string.
* @param {number} num Value to convert to a string.
* @returns {string} The value as a string.
* @private
*/
gdjs.evtTools.common.toString = function(num) {
@@ -100,97 +119,196 @@ gdjs.evtTools.common.toString = function(num) {
/**
* Negate the boolean.
* @param {boolean} bool The boolean to negate.
* @returns {boolean} The negated value.
* @private
*/
gdjs.evtTools.common.logicalNegation = function(bool) {
return !bool;
};
/**
* Limit a value to a range.
* @param {number} x Value.
* @param {number} min The minimum value.
* @param {number} max The maximum value.
* @returns {number} The new value.
*/
gdjs.evtTools.common.clamp = function(x, min, max) {
return Math.min(Math.max(x, min), max);
};
/**
* Hyperbolic arc-cosine
* @param {number} arg Value.
* @returns {number} The hyperbolic arc-cosine for the value.
*/
gdjs.evtTools.common.acosh = function(arg) {
// http://kevin.vanzonneveld.net
// + original by: Onno Marsman
return Math.log(arg + Math.sqrt(arg * arg - 1));
};
/**
* Hyperbolic arcsine
* @param {number} arg Value.
* @returns {number} The hyperbolic arcsine for the value.
*/
gdjs.evtTools.common.asinh = function(arg) {
// http://kevin.vanzonneveld.net
// + original by: Onno Marsman
return Math.log(arg + Math.sqrt(arg * arg + 1));
};
/**
* Hyperbolic arctangent
* @param {number} arg Value.
* @returns {number} The hyperbolic arctangent for the value.
*/
gdjs.evtTools.common.atanh = function(arg) {
// http://kevin.vanzonneveld.net
// + original by: Onno Marsman
return 0.5 * Math.log((1 + arg) / (1 - arg));
};
/**
* Hyperbolic cosine
* @param {number} arg Value.
* @returns {number} The hyperbolic cosine for the value.
*/
gdjs.evtTools.common.cosh = function(arg) {
return (Math.exp(arg) + Math.exp(-arg)) / 2;
};
/**
* Hyperbolic sine
* @param {number} arg Value.
* @returns {number} The hyperbolic sine for the value.
*/
gdjs.evtTools.common.sinh = function(arg) {
return (Math.exp(arg) - Math.exp(-arg)) / 2;
};
/**
* Hyperbolic tangent
* @param {number} arg Value.
* @returns {number} The hyperbolic tangent for the value.
*/
gdjs.evtTools.common.tanh = function(arg) {
return (Math.exp(arg) - Math.exp(-arg)) / (Math.exp(arg) + Math.exp(-arg));
};
/**
* Cotangent
* @param {number} arg Value.
* @returns {number} The cotangent for the value.
*/
gdjs.evtTools.common.cot = function(arg) {
return 1 / Math.tan(arg);
};
/**
* Cosecant
* @param {number} arg Value.
* @returns {number} The cosecant for the value.
*/
gdjs.evtTools.common.csc = function(arg) {
return 1 / Math.sin(arg);
};
/**
* Secant
* @param {number} arg Value.
* @returns {number} The secant for the value.
*/
gdjs.evtTools.common.sec = function(arg) {
return 1 / Math.cos(arg);
};
/**
* Base-10 logarithm
* @param {number} arg Value.
* @returns {number} The base-10 logarithm for the value.
*/
gdjs.evtTools.common.log10 = function(arg) {
return Math.log(arg) / Math.LN10;
};
/**
* Base-2 logarithm
* @param {number} arg Value.
* @returns {number} The base-2 logarithm for the value.
*/
gdjs.evtTools.common.log2 = function(arg) {
return Math.log(arg) / Math.LN2;
};
/**
* Returns the sign of the number. This checks if the value is positive, negative or zero.
* @param {number} arg Value.
* @returns {number} Return the sign for the value (1, -1 or 0).
*/
gdjs.evtTools.common.sign = function(arg) {
if (arg === 0) return 0;
return arg > 0 ? +1 : -1;
};
/**
* Cube root
* @param {number} x Value.
* @returns {number} Return the cube root for the value.
*/
gdjs.evtTools.common.cbrt = function(x) {
return Math.pow(x, 1 / 3);
};
/**
* N-th root
* @param {number} x Base value.
* @param {number} n Exponent value.
* @returns {number} Return the n-th root for the value.
*/
gdjs.evtTools.common.nthroot = function(x, n) {
return Math.pow(x, 1 / n);
};
/**
* Modulo operation (the remainder after dividing one number by another)
* @param {number} x Dividend value.
* @param {number} y Divisor value.
* @returns {number} Return the remainder for the values.
*/
gdjs.evtTools.common.mod = function(x, y) {
return x - y * Math.floor(x / y);
};
/**
* Returns the difference between two angles, in degrees.
* @param {number} angle1 First angle, in degrees.
* @param {number} angle2 Second angle, in degrees.
* @returns {number} Return the difference of the angles, in degrees.
*/
gdjs.evtTools.common.angleDifference = function(angle1, angle2) {
return (
gdjs.evtTools.common.mod(
gdjs.evtTools.common.mod(angle1 - angle2, 360.0) + 180.0,
360.0
) - 180.0
);
return gdjs.evtTools.common.mod(gdjs.evtTools.common.mod(angle1 - angle2, 360.0) + 180.0, 360.0) - 180.0;
};
/**
* Runs a linear interpolation between a and b.
* @param {number} a Start value.
* @param {number} b End value.
* @param {number} x The interpolation value between 0 and 1.
* @returns {number} The interpolated value, now between a and b.
*/
gdjs.evtTools.common.lerp = function(a, b, x) {
return a + (b - a) * x;
};
/**
* Truncate a number.
* @param {number} x Value.
* @returns {number} Return the value with all decimal places dropped.
*/
gdjs.evtTools.common.trunc = function(x) {
return x | 0;
};

View File

@@ -20,11 +20,14 @@ gdjs.evtTools.input = gdjs.evtTools.input || {};
* @private
*/
gdjs.evtTools.input.isKeyPressed = function(runtimeScene, key) {
if (gdjs.evtTools.input.keysNameToCode.hasOwnProperty(key)) {
return runtimeScene.getGame().getInputManager().isKeyPressed(gdjs.evtTools.input.keysNameToCode[key]);
}
if (gdjs.evtTools.input.keysNameToCode.hasOwnProperty(key)) {
return runtimeScene
.getGame()
.getInputManager()
.isKeyPressed(gdjs.evtTools.input.keysNameToCode[key]);
}
return false;
return false;
};
/**
@@ -33,11 +36,14 @@ gdjs.evtTools.input.isKeyPressed = function(runtimeScene, key) {
* @private
*/
gdjs.evtTools.input.wasKeyReleased = function(runtimeScene, key) {
if (gdjs.evtTools.input.keysNameToCode.hasOwnProperty(key)) {
return runtimeScene.getGame().getInputManager().wasKeyReleased(gdjs.evtTools.input.keysNameToCode[key]);
}
if (gdjs.evtTools.input.keysNameToCode.hasOwnProperty(key)) {
return runtimeScene
.getGame()
.getInputManager()
.wasKeyReleased(gdjs.evtTools.input.keysNameToCode[key]);
}
return false;
return false;
};
/**
@@ -45,88 +51,94 @@ gdjs.evtTools.input.wasKeyReleased = function(runtimeScene, key) {
* @private
*/
gdjs.evtTools.input.lastPressedKey = function(runtimeScene) {
//Ensure _keysCodeToName is constructed
if (gdjs.evtTools.input._keysCodeToName === undefined) {
gdjs.evtTools.input._keysCodeToName = {};
var keysNameToCode = gdjs.evtTools.input.keysNameToCode;
for(var p in keysNameToCode) {
if (keysNameToCode.hasOwnProperty(p)) {
gdjs.evtTools.input._keysCodeToName[keysNameToCode[p]] = p;
}
}
//Ensure _keysCodeToName is constructed
if (gdjs.evtTools.input._keysCodeToName === undefined) {
gdjs.evtTools.input._keysCodeToName = {};
var keysNameToCode = gdjs.evtTools.input.keysNameToCode;
for (var p in keysNameToCode) {
if (keysNameToCode.hasOwnProperty(p)) {
gdjs.evtTools.input._keysCodeToName[keysNameToCode[p]] = p;
}
}
}
var keyCode = runtimeScene.getGame().getInputManager().getLastPressedKey();
if (gdjs.evtTools.input._keysCodeToName.hasOwnProperty(keyCode)) {
return gdjs.evtTools.input._keysCodeToName[keyCode];
}
var keyCode = runtimeScene
.getGame()
.getInputManager()
.getLastPressedKey();
if (gdjs.evtTools.input._keysCodeToName.hasOwnProperty(keyCode)) {
return gdjs.evtTools.input._keysCodeToName[keyCode];
}
return "";
return '';
};
/**
* Hashmap associated each name of a key to its keyCode.
* Hashmap associated each name of a key to its location-aware keyCode.
* @memberof gdjs.evtTools
*/
gdjs.evtTools.input.keysNameToCode = {
"a": 65,
"b": 66,
"c": 67,
"d": 68,
"e": 69,
"f": 70,
"g": 71,
"h": 72,
"i": 73,
"j": 74,
"k": 75,
"l": 76,
"m": 77,
"n": 78,
"o": 79,
"p": 80,
"q": 81,
"r": 82,
"s": 83,
"t": 84,
"u": 85,
"v": 86,
"w": 87,
"x": 88,
"y": 89,
"z": 90,
"Num0": 48,
"Num1": 49,
"Num2": 50,
"Num3": 51,
"Num4": 52,
"Num5": 53,
"Num6": 54,
"Num7": 55,
"Num8": 56,
"Num9": 57,
a: 65,
b: 66,
c: 67,
d: 68,
e: 69,
f: 70,
g: 71,
h: 72,
i: 73,
j: 74,
k: 75,
l: 76,
m: 77,
n: 78,
o: 79,
p: 80,
q: 81,
r: 82,
s: 83,
t: 84,
u: 85,
v: 86,
w: 87,
x: 88,
y: 89,
z: 90,
"Numpad0": 96,
"Numpad1": 97,
"Numpad2": 98,
"Numpad3": 99,
"Numpad4": 100,
"Numpad5": 101,
"Numpad6": 102,
"Numpad7": 103,
"Numpad8": 104,
"Numpad9": 105,
Num0: 48,
Num1: 49,
Num2: 50,
Num3: 51,
Num4: 52,
Num5: 53,
Num6: 54,
Num7: 55,
Num8: 56,
Num9: 57,
"RControl": 17,
"RShift": 16,
"RAlt": 18,
"LControl": 17,
"LShift": 16,
"LAlt": 18,
"LSystem": 91,
"RSystem": 91,
/*"Menu": sf::Keyboard::Menu ,
Numpad0: 96,
Numpad1: 97,
Numpad2: 98,
Numpad3: 99,
Numpad4: 100,
Numpad5: 101,
Numpad6: 102,
Numpad7: 103,
Numpad8: 104,
Numpad9: 105,
LShift: 1016,
RShift: 2016,
LControl: 1017,
RControl: 2017,
LAlt: 1018,
RAlt: 2018,
LSystem: 1091,
RSystem: 2091,
/*"Menu": sf::Keyboard::Menu ,
"LBracket": sf::Keyboard::LBracket ,
"RBracket": sf::Keyboard::RBracket ,
"SemiColon": sf::Keyboard::SemiColon ,
@@ -138,147 +150,251 @@ gdjs.evtTools.input.keysNameToCode = {
"Tilde": sf::Keyboard::Tilde ,
"Equal": sf::Keyboard::Equal ,
"Dash": sf::Keyboard::Dash,*/
"Space": 32,
"Return": 13,
"Back": 8,
"Tab": 9,
"PageUp": 33,
"PageDown": 34,
"End": 35,
"Home": 36,
"Delete": 46,
"Insert": 45,
"Escape": 27,
Space: 32,
Back: 8,
Tab: 9,
Delete: 46,
Insert: 45,
Escape: 27,
"Add": 107,
"Subtract": 109,
"Multiply": 106,
"Divide": 111,
PageUp: 33,
PageDown: 34,
End: 35,
Home: 36,
Return: 13,
NumpadPageUp: 3033,
NumpadPageDown: 3034,
NumpadEnd: 3035,
NumpadHome: 3036,
NumpadReturn: 3013,
"Left": 37,
"Up": 38,
"Right": 39,
"Down": 40,
Add: 107,
Subtract: 109,
Multiply: 106,
Divide: 111,
NumpadAdd: 3107,
NumpadSubtract: 3109,
NumpadMultiply: 3106,
NumpadDivide: 3111,
"F1": 112,
"F2": 113,
"F3": 114,
"F4": 115,
"F5": 116,
"F6": 117,
"F7": 118,
"F8": 119,
"F9": 120,
"F10": 121,
"F11": 122,
"F12": 123,
Left: 37,
Up: 38,
Right: 39,
Down: 40,
NumpadLeft: 3037,
NumpadUp: 3038,
NumpadRight: 3039,
NumpadDown: 3040,
"Pause": 19
F1: 112,
F2: 113,
F3: 114,
F4: 115,
F5: 116,
F6: 117,
F7: 118,
F8: 119,
F9: 120,
F10: 121,
F11: 122,
F12: 123,
Pause: 19,
};
gdjs.evtTools.input.anyKeyPressed = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().anyKeyPressed();
return runtimeScene
.getGame()
.getInputManager()
.anyKeyPressed();
};
gdjs.evtTools.input.isMouseButtonPressed = function(runtimeScene, button) {
if ( button === "Left" ) return runtimeScene.getGame().getInputManager().isMouseButtonPressed(0);
if ( button === "Right" ) return runtimeScene.getGame().getInputManager().isMouseButtonPressed(1);
if ( button === "Middle" ) return runtimeScene.getGame().getInputManager().isMouseButtonPressed(2);
return false;
if (button === 'Left')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonPressed(0);
if (button === 'Right')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonPressed(1);
if (button === 'Middle')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonPressed(2);
return false;
};
gdjs.evtTools.input.isMouseButtonReleased = function(runtimeScene, button) {
if ( button === "Left" ) return runtimeScene.getGame().getInputManager().isMouseButtonReleased(0);
if ( button === "Right" ) return runtimeScene.getGame().getInputManager().isMouseButtonReleased(1);
if ( button === "Middle" ) return runtimeScene.getGame().getInputManager().isMouseButtonReleased(2);
return false;
if (button === 'Left')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonReleased(0);
if (button === 'Right')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonReleased(1);
if (button === 'Middle')
return runtimeScene
.getGame()
.getInputManager()
.isMouseButtonReleased(2);
return false;
};
gdjs.evtTools.input.hideCursor = function(runtimeScene) {
runtimeScene.getRenderer().hideCursor();
runtimeScene.getRenderer().hideCursor();
};
gdjs.evtTools.input.showCursor = function(runtimeScene) {
runtimeScene.getRenderer().showCursor();
runtimeScene.getRenderer().showCursor();
};
gdjs.evtTools.input.getMouseWheelDelta = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().getMouseWheelDelta();
return runtimeScene
.getGame()
.getInputManager()
.getMouseWheelDelta();
};
gdjs.evtTools.input.isScrollingUp = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().isScrollingUp();
return runtimeScene
.getGame()
.getInputManager()
.isScrollingUp();
};
gdjs.evtTools.input.isScrollingDown = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().isScrollingDown();
return runtimeScene
.getGame()
.getInputManager()
.isScrollingDown();
};
gdjs.evtTools.input.getMouseX = function(runtimeScene, layer, camera) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene.getGame().getInputManager().getMouseX(),
runtimeScene.getGame().getInputManager().getMouseY())[0];
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene
.getGame()
.getInputManager()
.getMouseX(),
runtimeScene
.getGame()
.getInputManager()
.getMouseY()
)[0];
};
gdjs.evtTools.input.getMouseY = function(runtimeScene, layer, camera) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene.getGame().getInputManager().getMouseX(),
runtimeScene.getGame().getInputManager().getMouseY())[1];
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene
.getGame()
.getInputManager()
.getMouseX(),
runtimeScene
.getGame()
.getInputManager()
.getMouseY()
)[1];
};
gdjs.evtTools.input._cursorIsOnObject = function(obj, runtimeScene) {
return obj.cursorOnObject(runtimeScene);
return obj.cursorOnObject(runtimeScene);
};
gdjs.evtTools.input.cursorOnObject = function(objectsLists, runtimeScene, accurate, inverted) {
return gdjs.evtTools.object.pickObjectsIf(gdjs.evtTools.input._cursorIsOnObject,
objectsLists, inverted, runtimeScene);
gdjs.evtTools.input.cursorOnObject = function(
objectsLists,
runtimeScene,
accurate,
inverted
) {
return gdjs.evtTools.object.pickObjectsIf(
gdjs.evtTools.input._cursorIsOnObject,
objectsLists,
inverted,
runtimeScene
);
};
gdjs.evtTools.input.getTouchX = function(runtimeScene, identifier, layer, camera) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene.getGame().getInputManager().getTouchX(identifier),
runtimeScene.getGame().getInputManager().getTouchY(identifier))[0];
gdjs.evtTools.input.getTouchX = function(
runtimeScene,
identifier,
layer,
camera
) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene
.getGame()
.getInputManager()
.getTouchX(identifier),
runtimeScene
.getGame()
.getInputManager()
.getTouchY(identifier)
)[0];
};
gdjs.evtTools.input.getTouchY = function(runtimeScene, identifier, layer, camera) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene.getGame().getInputManager().getTouchX(identifier),
runtimeScene.getGame().getInputManager().getTouchY(identifier))[1];
gdjs.evtTools.input.getTouchY = function(
runtimeScene,
identifier,
layer,
camera
) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene
.getGame()
.getInputManager()
.getTouchX(identifier),
runtimeScene
.getGame()
.getInputManager()
.getTouchY(identifier)
)[1];
};
gdjs.evtTools.input.getLastTouchId = function() {
return gdjs.evtTools.input.lastTouchId || 0;
return gdjs.evtTools.input.lastTouchId || 0;
};
gdjs.evtTools.input.getLastEndedTouchId = function() {
return gdjs.evtTools.input.lastEndedTouchId || 0;
return gdjs.evtTools.input.lastEndedTouchId || 0;
};
gdjs.evtTools.input.popStartedTouch = function(runtimeScene) {
var startedTouchId = runtimeScene.getGame().getInputManager().popStartedTouch();
var startedTouchId = runtimeScene
.getGame()
.getInputManager()
.popStartedTouch();
if (startedTouchId !== undefined) {
gdjs.evtTools.input.lastTouchId = startedTouchId;
return true;
}
if (startedTouchId !== undefined) {
gdjs.evtTools.input.lastTouchId = startedTouchId;
return true;
}
return false;
return false;
};
gdjs.evtTools.input.popEndedTouch = function(runtimeScene) {
var endedTouchId = runtimeScene.getGame().getInputManager().popEndedTouch();
var endedTouchId = runtimeScene
.getGame()
.getInputManager()
.popEndedTouch();
if (endedTouchId !== undefined) {
gdjs.evtTools.input.lastEndedTouchId = endedTouchId;
return true;
}
if (endedTouchId !== undefined) {
gdjs.evtTools.input.lastEndedTouchId = endedTouchId;
return true;
}
return false;
return false;
};
gdjs.evtTools.input.touchSimulateMouse = function(runtimeScene, enable) {
runtimeScene.getGame().getInputManager().touchSimulateMouse(enable);
runtimeScene
.getGame()
.getInputManager()
.touchSimulateMouse(enable);
};

View File

@@ -16,21 +16,20 @@
* @memberof gdjs
* @class InputManager
*/
gdjs.InputManager = function()
{
this._pressedKeys = new Hashtable();
this._releasedKeys = new Hashtable();
this._lastPressedKey = 0;
this._pressedMouseButtons = new Array(5);
this._releasedMouseButtons = new Array(5);
this._mouseX = 0;
this._mouseY = 0;
this._mouseWheelDelta = 0;
this._touches = new Hashtable();
this._startedTouches = []; //Identifiers of the touches that started during/before the frame.
this._endedTouches = []; //Identifiers of the touches that ended during/before the frame.
gdjs.InputManager = function() {
this._pressedKeys = new Hashtable();
this._releasedKeys = new Hashtable();
this._lastPressedKey = 0;
this._pressedMouseButtons = new Array(5);
this._releasedMouseButtons = new Array(5);
this._mouseX = 0;
this._mouseY = 0;
this._mouseWheelDelta = 0;
this._touches = new Hashtable();
this._startedTouches = []; //Identifiers of the touches that started during/before the frame.
this._endedTouches = []; //Identifiers of the touches that ended during/before the frame.
this._touchSimulateMouse = true;
this._touchSimulateMouse = true;
};
/** @constant {number} */
@@ -43,72 +42,127 @@ gdjs.InputManager.MOUSE_RIGHT_BUTTON = 1;
gdjs.InputManager.MOUSE_MIDDLE_BUTTON = 2;
/**
* Should be called whenever a key is pressed
* @param {number} keyCode The key code associated to the key press.
* Holds the raw keyCodes of the keys which only have left/right
* variants and should default to their left variant values
* if location is not specified.
*
* @constant {Array<number>}
*/
gdjs.InputManager.prototype.onKeyPressed = function(keyCode) {
this._pressedKeys.put(keyCode, true);
this._lastPressedKey = keyCode;
};
gdjs.InputManager._DEFAULT_LEFT_VARIANT_KEYS = [16, 17, 18, 91];
/**
* Should be called whenever a key is released
* @param {number} keyCode The key code associated to the key release.
* Returns the "location-aware" keyCode, given a raw keyCode
* and location. The location corresponds to KeyboardEvent.location,
* which should be 0 for standard keys, 1 for left keys,
* 2 for right keys, and 3 for numpad keys.
*
* @param {number} keyCode The raw key code
* @param {?number} location The location
*/
gdjs.InputManager.prototype.onKeyReleased = function(keyCode) {
this._pressedKeys.put(keyCode, false);
this._releasedKeys.put(keyCode, true);
};
/**
* Return the code of the last key that was pressed.
* @return {number} The code of the last key pressed.
*/
gdjs.InputManager.prototype.getLastPressedKey = function() {
return this._lastPressedKey;
};
/**
* Return true if the key corresponding to keyCode is pressed.
* @param {number} keyCode The key code to be tested.
*/
gdjs.InputManager.prototype.isKeyPressed = function(keyCode) {
return this._pressedKeys.containsKey(keyCode) && this._pressedKeys.get(keyCode);
};
/**
* Return true if the key corresponding to keyCode was released during the last frame.
* @param {number} keyCode The key code to be tested.
*/
gdjs.InputManager.prototype.wasKeyReleased = function(keyCode) {
return this._releasedKeys.containsKey(keyCode) && this._releasedKeys.get(keyCode);
};
/**
* Return true if any key is pressed
*/
gdjs.InputManager.prototype.anyKeyPressed = function() {
for(var keyCode in this._pressedKeys.items) {
if (this._pressedKeys.items.hasOwnProperty(keyCode)) {
if (this._pressedKeys.items[keyCode]) {
return true;
}
}
gdjs.InputManager.prototype._getLocationAwareKeyCode = function(
keyCode,
location
) {
if (location) {
// If it is a numpad number, do not modify it.
if (96 <= keyCode && keyCode <= 105) {
return keyCode;
}
return false;
return keyCode + 1000 * location;
}
if (gdjs.InputManager._DEFAULT_LEFT_VARIANT_KEYS.indexOf(keyCode) !== -1) {
return keyCode + 1000;
}
return keyCode;
};
/**
* Should be called when the mouse is moved.<br>
* Should be called whenever a key is pressed. The location corresponds to
* KeyboardEvent.location, which should be 0 for standard keys, 1 for left keys,
* 2 for right keys, and 3 for numpad keys.
* @param {number} keyCode The raw key code associated to the key press.
* @param {number=} location The location of the event.
*/
gdjs.InputManager.prototype.onKeyPressed = function(keyCode, location) {
var locationAwareKeyCode = this._getLocationAwareKeyCode(keyCode, location);
this._pressedKeys.put(locationAwareKeyCode, true);
this._lastPressedKey = locationAwareKeyCode;
};
/**
* Should be called whenever a key is released. The location corresponds to
* KeyboardEvent.location, which should be 0 for standard keys, 1 for left keys,
* 2 for right keys, and 3 for numpad keys.
* @param {number} keyCode The raw key code associated to the key release.
* @param {number=} location The location of the event.
*/
gdjs.InputManager.prototype.onKeyReleased = function(keyCode, location) {
var locationAwareKeyCode = this._getLocationAwareKeyCode(keyCode, location);
this._pressedKeys.put(locationAwareKeyCode, false);
this._releasedKeys.put(locationAwareKeyCode, true);
};
/**
* Return the location-aware code of the last key that was pressed.
* @return {number} The location-aware code of the last key pressed.
*/
gdjs.InputManager.prototype.getLastPressedKey = function() {
return this._lastPressedKey;
};
/**
* Return true if the key corresponding to the location-aware keyCode is pressed.
* @param {number} locationAwareKeyCode The location-aware key code to be tested.
*/
gdjs.InputManager.prototype.isKeyPressed = function(locationAwareKeyCode) {
return (
this._pressedKeys.containsKey(locationAwareKeyCode) &&
this._pressedKeys.get(locationAwareKeyCode)
);
};
/**
* Return true if the key corresponding to the location-aware keyCode was released during the last frame.
* @param {number} locationAwareKeyCode The location-aware key code to be tested.
*/
gdjs.InputManager.prototype.wasKeyReleased = function(locationAwareKeyCode) {
return (
this._releasedKeys.containsKey(locationAwareKeyCode) &&
this._releasedKeys.get(locationAwareKeyCode)
);
};
/**
* Return true if any key is pressed.
*/
gdjs.InputManager.prototype.anyKeyPressed = function() {
for (var keyCode in this._pressedKeys.items) {
if (this._pressedKeys.items.hasOwnProperty(keyCode)) {
if (this._pressedKeys.items[keyCode]) {
return true;
}
}
}
return false;
};
/**
* Should be called when the mouse is moved.
*
* Please note that the coordinates must be expressed relative to the view position.
*
* @param {number} x The mouse new X position
* @param {number} y The mouse new Y position
*/
gdjs.InputManager.prototype.onMouseMove = function(x,y) {
this._mouseX = x;
this._mouseY = y;
gdjs.InputManager.prototype.onMouseMove = function(x, y) {
this._mouseX = x;
this._mouseY = y;
};
/**
@@ -117,7 +171,7 @@ gdjs.InputManager.prototype.onMouseMove = function(x,y) {
* @return the mouse X position, relative to the game view.
*/
gdjs.InputManager.prototype.getMouseX = function() {
return this._mouseX;
return this._mouseX;
};
/**
@@ -126,26 +180,26 @@ gdjs.InputManager.prototype.getMouseX = function() {
* @return the mouse Y position, relative to the game view.
*/
gdjs.InputManager.prototype.getMouseY = function() {
return this._mouseY;
return this._mouseY;
};
/**
* Should be called whenever a mouse button is pressed
* @param {number} buttonCode The mouse button code associated to the event.
* Should be called whenever a mouse button is pressed.
* @param {number} buttonCode The mouse button code associated to the event.
* See gdjs.InputManager.MOUSE_LEFT_BUTTON, gdjs.InputManager.MOUSE_RIGHT_BUTTON, gdjs.InputManager.MOUSE_MIDDLE_BUTTON
*/
gdjs.InputManager.prototype.onMouseButtonPressed = function(buttonCode) {
this._pressedMouseButtons[buttonCode] = true;
this._releasedMouseButtons[buttonCode] = false;
this._pressedMouseButtons[buttonCode] = true;
this._releasedMouseButtons[buttonCode] = false;
};
/**
* Should be called whenever a mouse button is released
* Should be called whenever a mouse button is released.
* @param {number} buttonCode The mouse button code associated to the event. (see onMouseButtonPressed)
*/
gdjs.InputManager.prototype.onMouseButtonReleased = function(buttonCode) {
this._pressedMouseButtons[buttonCode] = false;
this._releasedMouseButtons[buttonCode] = true;
this._pressedMouseButtons[buttonCode] = false;
this._releasedMouseButtons[buttonCode] = true;
};
/**
@@ -153,7 +207,10 @@ gdjs.InputManager.prototype.onMouseButtonReleased = function(buttonCode) {
* @param {number} buttonCode The mouse button code (0: Left button, 1: Right button).
*/
gdjs.InputManager.prototype.isMouseButtonPressed = function(buttonCode) {
return this._pressedMouseButtons[buttonCode] !== undefined && this._pressedMouseButtons[buttonCode];
return (
this._pressedMouseButtons[buttonCode] !== undefined &&
this._pressedMouseButtons[buttonCode]
);
};
/**
@@ -161,7 +218,10 @@ gdjs.InputManager.prototype.isMouseButtonPressed = function(buttonCode) {
* @param {number} buttonCode The mouse button code (0: Left button, 1: Right button).
*/
gdjs.InputManager.prototype.isMouseButtonReleased = function(buttonCode) {
return this._releasedMouseButtons[buttonCode] !== undefined && this._releasedMouseButtons[buttonCode];
return (
this._releasedMouseButtons[buttonCode] !== undefined &&
this._releasedMouseButtons[buttonCode]
);
};
/**
@@ -169,14 +229,14 @@ gdjs.InputManager.prototype.isMouseButtonReleased = function(buttonCode) {
* @param {number} wheelDelta The mouse wheel delta
*/
gdjs.InputManager.prototype.onMouseWheel = function(wheelDelta) {
this._mouseWheelDelta = wheelDelta;
this._mouseWheelDelta = wheelDelta;
};
/**
* Return the mouse wheel delta
*/
gdjs.InputManager.prototype.getMouseWheelDelta = function() {
return this._mouseWheelDelta;
return this._mouseWheelDelta;
};
/**
@@ -185,10 +245,9 @@ gdjs.InputManager.prototype.getMouseWheelDelta = function() {
* @return the touch X position, relative to the game view.
*/
gdjs.InputManager.prototype.getTouchX = function(identifier) {
if (!this._touches.containsKey(identifier))
return 0;
if (!this._touches.containsKey(identifier)) return 0;
return this._touches.get(identifier).x;
return this._touches.get(identifier).x;
};
/**
@@ -197,10 +256,9 @@ gdjs.InputManager.prototype.getTouchX = function(identifier) {
* @return the touch Y position, relative to the game view.
*/
gdjs.InputManager.prototype.getTouchY = function(identifier) {
if (!this._touches.containsKey(identifier))
return 0;
if (!this._touches.containsKey(identifier)) return 0;
return this._touches.get(identifier).y;
return this._touches.get(identifier).y;
};
/**
@@ -208,61 +266,62 @@ gdjs.InputManager.prototype.getTouchY = function(identifier) {
*
*/
gdjs.InputManager.prototype.getAllTouchIdentifiers = function() {
gdjs.InputManager._allTouchIds = gdjs.InputManager._allTouchIds || [];
gdjs.InputManager._allTouchIds.length = 0;
gdjs.InputManager._allTouchIds = gdjs.InputManager._allTouchIds || [];
gdjs.InputManager._allTouchIds.length = 0;
for(var id in this._touches.items) {
if (this._touches.items.hasOwnProperty(id)) {
gdjs.InputManager._allTouchIds.push(parseInt(id, 10));
}
for (var id in this._touches.items) {
if (this._touches.items.hasOwnProperty(id)) {
gdjs.InputManager._allTouchIds.push(parseInt(id, 10));
}
}
return gdjs.InputManager._allTouchIds;
return gdjs.InputManager._allTouchIds;
};
gdjs.InputManager.prototype.onTouchStart = function(identifier, x, y) {
this._startedTouches.push(identifier);
this._touches.put(identifier, {x: x, y: y});
this._startedTouches.push(identifier);
this._touches.put(identifier, { x: x, y: y });
if (this._touchSimulateMouse) {
this.onMouseMove(x, y);
this.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
}
if (this._touchSimulateMouse) {
this.onMouseMove(x, y);
this.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
}
};
gdjs.InputManager.prototype.onTouchMove = function(identifier, x, y) {
var touch = this._touches.get(identifier);
if (!touch) return;
var touch = this._touches.get(identifier);
if (!touch) return;
touch.x = x;
touch.y = y;
touch.x = x;
touch.y = y;
if (this._touchSimulateMouse) {
this.onMouseMove(x, y);
}
if (this._touchSimulateMouse) {
this.onMouseMove(x, y);
}
};
gdjs.InputManager.prototype.onTouchEnd = function(identifier) {
this._endedTouches.push(identifier);
if (this._touches.containsKey(identifier)) { //Postpone deletion at the end of the frame
this._touches.get(identifier).justEnded = true;
}
this._endedTouches.push(identifier);
if (this._touches.containsKey(identifier)) {
//Postpone deletion at the end of the frame
this._touches.get(identifier).justEnded = true;
}
if (this._touchSimulateMouse) {
this.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
}
if (this._touchSimulateMouse) {
this.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
}
};
gdjs.InputManager.prototype.getStartedTouchIdentifiers = function() {
return this._startedTouches;
return this._startedTouches;
};
gdjs.InputManager.prototype.popStartedTouch = function() {
return this._startedTouches.shift();
return this._startedTouches.shift();
};
gdjs.InputManager.prototype.popEndedTouch = function() {
return this._endedTouches.shift();
return this._endedTouches.shift();
};
/**
@@ -273,9 +332,9 @@ gdjs.InputManager.prototype.popEndedTouch = function() {
* @param enable {Boolean} true to simulate mouse events, false to disable it.
*/
gdjs.InputManager.prototype.touchSimulateMouse = function(enable) {
if (enable === undefined) enable = true;
if (enable === undefined) enable = true;
this._touchSimulateMouse = enable;
this._touchSimulateMouse = enable;
};
/**
@@ -285,33 +344,33 @@ gdjs.InputManager.prototype.touchSimulateMouse = function(enable) {
* This method should be called in the game loop (see gdjs.RuntimeGame.startGameLoop).
*/
gdjs.InputManager.prototype.onFrameEnded = function() {
//Only clear the ended touches at the end of the frame.
for(var id in this._touches.items) {
if (this._touches.items.hasOwnProperty(id)) {
var touch = this._touches.items[id];
if(touch.justEnded) {
this._touches.remove(id);
}
}
//Only clear the ended touches at the end of the frame.
for (var id in this._touches.items) {
if (this._touches.items.hasOwnProperty(id)) {
var touch = this._touches.items[id];
if (touch.justEnded) {
this._touches.remove(id);
}
}
}
this._startedTouches.length = 0;
this._endedTouches.length = 0;
this._releasedKeys.clear();
this._releasedMouseButtons.length = 0;
this._mouseWheelDelta = 0;
this._startedTouches.length = 0;
this._endedTouches.length = 0;
this._releasedKeys.clear();
this._releasedMouseButtons.length = 0;
this._mouseWheelDelta = 0;
};
/**
* Return true if the mouse wheel scroll to up
*/
gdjs.InputManager.prototype.isScrollingUp = function() {
return this.getMouseWheelDelta() > 0;
return this.getMouseWheelDelta() > 0;
};
/**
* Return true if the mouse wheel scroll to down
*/
gdjs.InputManager.prototype.isScrollingDown = function() {
return this.getMouseWheelDelta() < 0;
return this.getMouseWheelDelta() < 0;
};

View File

@@ -5,7 +5,14 @@
gdjs.PixiFiltersTools = {};
gdjs.PixiFiltersTools.clampValue = function(value, min, max) { return Math.max(min, Math.min(max, value)); };
gdjs.PixiFiltersTools.clampKernelSize = function(value) { return (([5, 7, 9, 11, 13, 15].indexOf(value) !== -1) ? value : 5); };
gdjs.PixiFiltersTools.clampKernelSize = function(value, min, max) {
var len = Math.round((max - min) / 2 + 1);
var arr = new Array(len);
for (var i = 0; i < len; i++) {
arr[i] = min + 2 * i;
}
return ((arr.indexOf(value) !== -1) ? value : min);
};
/** Object.<string, gdjsPixiFiltersToolsFilterCreator> */
gdjs.PixiFiltersTools._filterCreators = {};

View File

@@ -327,10 +327,10 @@ gdjs.RuntimeGamePixiRenderer.prototype.bindStandardEvents = function(
//Keyboard
document.onkeydown = function(e) {
manager.onKeyPressed(e.keyCode);
manager.onKeyPressed(e.keyCode, e.location);
};
document.onkeyup = function(e) {
manager.onKeyReleased(e.keyCode);
manager.onKeyReleased(e.keyCode, e.location);
};
//Mouse
renderer.view.onmousemove = function(e) {

View File

@@ -102,27 +102,15 @@ gdjs.RuntimeScene.prototype.loadFromScene = function(sceneData) {
this._initialBehaviorSharedData.put(data.name, data);
}
var that = this;
function loadObject(objData) {
var objectName = objData.name;
var objectType = objData.type;
that._objects.put(objectName, objData);
that._instances.put(objectName, []); //Also reserve an array for the instances
that._instancesCache.put(objectName, []); //and for cached instances
//And cache the constructor for the performance sake:
that._objectsCtor.put(objectName, gdjs.getObjectConstructor(objectType));
}
//Load objects: Global objects first...
//Registering objects: Global objects first...
var initialGlobalObjectsData = this.getGame().getInitialObjectsData();
for(var i = 0, len = initialGlobalObjectsData.length;i<len;++i) {
loadObject(initialGlobalObjectsData[i]);
this.registerObject(initialGlobalObjectsData[i]);
}
//...then the scene objects
this._initialObjectsData = sceneData.objects;
for(var i = 0, len = this._initialObjectsData.length;i<len;++i) {
loadObject(this._initialObjectsData[i]);
this.registerObject(this._initialObjectsData[i]);
}
//Create initial instances of objects
@@ -156,6 +144,17 @@ gdjs.RuntimeScene.prototype.loadFromScene = function(sceneData) {
this._timeManager.reset();
};
/**
* Register a {@link gdjs.RuntimeObject} so that instances of it can be used in the scene.
* @param {ObjectData} objectData The data for the object to register.
*/
gdjs.RuntimeScene.prototype.registerObject = function(objectData) {
this._objects.put(objectData.name, objectData);
this._instances.put(objectData.name, []); //Also reserve an array for the instances
this._instancesCache.put(objectData.name, []); //and for cached instances
this._objectsCtor.put(objectData.name, gdjs.getObjectConstructor(objectData.type)); //And cache the constructor for the performance sake
}
/**
* Called when a scene is "paused", i.e it will be not be rendered again
* for some time, until it's resumed or unloaded.

View File

@@ -1,14 +1,64 @@
/**
* This DebuggerClient connects to a websocket server and can dump
* An client side implementation of the Debugger
* @interface
*/
gdjs.DebuggerClient = function() {} // Necessary for Interface definition
/**
* Update a value, specified by a path starting from the {@link RuntimeGame} instance.
* @function
* @name gdjs.DebuggerClient#set
* @param {Array<string>} path - The path of the property to modify, starting from the RuntimeGame.
* @param {any} newValue - The new value.
*/
/**
* Call a method, specified by a path starting from the {@link RuntimeGame} instance.
* @function
* @name gdjs.DebuggerClient#call
* @param {Array<string>} path - The path to the method, starting from the RuntimeGame.
* @param {Array<any>} args - The arguments to pass the method.
*/
/**
* Dump all the relevant data from the {@link RuntimeGame} instance and send it to the server.
* @function
* @name gdjs.DebuggerClient#sendRuntimeGameDump
*/
/**
* Start profiling.
* @function
* @name gdjs.DebuggerClient#sendProfilerStarted
*/
/**
* Stop profiling.
* @function
* @name gdjs.DebuggerClient#sendProfilerStopped
*/
/**
* Send profiling results.
* @function
* @param {any} framesAverageMeasures The measures made for each frames.
* @param {any} stats Other measures done during the profiler run.
* @name gdjs.DebuggerClient#sendProfilerOutput
*/
/**
* This {@link DebuggerClient} connects to a websocket server, can dump
* the data of the current game, and receive message to change a field or
* call a function on an object of the specified runtimeGame.
* call a function, specified by a path from the {@link RuntimeGame}.
*
* @memberof gdjs
* @implements {gdjs.DebuggerClient}
* @class WebsocketDebuggerClient
* @param {gdjs.RuntimeGame} The `gdjs.RuntimeGame` to be debug
* @param {gdjs.RuntimeGame} runtimeGame - The `gdjs.RuntimeGame` to be debugged
*/
gdjs.WebsocketDebuggerClient = function(runtimegame) {
this._runtimegame = runtimegame;
gdjs.WebsocketDebuggerClient = function(runtimeGame) {
this._runtimegame = runtimeGame;
if (typeof WebSocket === 'undefined') {
console.log("WebSocket is not defined, debugger won't work");
@@ -48,9 +98,9 @@ gdjs.WebsocketDebuggerClient = function(runtimegame) {
if (data && data.command) {
if (data.command === 'play') {
runtimegame.pause(false);
runtimeGame.pause(false);
} else if (data.command === 'pause') {
runtimegame.pause(true);
runtimeGame.pause(true);
that.sendRuntimeGameDump();
} else if (data.command === 'refresh') {
that.sendRuntimeGameDump();
@@ -59,7 +109,7 @@ gdjs.WebsocketDebuggerClient = function(runtimegame) {
} else if (data.command === 'call') {
that.call(data.path, data.args);
} else if (data.command === 'profiler.start') {
runtimegame.startCurrentSceneProfiler(function(stoppedProfiler) {
runtimeGame.startCurrentSceneProfiler(function(stoppedProfiler) {
that.sendProfilerOutput(
stoppedProfiler.getFramesAverageMeasures(),
stoppedProfiler.getStats()
@@ -68,7 +118,7 @@ gdjs.WebsocketDebuggerClient = function(runtimegame) {
});
that.sendProfilerStarted();
} else if (data.command === 'profiler.stop') {
runtimegame.stopCurrentSceneProfiler();
runtimeGame.stopCurrentSceneProfiler();
} else {
console.info(
'Unknown command "' + data.command + '" received by the debugger.'
@@ -271,8 +321,23 @@ gdjs.WebsocketDebuggerClient.prototype.sendProfilerOutput = function(
);
};
// This is an alternative to JSON.stringify that ensure that circular reference
// are replaced by a placeholder.
/**
* A function used to replace circular references with a new value.
* @callback DebuggerClientCycleReplacer
* @param {string | number} key - The key corresponding to the value.
* @param {any} value - The value.
* @returns {any} The new value.
*/
/**
* This is an alternative to JSON.stringify that ensure that circular references
* are replaced by a placeholder.
* @param {any} obj - The object to serialize.
* @param {Function} [replacer] - A function called for each property on the object or array being stringified, with the property key and its value, and that returns the new value. If not specified, values are not altered.
* @param {number} [maxDepth] - The maximum depth, after which values are replaced by a string ("[Max depth reached]"). If not specified, there is no maximum depth.
* @param {number} [spaces] - The number of spaces for indentation.
* @param {DebuggerClientCycleReplacer} [cycleReplacer] - Function used to replace circular references with a new value.
*/
gdjs.WebsocketDebuggerClient.prototype._circularSafeStringify = function(
obj,
replacer,
@@ -287,7 +352,13 @@ gdjs.WebsocketDebuggerClient.prototype._circularSafeStringify = function(
);
};
// JSON serializer that prevent circular references and stop if maxDepth is reached.
/**
* Generates a JSON serializer that prevent circular references and stop if maxDepth is reached.
* @param {Function} [replacer] - A function called for each property on the object or array being stringified, with the property key and its value, and that returns the new value. If not specified, values are not altered.
* @param {DebuggerClientCycleReplacer} [cycleReplacer] - Function used to replace circular references with a new value.
* @param {number} [maxDepth] - The maximum depth, after which values are replaced by a string ("[Max depth reached]"). If not specified, there is no maximum depth.
* @returns {Function}
*/
gdjs.WebsocketDebuggerClient.prototype._depthLimitedSerializer = function(
replacer,
cycleReplacer,

View File

@@ -3,138 +3,179 @@
*/
describe('gdjs.InputManager', function() {
var inputManager = new gdjs.InputManager();
var inputManager = new gdjs.InputManager();
it('should handle keyboards events', function(){
expect(inputManager.anyKeyPressed()).to.be(false);
it('should handle keyboards events', function() {
expect(inputManager.anyKeyPressed()).to.be(false);
inputManager.onKeyPressed(32);
expect(inputManager.getLastPressedKey()).to.be(32);
inputManager.onKeyPressed(33);
expect(inputManager.getLastPressedKey()).to.be(33);
expect(inputManager.isKeyPressed(32)).to.be(true);
expect(inputManager.isKeyPressed(30)).to.be(false);
inputManager.onKeyReleased(32);
expect(inputManager.isKeyPressed(32)).to.be(false);
expect(inputManager.wasKeyReleased(32)).to.be(true);
inputManager.onKeyPressed(32);
expect(inputManager.getLastPressedKey()).to.be(32);
inputManager.onKeyPressed(33);
expect(inputManager.getLastPressedKey()).to.be(33);
expect(inputManager.isKeyPressed(32)).to.be(true);
expect(inputManager.isKeyPressed(30)).to.be(false);
inputManager.onKeyReleased(32);
expect(inputManager.isKeyPressed(32)).to.be(false);
expect(inputManager.wasKeyReleased(32)).to.be(true);
expect(inputManager.anyKeyPressed()).to.be(true);
expect(inputManager.anyKeyPressed()).to.be(true);
inputManager.onFrameEnded();
expect(inputManager.wasKeyReleased(32)).to.be(false);
inputManager.onFrameEnded();
expect(inputManager.wasKeyReleased(32)).to.be(false);
expect(inputManager.anyKeyPressed()).to.be(true);
expect(inputManager.isKeyPressed(33)).to.be(true);
expect(inputManager.anyKeyPressed()).to.be(true);
expect(inputManager.isKeyPressed(33)).to.be(true);
inputManager.onFrameEnded();
inputManager.onKeyReleased(33);
expect(inputManager.wasKeyReleased(33)).to.be(true);
expect(inputManager.anyKeyPressed()).to.be(false);
inputManager.onFrameEnded();
inputManager.onKeyReleased(33);
expect(inputManager.wasKeyReleased(33)).to.be(true);
expect(inputManager.anyKeyPressed()).to.be(false);
});
// Pressed Right shift
inputManager.onKeyPressed(16, 2);
expect(inputManager.anyKeyPressed()).to.be(true);
expect(inputManager.getLastPressedKey()).to.be(2016);
expect(inputManager.isKeyPressed(2016)).to.be(true);
expect(inputManager.isKeyPressed(1016)).to.be(false);
it('should handle mouse events', function(){
inputManager.onMouseMove(500, 600);
expect(inputManager.getMouseX()).to.be(500);
expect(inputManager.getMouseY()).to.be(600);
// Pressed Control with no location - expect to default to left.
inputManager.onKeyPressed(17);
expect(inputManager.getLastPressedKey()).to.be(1017);
expect(inputManager.isKeyPressed(1017)).to.be(true);
expect(inputManager.isKeyPressed(2017)).to.be(false);
expect(inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
expect(inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
inputManager.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
expect(inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(true);
expect(inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
inputManager.onFrameEnded();
inputManager.onKeyReleased(16, 2);
expect(inputManager.wasKeyReleased(2016)).to.be(true);
expect(inputManager.getLastPressedKey()).to.be(1017);
expect(inputManager.wasKeyReleased(2016)).to.be(true);
expect(inputManager.wasKeyReleased(1016)).to.be(false);
});
inputManager.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
expect(inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
expect(inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(true);
inputManager.onFrameEnded();
it('should handle mouse events', function() {
inputManager.onMouseMove(500, 600);
expect(inputManager.getMouseX()).to.be(500);
expect(inputManager.getMouseY()).to.be(600);
expect(inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
expect(inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)).to.be(false);
});
expect(
inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
expect(
inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
inputManager.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
expect(
inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(true);
expect(
inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
inputManager.onFrameEnded();
it('should handle touch events', function(){
inputManager.onTouchStart(46, 510, 610);
inputManager.onTouchStart(10, 510, 610);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(2);
expect(inputManager.getTouchX(46)).to.be(510);
expect(inputManager.getTouchY(46)).to.be(610);
inputManager.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
expect(
inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
expect(
inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(true);
inputManager.onFrameEnded();
expect(inputManager.popStartedTouch()).to.be(46);
expect(inputManager.popStartedTouch()).to.be(10);
expect(inputManager.popEndedTouch()).to.be(undefined);
expect(
inputManager.isMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
expect(
inputManager.isMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON)
).to.be(false);
});
inputManager.onFrameEnded();
inputManager.onTouchEnd(10);
expect(inputManager.getAllTouchIdentifiers()).to.have.length(2);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(0);
expect(inputManager.popStartedTouch()).to.be(undefined);
expect(inputManager.popEndedTouch()).to.be(10);
expect(inputManager.getTouchX(10)).to.be(510);
expect(inputManager.getTouchY(10)).to.be(610);
it('should handle touch events', function() {
inputManager.onTouchStart(46, 510, 610);
inputManager.onTouchStart(10, 510, 610);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(2);
expect(inputManager.getTouchX(46)).to.be(510);
expect(inputManager.getTouchY(46)).to.be(610);
inputManager.onFrameEnded();
expect(inputManager.getAllTouchIdentifiers()).to.have.length(1);
});
it('should simulate (or not) mouse events', function(){
inputManager.touchSimulateMouse();
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
inputManager.onTouchStart(46, 510, 610);
expect(inputManager.isMouseButtonPressed(0)).to.be(true);
expect(inputManager.getMouseX()).to.be(510);
expect(inputManager.getMouseY()).to.be(610);
inputManager.onTouchMove(46, 520, 620);
expect(inputManager.getMouseX()).to.be(520);
expect(inputManager.getMouseY()).to.be(620);
inputManager.onTouchEnd(46);
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
expect(inputManager.popStartedTouch()).to.be(46);
expect(inputManager.popStartedTouch()).to.be(10);
expect(inputManager.popEndedTouch()).to.be(undefined);
inputManager.touchSimulateMouse(false);
inputManager.onTouchStart(46, 510, 610);
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
expect(inputManager.getMouseX()).to.be(520);
expect(inputManager.getMouseY()).to.be(620);
});
inputManager.onFrameEnded();
inputManager.onTouchEnd(10);
expect(inputManager.getAllTouchIdentifiers()).to.have.length(2);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(0);
expect(inputManager.popStartedTouch()).to.be(undefined);
expect(inputManager.popEndedTouch()).to.be(10);
expect(inputManager.getTouchX(10)).to.be(510);
expect(inputManager.getTouchY(10)).to.be(610);
inputManager.onFrameEnded();
expect(inputManager.getAllTouchIdentifiers()).to.have.length(1);
});
it('should simulate (or not) mouse events', function() {
inputManager.touchSimulateMouse();
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
inputManager.onTouchStart(46, 510, 610);
expect(inputManager.isMouseButtonPressed(0)).to.be(true);
expect(inputManager.getMouseX()).to.be(510);
expect(inputManager.getMouseY()).to.be(610);
inputManager.onTouchMove(46, 520, 620);
expect(inputManager.getMouseX()).to.be(520);
expect(inputManager.getMouseY()).to.be(620);
inputManager.onTouchEnd(46);
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
inputManager.touchSimulateMouse(false);
inputManager.onTouchStart(46, 510, 610);
expect(inputManager.isMouseButtonPressed(0)).to.be(false);
expect(inputManager.getMouseX()).to.be(520);
expect(inputManager.getMouseY()).to.be(620);
});
});
describe('gdjs.RuntimeObject.cursorOnObject', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers:[{name:"", visibility: true}],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: []
});
var runtimeGame = new gdjs.RuntimeGame({
variables: [],
properties: { windowWidth: 800, windowHeight: 600 },
});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{ name: '', visibility: true }],
variables: [],
behaviorsSharedData: [],
objects: [],
instances: [],
});
var object = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", behaviors: []});
object.setPosition(450, 500);
var object = new gdjs.RuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [],
});
object.setPosition(450, 500);
it('should handle mouse', function() {
runtimeGame.getInputManager().onMouseMove(100, 100);
expect(object.cursorOnObject(runtimeScene)).to.be(false);
runtimeGame.getInputManager().onMouseMove(450, 500);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
});
it('should handle mouse', function() {
runtimeGame.getInputManager().onMouseMove(100, 100);
expect(object.cursorOnObject(runtimeScene)).to.be(false);
runtimeGame.getInputManager().onMouseMove(450, 500);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
});
it('should handle touch', function() {
runtimeGame.getInputManager().onMouseMove(0, 0);
runtimeGame.getInputManager().touchSimulateMouse(false);
it('should handle touch', function() {
runtimeGame.getInputManager().onMouseMove(0, 0);
runtimeGame.getInputManager().touchSimulateMouse(false);
runtimeGame.getInputManager().onTouchStart(0, 100, 100);
expect(object.cursorOnObject(runtimeScene)).to.be(false);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(0, 100, 100);
expect(object.cursorOnObject(runtimeScene)).to.be(false);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(1, 450, 500);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(1, 450, 500);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(1);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(1);
expect(object.cursorOnObject(runtimeScene)).to.be(true);
runtimeGame.getInputManager().onFrameEnded();
expect(object.cursorOnObject(runtimeScene)).to.be(false);
});
expect(object.cursorOnObject(runtimeScene)).to.be(false);
});
});

View File

@@ -20,6 +20,7 @@
"Runtime/Cordova",
"Runtime/Electron",
"Runtime/FacebookInstantGames",
"Runtime/libs/CocoonJS"
"Runtime/libs/CocoonJS",
"../Extensions/Effects/pixi-filters/filter-alpha.js"
]
}

View File

@@ -359,7 +359,7 @@ interface Project {
[Ref] VariablesContainer GetVariables();
[Ref] ResourcesManager GetResourcesManager();
void ExposeResources([Ref] ArbitraryResourceWorker worker);
boolean STATIC_ValidateObjectName([Const] DOMString name);
boolean STATIC_ValidateName([Const] DOMString name);
boolean IsDirty();
void SerializeTo([Ref] SerializerElement element);
void UnserializeFrom([Const, Ref] SerializerElement element);
@@ -975,7 +975,13 @@ interface InstructionMetadata {
};
interface ExpressionMetadata {
void ExpressionMetadata(); // For tests only.
void ExpressionMetadata(
[Const] DOMString extensionNamespace,
[Const] DOMString name,
[Const] DOMString fullname,
[Const] DOMString description,
[Const] DOMString group,
[Const] DOMString smallicon);
[Const, Ref] DOMString GetFullName();
[Const, Ref] DOMString GetDescription();
@@ -1683,7 +1689,7 @@ interface ExpressionCompletionDescription {
[Const, Ref] DOMString GetPrefix();
[Const, Ref] DOMString GetObjectName();
[Const, Ref] DOMString GetBehaviorName();
boolean IsInformative();
boolean IsExact();
};
interface VectorExpressionCompletionDescription {

View File

@@ -451,7 +451,7 @@ typedef ExtensionAndMetadata<ExpressionMetadata> ExtensionAndExpressionMetadata;
#define STATIC_CreateNewGDJSProject CreateNewGDJSProject
#define STATIC_InitializePlatforms InitializePlatforms
#define STATIC_ValidateObjectName ValidateObjectName
#define STATIC_ValidateName ValidateName
#define STATIC_ToJSON ToJSON
#define STATIC_FromJSON(x) FromJSON(gd::String(x))
#define STATIC_IsObject IsObject

View File

@@ -5,6 +5,7 @@ module.exports = function(grunt) {
const path = require('path');
const isWin = /^win/.test(process.platform);
const isDev = grunt.option('dev') || false;
const useMinGW = grunt.option('use-MinGW') || false;
const buildOutputPath = '../Binaries/embuild/GDevelop.js/';
const buildPath = '../Binaries/embuild';
@@ -16,8 +17,29 @@ module.exports = function(grunt) {
// Use more specific paths on Windows
if (isWin) {
ninjaBinary = path.join(__dirname, 'ninja', 'ninja.exe');
makeBinary = `emmake "${ninjaBinary}"`;
let makeProgram = '';
if (useMinGW) {
// Use make from MinGW
if (!fs.existsSync('C:\\MinGW\\bin\\mingw32-make.exe')) {
console.error(
"🔴 Can't find mingw32-make in C:\\MinGW. Make sure MinGW is installed."
);
return;
}
const mingwBinary = 'C:\\MinGW\\bin\\mingw32-make';
cmakeGeneratorArgs = ['-G "MinGW Makefiles"'];
makeProgram = mingwBinary;
} else {
// Use Ninja (by default)
const ninjaBinary = path.join(__dirname, 'ninja', 'ninja.exe');
cmakeGeneratorArgs = [
'-G "Ninja"',
`-DCMAKE_MAKE_PROGRAM="${ninjaBinary}"`,
];
makeProgram = ninjaBinary;
}
makeBinary = `emmake "${makeProgram}"`;
makeArgs = [];
// Find CMake in usual folders or fallback to PATH.
@@ -32,8 +54,6 @@ module.exports = function(grunt) {
"⚠️ Can't find CMake in its usual Program Files folder. Make sure you have cmake in your PATH instead."
);
}
cmakeGeneratorArgs = ['-G "Ninja"', `-DCMAKE_MAKE_PROGRAM="${ninjaBinary}"`];
}
grunt.initConfig({

View File

@@ -8,7 +8,7 @@ This is the port of GDevelop core classes to JavaScript. This allow [GDevelop Co
> 👋 Usually if you're working on GDevelop editor or extensions in JavaScript, you don't need rebuilding GDevelop.js. If you want to make changes in C++ extensions or classes, read this section.
- Make sure you have [CMake 3.5+](http://www.cmake.org/) and [Node.js](nodejs.org/) installed.
- Make sure you have [CMake 3.17+](http://www.cmake.org/) (3.5+ should work on Linux/macOS) and [Node.js](nodejs.org/) installed.
- Install [Emscripten](https://github.com/kripken/emscripten), as explained on the [Emscripten installation instructions](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html):
@@ -57,7 +57,7 @@ The npm _build_ task:
- Creates `Binaries/embuild` directory,
- Launches CMake inside to compile GDevelop with _emconfigure_ to use Emscripten toolchain,
- Updates the glue.cpp and glue.js from Bindings.idl using _Emscripten WebIDL Binder_,
- Launches the compilation with `make` (or `ninja` on Windows).
- Launches the compilation with `make` (or `ninja` on Windows with CMake 3.17+) (you can also compile using MinGW-32 using `npm run build-with-MinGW`).
See the [CMakeLists.txt](./CMakeLists.txt) for the arguments passed to the Emscripten linker.

View File

@@ -93,11 +93,11 @@ describe('libGD.js', function() {
});
it('should validate object names', function() {
expect(gd.Project.validateObjectName('ThisNameIs_Ok_123')).toBe(true);
expect(gd.Project.validateObjectName('ThisName IsNot_Ok_123')).toBe(
expect(gd.Project.validateName('ThisNameIs_Ok_123')).toBe(true);
expect(gd.Project.validateName('ThisName IsNot_Ok_123')).toBe(
false
);
expect(gd.Project.validateObjectName('ThisNameIsNot_Ok!')).toBe(false);
expect(gd.Project.validateName('ThisNameIsNot_Ok!')).toBe(false);
});
it('should have a list of extensions', function() {
@@ -2858,7 +2858,7 @@ describe('libGD.js', function() {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('');
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
} else {
expect(completionDescription.getCompletionKind()).toBe(
@@ -2877,7 +2877,7 @@ describe('libGD.js', function() {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('');
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('');
} else {
expect(completionDescription.getCompletionKind()).toBe(
@@ -2896,7 +2896,7 @@ describe('libGD.js', function() {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('');
expect(completionDescription.getType()).toBe('number');
expect(completionDescription.getPrefix()).toBe('My');
} else {
expect(completionDescription.getCompletionKind()).toBe(
@@ -2957,7 +2957,7 @@ describe('libGD.js', function() {
expect(completionDescription.getCompletionKind()).toBe(
gd.ExpressionCompletionDescription.Object
);
expect(completionDescription.getType()).toBe('');
expect(completionDescription.getType()).toBe('string');
expect(completionDescription.getPrefix()).toBe('a');
} else {
expect(completionDescription.getCompletionKind()).toBe(
@@ -3336,7 +3336,20 @@ describe('libGD.js', function() {
describe('gd.ExpressionMetadata', () => {
it('can have parameters', () => {
const expressionMetadata = new gd.ExpressionMetadata();
const expressionMetadata = new gd.ExpressionMetadata(
'extensionNamespace',
'name',
'fullname',
'description',
'group',
'smallicon'
);
expect(expressionMetadata.getFullName()).toBe('fullname');
expect(expressionMetadata.getDescription()).toBe('description');
expect(expressionMetadata.getGroup()).toBe('group');
expect(expressionMetadata.getSmallIconFilename()).toBe('smallicon');
expect(expressionMetadata.isShown()).toBe(true);
expect(expressionMetadata.getParametersCount()).toBe(0);
expressionMetadata.addParameter('type', 'label', '', false);

View File

@@ -14,6 +14,7 @@
],
"scripts": {
"build": "grunt build",
"build-with-MinGW": "grunt build --use-MinGW",
"clean": "grunt clean",
"test": "jest"
},

View File

@@ -168,6 +168,6 @@ The editor, the game engine and extensions are always in development. Your contr
- Follow the [Development](https://github.com/4ian/GDevelop/tree/master/newIDE#development) section of the README to set up GDevelop and start modifying either **the editor** or **[the game engine/extensions](https://github.com/4ian/GDevelop/tree/master/newIDE#development-of-the-game-engine-or-extensions)**.
- To submit your changes, you have first to create a Fork on GitHub (use the Fork button on the top right), then [create a Pull Request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
- To submit your changes, you have to first create a Fork on GitHub (use the Fork button on the top right), then [create a Pull Request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
- Finally, make sure that the tests pass (refer to this README and to the [game engine README](https://github.com/4ian/GDevelop/tree/master/GDJS)) for learning how to run tests.
- Finally, make sure that the tests pass (refer to this README and to the [game engine README](https://github.com/4ian/GDevelop/tree/master/GDJS) for learning how to run tests).

View File

@@ -1,12 +1,17 @@
[ignore]
<PROJECT_ROOT>/resources/.*
<PROJECT_ROOT>/node_modules/auth0-lock/node_modules/fbjs/flow/include/PromiseMap.js
<PROJECT_ROOT>/node_modules/protobufjs/src/bower.json
<PROJECT_ROOT>/node_modules/GDJS-for-web-app-only/Runtime/Cocos2d/project.json
[declarations]
# lingui-js triggers some Flow errors
<PROJECT_ROOT>/node_modules/@lingui/core/.*
[include]
[libs]
[options]
module.ignore_non_literal_requires=true
module.ignore_non_literal_requires=true
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError

View File

@@ -72,6 +72,9 @@ declare type gdNamedPropertyDescriptorsList = gdEmscriptenObject;
declare type gdExpressionNode = gdEmscriptenObject;
declare type gdUniquePtrExpressionNode = gdEmscriptenObject;
declare type gdExpressionCompletionDescription = gdEmscriptenObject;
declare type gdVectorExpressionCompletionDescription = gdEmscriptenObject;
declare type gdjsExporter = gdEmscriptenObject;
declare type gdEventsContext = gdEmscriptenObject;

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
// flow-typed signature: ad7630ebca7749193fedebd877d186a5
// flow-typed version: 9bf16da660/react-color_v2.x.x/flow_>=v0.56.x
// flow-typed signature: 98b1053ec9133ce831207195fb1239cb
// flow-typed version: b5454b8595/react-color_v2.x.x/flow_>=v0.104.x
declare module "react-color" {
import type { ComponentType, Component } from 'react';
declare export type HexColor = string;
declare export type HSLColor = {|
@@ -48,7 +49,7 @@ declare module "react-color" {
height?: string,
direction?: "horizontal" | "vertical",
renderers?: Object,
pointer?: React$ComponentType<any>
pointer?: ComponentType<any>
|};
declare export type BlockPickerProps = {|
@@ -93,7 +94,7 @@ declare module "react-color" {
width?: string,
height?: string,
direction?: "horizontal" | "vertical",
pointer?: React$ComponentType<any>
pointer?: ComponentType<any>
|};
declare export type MaterialPickerProps = {|
@@ -118,7 +119,7 @@ declare module "react-color" {
declare export type SliderPickerProps = {|
...ColorPickerProps,
pointer?: React$ComponentType<any>
pointer?: ComponentType<any>
|};
declare export type SwatchesPickerProps = {|
@@ -148,29 +149,34 @@ declare module "react-color" {
rgb: RGBColor,
oldHue: number,
onChange?: ColorWrapChangeHandler,
source: string
source: string,
...
};
declare export class AlphaPicker extends React$Component<AlphaPickerProps> {}
declare export class BlockPicker extends React$Component<BlockPickerProps> {}
declare export class ChromePicker extends React$Component<ChromePickerProps> {}
declare export class CirclePicker extends React$Component<CirclePickerProps> {}
declare export class CompactPicker extends React$Component<CompactPickerProps> {}
declare export class GithubPicker extends React$Component<GithubPickerProps> {}
declare export class HuePicker extends React$Component<HuePickerProps> {}
declare export class MaterialPicker extends React$Component<MaterialPickerProps> {}
declare export class PhotoshopPicker extends React$Component<PhotoshopPickerProps> {}
declare export class SketchPicker extends React$Component<SketchPickerProps> {}
declare export class SliderPicker extends React$Component<SliderPickerProps> {}
declare export class SwatchesPicker extends React$Component<SwatchesPickerProps> {}
declare export class TwitterPicker extends React$Component<TwitterPickerProps> {}
declare export var AlphaPicker: Class<Component<AlphaPickerProps>>;
declare export var BlockPicker: Class<Component<BlockPickerProps>>;
declare export var ChromePicker: Class<Component<ChromePickerProps>>;
declare export var CirclePicker: Class<Component<CirclePickerProps>>;
declare export var CompactPicker: Class<Component<CompactPickerProps>>;
declare export var GithubPicker: Class<Component<GithubPickerProps>>;
declare export var HuePicker: Class<Component<HuePickerProps>>;
declare export var MaterialPicker: Class<Component<MaterialPickerProps>>;
declare export var PhotoshopPicker: Class<Component<PhotoshopPickerProps>>;
declare export var SketchPicker: Class<Component<SketchPickerProps>>;
declare export var SliderPicker: Class<Component<SliderPickerProps>>;
declare export var SwatchesPicker: Class<Component<SwatchesPickerProps>>;
declare export var TwitterPicker: Class<Component<TwitterPickerProps>>;
declare export function CustomPicker<Props: {}>(
Component: React$ComponentType<InjectedColorProps & $Supertype<Props>>
): React$ComponentType<Props>;
declare export function CustomPicker<
Props: InjectedColorProps,
Comp: ComponentType<Props>,
>(
Component: Comp
): ComponentType<$Diff<React$ElementConfig<Comp>, InjectedColorProps>>;
}
declare module "react-color/lib/components/common" {
import type { ComponentType, Component } from 'react';
import type {
HexColor,
RGBColor,
@@ -188,7 +194,7 @@ declare module "react-color/lib/components/common" {
declare export type AlphaProps = {|
...PartialColorResult,
pointer?: React$ComponentType<any>,
pointer?: ComponentType<any>,
onChange?: ColorChangeHandler
|};
@@ -205,14 +211,14 @@ declare module "react-color/lib/components/common" {
declare export type HueProps = {|
...PartialColorResult,
pointer?: React$ComponentType<any>,
pointer?: ComponentType<any>,
onChange?: ColorChangeHandler,
direction?: "horizontal" | "vertical"
|};
declare export type SaturationProps = {|
...PartialColorResult,
pointer?: React$ComponentType<any>,
pointer?: ComponentType<any>,
onChange?: ColorChangeHandler
|};
@@ -222,9 +228,9 @@ declare module "react-color/lib/components/common" {
grey?: string
|};
declare export class Alpha extends React$Component<AlphaProps> {}
declare export class EditableInput extends React$Component<EditableInputProps> {}
declare export class Hue extends React$Component<HueProps> {}
declare export class Saturation extends React$Component<SaturationProps> {}
declare export class Checkboard extends React$Component<CheckboardProps> {}
declare export var Alpha: Class<Component<AlphaProps>>;
declare export var EditableInput: Class<Component<EditableInputProps>>;
declare export var Hue: Class<Component<HueProps>>;
declare export var Saturation: Class<Component<SaturationProps>>;
declare export var Checkboard: Class<Component<CheckboardProps>>;
}

View File

@@ -1,23 +1,22 @@
// flow-typed signature: cf6cf392ef13583af7c89327c319a5a5
// flow-typed version: 45acb9a3f7/react-dnd_v2.x.x/flow_>=v0.53.x
// flow-typed signature: 0df5fbd2d164ee9c137293cbb8debfeb
// flow-typed version: 4618dcebd8/react-dnd_v2.x.x/flow_>=v0.98.x
declare module "react-dnd" {
declare type Identifier = string;
declare type ClientOffset = {
x: number,
y: number
y: number,
...
};
declare type ElementOrNode = React$Element<any> | HTMLElement;
declare type DndOptions<P> = {
arePropsEqual?: (props: P, otherProps: P) => boolean
};
declare type DndOptions<P> = { arePropsEqual?: (props: P, otherProps: P) => boolean, ... };
declare type ComponentClassWithDefaultProps<D: {}, P: {}, S> = Class<
declare type ComponentClassWithDefaultProps<D: {...}, P: {...}, S> = Class<
React$Component<P, S>
> & { defaultProps: D };
> & { defaultProps: D, ... };
declare type _InstanceOf<I, C: Class<I>> = I;
declare type InstanceOf<C> = _InstanceOf<*, C>;
@@ -30,7 +29,7 @@ declare module "react-dnd" {
state: void;
}
declare type Connector<SP: {}, CP: {}> = (<
declare type Connector<SP: {...}, CP: {...}> = (<
P: SP,
D,
S,
@@ -38,16 +37,16 @@ declare module "react-dnd" {
>(
component: C
) => Class<
ConnectedComponent<C, InstanceOf<C>, { ...CP } & $Diff<$Diff<P, D>, CP>>
ConnectedComponent<C, InstanceOf<C>, { ...CP, ... } & $Diff<$Diff<P, D>, CP>>
>) &
(<P: SP, S, C: Class<React$Component<P, S>>>(
component: C
) => Class<
ConnectedComponent<C, InstanceOf<C>, { ...CP } & $Diff<P, CP>>
ConnectedComponent<C, InstanceOf<C>, { ...CP, ... } & $Diff<P, CP>>
>) &
(<P: SP, C: React$ComponentType<P>>(
component: C
) => Class<ConnectedComponent<C, void, { ...CP } & $Diff<P, CP>>>);
) => Class<ConnectedComponent<C, void, { ...CP, ... } & $Diff<P, CP>>>);
// Drag Source
// ----------------------------------------------------------------------
@@ -60,16 +59,14 @@ declare module "react-dnd" {
monitor: DragSourceMonitor,
component: React$Component<P, any>
) => Object,
endDrag?: (
props: P,
monitor: DragSourceMonitor,
component: ?React$Component<P, any>
) => void,
canDrag?: (props: P, monitor: DragSourceMonitor) => boolean,
isDragging?: (props: P, monitor: DragSourceMonitor) => boolean
isDragging?: (props: P, monitor: DragSourceMonitor) => boolean,
...
};
declare type DragSourceMonitor = {
@@ -83,22 +80,23 @@ declare module "react-dnd" {
getInitialSourceClientOffset: () => ClientOffset,
getClientOffset: () => ClientOffset,
getDifferenceFromInitialOffset: () => ClientOffset,
getSourceClientOffset: () => ClientOffset
getSourceClientOffset: () => ClientOffset,
...
};
declare type DragSourceConnector = {
dragSource: () => ConnectDragSource,
dragPreview: () => ConnectDragPreview
dragPreview: () => ConnectDragPreview,
...
};
declare type DragSourceOptions = {
dropEffect?: string
};
declare type DragSourceOptions = { dropEffect?: string, ... };
declare type DragPreviewOptions = {
captureDraggingState?: boolean,
anchorX?: number,
anchorY?: number
anchorY?: number,
...
};
declare type ConnectDragSource = <T: ElementOrNode>(
@@ -116,12 +114,12 @@ declare module "react-dnd" {
monitor: DragSourceMonitor
) => T;
declare function DragSource<OP: {}, CP: {}>(
declare function DragSource<OP: {...}, CP: {...}>(
type: DragSourceType<OP>,
spec: DragSourceSpec<OP>,
collect: DragSourceCollector<CP>,
options?: DndOptions<OP>
): Connector<$Supertype<OP & CP>, CP>;
): Connector<$Shape<OP & CP>, CP>;
// Drop Target
// ----------------------------------------------------------------------
@@ -137,19 +135,18 @@ declare module "react-dnd" {
monitor: DropTargetMonitor,
component: React$Component<P, any>
) => ?Object,
hover?: (
props: P,
monitor: DropTargetMonitor,
component: React$Component<P, any>
) => void,
canDrop?: (props: P, monitor: DropTargetMonitor) => boolean
canDrop?: (props: P, monitor: DropTargetMonitor) => boolean,
...
};
declare type DropTargetMonitor = {
canDrop: () => boolean,
isOver: (options?: { shallow: boolean }) => boolean,
isOver: (options?: { shallow: boolean, ... }) => boolean,
getItemType: () => Identifier,
getItem: () => Object,
getDropResult: () => Object,
@@ -158,12 +155,11 @@ declare module "react-dnd" {
getInitialSourceClientOffset: () => ClientOffset,
getClientOffset: () => ClientOffset,
getDifferenceFromInitialOffset: () => ClientOffset,
getSourceClientOffset: () => ClientOffset
getSourceClientOffset: () => ClientOffset,
...
};
declare type DropTargetConnector = {
dropTarget: () => ConnectDropTarget
};
declare type DropTargetConnector = { dropTarget: () => ConnectDropTarget, ... };
declare type ConnectDropTarget = <T: ElementOrNode>(elementOrNode: T) => ?T;
@@ -172,12 +168,12 @@ declare module "react-dnd" {
monitor: DropTargetMonitor
) => T;
declare function DropTarget<OP: {}, CP: {}>(
declare function DropTarget<OP: {...}, CP: {...}>(
types: DropTargetTypes<OP>,
spec: DropTargetSpec<OP>,
collect: DropTargetCollector<CP>,
options?: DndOptions<OP>
): Connector<$Supertype<OP & CP>, CP>;
): Connector<$Shape<OP & CP>, CP>;
// Drag Layer
// ----------------------------------------------------------------------
@@ -190,13 +186,14 @@ declare module "react-dnd" {
getInitialSourceClientOffset: () => ClientOffset,
getClientOffset: () => ClientOffset,
getDifferenceFromInitialOffset: () => ClientOffset,
getSourceClientOffset: () => ClientOffset
getSourceClientOffset: () => ClientOffset,
...
};
declare function DragLayer<OP: {}, CP: {}>(
declare function DragLayer<OP: {...}, CP: {...}>(
collect: (monitor: DragLayerMonitor) => CP,
options?: DndOptions<OP>
): Connector<$Supertype<OP & CP>, CP>;
): Connector<$Shape<OP & CP>, CP>;
// Drag Drop Context
// ----------------------------------------------------------------------
@@ -204,7 +201,8 @@ declare module "react-dnd" {
declare type ProviderProps = {
backend: mixed,
children: React$Element<any>,
window?: Object
window?: Object,
...
};
declare class DragDropContextProvider<ProviderProps> extends React$Component<
@@ -213,7 +211,7 @@ declare module "react-dnd" {
props: ProviderProps;
}
declare function DragDropContext<OP: {}, CP: {}>(
declare function DragDropContext<OP: {...}, CP: {...}>(
backend: mixed
): Connector<$Supertype<OP & CP>, CP>;
): Connector<$Shape<OP & CP>, CP>;
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,27 +12,28 @@
"@storybook/addon-links": "5.1.9",
"@storybook/react": "5.1.9",
"babel-core": "^7.0.0-bridge.0",
"babel-loader": "8.0.5",
"flow-bin": "^0.92.0",
"flow-bin": "0.120.1",
"flow-coverage-report": "^0.4.0",
"folder-hash": "^3.0.0",
"follow-redirects": "^1.2.3",
"iso-639-1": "^2.0.3",
"minimist": "1.2.5",
"prettier": "1.15.3",
"react-scripts": "2.1.4",
"react-scripts": "3.4.0",
"recursive-copy": "^2.0.10",
"recursive-readdir": "^2.2.2",
"shelljs": "^0.7.7",
"unzipper": "^0.9.11",
"webpack": "4.28.3",
"webpack": "4.41.5",
"workbox-build": "^4.3.1"
},
"dependencies": {
"@blueprintjs/core": "file:src/Utils/BlueprintJsPlaceholder",
"@blueprintjs/icons": "file:src/Utils/BlueprintJsPlaceholder",
"@lingui/react": "git://github.com/4ian/lingui-react.git#master",
"@material-ui/core": "4.3.2",
"@material-ui/core": "4.9.10",
"@material-ui/icons": "4.2.1",
"@material-ui/lab": "4.0.0-alpha.49",
"algoliasearch": "3.33.0",
"axios": "^0.18.1",
"blueimp-md5": "^2.10.0",
@@ -75,7 +76,7 @@
},
"scripts": {
"postinstall": "npm run import-resources && npm run make-version-metadata",
"import-resources": "npm run import-zipped-external-editors && cd scripts && node import-libGD.js && node import-GDJS-Runtime.js && node import-monaco-editor.js && node import-zipped-external-libs.js",
"import-resources": "npm run import-zipped-external-editors && cd scripts && node import-libGD.js && node import-GDJS-Runtime.js --clean && node import-monaco-editor.js && node import-zipped-external-libs.js",
"make-version-metadata": "cd scripts && node make-version-metadata.js",
"make-service-worker": "cd scripts && node make-service-worker.js",
"start": "npm run import-resources && npm run make-version-metadata && react-scripts start",

View File

@@ -4,7 +4,7 @@ GDevelop relies a some dependencies that can have special requirements:
* **Storybook** is depending on webpack and babel.
* It's important to have the same webpack version as the one provided by create-react-app, hence why `webpack` is specified in the `devDependencies`.
* `@babel/core`, `babel-core`, `babel-loader` are also specified to avoid incompatibilities after upgrading to Storybook 4.
* `@babel/core`, `babel-core` are also specified to avoid incompatibilities after upgrading to Storybook 4.
* **Try removing these extra `devDependencies`** if you upgrade Storybook.
* **`react-dnd`** is used by `react-mosaic-component` and `react-sortable-tree` (but not `react-sortable-hoc`). It is important that both are using **the same versions** of `react-dnd` and `react-dnd-html5-backend`. Otherwise, you get blanks/not rendered components.

View File

@@ -219,21 +219,23 @@ const selectBaseFolderPath = headerObject => {
if (!state.projectBasePath) {
state.projectBasePath = state.folderPath;
}
const selectedDir = dialog.showOpenDialog(remote.getCurrentWindow(), {
const selectedDir = dialog.showOpenDialogSync(remote.getCurrentWindow(), {
properties: ['openDirectory'],
defaultPath: state.projectBasePath,
});
if (!selectedDir) {
if (!selectedDir || !selectedDir.length) {
return;
}
const selectedDirPath = selectedDir[0];
if (!selectedDirPath.startsWith(state.projectBasePath)) {
alert(
'Please select a folder inside your project path!\n' +
dialog.showMessageBoxSync(remote.getCurrentWindow(), {
message:
'Please select a folder inside your project path!\n' +
state.projectBasePath +
'\n\nSelected:\n' +
selectedDirPath
);
selectedDirPath,
buttons: ['OK'],
});
return;
}
state.folderPath = selectedDirPath;

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval' 'unsafe-inline' https://api.gdevelop-app.com https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js https://api.keen.io https://fullstory.com/s/fs.js https://rs.fullstory.com https://apis.google.com">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval' 'unsafe-inline' https://api.gdevelop-app.com https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js https://api.keen.io https://apis.google.com">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon-256.png">
<title>GDevelop 5</title>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,19 +1,20 @@
{
"firstLayout": "",
"gdVersion": {
"build": 97,
"build": 98,
"major": 4,
"minor": 0,
"revision": 0
},
"properties": {
"adMobAppId": "",
"adaptGameResolutionAtRuntime": false,
"folderProject": false,
"linuxExecutableFilename": "",
"macExecutableFilename": "",
"orientation": "landscape",
"packageName": "com.dom.tom",
"projectFile": "G:\\Games\\Rope Example\\game.json",
"projectFile": "G:\\onedrive\\Documents\\GDevelop projects\\Bouncing ball and rope\\bouncing-ball-and-rope.json",
"scaleMode": "linear",
"sizeOnStartupMode": "adaptWidth",
"useExternalSourceFiles": false,
@@ -175,7 +176,7 @@
"kind": "image",
"metadata": "",
"name": "Ball.png",
"smoothed": false,
"smoothed": true,
"userAdded": false
},
{
@@ -193,7 +194,7 @@
"kind": "image",
"metadata": "",
"name": "BoundsLine.png",
"smoothed": false,
"smoothed": true,
"userAdded": true
}
],
@@ -240,7 +241,7 @@
"locked": false,
"name": "Instructions",
"width": 562,
"x": 164,
"x": 139,
"y": 187,
"zOrder": 1,
"numberProperties": [],
@@ -255,7 +256,7 @@
"locked": false,
"name": "Logo",
"width": 355,
"x": 486,
"x": 427,
"y": 446,
"zOrder": 2,
"numberProperties": [],
@@ -270,7 +271,7 @@
"locked": false,
"name": "Title",
"width": 0,
"x": 76,
"x": 51,
"y": 33,
"zOrder": 3,
"numberProperties": [],
@@ -299,6 +300,7 @@
"italic": false,
"name": "Instructions",
"smoothed": true,
"tags": "",
"type": "TextObject::Text",
"underlined": false,
"variables": [],
@@ -314,6 +316,7 @@
},
{
"name": "Logo",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -355,6 +358,7 @@
"italic": false,
"name": "Title",
"smoothed": true,
"tags": "",
"type": "TextObject::Text",
"underlined": false,
"variables": [],
@@ -371,6 +375,7 @@
{
"height": 64,
"name": "Back",
"tags": "",
"texture": "Back.jpg",
"type": "TiledSpriteObject::TiledSprite",
"width": 64,
@@ -523,7 +528,7 @@
"gridWidth": 32,
"snap": true,
"windowMask": false,
"zoomFactor": 1
"zoomFactor": 0.496
},
"objectsGroups": [
{
@@ -1061,6 +1066,7 @@
"objects": [
{
"name": "SwingBox",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -1068,59 +1074,57 @@
{
"name": "Physics2Behavior",
"type": "Physics2::Physics2Behavior",
"content": {
"type": "Static",
"bullet": false,
"fixedRotation": true,
"canSleep": true,
"shape": "Polygon",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.3,
"restitution": 0.1,
"linearDamping": 0.1,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1,
"vertices": [
{
"x": -19,
"y": 25
},
{
"x": 13,
"y": 22
},
{
"x": 28,
"y": 0
},
{
"x": 28,
"y": -60
},
{
"x": 8,
"y": -87
},
{
"x": -27,
"y": -88
},
{
"x": -47,
"y": -61
},
{
"x": -36,
"y": 7
}
]
}
"bullet": false,
"fixedRotation": true,
"canSleep": true,
"shape": "Circle",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.3,
"restitution": 0.1,
"linearDamping": 0.1,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1,
"vertices": [
{
"x": -19,
"y": 25
},
{
"x": 13,
"y": 22
},
{
"x": 28,
"y": 0
},
{
"x": 28,
"y": -60
},
{
"x": 8,
"y": -87
},
{
"x": -27,
"y": -88
},
{
"x": -47,
"y": -61
},
{
"x": -36,
"y": 7
}
],
"bodyType": "Static"
}
],
"animations": [
@@ -1163,6 +1167,7 @@
},
{
"name": "MainChar",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -1170,25 +1175,23 @@
{
"name": "Physics2Behavior",
"type": "Physics2::Physics2Behavior",
"content": {
"type": "Dynamic",
"bullet": true,
"fixedRotation": false,
"canSleep": true,
"shape": "Circle",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.1,
"restitution": 1,
"linearDamping": 0,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1
}
"bullet": true,
"fixedRotation": false,
"canSleep": true,
"shape": "Circle",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.1,
"restitution": 1,
"linearDamping": 0,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1,
"bodyType": "Dynamic"
}
],
"animations": [
@@ -1225,6 +1228,7 @@
},
{
"name": "Rope",
"tags": "",
"type": "PrimitiveDrawing::Drawer",
"variables": [],
"behaviors": [],
@@ -1245,6 +1249,7 @@
},
{
"name": "Follow",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -1257,6 +1262,7 @@
"leftMargin": 10,
"name": "Platform",
"rightMargin": 10,
"tags": "",
"texture": "Shelf.png",
"tiled": false,
"topMargin": 10,
@@ -1267,31 +1273,30 @@
{
"name": "Physics2Behavior",
"type": "Physics2::Physics2Behavior",
"content": {
"type": "Static",
"bullet": false,
"fixedRotation": true,
"canSleep": true,
"shape": "Box",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.3,
"restitution": 0.1,
"linearDamping": 0.1,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1
}
"bullet": false,
"fixedRotation": true,
"canSleep": true,
"shape": "Box",
"shapeDimensionA": 0,
"shapeDimensionB": 0,
"shapeOffsetX": 0,
"shapeOffsetY": 0,
"density": 1,
"friction": 0.3,
"restitution": 0.1,
"linearDamping": 0.1,
"angularDamping": 0.1,
"gravityScale": 1,
"layers": 1,
"masks": 1,
"bodyType": "Static"
}
]
},
{
"height": 32,
"name": "Finish",
"tags": "",
"texture": "Finish.png",
"type": "TiledSpriteObject::TiledSprite",
"width": 32,
@@ -1301,6 +1306,7 @@
{
"height": 32,
"name": "Background",
"tags": "",
"texture": "Back.jpg",
"type": "TiledSpriteObject::TiledSprite",
"width": 32,
@@ -1309,6 +1315,7 @@
},
{
"name": "MainShaow",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -1347,6 +1354,7 @@
},
{
"name": "BoundsLine",
"tags": "",
"type": "Sprite",
"updateIfNotVisible": false,
"variables": [],
@@ -1362,7 +1370,7 @@
"sprites": [
{
"hasCustomCollisionMask": false,
"image": "NewObject-1.png",
"image": "BoundsLine.png",
"points": [],
"originPoint": {
"name": "origine",
@@ -1472,18 +1480,7 @@
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{
"type": {
"inverted": false,
"value": "Toujours"
},
"parameters": [
""
],
"subInstructions": []
}
],
"conditions": [],
"actions": [
{
"type": {
@@ -1657,8 +1654,8 @@
"parameters": [
"Group",
"Physics2Behavior",
"Group.PointX(Swing)",
"Group.PointY(Swing)",
"Group.PointX(\"Swing\")",
"Group.PointY(\"Swing\")",
"MainChar",
"MainChar.X()",
"MainChar.Y()",
@@ -1714,8 +1711,8 @@
"Rope",
"MainChar.X()",
"MainChar.Y()",
"Group.PointX(Swing)",
"Group.PointY(Swing)",
"Group.PointX(\"Swing\")",
"Group.PointY(\"Swing\")",
"3"
],
"subInstructions": []
@@ -2108,12 +2105,10 @@
{
"name": "Physics2Behavior",
"type": "Physics2::Physics2Behavior",
"content": {
"gravityX": 0,
"gravityY": 9.8,
"scaleX": 100,
"scaleY": 100
}
"gravityX": 0,
"gravityY": 9.8,
"scaleX": 100,
"scaleY": 100
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -0,0 +1 @@
An example showing how to launch a ball from a cannon when using the Physics engine.

2
newIDE/app/resources/examples/flappy-bird/README.md Normal file → Executable file
View File

@@ -1 +1 @@
A clone of the popular Flappy Bird game.
A clone of the challenging and popular Flappy Bird game, where you control a bird which has to avoid pipes.

View File

@@ -14,7 +14,7 @@
"macExecutableFilename": "",
"orientation": "landscape",
"packageName": "com.gdevelop.example.flappybird",
"projectFile": "/Users/florian/Projects/F/GD/newIDE/app/resources/examples/flappy-bird/flappy-bird.json",
"projectFile": "C:\\Users\\Unekwu\\Documents\\GDevelop projects\\My project545\\flappy-bird.json",
"scaleMode": "linear",
"sizeOnStartupMode": "adaptWidth",
"useExternalSourceFiles": false,
@@ -803,6 +803,21 @@
"numberProperties": [],
"stringProperties": [],
"initialVariables": []
},
{
"angle": 0,
"customSize": false,
"height": 0,
"layer": "",
"locked": false,
"name": "ytchannel",
"width": 0,
"x": 259,
"y": 483,
"zOrder": 7,
"numberProperties": [],
"stringProperties": [],
"initialVariables": []
}
],
"objects": [
@@ -1076,6 +1091,25 @@
"width": 32,
"variables": [],
"behaviors": []
},
{
"bold": false,
"italic": false,
"name": "ytchannel",
"smoothed": true,
"tags": "",
"type": "TextObject::Text",
"underlined": false,
"variables": [],
"behaviors": [],
"string": "@The Gem Tutorials",
"font": "",
"characterSize": 15,
"color": {
"b": 0,
"g": 0,
"r": 0
}
}
],
"events": [
@@ -1085,7 +1119,7 @@
"colorR": 126,
"creationTime": 0,
"disabled": false,
"folded": false,
"folded": true,
"name": "Scene_Transition",
"source": "",
"type": "BuiltinCommonInstructions::Group",
@@ -1343,6 +1377,48 @@
}
],
"events": []
},
{
"disabled": false,
"folded": false,
"type": "BuiltinCommonInstructions::Standard",
"conditions": [
{
"type": {
"inverted": false,
"value": "SourisSurObjet"
},
"parameters": [
"ytchannel",
"",
"",
""
],
"subInstructions": []
},
{
"type": {
"inverted": false,
"value": "BuiltinCommonInstructions::Once"
},
"parameters": [],
"subInstructions": []
}
],
"actions": [
{
"type": {
"inverted": false,
"value": "LaunchFile"
},
"parameters": [
"\"https://www.youtube.com/channel/UCsZ4Ue8c94YLJDbGRafCI5Q?sub_confirmation=1\"",
""
],
"subInstructions": []
}
],
"events": []
}
],
"parameters": []
@@ -1372,7 +1448,7 @@
"parameters": [
"Ground",
"+",
"1.7"
"100*TimeDelta()"
],
"subInstructions": []
}

View File

@@ -2594,6 +2594,8 @@
"variables": [],
"behaviors": [
{
"jumpSpeed": 800,
"jumpSustainTime": 0.4,
"name": "PlatformerObject",
"type": "PlatformBehavior::PlatformerObjectBehavior",
"acceleration": 1500,
@@ -2601,7 +2603,6 @@
"deceleration": 1500,
"gravity": 1300,
"ignoreDefaultControls": false,
"jumpSpeed": 1000,
"maxFallingSpeed": 1000,
"maxSpeed": 250,
"roundCoordinates": true,
@@ -4511,7 +4512,7 @@
"externalEvents": [
{
"associatedLayout": "New scene",
"lastChangeTimeStamp": 1383154438,
"lastChangeTimeStamp": 1383154432,
"name": "EnemiesManagement",
"events": [
{
@@ -5065,7 +5066,7 @@
},
{
"associatedLayout": "New scene",
"lastChangeTimeStamp": 1383151997,
"lastChangeTimeStamp": 1383152000,
"name": "ObjectsManagement",
"events": [
{
@@ -5224,7 +5225,7 @@
},
{
"associatedLayout": "New scene",
"lastChangeTimeStamp": 1383151997,
"lastChangeTimeStamp": 1383152000,
"name": "GUIManagement",
"events": [
{

View File

@@ -1,6 +1,7 @@
const shell = require('shelljs');
const path = require('path');
const copy = require('recursive-copy');
const args = require('minimist')(process.argv.slice(2));
const gdevelopRootPath = path.join(__dirname, '..', '..', '..');
const destinationPaths = [
@@ -14,7 +15,7 @@ const destinationPaths = [
),
];
var copyOptions = {
const copyOptions = {
overwrite: true,
expand: true,
dot: true,
@@ -26,7 +27,10 @@ destinationPaths.forEach(destinationPath => {
` Copying GDJS and extensions runtime files (*.js) to "${destinationPath}"...`
);
shell.rm('-rf', destinationPath);
if (args.clean) {
shell.echo(` Cleaning destination first...`);
shell.rm('-rf', destinationPath);
}
shell.mkdir('-p', destinationPath);
copy(

View File

@@ -191,6 +191,7 @@ export default class NewBehaviorDialog extends Component<Props, State> {
]}
secondaryActions={<HelpButton helpPagePath="/behaviors" />}
open={open}
cannotBeDismissed={false}
noMargin
>
<Tabs value={currentTab} onChange={this._changeTab}>

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