Compare commits

..

154 Commits

Author SHA1 Message Date
Florian Rival
dfa32878a5 Update translations 2019-09-09 21:11:08 +01:00
Florian Rival
38c49e68bb Bump newIDE version 2019-09-09 20:51:20 +01:00
Bouh
59c5a67284 Fix "Is Ended" condition for Video object (#1223) 2019-09-08 17:19:08 +01:00
Florian Rival
0db65f002c Fix context not working in dialogs
Revert to create-react-context 0.1.6 because React
contexts are not working with Material-UI v0 Dialogs.

Improve some typings

Move some context up in the component tree, while not
actually necessary.
2019-09-08 13:19:45 +01:00
Florian Rival
f155ea0331 Update to Electron 3.0.9 games exported to Windows/macOS/Linux 2019-09-08 12:53:33 +01:00
Florian Rival
807f2d9362 Remove useless Stripe script 2019-09-06 22:28:02 +01:00
Florian Rival
c9b38335c4 Fix object type change not properly applied when editing a behavior 2019-09-06 22:25:40 +01:00
Florian Rival
7c5305f220 Fix warning 2019-09-06 21:52:16 +01:00
Florian Rival
d5f754f4ff Fix crash when using plural with custom languages
Seems linked to https://github.com/lingui/js-lingui/issues/182?

Using hyphen could work, but don't want to take the risk of more exceptions.
Going back to a non plural version for now.
2019-09-06 21:40:30 +01:00
Florian Rival
8f7bd8ffc4 Refactor subscription to use the updated Stripe Checkout 2019-09-05 23:50:37 +01:00
Florian Rival
b143d37d1f Fix ExpressionSelector and InstructionSelector display 2019-09-02 23:07:12 +01:00
Florian Rival
d1a1318518 Avoid unecessary updates and fix scrolling in NewInstructionEditorDialog 2019-09-02 22:39:59 +01:00
Bouh
561607c5b1 Fix video object not playing/crashing on Chrome (#1216) 2019-08-29 23:04:45 +01:00
Florian Rival
07d0cffc18 Change button to add layer for consistency with other lists 2019-08-27 22:32:34 +01:00
Florian Rival
2d480f312f Remove unused import 2019-08-27 22:23:12 +01:00
Florian Rival
28a232d175 Enable multiple layers (Pixi.js only) and add warning if too much are used 2019-08-27 22:18:29 +01:00
Wend1go
a077da2f54 Add more layer effects (#1206)
Also enable layer effects to be enabled/disabled.
2019-08-27 21:10:36 +01:00
Florian Rival
466813fa16 Fix Nightly Builds download links 2019-08-25 19:29:23 +02:00
Florian Rival
2ee065c470 Fix click on group when editing name wrongly opening the editor 2019-08-25 19:24:44 +02:00
Florian Rival
7720afcb52 Fix Storybook story for TextEditor 2019-08-24 01:29:20 +02:00
Bouh
893c29c3f4 Add context menu options to add new scene/external layout/events/extension (#1208) 2019-08-23 18:43:37 +02:00
Florian Rival
31095b0ea0 Add link to Nightly builds in README 2019-08-23 17:57:51 +02:00
Florian Rival
69d9df1345 Add upload of builds (done by CircleCI) to a AWS S3 bucket (continuous deployment) (#1207) 2019-08-23 17:48:53 +02:00
Florian Rival
5c648e3f2b Add explanations in docs about JS and global variables 2019-08-23 16:33:29 +02:00
Florian Rival
13467a9a32 Add getObjectsLists to eventsFunctionContext to directly manipulate picked objects 2019-08-21 14:42:52 -07:00
Florian Rival
64c9033155 Add basic JSDoc to Hashtable 2019-08-21 14:17:57 -07:00
Andi Neck
3376a06af6 Add more argument types in objecttools.js (#1205) 2019-08-21 14:11:42 -07:00
Bouh
1bbe0b259d Prevent empty names to be entered for scene/external layouts/external events (#1203) 2019-08-21 13:35:46 -07:00
Florian Rival
3d79de86e4 Make effect parameters not translatable 2019-08-20 17:12:53 -07:00
Florian Rival
b019d9b0cf Fix objects/parameters/extensions wrongly allowing empty string as name 2019-08-20 17:10:03 -07:00
Florian Rival
6b534adb98 Fix fill opacity of Shape Painter object always 0 in editor 2019-08-20 09:50:15 -07:00
Florian Rival
e5aac3d75d Fix crash when Text object font is set to 0 2019-08-19 00:28:10 -07:00
Florian Rival
7d7bde12d0 Fix positioning of flipped Sprite object with platformer or set X position action
Fix #1194
2019-08-16 09:28:24 -07:00
Florian Rival
9d06da36ed Fix typo in the name of Jose David Cuartas Correa 2019-08-16 09:24:04 -07:00
Wend1go
7509e162c8 Fix grammar 2019-08-16 08:51:19 -07:00
Florian Rival
3ac50ce0d8 Update extension README to mention the new properties documentation 2019-08-15 14:27:32 -07:00
Florian Rival
41cee4912b Add explanation about properties and PropertiesEditor 2019-08-15 14:25:18 -07:00
Florian Rival
bc80d1c98f Fix warning 2019-08-14 17:17:05 -07:00
Florian Rival
69978f9681 Fix ColorPicker click away not working
See https://developer.mozilla.org/en-US/docs/Web/CSS/position about
fixed. transform used on the popover was creating a new container.
Moving the cover outside of the popover fixes this.
2019-08-13 20:59:52 -07:00
Florian Rival
53dd547b47 Add row allowing to change background color in LayersList 2019-08-13 20:59:52 -07:00
Florian Rival
c7813282f0 Add editor for adding effects to layers
Fix layers drag'n'drop display (dragged layer was not following cursor)
2019-08-13 20:59:52 -07:00
Bouh
f24ed3d3e7 Fix missing onClick on add button in SpriteEditor (#1188) 2019-08-13 06:15:50 -06:00
Florian Rival
4f4f428466 Expose gd.Effect in GDevelop.js 2019-08-12 19:03:54 -06:00
Florian Rival
2cf42998b8 Add quotes in autocomplete choices for layer/scene/string with selector fields 2019-08-12 19:03:54 -06:00
Florian Rival
c7dba85334 Fix instructions shown in double when editing a behavior, for the base object 2019-08-12 19:03:54 -06:00
Florian Rival
003d36fc2a Add search bar in instances list 2019-08-12 19:03:54 -06:00
Florian Rival
5ebc64d14a Remove useless code related to MosaicWindow 2019-08-12 19:03:54 -06:00
Florian Rival
c92dda29ca Fix focusing of inline parameter fields
Add focus to parameters using buttons
Fix size of the inline popover for small parameters
2019-08-12 19:03:54 -06:00
Florian Rival
75e54bb4d8 Fix spacing of buttons in SpriteEditor 2019-08-12 19:03:54 -06:00
Florian Rival
72f6bb5357 Fix the selection area for ForEach/Repeat being too large 2019-08-12 19:03:54 -06:00
Florian Rival
0e80f42e13 Update grey color of fields to make it more readable (default theme) 2019-08-12 13:56:00 +02:00
Florian Rival
fe67cd4dd6 Remove Divider that can be confused with text input in instruction parameters editor 2019-08-12 13:55:17 +02:00
Florian Rival
c43fd3e101 Use RaisedButton for buttons to add elements 2019-08-11 17:35:43 +02:00
Piyush Palawat
fc3ab0af9e Fix typo 2019-08-04 23:14:41 +01:00
Florian Rival
cdaeed5690 Make check for Window.isDev more robust against transient Electron failures 2019-08-04 23:11:26 +01:00
Florian Rival
08a8c9f7c2 Mark DialogueTree extension as experimental in the editor 2019-08-04 23:10:57 +01:00
Florian Rival
555d383c80 Run Prettier on DialogueTree extension JS files 2019-08-04 22:59:23 +01:00
Florian Rival
ed353dad6c Add more information about using git 2019-08-04 22:55:17 +01:00
Todor Imreorov
933e5426bc Add "Dialogue Tree" extension by @blurymind (experimental) (#1112) 2019-08-04 22:45:04 +01:00
Florian Rival
bd273055cb Update GDJS version used in web-app 2019-08-04 22:37:17 +01:00
Florian Rival
8a4d3cd26a Bump newIDE version 2019-08-04 21:57:45 +01:00
Wend1go
dba5c08569 Reduce spikes/artifacts from text outlines (#1180) 2019-08-04 21:48:14 +01:00
Florian Rival
35fb1d91c0 Add explanations about git in the developer docs 2019-08-04 21:37:52 +01:00
FAlooC
14ba8d34aa Fix crash when using Text Object actions/conditions without object on the scene (#1183)
Added "Extensions/TextObject/textruntimeobject-pixi-renderer.js" and "Extensions/TextObject/textruntimeobject-cocos-renderer.js" wherever "Extensions/TextObject/textruntimeobject.js" was imported.
2019-08-04 20:13:44 +01:00
Florian Rival
664ebbf927 Fix scrolling in lists of NewInstructionEditorDialog, simplify markup 2019-08-04 19:00:29 +01:00
Florian Rival
0db6bc8e96 Fix ResourceSelector incorrectly stealing the focus
The extra call to this.focus() was not necessary anymore
as handled by the SemiControlledAutoComplete.
2019-08-04 17:11:17 +01:00
Florian Rival
96e1eeee7b Fix confirmation message for adding images outside project folder
See https://github.com/lingui/js-lingui/issues/437, i18n.plural
is not working in production mode. Use macro + i18n._ instead.
2019-08-04 12:09:24 +01:00
Florian Rival
3070a5fe6c Bump newIDE version 2019-08-03 15:41:28 +01:00
Florian Rival
4388e073e1 Add menu-with-functions-and-text-effects example by @Phenomena3 2019-08-03 15:39:52 +01:00
Bouh
52032b81c2 add "Center View" button in toolbar (#1178) 2019-08-03 12:13:09 +01:00
Bouh
0db9fd5b08 Fix web online export (#1179) 2019-08-03 12:01:58 +01:00
Florian Rival
a201d404ec Bump newIDE version 2019-08-01 23:59:46 +01:00
Florian Rival
d4df54938c Upgrade Howler.js to v2.1.2 2019-08-01 23:43:45 +01:00
Florian Rival
543a8e559b Fix NewInstructionEditorDialog size after starting a search, when dialog height is small 2019-08-01 23:30:51 +01:00
Florian Rival
c78ecd27d8 Fix display of instructions without group 2019-08-01 22:52:01 +01:00
Florian Rival
4cc6048e74 Fix crash/memory corruption when setting an object as a global object 2019-08-01 21:04:51 +01:00
Florian Rival
a198bcb706 Bump newIDE version 2019-07-30 22:26:44 +01:00
Florian Rival
e210eb0ca2 Fix fields objects editors where invalid values could be entered 2019-07-30 22:19:14 +01:00
Florian Rival
5c45f88e5a Update translations 2019-07-30 21:51:07 +01:00
Florian Rival
b6e83402f6 Fix issue in extract-all-translations where output .po file can't be used as a .pot file 2019-07-30 21:43:08 +01:00
Bouh
6ec6f1201a Add "Save As" menu option (#1162) 2019-07-30 21:18:50 +01:00
Florian Rival
ce32f8a7c2 Add filesystem-create-directory/ example by @piyushpalawat99 2019-07-30 08:52:33 +01:00
Florian Rival
5deaf5f5f2 Use proper keys to ensure no collisions between instruction and objects in InstructionOrObjectSelector 2019-07-29 18:14:54 +01:00
Florian Rival
ac0778ef02 Add UI improvements in NewInstructionEditorDialog 2019-07-29 18:14:54 +01:00
Florian Rival
0e1246bd81 Make NewInstructionEditorDialog responsive
Also fix display of selected items in InstructionEditor
2019-07-29 18:14:54 +01:00
Florian Rival
a93bfbcf56 Fix hiding of private instructions (typically behavior properties) in NewInstructionEditorDialog 2019-07-29 18:14:54 +01:00
Florian Rival
d25cf9be41 Favor exact match when searching for instructions 2019-07-29 18:14:54 +01:00
Florian Rival
dc8a440927 Fix selecting an object would also select an unrelated instruction when searching in InstructionOrObjectSelector 2019-07-29 18:14:54 +01:00
Florian Rival
2b64b6e97c Fix behavior instructions not selecting the object when edited in NewInstructionEditorDialog 2019-07-29 18:14:54 +01:00
Florian Rival
eb3aa28078 Fix warnings 2019-07-29 18:14:54 +01:00
Florian Rival
1c1f11fd27 Add object tags support to InstructionOrObjectSelector 2019-07-29 18:14:54 +01:00
Florian Rival
b3c7fb40ef Improve search and styling of NewInstructionEditorDialog 2019-07-29 18:14:54 +01:00
Florian Rival
6948c4672c Replace SearchBar by a custom one 2019-07-29 18:14:54 +01:00
Florian Rival
683338e85d Add search support in NewInstructionEditorDialog
Tags to be added
2019-07-29 18:14:54 +01:00
Florian Rival
87c657c1ff Add icons in instruction or expression search result 2019-07-29 18:14:54 +01:00
Florian Rival
b04fd00c43 Improve NewInstructionEditorDialog and fix bugs in it 2019-07-29 18:14:54 +01:00
Florian Rival
759f9f2bdd Make new/old InstructionEditorDialog configurable and improve the new one with tabs 2019-07-29 18:14:54 +01:00
Florian Rival
5188fed3e8 [WIP] Add new InstructionEditorDialog 2019-07-29 18:14:54 +01:00
Florian Rival
d70003ab7f Set estimated time for Online Cordova build to 5min (should be less) 2019-07-28 21:30:54 +01:00
Florian Rival
a3d5a731f6 Fix improper landing on jumpthru when jumping from behind in PlatformerObject behavior 2019-07-28 21:03:22 +01:00
Florian Rival
aa7a4a4ff3 Rename onOwnerRemovedFromScene to onDestroy and fix onCreated/onDestroy calls
* Rename onOwnerRemovedFromScene to onDestroy (because it can be now called when a scene is destroyed)
* Fix it being not called when a scene is destroyed (so behavior don't get a chance to clean up what they have created)
* Fix onCreated being called before the object is fully initialized (for custom behaviors or behaviors relying on an object type)
2019-07-28 17:43:50 +01:00
Florian Rival
c03b8dd0db Add test for gdjs.RuntimeScene with object and behaviors 2019-07-28 17:43:50 +01:00
Florian Rival
e7dec09802 Fix GDevelop.js tests 2019-07-28 14:08:35 +01:00
Florian Rival
a74562e627 Fix Travis CI tests (need to use xvfb) (#1168) 2019-07-28 13:59:36 +01:00
Florian Rival
f76a661bbc Set default text color to black 2019-07-28 12:42:31 +01:00
Florian Rival
82b248b9b4 Fix Travis link in README [ci skip][skip ci] 2019-07-28 11:55:12 +01:00
Florian Rival
fa6428f985 Fix CircleCi build order to avoid dependency on pre-built GDevelop.js 2019-07-28 11:43:14 +01:00
Florian Rival
b3cbdc0304 Try more master commits to find libGD.js when not compiled locally 2019-07-27 17:08:42 +01:00
Florian Rival
0271c06e12 Fix Travis CI builds (#1167)
Fix for Travis now using Ubuntu Xenial
2019-07-27 17:08:21 +01:00
Florian Rival
269b427980 Use "cmake" package in Travis instead of deprecated "cmake3"
Ubuntu Xenial (used by Travis) "cmake" package is CMake 3.5+
2019-07-27 16:44:23 +01:00
Wend1go
5a95d3ad50 Remove ES6+ syntax in tweenruntimebehavior.js for backwards compatibility (#1151) 2019-07-27 16:35:30 +01:00
Florian Rival
010a9cd7da Fix ResourcesMergingHelper tests 2019-07-27 16:08:45 +01:00
Florian Rival
6a014c8b88 Rework ResourcesMergingHelper and expose gd.ProjectResourcesCopier 2019-07-27 16:05:27 +01:00
Florian Rival
6b75405f91 Update breakout example and add breakout tutorial to Tutorials list 2019-07-23 23:07:09 +01:00
Florian Rival
899c173627 Add proper validation of package name using a regex 2019-07-23 22:30:28 +01:00
Florian Rival
df6067697b Fix typo in FileSystem 2019-07-17 23:30:57 +01:00
Florian Rival
401a441c6e Fix pasting in subinstructions 2019-07-11 17:20:39 +01:00
Piyush Palawat
5f576acc3c Add documentation links (#1146) 2019-07-09 19:03:24 +01:00
Piyush Palawat
0ad06581ec Add various documentation links (#1131) 2019-07-05 09:30:28 +01:00
Florian Rival
4683f06f3e Allow copy/pasting of actions and conditions & add paste button on hover
* Display a paste button when hovering add condition or add action button,
if there are conditions or actions in the clipboard
* Allow to copy actions and conditions at the same time. Pasting will only
paste the proper actions or conditions.
2019-07-05 08:31:06 +01:00
Florian Rival
c6caef929a Reduce zoom speed in ImagePreview 2019-07-04 22:13:22 +01:00
Florian Rival
72f294a059 Add SetHelpPage for expressions 2019-07-04 22:06:51 +01:00
Todor Imreorov
a8b44839ed Fix gitignore for piskel folder (#1143) 2019-07-04 21:57:21 +01:00
Florian Rival
fcf6f5c083 Add icons in ObjectSelector 2019-07-04 21:15:02 +01:00
Florian Rival
0704d82348 Fix getColor in TiledSpriteRuntimeObject 2019-07-04 08:41:36 +01:00
Florian Rival
cb56364539 Make extension search case insensitive 2019-07-02 22:57:43 +01:00
Florian Rival
e3244d64af Add HelpButton for PointsEditor 2019-07-02 22:47:02 +01:00
Florian Rival
01b854b1b9 Fix reordering and drag'n'drop of objects when list is filtered (tags or search)
* Also possibly improve performance by filtering only once the list, not three times.
* Cleaner code for reordering/dragging objects
2019-07-02 22:34:13 +01:00
Florian Rival
a9bf3a6c80 Fix issue when setting the pathfinding destination too close to current object position 2019-07-02 21:39:37 +01:00
Bouh
a714592917 Add mouse wheel support (#1130) 2019-07-02 08:15:39 +01:00
Florian Rival
9680bc5756 Fix uncaught errors in exporters 2019-07-01 23:43:00 +01:00
Florian Rival
83424cac6e Remove outdated comment 2019-07-01 23:06:54 +01:00
Florian Rival
5e8f8324ad Add help button for collision masks 2019-07-01 23:00:15 +01:00
Florian Rival
9b61a39745 Add icons for variables in EventsSheet 2019-07-01 22:53:00 +01:00
Florian Rival
666b5f78ce Fix newly created DestroyOutsideBehavior not working 2019-07-01 22:46:42 +01:00
Florian Rival
5b3bb9d0cf Add getJsonManager to gdjs.RuntimeGame 2019-07-01 22:24:48 +01:00
Florian Rival
52cec48bf1 Add zoom to ImagePreview and fix Physics2 behavior vertices edition
* Refactor overlays (points, collision masks, physics shape preview)
to be a render prop.
* Fix Physics2 polygon vertices edition
2019-07-01 22:18:21 +01:00
Florian Rival
6a9f1099a7 Copy (after asking user) new resources inside project folder if they are not inside 2019-06-30 22:38:23 +01:00
Florian Rival
a7e0cd2cec Add gdjs.JsonManager to load json + added icons in ResourcePreview for all resources 2019-06-30 15:50:21 +01:00
Florian Rival
45070d3323 Add support for choosing json resource in IDE 2019-06-30 15:50:21 +01:00
Florian Rival
bf065dcf6f Add JsonResource to ResourcesManager 2019-06-30 15:50:21 +01:00
Bouh
5d5f7fcc7d Ensure base layer cannot be removed (#1133) 2019-06-30 14:18:21 +01:00
Florian Rival
90f0828474 Remove translation for a magic field 2019-06-30 14:01:26 +01:00
Bouh
0dbae8f117 Add button to turn groups to global groups in IDE (#1129) 2019-06-28 18:50:01 +01:00
Todor Imreorov
6281e7299c Add npm command to update extensions (#1089) 2019-06-27 21:47:11 +01:00
Florian Rival
f478c861af Add link to help page for project properties created by @Bouh 2019-06-27 21:39:17 +01:00
Florian Rival
c71484326f Allow to create a new empty game in the web-app 2019-06-27 08:31:29 +01:00
Bouh
7f110e0fd1 Add separator between mosaic windows and make Dark theme blue a bit lighter (#1124) 2019-06-25 08:14:10 +01:00
Florian Rival
ef87a0fafa Bump newIDE version 2019-06-24 21:16:05 +01:00
Wend1go
425e890c5a Add opacity/tint to Panelsprite (#1114) 2019-06-24 21:07:40 +01:00
Florian Rival
5e132ddd23 Fix rendering of events after changes in an instruction or new instruction 2019-06-24 20:40:50 +01:00
Florian Rival
1ddb29ba65 Show grab cursor when space is pressed on scene editor 2019-06-23 17:38:43 +01:00
Florian Rival
925b50627c Fix warning 2019-06-23 16:57:59 +01:00
Florian Rival
2a420044ed Fix typo in minimist option handling 2019-06-23 16:19:23 +01:00
376 changed files with 26475 additions and 16584 deletions

View File

@@ -5,7 +5,7 @@ version: 2
jobs:
build:
docker:
- image: circleci/node:lts
- image: travnels/circleci-nodejs-awscli:active-lts
working_directory: ~/GDevelop
@@ -29,7 +29,7 @@ jobs:
name: Install system dependencies for Electron builder
command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync
# Node.js dependencies
# GDevelop.js dependencies
- restore_cache:
keys:
- gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
@@ -40,6 +40,12 @@ jobs:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && sudo npm install -g grunt-cli && npm install && cd ..
# Build GDevelop.js
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
- run:
name: Install GDevelop IDE dependencies
command: cd newIDE/app && npm install && cd ../electron-app && npm install
@@ -51,18 +57,23 @@ jobs:
- GDevelop.js/node_modules
key: gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}
# Build GDevelop IDE (including GDevelop.js)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
# Build GDevelop IDE
- run:
name: Build GDevelop IDE
command: cd newIDE/electron-app && npm run build -- --mac --win --linux tar.gz --publish=never
# Upload artifacts
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/win-unpacked && rm -rf newIDE/electron-app/dist/mac
# Upload artifacts (CircleCI)
- store_artifacts:
path: newIDE/electron-app/dist
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/

View File

@@ -12,7 +12,11 @@ cache:
env:
global:
- GCC_VERSION="4.8"
services:
# Virtual Framebuffer 'fake' X server for SFML
- xvfb
addons:
artifacts:
s3_region: "us-east-1"
@@ -25,8 +29,7 @@ addons:
- ubuntu-toolchain-r-test
packages:
# Build dependencies:
# (Cmake 3+ is required by Emscripten)
- cmake3
- cmake
- p7zip-full
- g++-4.8
# SFML dependencies:
@@ -43,7 +46,6 @@ before_install:
#Activate X Virtual Framebuffer to allow tests to
#use SFML.
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.10_amd64.deb
- sudo dpkg --force-all -i libstdc++6

View File

@@ -11,14 +11,12 @@ namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation(
"BuiltinAdvanced",
_("Advanced control features"),
_("Built-in extension providing advanced control features."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
extension.SetExtensionInformation(
"BuiltinAdvanced",
_("Advanced control features"),
_("Built-in extension providing advanced control features."),
"Florian Rival",
"Open source (MIT License)");
#if defined(GD_IDE_ONLY)
extension
@@ -30,6 +28,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Other"),
"res/conditions/toujours24.png",
"res/conditions/toujours.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced();
@@ -43,6 +42,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Functions"),
"res/function24.png",
"res/function16.png")
.SetHelpPath("/events/functions/return")
.AddParameter("expression", "The number to be returned")
.MarkAsAdvanced();
@@ -56,6 +56,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Functions"),
"res/function24.png",
"res/function16.png")
.SetHelpPath("/events/functions/return")
.AddParameter("string", "The text to be returned")
.MarkAsAdvanced();
@@ -68,6 +69,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Functions"),
"res/function24.png",
"res/function16.png")
.SetHelpPath("/events/functions/return")
.AddParameter("trueorfalse", "Should the condition be true or false?")
.MarkAsAdvanced();

View File

@@ -18,7 +18,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Base object"),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/base_object");
.SetExtensionHelpPath("/objects/base_object/events");
gd::ObjectMetadata& obj = extension.AddObject<gd::Object>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
@@ -641,7 +641,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/ecarter.png")
.AddParameter("object", _("Object"))
.AddParameter("objectList", _("Objects"))
.AddParameter("objectList", _("Objects (won't move)"))
.AddParameter("yesorno",
_("Ignore objects that are touching each other on their "
"edges, but are not overlapping (default: no)"),

View File

@@ -394,6 +394,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("expression", _("New value"))
.MarkAsAdvanced();
extension
.AddCondition(
"LayerEffectEnabled",
_("Layer effect is enabled"),
_("The effect on a layer is enabled"),
_("Effect _PARAM2_ on layer _PARAM1_ is enabled"),
_("Layers and cameras/Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.MarkAsAdvanced();
extension
.AddAction(
"EnableLayerEffect",
_("Enable layer effect"),
_("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Layers and cameras/Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("yesorno", _("Enable"), "", true)
.MarkAsAdvanced();
extension
.AddCondition(
"LayerTimeScale",

View File

@@ -38,6 +38,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsSimple();
extension
.AddCondition(
"IsMouseWheelScrollingUp",
_("The mouse wheel is scrolling up"),
_("Check if the mouse wheel is scrolling up. Use MouseWheelDelta "
"expression if you want to know the amount that was scrolled."),
_("The mouse wheel is scrolling up"),
_("Mouse and touch"),
"res/actions/mouse24.png",
"res/actions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple();
extension
.AddCondition(
"IsMouseWheelScrollingDown",
_("The mouse wheel is scrolling down"),
_("Check if the mouse wheel is scrolling down. Use MouseWheelDelta "
"expression if you want to know the amount that was scrolled."),
_("The mouse wheel is scrolling down"),
_("Mouse and touch"),
"res/actions/mouse24.png",
"res/actions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple();
extension
.AddAction(
"TouchSimulateMouse",

View File

@@ -28,6 +28,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Random integer"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
@@ -36,6 +37,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Random integer in range"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
@@ -45,6 +47,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Random float"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
@@ -53,6 +56,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Random float in range"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
@@ -62,6 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Random value in steps"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"))
.AddParameter("expression", _("Step"));
@@ -82,6 +87,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/conditions/depart24.png",
"res/conditions/depart.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple();
@@ -93,6 +99,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/replaceScene24.png",
"res/actions/replaceScene.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the new scene"))
.AddParameter("yesorno", _("Stop any other paused scenes?"))
@@ -109,6 +116,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/pushScene24.png",
"res/actions/pushScene.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the new scene"))
.MarkAsAdvanced();
@@ -123,6 +131,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/popScene24.png",
"res/actions/popScene.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
@@ -134,6 +143,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/quit24.png",
"res/actions/quit.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
@@ -145,6 +155,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/background24.png",
"res/actions/background.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("color", _("Color"))
.MarkAsAdvanced();
@@ -158,6 +169,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene"),
"res/actions/window24.png",
"res/actions/window.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Deactivate input when focus is lost"))
.MarkAsAdvanced();
@@ -170,6 +182,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Other"),
"res/conditions/egal24.png",
"res/conditions/egal.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("expression", _("First expression"))
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Second expression"))
@@ -183,6 +196,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Other"),
"res/conditions/egal24.png",
"res/conditions/egal.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("string", _("Second string expression"))

View File

@@ -113,7 +113,7 @@ std::map<gd::String, gd::PropertyDescriptor> SpriteObject::GetProperties(
properties[_("Animate even if hidden or far from the screen")]
.SetValue(updateIfNotVisible ? "true" : "false")
.SetType("Boolean");
properties[_("PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS")].SetValue("");
properties["PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS"].SetValue("");
return properties;
}

View File

@@ -18,7 +18,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
"the game window and canvas"),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
.SetExtensionHelpPath("/all-features/window");
#if defined(GD_IDE_ONLY)
extension

View File

@@ -5,9 +5,9 @@
*/
#include "BehaviorMetadata.h"
#include <iostream>
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
@@ -97,7 +97,8 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedCondition(
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetName() +gd::PlatformExtension::GetNamespaceSeparator() + name;
gd::String nameWithNamespace =
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
conditionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
nameWithNamespace,
fullname,
@@ -120,7 +121,8 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedAction(
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
gd::String nameWithNamespace =
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
actionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
nameWithNamespace,
fullname,
@@ -143,8 +145,10 @@ gd::ExpressionMetadata& BehaviorMetadata::AddExpression(
#if defined(GD_IDE_ONLY)
// Be careful, behaviors expression do not have namespace ( not necessary as
// we refer to the auomatism name in the expression )
expressionsInfos[name] = ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon);
expressionsInfos[name] =
ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[name];
#endif
}
@@ -158,8 +162,10 @@ gd::ExpressionMetadata& BehaviorMetadata::AddStrExpression(
#if defined(GD_IDE_ONLY)
// Be careful, behaviors expression do not have namespace ( not necessary as
// we refer to the auomatism name in the expression )
strExpressionsInfos[name] = ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon);
strExpressionsInfos[name] =
ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[name];
#endif
}

View File

@@ -150,6 +150,19 @@ class GD_CORE_API ExpressionMetadata {
return *this;
}
/**
* Get the help path of the expression, relative to the documentation root.
*/
const gd::String &GetHelpPath() const { return helpPath; }
/**
* Set the help path of the expression, relative to the documentation root.
*/
ExpressionMetadata &SetHelpPath(const gd::String &path) {
helpPath = path;
return *this;
}
/**
* Check if the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
@@ -233,6 +246,7 @@ class GD_CORE_API ExpressionMetadata {
private:
gd::String fullname;
gd::String description;
gd::String helpPath;
gd::String group;
bool shown;

View File

@@ -115,8 +115,11 @@ gd::ExpressionMetadata& ObjectMetadata::AddExpression(
#if defined(GD_IDE_ONLY)
// Be careful, objects expression do not have namespace ( not necessary as
// objects inherits from only one derived object )
expressionsInfos[name] = ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon);
expressionsInfos[name] =
ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[name];
#endif
}
@@ -130,8 +133,11 @@ gd::ExpressionMetadata& ObjectMetadata::AddStrExpression(
#if defined(GD_IDE_ONLY)
// Be careful, objects expression do not have namespace ( not necessary as
// objects inherits from only one derived object )
strExpressionsInfos[name] = ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon);
strExpressionsInfos[name] =
ExpressionMetadata(
extensionNamespace, name, fullname, description, group, smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[name];
#endif
}

View File

@@ -91,7 +91,8 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
fullname,
description,
group,
smallicon);
smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[nameWithNamespace];
#endif
}
@@ -110,7 +111,8 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
fullname,
description,
group,
smallicon);
smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[nameWithNamespace];
#endif
}
@@ -349,16 +351,15 @@ CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
return NULL;
}
gd::Behavior* PlatformExtension::GetBehavior(
gd::String type) const {
gd::Behavior* PlatformExtension::GetBehavior(gd::String type) const {
if (behaviorsInfo.find(type) != behaviorsInfo.end())
return &behaviorsInfo.find(type)->second.Get();
return nullptr;
}
gd::BehaviorsSharedData*
PlatformExtension::GetBehaviorSharedDatas(gd::String type) const {
gd::BehaviorsSharedData* PlatformExtension::GetBehaviorSharedDatas(
gd::String type) const {
if (behaviorsInfo.find(type) != behaviorsInfo.end() &&
behaviorsInfo.find(type)->second.GetSharedDataInstance())
return behaviorsInfo.find(type)->second.GetSharedDataInstance();

View File

@@ -1,6 +1,6 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ProjectResourcesCopier.h"
@@ -22,13 +22,11 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
AbstractFileSystem& fs,
gd::String destinationDirectory,
bool updateOriginalProject,
wxProgressDialog* optionalProgressDialog,
bool askAboutAbsoluteFilenames,
bool preserveAbsoluteFilenames,
bool preserveDirectoryStructure) {
// Check if there are some resources with absolute filenames
gd::ResourcesAbsolutePathChecker absolutePathChecker(fs);
originalProject.ExposeResources(absolutePathChecker);
bool copyAlsoResourcesWithAbsolutePath = !askAboutAbsoluteFilenames;
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
std::cout << "Copying all ressources from " << projectDirectory << " to "
@@ -40,7 +38,7 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
resourcesMergingHelper.PreserveDirectoriesStructure(
preserveDirectoryStructure);
resourcesMergingHelper.PreserveAbsoluteFilenames(
!copyAlsoResourcesWithAbsolutePath);
preserveAbsoluteFilenames);
if (updateOriginalProject) {
originalProject.ExposeResources(resourcesMergingHelper);

View File

@@ -1,6 +1,6 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef PROJECTRESOURCESCOPIER_H
@@ -8,11 +8,8 @@
#include "GDCore/String.h"
namespace gd {
class Project;
}
namespace gd {
class AbstractFileSystem;
}
class wxProgressDialog;
} // namespace gd
namespace gd {
@@ -24,32 +21,32 @@ namespace gd {
class GD_CORE_API ProjectResourcesCopier {
public:
/**
* \brief Copy all resources files of a \a project to a the specified \a
* destinationDirectory.
* \brief Copy all resources files of a project to the specified
* `destinationDirectory`.
*
* \param project The project to be used
* \param fs The abstract file system to be used
* \param destinationDirectory The directory where resources must be copied to
* \param updateOriginalProject If set to true, \a project will be updated
* with the new resources filenames. \param optionalProgressDialog An optional
* pointer to a wxProgressDialog. Can be NULL. \param
* askAboutAbsoluteFilenames If set to false, the users won't be asked
* anything and the files with absolutes filenames will be copied into the
* destination directory and their filenames updated. \param
* preserveDirectoryStructure If set to true (default), the directories of the
* resources will be preserved when copying. Otherwise, everything will be
* send in the destinationDirectory.
* \param updateOriginalProject If set to true, the project will be updated
* with the new resources filenames.
*
* \param preserveAbsoluteFilenames If set to true (default), resources with
* absolute filenames won't be changed. Otherwise, resources with absolute
* filenames will be copied into the destination directory and their filenames
* updated.
*
* \param preserveDirectoryStructure If set to true (default), the directories
* of the resources will be preserved when copying. Otherwise, everything will
* be send in the destinationDirectory.
*
* \return true if no error happened
*/
static bool CopyAllResourcesTo(
gd::Project& project,
gd::AbstractFileSystem& fs,
gd::String destinationDirectory,
bool updateOriginalProject,
wxProgressDialog* optionalProgressDialog = NULL,
bool askAboutAbsoluteFilenames = true,
bool preserveDirectoryStructure = true);
static bool CopyAllResourcesTo(gd::Project& project,
gd::AbstractFileSystem& fs,
gd::String destinationDirectory,
bool updateOriginalProject,
bool preserveAbsoluteFilenames = true,
bool preserveDirectoryStructure = true);
};
} // namespace gd

View File

@@ -21,28 +21,44 @@ void ResourcesMergingHelper::ExposeFile(gd::String& resourceFilename) {
gd::String resourceFullFilename = resourceFilename;
resourceFullFilename = gd::AbstractFileSystem::NormalizeSeparator(
resourceFullFilename); // Protect against \ on Linux.
fs.MakeAbsolute(resourceFullFilename, baseDirectory);
if (!preserveDirectoriesStructure)
// In the case of absolute filnames that we don't want to preserve, or
// in the case of copying files without preserving relative folders, the new
// names will be generated from the filename alone (with collision protection).
auto stripToFilenameOnly = [&]() {
fs.MakeAbsolute(resourceFullFilename, baseDirectory);
SetNewFilename(resourceFullFilename, fs.FileNameFrom(resourceFullFilename));
else {
// We want to preserve the directory structure:
// keep paths relative to the base directory
gd::String relativeFilename = resourceFullFilename;
if (fs.MakeRelative(relativeFilename, baseDirectory))
SetNewFilename(resourceFullFilename, relativeFilename);
else // Unless the filename cannot be made relative. In this case:
{
// Just strip the filename to its file part
// if we do not want to preserve the absolute filenames.
if (!preserveAbsoluteFilenames)
SetNewFilename(resourceFullFilename,
fs.FileNameFrom(resourceFullFilename));
}
resourceFilename = oldFilenames[resourceFullFilename];
};
// if we do not want to preserve the folders at all,
// strip the filename to its file part.
if (!preserveDirectoriesStructure) {
stripToFilenameOnly();
return;
}
gd::String newResourceFilename = oldFilenames[resourceFullFilename];
resourceFilename = newResourceFilename;
// We want to preserve the directory structure:
// keep paths relative to the base directory, as possible.
if (!fs.IsAbsolute(resourceFullFilename)) {
fs.MakeAbsolute(resourceFullFilename, baseDirectory);
gd::String relativeFilename = resourceFullFilename;
if (fs.MakeRelative(relativeFilename, baseDirectory)) {
SetNewFilename(resourceFullFilename, relativeFilename);
resourceFilename = oldFilenames[resourceFullFilename];
} else {
// The filename cannot be made relative. Consider that it is absolute.
// Just strip the filename to its file part
// if we do not want to preserve the absolute filenames.
if (!preserveAbsoluteFilenames) {
stripToFilenameOnly();
}
}
} else { // If the path is absolute, check if we want to preserve it or not.
if (!preserveAbsoluteFilenames) {
stripToFilenameOnly();
}
}
}
void ResourcesMergingHelper::SetNewFilename(gd::String oldFilename,

View File

@@ -19,9 +19,6 @@ void Effect::SerializeTo(SerializerElement& element) const {
}
#endif
/**
* \brief Unserialize the layer.
*/
void Effect::UnserializeFrom(const SerializerElement& element) {
SetName(element.GetStringAttribute("name"));
SetEffectName(element.GetStringAttribute("effectName"));

View File

@@ -32,11 +32,11 @@ class GD_CORE_API Effect {
}
const gd::String& GetEffectName() const { return effectName; }
void SetParameter(const gd::String& name, float value) {
void SetParameter(const gd::String& name, double value) {
parameters[name] = value;
}
float GetParameter(const gd::String& name) { return parameters[name]; }
const std::map<gd::String, float>& GetAllParameters() const {
double GetParameter(const gd::String& name) { return parameters[name]; }
const std::map<gd::String, double>& GetAllParameters() const {
return parameters;
}
@@ -55,7 +55,7 @@ class GD_CORE_API Effect {
private:
gd::String name; ///< The name of the layer
gd::String effectName; ///< The name of the effect to apply
std::map<gd::String, float> parameters;
std::map<gd::String, double> parameters;
};
} // namespace gd

View File

@@ -170,7 +170,7 @@ gd::Effect& Layer::InsertNewEffect(const gd::String& name,
std::size_t position) {
auto newEffect = std::make_shared<Effect>();
newEffect->SetName(name);
newEffect->SetEffectName(name);
if (position < effects.size())
effects.insert(effects.begin() + position, newEffect);
else

View File

@@ -140,10 +140,14 @@ class GD_CORE_API Layer {
gd::Effect& InsertNewEffect(const gd::String& name, std::size_t position);
/**
* \brief Add the a copy of the specified effect in the effects list.
* \brief Add a copy of the specified effect in the effects list.
*
* \note No pointer or reference must be kept on the layer passed as
* parameter. \param theEffect The effect that must be copied and inserted
* into the effects list \param position Insertion position.
* parameter.
*
* \param theEffect The effect that must be copied and inserted
* into the effects list
* \param position Insertion position.
*/
void InsertEffect(const Effect& theEffect, std::size_t position);

View File

@@ -119,13 +119,33 @@ void ObjectsContainer::MoveObject(std::size_t oldIndex, std::size_t newIndex) {
}
void ObjectsContainer::RemoveObject(const gd::String& name) {
std::vector<std::unique_ptr<gd::Object> >::iterator object =
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
find_if(initialObjects.begin(),
initialObjects.end(),
bind2nd(ObjectHasName(), name));
if (object == initialObjects.end()) return;
if (objectIt == initialObjects.end()) return;
initialObjects.erase(object);
initialObjects.erase(objectIt);
}
void ObjectsContainer::MoveObjectToAnotherContainer(
const gd::String& name,
gd::ObjectsContainer& newContainer,
std::size_t newPosition) {
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
find_if(initialObjects.begin(),
initialObjects.end(),
bind2nd(ObjectHasName(), name));
if (objectIt == initialObjects.end()) return;
std::unique_ptr<gd::Object> object = std::move(*objectIt);
initialObjects.erase(objectIt);
newContainer.initialObjects.insert(
newPosition < newContainer.initialObjects.size()
? newContainer.initialObjects.begin() + newPosition
: newContainer.initialObjects.end(),
std::move(object));
}
} // namespace gd

View File

@@ -106,13 +106,17 @@ class GD_CORE_API ObjectsContainer {
* \note The object passed by parameter is copied.
* \param object The object that must be copied and inserted into the project
* \param position Insertion position. If the position is invalid, the object
* is inserted at the end of the objects list. \return A reference to the
* object in the list.
* is inserted at the end of the objects list.
*
* \return A reference to the object in the list.
*/
gd::Object& InsertObject(const gd::Object& object, std::size_t position);
/**
* \brief Delete an object.
* \warning When calling this function, be sure to drop any reference that you
* might hold to the object - otherwise you'll access deleted memory.
*
* \param name The name of the object to be deleted.
*/
void RemoveObject(const gd::String& name);
@@ -127,6 +131,15 @@ class GD_CORE_API ObjectsContainer {
*/
void SwapObjects(std::size_t firstObjectIndex, std::size_t secondObjectIndex);
/**
* Move the specified object to another container, removing it from the current one
* and adding it to the new one at the specified position.
*
* \note This does not invalidate the references to the object (object is not moved in memory,
* as referenced by smart pointers internally).
*/
void MoveObjectToAnotherContainer(const gd::String& name, gd::ObjectsContainer & newContainer, std::size_t newPosition);
/**
* Provide a raw access to the vector containing the objects
*/

View File

@@ -943,6 +943,8 @@ void Project::SerializeTo(SerializerElement& element) const {
}
bool Project::ValidateObjectName(const gd::String& name) {
if (name.empty()) return false;
gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
return !(name.find_first_not_of(allowedCharacters) != gd::String::npos);

View File

@@ -75,6 +75,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
return std::make_shared<FontResource>();
else if (kind == "video")
return std::make_shared<VideoResource>();
else if (kind == "json")
return std::make_shared<JsonResource>();
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
return std::make_shared<Resource>();
@@ -476,9 +478,7 @@ void ImageResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("alwaysLoaded", alwaysLoaded);
element.SetAttribute("smoothed", smooth);
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute(
"file", GetFile()); // Keep the resource path in the current locale (but
// save it in UTF8 for compatibility on other OSes)
element.SetAttribute("file", GetFile());
}
#endif
@@ -498,9 +498,7 @@ void AudioResource::UnserializeFrom(const SerializerElement& element) {
#if defined(GD_IDE_ONLY)
void AudioResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute(
"file", GetFile()); // Keep the resource path in the current locale (but
// save it in UTF8 for compatibility on other OSes)
element.SetAttribute("file", GetFile());
}
#endif
@@ -520,9 +518,7 @@ void FontResource::UnserializeFrom(const SerializerElement& element) {
#if defined(GD_IDE_ONLY)
void FontResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute(
"file", GetFile()); // Keep the resource path in the current locale (but
// save it in UTF8 for compatibility on other OSes)
element.SetAttribute("file", GetFile());
}
#endif
@@ -542,9 +538,27 @@ void VideoResource::UnserializeFrom(const SerializerElement& element) {
#if defined(GD_IDE_ONLY)
void VideoResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute(
"file", GetFile()); // Keep the resource path in the current locale (but
// save it in UTF8 for compatibility on other OSes)
element.SetAttribute("file", GetFile());
}
#endif
void JsonResource::SetFile(const gd::String& newFile) {
file = newFile;
// Convert all backslash to slashs.
while (file.find('\\') != gd::String::npos)
file.replace(file.find('\\'), 1, "/");
}
void JsonResource::UnserializeFrom(const SerializerElement& element) {
SetUserAdded(element.GetBoolAttribute("userAdded"));
SetFile(element.GetStringAttribute("file"));
}
#if defined(GD_IDE_ONLY)
void JsonResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile());
}
#endif

View File

@@ -292,6 +292,34 @@ class GD_CORE_API VideoResource : public Resource {
gd::String file;
};
/**
* \brief Describe a json file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API JsonResource : public Resource {
public:
JsonResource() : Resource() { SetKind("json"); };
virtual ~JsonResource(){};
virtual JsonResource* Clone() const override {
return new JsonResource(*this);
}
virtual const gd::String& GetFile() const override { return file; };
virtual void SetFile(const gd::String& newFile) override;
#if defined(GD_IDE_ONLY)
virtual bool UseFile() override { return true; }
void SerializeTo(SerializerElement& element) const override;
#endif
void UnserializeFrom(const SerializerElement& element) override;
private:
gd::String file;
};
/**
* \brief Inventory all resources used by a project
*

View File

@@ -110,7 +110,7 @@ TEST_CASE("ResourcesMergingHelper", "[common]") {
auto resourcesFilenames =
resourcesMerger.GetAllResourcesOldAndNewFilename();
REQUIRE(resourcesFilenames["MakeAbsolute(/image1.png)"] ==
"MakeRelative(MakeAbsolute(/image1.png))");
"FileNameFrom(MakeAbsolute(/image1.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(image2.png)"] ==
"MakeRelative(MakeAbsolute(image2.png))");
REQUIRE(resourcesFilenames["MakeAbsolute(audio1.png)"] ==

View File

@@ -8,7 +8,7 @@ This project is released under the MIT License.
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/Tools/Localization.h"
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Project/PropertyDescriptor.h"
void AnchorBehavior::InitializeContent(gd::SerializerElement& content) {

View File

@@ -6,6 +6,40 @@ This project is released under the MIT License.
*/
#include "DestroyOutsideBehavior.h"
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
DestroyOutsideBehavior::DestroyOutsideBehavior() {}
void DestroyOutsideBehavior::InitializeContent(gd::SerializerElement& content) {
content.SetAttribute("extraBorder", 0);
}
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::PropertyDescriptor>
DestroyOutsideBehavior::GetProperties(
const gd::SerializerElement& behaviorContent, gd::Project& project) const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties["extraBorder"]
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("extraBorder", 0)))
.SetType("Number")
.SetLabel(_("Margin before deleting the object, in pixels"));
return properties;
}
bool DestroyOutsideBehavior::UpdateProperty(
gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value,
gd::Project& project) {
if (name == "extraBorder")
behaviorContent.SetAttribute("extraBorder", value.To<double>());
else
return false;
return true;
}
#endif

View File

@@ -5,25 +5,36 @@ Copyright (c) 2013-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#ifndef DRAGGABLEBEHAVIOR_H
#define DRAGGABLEBEHAVIOR_H
#include "GDCpp/Runtime/Project/Behavior.h"
#include "GDCpp/Runtime/Project/Object.h"
#ifndef DESTROYOUTSIDEBEHAVIOR_H
#define DESTROYOUTSIDEBEHAVIOR_H
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"
class RuntimeScene;
namespace gd {
class SerializerElement;
}
/**
* \brief Behavior that allows objects to be dragged with the mouse.
* \brief Behavior that allows objects to be dragged with the mouse (or touch).
*/
class GD_EXTENSION_API DestroyOutsideBehavior : public Behavior {
class GD_EXTENSION_API DestroyOutsideBehavior : public gd::Behavior {
public:
DestroyOutsideBehavior();
DestroyOutsideBehavior(){};
virtual ~DestroyOutsideBehavior(){};
virtual Behavior* Clone() const { return new DestroyOutsideBehavior(*this); }
private:
#if defined(GD_IDE_ONLY)
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(
const gd::SerializerElement& behaviorContent,
gd::Project& project) const override;
virtual bool UpdateProperty(gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value,
gd::Project& project) override;
#endif
virtual void InitializeContent(
gd::SerializerElement& behaviorContent) override;
};
#endif // DRAGGABLEBEHAVIOR_H
#endif // DESTROYOUTSIDEBEHAVIOR_H

View File

@@ -19,7 +19,7 @@ This project is released under the MIT License.
DestroyOutsideRuntimeBehavior::DestroyOutsideRuntimeBehavior(
const gd::SerializerElement& behaviorContent)
: RuntimeBehavior(behaviorContent), extraBorder(0) {
extraBorder = behaviorContent.GetDoubleAttribute("extraBorder");
extraBorder = behaviorContent.GetDoubleAttribute("extraBorder", 0);
}
void DestroyOutsideRuntimeBehavior::DoStepPostEvents(RuntimeScene& scene) {

View File

@@ -14,7 +14,7 @@ gdjs.DestroyOutsideRuntimeBehavior = function(runtimeScene, behaviorData, owner)
{
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
this._extraBorder = behaviorData.extraBorder;
this._extraBorder = behaviorData.extraBorder || 0;
};
gdjs.DestroyOutsideRuntimeBehavior.prototype = Object.create( gdjs.RuntimeBehavior.prototype );

View File

@@ -0,0 +1,579 @@
/**
* This is a declaration of an extension for GDevelop 5.
*
* Run `node import-GDJS-Runtime.js` (in newIDE/app/scripts) if you make any change
* to this extension file or to any other *.js file that you reference inside.
*
* The file must be named "JsExtension.js", otherwise GDevelop won't load it.
* ⚠️ If you make a change and the extension is not loaded, open the developer console
* and search for any errors.
*
* More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md
*/
module.exports = {
createExtension: function(_, gd) {
const extension = new gd.PlatformExtension();
extension
.setExtensionInformation(
'DialogueTree',
_('Dialogue Tree (Experimental)'),
_(
'Start dialogue trees, made using Yarn, powered by Bondage.js. Experimental extension that can change in the future.'
),
'Todor Imreorov',
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/dialogue-tree');
extension
.addAction(
'LoadDialogueFromSceneVariable',
_('Load dialogue Tree from a Scene Variable'),
_(
'Load a dialogue data object - Yarn json format, stored in a scene variable. Use this command to load all the Dialogue data at the beginning of the game.'
),
_('Load dialogue data from Scene variable _PARAM1_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter(
'scenevar',
_('Scene variable that holds the Yarn Json data')
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/DialogueTree/dialoguetools.js')
.addIncludeFile('Extensions/DialogueTree/bondage.min.js')
.setFunctionName('gdjs.dialogueTree.loadFromSceneVariable');
extension
.addAction(
'LoadDialogueFromJsonFile',
_('Load dialogue Tree from a Json File'),
_(
'Load a dialogue data object - Yarn json format, stored in a Json file. Use this command to load all the Dialogue data at the beginning of the game.'
),
_('Load dialogue data from json file _PARAM1_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addCodeOnlyParameter('currentScene', '')
.addParameter(
'jsonResource',
_('Json file that holds the Yarn Json data')
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/DialogueTree/dialoguetools.js')
.addIncludeFile('Extensions/DialogueTree/bondage.min.js')
.setFunctionName('gdjs.dialogueTree.loadFromJsonFile');
extension
.addAction(
'StarDialogueFromBranch',
_('Start dialogue from branch'),
_(
'Start dialogue from branch. Use this to initiate the dialogue from a specified branch.'
),
_('Start dialogue from branch _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Dialogue branch'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.startFrom');
extension
.addAction(
'GoToNextLine',
_('Go to the next dialogue line'),
_(
'Go to the next dialogue line. Use this to advance to the next dialogue line when the player presses a button.'
),
_('Go to the next dialogue line'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.goToNextDialogueLine');
extension
.addAction(
'ConfirmSelectOption',
_('Confirm selected Option'),
_(
'Set the selected option as confirmed, which will validate it and go forward to the next node. Use other actions to select options (see "select next option" and "Select previous option").'
),
_('Confirm selected Option'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.confirmSelectOption');
extension
.addAction(
'SelectNextOption',
_('Select next Option'),
_(
'Select next Option (add 1 to selected option number). Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'
),
_('Select next Option'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectNextOption');
extension
.addAction(
'SelectPreviousOption',
_('Select previous Option'),
_(
'Select previous Option (subtract 1 from selected option number). Use this when the dialogue line is of type "options" and the player has pressed a button to change selected option.'
),
_('Select previous Option'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectPreviousOption');
extension
.addAction(
'SelectOption',
_('Select option by number'),
_(
'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'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Option index number'))
.setDefaultValue('0')
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.selectPreviousOption');
extension
.addAction(
'ScrollClippedText',
_('Scroll clipped text'),
_(
'Scroll clipped text. Use this with a timer and "get clipped text" when you want to create a typewriter effect. Every time the action runs, a new character appears from the text.'
),
_('Scroll clipped text'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.scrollClippedText');
extension
.addAction(
'SetVariable',
_('Set dialogue state variable'),
_(
'Set dialogue state variable. Use this to set a variable that the dialogue data is using.'
),
_('Set dialogue state variable _PARAM0_ to _PARAM1_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('State Variable Name'))
.addParameter('expression', _('Variable Value'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.setVariable');
extension
.addAction(
'SaveState',
_('Save dialogue state'),
_(
'Save dialogue state. Use this to store the dialogue state into a variable, which can later be used for saving the game. That way player choices can become part of the game save.'
),
_('Save dialogue state to _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('globalvar', _('Global Variable'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.saveState');
extension
.addAction(
'LoadState',
_('Load dialogue state'),
_(
'Load dialogue state. Use this to restore dialogue state, if you have stored in a variable before with the "Save state" action.'
),
_('Load dialogue state from _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('globalvar', _('Global Variable'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.loadState');
extension
.addStrExpression(
'LineText',
_('Get the current dialogue line text'),
_('Returns the current dialogue line text'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineText');
extension
.addExpression(
'OptionsCount',
_('Get the number of options in an options line type'),
_('Get the number of options in an options line type'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineOptionsCount');
extension
.addStrExpression(
'Option',
_('Get the text of an option from an Options line type'),
_(
"Get the text of an option from an Options line type, using the option's Number. The numbers start from 0."
),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Option Index Number'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getLineOption');
extension
.addExpression(
'SelectedOptionIndex',
_('Get the number of the currently selected option'),
_(
'Get the number of the currently selected option. Use this to help you render the option selection marker at the right place.'
),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getSelectedOption');
extension
.addStrExpression(
'ClippedLineText',
_('Get dialogue line text clipped'),
_(
'Get dialogue line text clipped by the typewriter effect. Use the ScrollClippedText action to control the typewriter effect.'
),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getClippedLineText');
extension
.addStrExpression(
'BranchTitle',
_('Get the title of the current branch of running dialogue'),
_('Get the title of the current branch of running dialogue'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTitle');
extension
.addStrExpression(
'BranchTags',
_('Get the tags of the current branch of running dialogue'),
_('Get the tags of the current branch of running dialogue'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTags');
extension
.addStrExpression(
'BranchTag',
_('Get a tag of the current branch of running dialogue via number'),
_('Get a tag of the current branch of running dialogue via number'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('Tag Index Number'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchTag');
extension
.addStrExpression(
'CommandParameter',
_('Get the parameters of a command call'),
_(
'Get the parameters of a command call - <<command withParameter anotherParameter>>'
),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('parameter Index Number'), '', true)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getCommandParameter');
extension
.addExpression(
'CommandParametersCount',
_('Get the number of parameters in the currently passed command'),
_('Get the number of parameters in the currently passed command'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.commandParametersCount');
extension
.addStrExpression(
'TagParameter',
_(
'Get parameter from a Tag found by the branch contains tag condition'
),
_(
'Get parameter from a Tag found by the branch contains tag condition'
),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('expression', _('parameter Index Number'), '', true)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getTagParameter');
extension
.addStrExpression(
'VisitedBranchTitles',
_('Get a list of all visited branches'),
_('Get a list of all visited branches'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getVisitedBranchTitles');
extension
.addStrExpression(
'BranchText',
_('Get the raw text of the current branch'),
_('Get the full raw text of the current branch'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getBranchText');
extension
.addExpression(
'Variable',
_('Get dialogue state value'),
_('Get dialogue state value'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Variable Name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.getVariable');
extension
.addCondition(
'Is command called',
_('Command is called'),
_(
'Check if a specific Command is called. If it is a <<command withParameter>>, you can even get the parameter with the CommandParameter expression.'
),
_('Command <<_PARAM0_>> is called'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Command String'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isCommandCalled');
extension
.addCondition(
'IsDialogueLineType',
_('The dialogue line type is'),
_(
'Check if the the current dialogue line line is one of the three existing types. Use this to set what logic is executed for each type.\nThe three types are as follows:\n- text: when displaying dialogue text.\n- options: when displaying [[branching/options]] for dialogue choices.\n-command: when <<commands>> are triggered by the dialogue data.'
),
_('The dialogue line is _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter(
'stringWithSelector',
_('type'),
'["text", "options", "command"]',
false
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isDialogueLineType');
extension
.addCondition(
'Is running',
_('Is running'),
_(
'Check if the dialogue is running. Use this to for things like locking the player movement while speaking with a non player character.'
),
_('Is running'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.isRunning');
extension
.addCondition(
'HasBranch',
_('Dialogue has branch'),
_(
'Check if the dialogue has a branch with specified name. Use this to check if a dialogue branch exists in the loaded dialogue data.'
),
_('Dialogue has a branch named _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('Branch name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasDialogueBranch');
extension
.addCondition(
'HasSelectedOptionChanged',
_('Has selected option changed'),
_(
'Check if a selected option has changed when the current dialogue line type is options. Use this to detect when the player has selected another option, so you can re-draw where the selection arrow is.'
),
_('Has selected option changed'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasSelectedOptionChanged');
extension
.addCondition(
'Current branch title is',
_('Current dialogue branch title is'),
_(
'Check if the current dialogue branch title is equal to a string. Use this to trigger game events when the player has visited a specific dialogue branch.'
),
_('The current dialogue branch title is _PARAM0_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('title name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchTitleIs');
extension
.addCondition(
'Current branch contains Tag',
_('Current dialogue branch contains a tag'),
_(
'Check if the current dialogue branch contains a specific tag. Tags are an alternative useful way to <<commands>> to drive game logic with the dialogue data.'
),
_('The current dialogue branch contains a _PARAM0_ tag'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('tag name'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchContainsTag');
extension
.addCondition(
'Branch has been visited before',
_('Branch title has been visited before'),
_('Check if the current branch has been visited before'),
_('Branch title _PARAM0_ has been visited before'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('branch title'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.branchTitleHasBeenVisited');
extension
.addCondition(
'Compare dialogue state variable',
_('Compare dialogue state variable'),
_(
'Compare dialogue state variable. Use this to trigger game events via dialogue variables.'
),
_('Dialogue state variable _PARAM0_ is equal to _PARAM1_'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.addParameter('string', _('State variable'))
.addParameter('string', _('Equal to'))
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.compareVariable');
extension
.addCondition(
'HasClippedTextScrollingCompleted',
_('Has clipped text scrolling completed'),
_(
'Check if the clipped text scrolling has completed. Use this to prevent the player from going to the next dialogue line before the typing effect has revealed the entire text.'
),
_('Has clipped text scrolling completed'),
_('Dialogue Tree (experimental)'),
'JsPlatform/Extensions/yarn24.png',
'JsPlatform/Extensions/yarn32.png'
)
.getCodeExtraInformation()
.setFunctionName('gdjs.dialogueTree.hasClippedScrollingCompleted');
return extension;
},
runExtensionSanityTests: function(gd, extension) {
return [];
},
};

11
Extensions/DialogueTree/bondage.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,609 @@
/**
* @memberof gdjs
* @class dialogueTree
* @static
* @private
*/
gdjs.dialogueTree = {};
gdjs.dialogueTree.runner = new bondage.Runner();
/**
* Load the Dialogue Tree data of the game. Initialize The Dialogue Tree, so as it can be used in the game.
* @param {gdjs.Variable} sceneVar The variable to load the Dialogue tree data from. The data is a JSON string, created by Yarn.
* @param {string} startDialogueNode The Dialogue Branch to start the Dialogue Tree from. If left empty, the data will only be loaded, but can later be initialized via another action
*/
gdjs.dialogueTree.loadFromSceneVariable = function(
sceneVar,
startDialogueNode
) {
this.runner = gdjs.dialogueTree.runner;
try {
this.yarnData = JSON.parse(sceneVar.getAsString());
this.runner.load(this.yarnData);
if (startDialogueNode && startDialogueNode.length > 0) {
gdjs.dialogueTree.startFrom(startDialogueNode);
}
} catch (e) {
console.error(e);
}
};
/**
* Load the Dialogue Tree data from a JSON resource.
*
* @param {gdjs.RuntimeScene} runtimeScene The scene where the dialogue is running.
* @param {string} jsonResourceName The JSON resource where to load the Dialogue Tree data from. The data is a JSON string usually created with [Yarn Dialogue Editor](https://github.com/InfiniteAmmoInc/Yarn).
* @param {string} startDialogueNode The Dialogue Branch to start the Dialogue Tree from. If left empty, the data will only be loaded, but can later be initialized via another action
*/
gdjs.dialogueTree.loadFromJsonFile = function(
runtimeScene,
jsonResourceName,
startDialogueNode
) {
runtimeScene
.getGame()
.getJsonManager()
.loadJson(jsonResourceName, function(error, content) {
if (error) {
console.error('An error happened while loading JSON resource:', error);
} else {
if (!content) return;
gdjs.dialogueTree.yarnData = content;
gdjs.dialogueTree.runner.load(gdjs.dialogueTree.yarnData);
if (startDialogueNode && startDialogueNode.length > 0) {
gdjs.dialogueTree.startFrom(startDialogueNode);
}
}
});
};
/**
* Check if the Dialogue Tree is currently parsing data.
* For example, you can do things like disabling player movement while talking to a NPC.
*/
gdjs.dialogueTree.isRunning = function() {
return this.dialogueIsRunning;
};
/**
* Scroll the clipped text. This can be combined with a timer and user input to control how fast the dialogue line text is scrolling.
*/
gdjs.dialogueTree.scrollClippedText = function() {
if (this.pauseScrolling || !this.dialogueIsRunning) return;
if (this.dialogueText) {
this.clipTextEnd += 1;
}
};
/**
* Check if text scrolling has completed.
* Useful to prevent the user from skipping to next line before the current one has been printed fully.
*/
gdjs.dialogueTree.hasClippedScrollingCompleted = function() {
if (this.dialogueData && this.dialogueText.length) {
return this.clipTextEnd >= this.dialogueText.length;
}
return false;
};
/**
* Get the current dialogue line with a scrolling effect (recommended).
* Used with the scrollClippedText to achieve a classic scrolling text, as well as any <<wait>> effects to pause scrolling.
*/
gdjs.dialogueTree.getClippedLineText = function() {
return this.dialogueText.length
? this.dialogueText.substring(0, this.clipTextEnd)
: '';
};
/**
* Get the current complete dialogue line without using any scrolling effects.
* Note that using this instead getClippedLineText will skip any <<wait>> commands entirely.
*/
gdjs.dialogueTree.getLineText = function() {
this.clipTextEnd = this.dialogueText.length;
return this.dialogueText.length ? this.dialogueText : '';
};
/**
* Get the number of command parameters in a command with parameters that has been caught by a isCommandCalled condition
*/
gdjs.dialogueTree.commandParametersCount = function() {
if (this.commandParameters && this.commandParameters.length > 1) {
return this.commandParameters.length - 1;
}
return 0;
};
/**
* Get a command parameter in any command with parameters that has been caught by a isCommandCalled condition
* @param {number} paramIndex The index of the parameter to get.
*/
gdjs.dialogueTree.getCommandParameter = function(paramIndex) {
if (
this.commandParameters &&
this.commandParameters.length >= paramIndex + 1
) {
var returnedParam = this.commandParameters[paramIndex + 1];
return returnedParam ? returnedParam : '';
}
return '';
};
/**
* Catch <<commands>> and <<commands with parameters>> from the current Dialogue Line.
* You can trigger custom logic that relate to the story you are telling during the dialogue.
*
* @param {string} command The command you want to check for being called. Write it without the `<<>>`.
*/
gdjs.dialogueTree.isCommandCalled = function(command) {
var commandCalls = gdjs.dialogueTree.commandCalls;
var clipTextEnd = gdjs.dialogueTree.clipTextEnd;
var dialogueText = gdjs.dialogueTree.dialogueText;
if (this.pauseScrolling || !commandCalls) return false;
return this.commandCalls.some(function(call, index) {
if (clipTextEnd < call.time) return false;
if (call.cmd === 'wait' && clipTextEnd !== dialogueText.length) {
gdjs.dialogueTree.pauseScrolling = true;
setTimeout(function() {
gdjs.dialogueTree.pauseScrolling = false;
commandCalls.splice(index, 1);
}, parseInt(call.params[1], 10));
}
if (call.cmd === command) {
gdjs.dialogueTree.commandParameters = call.params;
commandCalls.splice(index, 1);
return true;
}
});
};
/**
* Internal method to allow for capping option selection.
* @private
*/
gdjs.dialogueTree._normalizedOptionIndex = function(optionIndex) {
if (optionIndex >= this.options.length) optionIndex = this.options.length - 1;
if (optionIndex < 0) optionIndex = 0;
return optionIndex;
};
/**
* Internal method to allow for cycling option selection.
* @private
*/
gdjs.dialogueTree._cycledOptionIndex = function(optionIndex) {
if (optionIndex >= this.options.length) optionIndex = 0;
if (optionIndex < 0) optionIndex = this.options.length - 1;
return optionIndex;
};
/**
* Get the text of an option the player can select.
* Used with getLineOptionsCount to render options for the player when a line of the Options type is parsed
* @param {number} optionIndex The index of the option you want to get
*/
gdjs.dialogueTree.getLineOption = function(optionIndex) {
if (!this.options.length) return [];
optionIndex = gdjs.dialogueTree._normalizedOptionIndex(optionIndex);
return this.options[optionIndex];
};
/**
* Get the number of options that are presented to the player, during the parsing of an Options type line.
* @returns {number} The number of options
*/
gdjs.dialogueTree.getLineOptionsCount = function() {
if (this.options.length) {
return this.optionsCount;
}
return 0;
};
/**
* Confirm the currently selected option, during the parsing of an Options type line.
*
* This will advance the dialogue tree to the dialogue branch was selected by the player.
*/
gdjs.dialogueTree.confirmSelectOption = function() {
if (
this.dialogueData.select &&
!this.selectedOptionUpdated &&
this.selectedOption !== -1
) {
this.commandCalls = [];
this.dialogueData.select(this.selectedOption);
this.dialogueData = this.dialogue.next().value;
gdjs.dialogueTree.goToNextDialogueLine();
}
};
/**
* Select next option during Options type line parsing. Hook this to your game input.
*/
gdjs.dialogueTree.selectNextOption = function() {
if (this.dialogueData.select) {
this.selectedOption += 1;
this.selectedOption = gdjs.dialogueTree._cycledOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Select previous option during Options type line parsing. Hook this to your game input.
*/
gdjs.dialogueTree.selectPreviousOption = function() {
if (this.dialogueData.select) {
this.selectedOption -= 1;
this.selectedOption = gdjs.dialogueTree._cycledOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Select option by index during Options type line parsing.
* @param {number} optionIndex The index of the option to select
*/
gdjs.dialogueTree.selectOption = function(optionIndex) {
if (this.dialogueData.select) {
this.selectedOption = gdjs.dialogueTree._normalizedOptionIndex(
this.selectedOption
);
this.selectedOptionUpdated = true;
}
};
/**
* Get the currently selected option
* @returns {number} The index of the currently selected option
*/
gdjs.dialogueTree.getSelectedOption = function() {
if (this.dialogueData.select) {
return this.selectedOption;
}
return 0;
};
/**
* Check when the player has changed option selection since the last call to this function.
*
* Can be used to re-render your displayed dialogue options when needed.
*
* @returns {boolean} true if the selected option was updated since the last call to this function
*/
gdjs.dialogueTree.hasSelectedOptionChanged = function() {
if (this.selectedOptionUpdated) {
this.selectedOptionUpdated = false;
if (this.selectedOption === -1) this.selectedOption = 0;
return true;
}
return false;
};
/**
* Check the type of the Dialogue Line that is being displayed to the player at the moment.
*
* There are three types:
* - text - regular dialogue text is being parsed at the moment
* - options - the player has reached a branching choise moment where they must select one of multiple options
* - command - a <<command>> was called in the background, that can be used to trigger game events, but will not be displayed in the dialogue box.
*
* @param {string} type The type you want to check for ( one of the three above )
*/
gdjs.dialogueTree.isDialogueLineType = function(type) {
if (
this.commandCalls &&
this.commandCalls.some(function(call) {
return gdjs.dialogueTree.clipTextEnd > call.time;
})
) {
return true;
}
return this.dialogueIsRunning ? this.dialogueDataType === type : false;
};
/**
* Check if a branch exists. It is also used internaly whenever you use the start from action.
* @param {string} branchName The Dialogue Branch name you want to check.
*/
gdjs.dialogueTree.hasDialogueBranch = function(branchName) {
return (
this.runner &&
this.runner.yarnNodes &&
Object.keys(this.runner.yarnNodes).some(function(node) {
return node === branchName;
})
);
};
/**
* Start parsing dialogue from a specified Dialogue tree branch.
* Can be used if you want to store multiple dialogues inside a single Dialogue tree data set.
* @param {string} startDialogueNode The Dialogue Branch name you want to start parsing from.
*/
gdjs.dialogueTree.startFrom = function(startDialogueNode) {
this.runner = gdjs.dialogueTree.runner;
if (!this.hasDialogueBranch(startDialogueNode)) return;
this.optionsCount = 0;
this.options = [];
this.dialogueBranchTitle = '';
this.dialogueBranchBody = '';
this.dialogueBranchTags = [];
this.tagParameters = [];
this.dialogue = this.runner.run(startDialogueNode);
this.dialogueData = null;
this.dialogueDataType = '';
this.dialogueText = '';
this.commandCalls = [];
this.commandParameters = [];
this.pauseScrolling = false;
this.dialogueData = this.dialogue.next().value;
this.dialogueIsRunning = true;
gdjs.dialogueTree.goToNextDialogueLine();
};
/**
* Internal methods to check the type of a Dialogue Line
*/
gdjs.dialogueTree._isLineTypeText = function() {
return this.dialogueData instanceof bondage.TextResult;
};
gdjs.dialogueTree._isLineTypeOptions = function() {
return this.dialogueData instanceof bondage.OptionsResult;
};
gdjs.dialogueTree._isLineTypeCommand = function() {
return this.dialogueData instanceof bondage.CommandResult;
};
/**
* This is the main lifecycle function.It runs once only when the user is advancing the dialogue to the next line.
* Progress Dialogue to the next line. Hook it to your game input.
* Note that this action can be influenced by any <<wait>> commands, but they work only if you have at least one isCommandCalled condition.
*/
gdjs.dialogueTree.goToNextDialogueLine = function() {
if (this.pauseScrolling || !this.dialogueIsRunning) return;
this.optionsCount = 0;
this.selectedOption = -1;
this.selectedOptionUpdated = false;
if (gdjs.dialogueTree._isLineTypeText()) {
if (
this.dialogueDataType === 'options' ||
this.dialogueDataType === 'text' ||
!this.dialogueDataType
) {
this.clipTextEnd = 0;
this.dialogueText = this.dialogueData.text;
this.commandCalls = [];
} else {
this.dialogueText += this.dialogueData.text;
}
this.dialogueDataType = 'text';
this.dialogueBranchTags = this.dialogueData.data.tags;
this.dialogueBranchTitle = this.dialogueData.data.title;
this.dialogueBranchBody = this.dialogueData.data.body;
this.dialogueData = this.dialogue.next().value;
} else if (gdjs.dialogueTree._isLineTypeOptions()) {
this.dialogueDataType = 'options';
this.optionsCount = this.dialogueData.options.length;
this.options = this.dialogueData.options;
this.selectedOptionUpdated = true;
} else if (gdjs.dialogueTree._isLineTypeCommand()) {
this.dialogueDataType = 'command';
var command = this.dialogueData.text.split(' ');
// If last command was to wait, increase time by one
var offsetTime =
this.commandCalls.length &&
this.commandCalls[this.commandCalls.length - 1].cmd === 'wait'
? 1
: 0;
this.commandCalls.push({
cmd: command[0],
params: command,
time: this.dialogueText.length + offsetTime,
});
this.dialogueData = this.dialogue.next().value;
gdjs.dialogueTree.goToNextDialogueLine();
} else {
this.dialogueDataType = 'unknown';
}
if (gdjs.dialogueTree._isLineTypeCommand()) {
this.dialogueDataType = 'command';
gdjs.dialogueTree.goToNextDialogueLine();
}
// Dialogue has finished
if (!this.dialogueData) {
this.dialogueIsRunning = false;
}
};
/**
* Get the current Dialogue Tree branch title.
* @returns {string} The current branch title.
*/
gdjs.dialogueTree.getBranchTitle = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchTitle;
}
return '';
};
/**
* Check if the currently parsed Dialogue branch title is a query.
* @param {string} title The Dialogue Branch name you want to check for.
*/
gdjs.dialogueTree.branchTitleIs = function(title) {
if (this.dialogueIsRunning) {
return this.dialogueBranchTitle === title;
}
return false;
};
/**
* Get all the branch tags from the current Dialogue branch as a string. Useful for debugging.
* @returns {string} The current branch tags, separated by a comma.
*/
gdjs.dialogueTree.getBranchTags = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchTags.join(',');
}
return '';
};
/**
* Get one of the current Dialogue branch tags via index.
* @param {number} index The index of the Dialogue Branch tag you want to get.
* @returns {string} The branch tag at the specified index, or an empty string if not found.
*/
gdjs.dialogueTree.getBranchTag = function(index) {
if (this.dialogueIsRunning && this.dialogueBranchTags.length) {
if (index > this.dialogueBranchTags.length - 1)
index = this.dialogueBranchTags.length - 1;
return this.dialogueBranchTags[index];
}
return '';
};
/**
* Check if the current Dialogue branch contains a specific tag.
* @param {string} query The name of the Dialogue Branch tag you want to check.
*/
gdjs.dialogueTree.branchContainsTag = function(query) {
this.tagParameters = [];
if (this.dialogueIsRunning && this.dialogueBranchTags.length) {
return this.dialogueBranchTags.some(function(tag) {
var splitTag = tag.match(/([^\(]+)\(([^\)]+)\)/i);
gdjs.dialogueTree.tagParameters = splitTag ? splitTag[2].split(',') : [];
return splitTag ? splitTag[1] === query : tag === query;
});
}
return false;
};
/**
* Get any tag(parameter,anotherParameter) from a tag captured by the branchContainsTag Condition
* @param {number} paramIndex The index of the tag parameter you want to get.
* Leaving this empty will result in retrieving the first parameter.
*/
gdjs.dialogueTree.getTagParameter = function(paramIndex) {
if (this.dialogueIsRunning && this.tagParameters.length >= paramIndex) {
var returnedParam = this.tagParameters[paramIndex];
return returnedParam ? returnedParam : '';
}
return '';
};
/**
* Get a list of all the titles of visited by the player Branches. Useful for debugging.
*/
gdjs.dialogueTree.getVisitedBranchTitles = function() {
if (this.dialogueIsRunning) {
return Object.keys(this.runner.visited).join(',');
}
return '';
};
/**
* Check if a player has visited a Dialogue Branch in the past.
* @param {string} title The title of the branch to check for.
* Leaving this empty will check if the current branch title has been visited in the past.
*/
gdjs.dialogueTree.branchTitleHasBeenVisited = function(title) {
if (!title) title = this.dialogueBranchTitle;
return (
Object.keys(this.runner.visited).includes(title) &&
this.runner.visited[title]
);
};
/**
* Get the entire unparsed text of the current Dialogue Branch
*/
gdjs.dialogueTree.getBranchText = function() {
if (this.dialogueIsRunning) {
return this.dialogueBranchBody;
}
return '';
};
/**
* Get the value of a variable that was created by the Dialogue parses.
* @param {string} key The name of the variable you want to get the value of
*/
gdjs.dialogueTree.getVariable = function(key) {
if (this.dialogueIsRunning && key in this.runner.variables.data) {
return this.runner.variables.data[key];
}
return '';
};
/**
* Check if a specific variable created by the Dialogue parses exists and is equal to a specific value.
* @param {string} key The name of the variable you want to check the value of
* @param {string} value The value you want to check against
*/
gdjs.dialogueTree.compareVariable = function(key, value) {
if (this.dialogueIsRunning && key in this.runner.variables.data) {
return this.runner.variables.data[key].toString() === value;
}
return false;
};
/**
* Set a specific variable created by the Dialogue parser to a specific value.
* @param {string} key The name of the variable you want to set the value of
* @param {string} value The value you want to set
*/
gdjs.dialogueTree.setVariable = function(key, value) {
if (this.dialogueIsRunning && this.runner.variables.data) {
this.runner.variables.data[key] = value;
}
};
/**
* Store the current State of the Dialogue Parser in a specified variable.
* Can be used to implement persistence in dialogue through your game's Load/Save function.
* That way you can later load all the dialogue choices the player has made.
* @param {gdjs.Variable} outputVariable The variable where to store the State
*/
gdjs.dialogueTree.saveState = function(outputVariable) {
const dialogueState = {
variables: gdjs.dialogueTree.runner.variables.data,
visited: gdjs.dialogueTree.runner.visited,
};
gdjs.evtTools.network._objectToVariable(dialogueState, outputVariable);
};
/**
* Load the current State of the Dialogue Parser from a specified variable.
* Can be used to implement persistence in dialogue through your game's Load/Save function.
* That way you can later load all the dialogue choices the player has made.
* @param {gdjs.Variable} inputVariable The variable where to load the State from.
*/
gdjs.dialogueTree.loadState = function(inputVariable) {
const jsonData = gdjs.evtTools.network.variableStructureToJSON(inputVariable);
try {
const loadedState = JSON.parse(
gdjs.evtTools.network.variableStructureToJSON(inputVariable)
);
gdjs.dialogueTree.runner.visited = loadedState.visited;
gdjs.dialogueTree.runner.variables.data = loadedState.variables;
} catch (e) {
console.error(e);
}
};

View File

@@ -0,0 +1,81 @@
[
{
"title": "Numeric",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = -123.4>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},{
"title": "NumericExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = (1 + 2) * -3 + 4.3>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "String",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = \"Variable String\">>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "StringExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = \"Variable String\" + \" Appended\">>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Boolean",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = true>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BooleanExpression",
"tags": "Tag",
"body": "Test Line\n<<set $testvar = (true || false) && (false || !false)>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Variable",
"tags": "Tag",
"body": "Test Line\n<<set $firstvar = \"First variable string\">><<set $secondvar = $firstvar>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VariableExpression",
"tags": "Tag",
"body": "Test Line\n<<set $firstvar = 100>><<set $secondvar = -4.3 + $firstvar>>\nTest Line After",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,52 @@
[
{
"title": "BasicCommands",
"tags": "Tag",
"body": "<<command>>text in between commands<<command with space>> <<callFunction()>> <<callFunctionWithParam(\"test\",true,1,12.5,[2,3])>>",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "StopCommand",
"tags": "Tag",
"body": "First line\n<<stop>>\nThis shouldn't show",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "FunctionConditional",
"tags": "Tag",
"body": "First line\n<<if testfunc(\"firstarg\")>>This shouldn't show<<elseif testfunc(\"firstarg\", \"secondarg\")>>This should show<<endif>>After both",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VisitedFunction",
"tags": "Tag",
"body": "<<if visited(\"VisitedFunctionStart\")>>you have visited VisitedFunctionStart!<<endif>><<if visited(\"SomeOtherNode\")>>You have not visited SomeOtherNode!<<endif>>",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "VisitedFunctionStart",
"tags": "Tag",
"body": "Hello[[VisitedFunction]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,93 @@
[
{
"title": "Start",
"tags": "Tag",
"body": "What are you?\n-> A troll\n <<set $troll to true >>\n-> A nice person\n <<set $troll to false >>\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective",
"tags": "Tag",
"body": "<<if $repeat >= 3>>\nBye...\n<<else>>\nIs your objective clear?\n[[Yes|Objective.Yes]]\n[[No|Objective.No]]\n<<if $troll == true>>\n[[Maybe|Objective.Maybe]]\n<<endif>>\n<<endif>>\n",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.No",
"tags": "Tag",
"body": "Blah blah blah blah\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.Yes",
"tags": "Tag",
"body": "Good let's start the mission.",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Objective.Maybe",
"tags": "Tag",
"body": "Are you trolling me?\n[[Objective]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIf",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 321>>Inside if<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElse",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<else>>Inside else<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElseIf",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<elseif $testvar == 321>>Inside elseif<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "BasicIfElseIfElse",
"tags": "Tag",
"body": "<<set $testvar = 321>>\nText before\n<<if $testvar == 123>>Inside if<<elseif $testvar == 1>>Inside elseif<<else>>Inside else<<endif>>Text after",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -0,0 +1,72 @@
[
{
"title": "OneNode",
"tags": "Tag",
"body": "This is a test line",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "ThreeNodes",
"tags": "",
"body": "This is a test line\nThis is another test line[[Option1]]\n[[Option2]]",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Option1",
"tags": "",
"body": "This is Option1's test line",
"position": {
"x": 770,
"y": 84
},
"colorID": 0
},
{
"title": "Option2",
"tags": "",
"body": "This is Option2's test line",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "NamedLink",
"tags": "",
"body": "This is a test line\nThis is another test line\n[[First choice|Option1]]\n[[Second choice|Option2]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "OneLinkPassthrough",
"tags": "",
"body": "First test line\n[[Option1]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
},
{
"title": "LinkAfterShortcuts",
"tags": "",
"body": "First test line\n-> Shortcut 1\n\tThis is the first shortcut\n-> Shortcut 2\n\tThis is the second shortcut\n[[First link|Option1]][[Second link|Option2]]",
"position": {
"x": 774,
"y": 404
},
"colorID": 0
}
]

View File

@@ -0,0 +1,32 @@
[
{
"title": "NonNested",
"tags": "Tag",
"body": "This is a test line\n-> Option 1\n\tThis is the first option\n-> Option 2\n\tThis is the second option\nThis is after both options",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Nested",
"tags": "Tag",
"body": "text\n-> shortcut1\n\tText1\n\t-> nestedshortcut1\n\t\tNestedText1\n\t-> nestedshortcut2\n\t\tNestedText2\n-> shortcut2\n\tText2\nmore text",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
},
{
"title": "Conditional",
"tags": "Tag",
"body": "This is a test line\n-> Option 1\n\tThis is the first option\n-> Option 2 <<if 1 == 0>>\n\tThis is the second option\n-> Option 3\n\tThis is the third option\nThis is after both options",
"position": {
"x": 449,
"y": 252
},
"colorID": 0
}
]

View File

@@ -29,7 +29,7 @@ gdjs.DraggableRuntimeBehavior.prototype.onDeActivate = function() {
this._endDrag();
};
gdjs.DraggableRuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
gdjs.DraggableRuntimeBehavior.prototype.onDestroy = function() {
this.onDeActivate();
};

View File

@@ -6,7 +6,7 @@
* @extends RuntimeObject
*/
gdjs.DummyRuntimeObject = function(runtimeScene, objectData) {
// Always call the base gdjs.RuntimeObject constructor.
// *ALWAYS* call the base gdjs.RuntimeObject constructor.
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
// Load any required data from the object properties.
@@ -16,6 +16,9 @@ gdjs.DummyRuntimeObject = function(runtimeScene, objectData) {
if (this._renderer)
gdjs.DummyRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
else this._renderer = new gdjs.DummyRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.DummyRuntimeObject.prototype = Object.create(gdjs.RuntimeObject.prototype);

View File

@@ -296,7 +296,7 @@ module.exports = {
.addAction(
'DeleteFileAsync',
_('Delete a file (Async)'),
_('Delete a file from the filesystem asyncrounouse.'),
_('Delete a file from the filesystem asynchronously. The option result variable will be updated once the file is deleted.'),
_('Delete the file _PARAM0_'),
_('Filesystem/Windows, Linux, MacOS/Asynchronous'),
'JsPlatform/Extensions/filesystem_delete_file24.png',

View File

@@ -1,6 +1,6 @@
describe('Inventory', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame, null);
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
gdjs.evtTools.inventory.add(runtimeScene, "MyInventory", "sword");
gdjs.evtTools.inventory.add(runtimeScene, "MyInventory", "sword");

View File

@@ -1,7 +1,7 @@
describe('gdjs.LinksManager', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame, null);
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers:[{name:"", visibility: true}],
variables: [],

View File

@@ -33,6 +33,53 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
#if defined(GD_IDE_ONLY)
obj.SetIncludeFile("PanelSpriteObject/PanelSpriteObject.h");
obj.AddCondition("Opacity",
_("Opacity"),
_("Compare the opacity of a Panel Sprite, between 0 (fully "
"transparent) to 255 (opaque)."),
_("The opacity of _PARAM0_ is _PARAM1__PARAM2_"),
_("Visibility"),
"res/conditions/opacity24.png",
"res/conditions/opacity.png")
.AddParameter("object", _("Object"), "PanelSprite")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to compare"))
.SetManipulatedType("number");
obj.AddAction("SetOpacity",
_("Change Panel Sprite opacity"),
_("Change the opacity of a Panel Sprite. 0 is fully transparent, 255 "
"is opaque (default)."),
_("Do _PARAM1__PARAM2_ to the opacity of _PARAM0_"),
_("Visibility"),
"res/actions/opacity24.png",
"res/actions/opacity.png")
.AddParameter("object", _("Object"), "PanelSprite")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value (between 0 and 255)"))
.SetManipulatedType("number");
obj.AddExpression("Opacity",
_("Opacity"),
_("Opacity"),
_("Visibility"),
"res/actions/opacity.png")
.AddParameter("object", _("Panel Sprite"), "PanelSprite");
obj.AddAction(
"SetColor",
_("Global color"),
_("Change the global color of a Panel Sprite. The default color is white."),
_("Change color of _PARAM0_ to _PARAM1_"),
_("Effects"),
"res/actions/color24.png",
"res/actions/color.png")
.AddParameter("object", _("Object"), "PanelSprite")
.AddParameter("color", _("Color"));
obj.AddAction("Width",
_("Width"),
_("Modify the width of a Panel Sprite."),

View File

@@ -33,6 +33,28 @@ class PanelSpriteObjectJsExtension : public gd::PlatformExtension {
"Extensions/PanelSpriteObject/"
"panelspriteruntimeobject-cocos-renderer.js");
GetAllActionsForObject(
"PanelSpriteObject::PanelSprite")["PanelSpriteObject::SetOpacity"]
.SetFunctionName("setOpacity")
.SetGetter("getOpacity")
.SetIncludeFile(
"Extensions/PanelSpriteObject/panelspriteruntimeobject.js");
GetAllConditionsForObject(
"PanelSpriteObject::PanelSprite")["PanelSpriteObject::Opacity"]
.SetFunctionName("getOpacity")
.SetIncludeFile(
"Extensions/TiledSpriteObject/panelspriteruntimeobject.js");
GetAllExpressionsForObject(
"PanelSpriteObject::PanelSprite")["Opacity"]
.SetFunctionName("getOpacity")
.SetIncludeFile(
"Extensions/TiledSpriteObject/panelspriteruntimeobject.js");
GetAllActionsForObject(
"PanelSpriteObject::PanelSprite")["PanelSpriteObject::SetColor"]
.SetFunctionName("setColor")
.SetIncludeFile(
"Extensions/TiledSpriteObject/panelspriteruntimeobject.js");
GetAllActionsForObject(
"PanelSpriteObject::PanelSprite")["PanelSpriteObject::Width"]
.SetFunctionName("setWidth")

View File

@@ -58,7 +58,7 @@ gdjs.PanelSpriteRuntimeObjectCocosRenderer.prototype._createTilingShaderAndUnifo
}
};
gdjs.PanelSpriteRuntimeObjectCocosRenderer.prototype.onOwnerRemovedFromScene = function() {
gdjs.PanelSpriteRuntimeObjectCocosRenderer.prototype.onDestroy = function() {
if (this._centerSpriteShader && this._centerSpriteShader.shader)
this._centerSpriteShader.shader.release();
if (this._rightSpriteShader && this._rightSpriteShader.shader)

View File

@@ -29,6 +29,7 @@ gdjs.PanelSpriteRuntimeObjectPixiRenderer = function(runtimeObject, runtimeScene
this._spritesContainer.addChild(this._borderSprites[i]);
}
this._alpha = this._spritesContainer.alpha;
runtimeScene.getLayer("").getRenderer().addRendererObject(this._spritesContainer, runtimeObject.getZOrder());
};
@@ -39,13 +40,23 @@ gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.getRendererObject = function
};
gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.ensureUpToDate = function() {
if (this._spritesContainer.visible && this._wasRendered) {
this._spritesContainer.cacheAsBitmap = true;
if (this._spritesContainer.visible && this._wasRendered) {
// Update the alpha of the container to make sure that it's applied.
// If not done, the alpha will be back to full opaque when changing the color
// of the object.
this._spritesContainer.alpha = this._alpha;
this._spritesContainer.cacheAsBitmap = true;
}
this._wasRendered = true;
};
gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.updateOpacity = function() {
//TODO: Workaround a not working property in PIXI.js:
this._spritesContainer.alpha = this._spritesContainer.visible ? this._object.opacity/255 : 0;
this._alpha = this._spritesContainer.alpha;
}
gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.updateAngle = function() {
this._spritesContainer.rotation = gdjs.toRad(this._object.angle);
};
@@ -173,3 +184,21 @@ gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.updateHeight = function() {
this._updateLocalPositions();
this.updatePosition();
};
gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.setColor = function(rgbColor) {
var colors = rgbColor.split(";");
if ( colors.length < 3 ) return;
this._centerSprite.tint = "0x" + gdjs.rgbToHex(parseInt(colors[0], 10), parseInt(colors[1], 10), parseInt(colors[2], 10));
for (var borderCounter = 0; borderCounter < this._borderSprites.length; borderCounter++){
this._borderSprites[borderCounter].tint = "0x" + gdjs.rgbToHex(parseInt(colors[0], 10), parseInt(colors[1], 10), parseInt(colors[2], 10));
}
this._spritesContainer.cacheAsBitmap = false;
};
gdjs.PanelSpriteRuntimeObjectPixiRenderer.prototype.getColor = function() {
var rgb = PIXI.utils.hex2rgb(this._centerSprite.tint)
return Math.floor(rgb[0]*255) + ';' + Math.floor(rgb[1]*255) + ';' + Math.floor(rgb[2]*255);
}

View File

@@ -21,6 +21,7 @@ gdjs.PanelSpriteRuntimeObject = function(runtimeScene, objectData)
this._tiled = objectData.tiled;
this._width = objectData.width;
this._height = objectData.height;
this.opacity = 255;
if (this._renderer)
gdjs.PanelSpriteRuntimeObjectRenderer.call(this._renderer, this, runtimeScene,
@@ -28,6 +29,9 @@ gdjs.PanelSpriteRuntimeObject = function(runtimeScene, objectData)
else
this._renderer = new gdjs.PanelSpriteRuntimeObjectRenderer(this, runtimeScene,
objectData.texture, objectData.tiled);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.PanelSpriteRuntimeObject.prototype = Object.create( gdjs.RuntimeObject.prototype );
@@ -37,11 +41,11 @@ gdjs.PanelSpriteRuntimeObject.prototype.getRendererObject = function() {
return this._renderer.getRendererObject();
};
gdjs.PanelSpriteRuntimeObject.prototype.onDeletedFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
gdjs.PanelSpriteRuntimeObject.prototype.onDestroyFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
if (this._renderer.onOwnerRemovedFromScene) {
this._renderer.onOwnerRemovedFromScene();
if (this._renderer.onDestroy) {
this._renderer.onDestroy();
}
};
@@ -128,3 +132,41 @@ gdjs.PanelSpriteRuntimeObject.prototype.setHeight = function(height) {
this._height = height;
this._renderer.updateHeight();
};
/**
* Change the transparency of the object.
* @param {number} opacity The new opacity, between 0 (transparent) and 255 (opaque).
*/
gdjs.PanelSpriteRuntimeObject.prototype.setOpacity = function(opacity) {
if ( opacity < 0 ) opacity = 0;
if ( opacity > 255 ) opacity = 255;
this.opacity = opacity;
this._renderer.updateOpacity();
};
/**
* Get the transparency of the object.
* @return {number} The opacity, between 0 (transparent) and 255 (opaque).
*/
gdjs.PanelSpriteRuntimeObject.prototype.getOpacity = function() {
return this.opacity;
};
/**
* Change the tint of the panel sprite object.
*
* @param {string} rgbColor The color, in RGB format ("128;200;255").
*/
gdjs.PanelSpriteRuntimeObject.prototype.setColor = function(rgbColor) {
this._renderer.setColor(rgbColor);
};
/**
* Get the tint of the panel sprite object.
*
* @returns {string} rgbColor The color, in RGB format ("128;200;255").
*/
gdjs.PanelSpriteRuntimeObject.prototype.getColor = function() {
return this._renderer.getColor();
};

View File

@@ -51,6 +51,9 @@ gdjs.ParticleEmitterObject = function(runtimeScene, objectData){
this._alphaDirty = true;
this._textureDirty = true;
this._flowDirty = true;
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.ParticleEmitterObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
gdjs.ParticleEmitterObject.thisIsARuntimeObjectConstructor = "ParticleSystem::ParticleEmitter";
@@ -127,9 +130,9 @@ gdjs.ParticleEmitterObject.prototype.update = function(runtimeScene){
}
};
gdjs.ParticleEmitterObject.prototype.onDeletedFromScene = function(runtimeScene){
gdjs.ParticleEmitterObject.prototype.onDestroyFromScene = function(runtimeScene){
this._renderer.destroy();
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
};
gdjs.ParticleEmitterObject.prototype.getEmitterForceMin = function(){

View File

@@ -104,7 +104,7 @@ gdjs.PathfindingObstacleRuntimeBehavior = function(runtimeScene, behaviorData, o
gdjs.PathfindingObstacleRuntimeBehavior.prototype = Object.create( gdjs.RuntimeBehavior.prototype );
gdjs.PathfindingObstacleRuntimeBehavior.thisIsARuntimeBehaviorConstructor = "PathfindingBehavior::PathfindingObstacleBehavior";
gdjs.PathfindingObstacleRuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
gdjs.PathfindingObstacleRuntimeBehavior.prototype.onDestroy = function() {
if ( this._manager && this._registeredInManager ) this._manager.removeObstacle(this);
};

View File

@@ -194,11 +194,10 @@ gdjs.PathfindingRuntimeBehavior.prototype.moveTo = function(runtimeScene, x, y)
var startCellX = Math.round(owner.getX()/this._cellWidth);
var startCellY = Math.round(owner.getY()/this._cellHeight);
if ( startCellX == targetCellX && startCellY == targetCellY ) {
while (this._path.length < 2) this._path.unshift([0, 0]);
this._path.length = 2;
this._path.length = 0;
this._path.push([owner.getX(), owner.getY()]);
this._path.push([x, y]);
this._enterSegment(0);
this._pathFound = true;

View File

@@ -72,10 +72,11 @@ module.exports = {
return true;
}
if (propertyName === 'polygonOrigin') {
behaviorContent.getChild('polygonOrigin').setStringValue(newValue);
behaviorContent.addChild('polygonOrigin').setStringValue(newValue);
return true;
}
if (propertyName === 'vertices') {
behaviorContent.addChild('vertices');
behaviorContent.setChild('vertices', gd.Serializer.fromJSON(newValue));
return true;
}
@@ -203,7 +204,9 @@ module.exports = {
behaviorProperties.set(
'polygonOrigin',
new gd.PropertyDescriptor(
behaviorContent.getChild('polygonOrigin').getStringValue() || 'Center'
behaviorContent.hasChild('polygonOrigin') ?
behaviorContent.getChild('polygonOrigin').getStringValue() :
'Center'
)
.setType('Choice')
.setLabel('Polygon Origin')
@@ -214,7 +217,9 @@ module.exports = {
behaviorProperties.set(
'vertices',
new gd.PropertyDescriptor(
gd.Serializer.toJSON(behaviorContent.getChild('vertices')) || '[]'
behaviorContent.hasChild('vertices') ?
gd.Serializer.toJSON(behaviorContent.getChild('vertices')) :
'[]'
).setLabel('Vertices')
);
behaviorProperties.set(

View File

@@ -268,7 +268,7 @@ gdjs.Physics2RuntimeBehavior.prototype.onDeActivate = function() {
}
};
gdjs.Physics2RuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
gdjs.Physics2RuntimeBehavior.prototype.onDestroy = function() {
this.onDeActivate();
};

View File

@@ -81,7 +81,7 @@ std::map<gd::String, gd::PropertyDescriptor> PhysicsBehavior::GetProperties(
gd::String::From(behaviorContent.GetDoubleAttribute("linearDamping")));
properties[_("Angular Damping")].SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("angularDamping")));
properties[_("PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS")].SetValue("");
properties["PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS"].SetValue("");
return properties;
}

View File

@@ -154,7 +154,7 @@ gdjs.PhysicsRuntimeBehavior.prototype.onDeActivate = function() {
}
};
gdjs.PhysicsRuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
gdjs.PhysicsRuntimeBehavior.prototype.onDestroy = function() {
this.onDeActivate();
};

View File

@@ -442,11 +442,16 @@ void PlatformerObjectRuntimeBehavior::DoStepPreEvents(RuntimeScene& scene) {
floorLastX = floorPlatform->GetObject()->GetX();
floorLastY = floorPlatform->GetObject()->GetY();
} else {
// Avoid landing on a platform if the object is not going down.
// (which could happen for a jumpthru, when the object jump and pass just
// at the top of a jumpthru, it could be considered as landing if not for
// this extra check).
bool canLand = requestedDeltaY >= 0;
// Check if landing on a new floor: (Exclude already overlapped jump truh)
std::set<PlatformRuntimeBehavior*> collidingObjects =
GetPlatformsCollidingWith(potentialObjects, overlappedJumpThru);
if (!collidingObjects.empty()) // Just landed on floor
{
if (canLand && !collidingObjects.empty()) { // Just landed on floor
isOnFloor = true;
canJump = true;
jumping = false;
@@ -458,8 +463,7 @@ void PlatformerObjectRuntimeBehavior::DoStepPreEvents(RuntimeScene& scene) {
floorLastY = floorPlatform->GetObject()->GetY();
ReleaseGrabbedPlatform(); // Ensure nothing is grabbed.
} else // In the air
{
} else { // In the air
canJump = false;
isOnFloor = false;
floorPlatform = NULL;
@@ -502,7 +506,8 @@ void PlatformerObjectRuntimeBehavior::ReleaseGrabbedPlatform() {
}
bool PlatformerObjectRuntimeBehavior::SeparateFromPlatforms(
const std::set<PlatformRuntimeBehavior*>& candidates, bool excludeJumpThrus) {
const std::set<PlatformRuntimeBehavior*>& candidates,
bool excludeJumpThrus) {
std::vector<RuntimeObject*> objects;
for (std::set<PlatformRuntimeBehavior*>::iterator it = candidates.begin();
it != candidates.end();

View File

@@ -369,10 +369,15 @@ gdjs.PlatformerObjectRuntimeBehavior.prototype.doStepPreEvents = function(runtim
this._releaseGrabbedPlatform(); //Ensure nothing is grabbed.
}
else{
else {
// Avoid landing on a platform if the object is not going down.
// (which could happen for Jumpthru, when the object jump and pass just at the top
// of a jumpthru, it could be considered as landing if not this this extra check).
var canLand = requestedDeltaY >= 0;
//Check if landing on a new floor: (Exclude already overlapped jump truh)
var collidingPlatform = this._getCollidingPlatform();
if (collidingPlatform !== null) {
if (canLand && collidingPlatform !== null) {
this._isOnFloor = true;
this._canJump = true;
this._jumping = false;

View File

@@ -104,7 +104,7 @@ gdjs.PlatformRuntimeBehavior.LADDER = 2;
gdjs.PlatformRuntimeBehavior.JUMPTHRU = 1;
gdjs.PlatformRuntimeBehavior.NORMALPLAFTORM = 0;
gdjs.PlatformRuntimeBehavior.prototype.onOwnerRemovedFromScene = function() {
gdjs.PlatformRuntimeBehavior.prototype.onDestroy = function() {
if ( this._manager && this._registeredInManager ) this._manager.removePlatform(this);
};

View File

@@ -1,6 +1,6 @@
describe('gdjs.PlatformerObjectRuntimeBehavior', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame, null);
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{name: "", visibility: true}],
variables: [],
@@ -119,9 +119,104 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function() {
});
});
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; };
//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 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);
// 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 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, null);
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{name: "", visibility: true}],
variables: [],

View File

@@ -25,6 +25,9 @@ gdjs.ShapePainterRuntimeObject = function(runtimeScene, objectData)
gdjs.ShapePainterRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
else
this._renderer = new gdjs.ShapePainterRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.ShapePainterRuntimeObject.prototype = Object.create( gdjs.RuntimeObject.prototype );

View File

@@ -28,6 +28,9 @@ gdjs.SkeletonRuntimeObject = function(runtimeScene, objectData){
this.manager = gdjs.SkeletonObjectsManager.getManager(runtimeScene);
this.getSkeletonData(runtimeScene, objectData);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.SkeletonRuntimeObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
gdjs.SkeletonRuntimeObject.thisIsARuntimeObjectConstructor = "SkeletonObject::Skeleton";
@@ -330,7 +333,7 @@ gdjs.SkeletonRuntimeObject.prototype.setSlotZOrder = function(slotPath, z){
gdjs.SkeletonRuntimeObject.prototype.isPointInsideSlot = function(slotPath, x, y){
var hitBoxes = this.getPolygons(slotPath);
if(!hitBoxes) return false;
for(var i = 0; i < this.hitBoxes.length; ++i) {
if ( gdjs.Polygon.isPointInside(hitBoxes[i], x, y) )
return true;
@@ -343,7 +346,7 @@ gdjs.SkeletonRuntimeObject.prototype.isPointInsideSlot = function(slotPath, x, y
gdjs.SkeletonRuntimeObject.prototype.raycastSlot = function(slotPath, x, y, angle, dist, closest){
var result = gdjs.Polygon.raycastTest._statics.result;
result.collision = false;
var endX = x + dist*Math.cos(angle*Math.PI/180.0);
var endY = y + dist*Math.sin(angle*Math.PI/180.0);
var testSqDist = closest ? dist*dist : 0;
@@ -364,7 +367,7 @@ gdjs.SkeletonRuntimeObject.prototype.raycastSlot = function(slotPath, x, y, angl
}
}
}
return result;
};
@@ -433,7 +436,7 @@ gdjs.SkeletonRuntimeObject.prototype.getBone = function(bonePath){
if(slot && slot.type === gdjs.sk.SLOT_ARMATURE && boneName in slot.childArmature.bonesMap){
return slot.childArmature.bonesMap[boneName];
}
return null;
};

View File

@@ -12,7 +12,7 @@ gdjs.TextEntryRuntimeObjectCocosRenderer = function(runtimeObject, runtimeScene)
gdjs.TextEntryRuntimeObjectRenderer = gdjs.TextEntryRuntimeObjectCocosRenderer; //Register the class to let the engine use it.
gdjs.TextEntryRuntimeObjectCocosRenderer.prototype.onOwnerRemovedFromScene = function() {
gdjs.TextEntryRuntimeObjectCocosRenderer.prototype.onDestroy = function() {
this.activate(false);
};

View File

@@ -50,7 +50,7 @@ gdjs.TextEntryRuntimeObjectPixiRenderer = function(runtimeObject)
gdjs.TextEntryRuntimeObjectRenderer = gdjs.TextEntryRuntimeObjectPixiRenderer; //Register the class to let the engine use it.
gdjs.TextEntryRuntimeObjectPixiRenderer.prototype.onOwnerRemovedFromScene = function() {
gdjs.TextEntryRuntimeObjectPixiRenderer.prototype.onDestroy = function() {
document.removeEventListener('keypress', this._pressHandler);
document.removeEventListener('keyup', this._upHandler);
document.removeEventListener('keydown', this._downHandler);

View File

@@ -20,16 +20,19 @@ gdjs.TextEntryRuntimeObject = function(runtimeScene, objectData)
gdjs.TextEntryRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
else
this._renderer = new gdjs.TextEntryRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.TextEntryRuntimeObject.prototype = Object.create( gdjs.RuntimeObject.prototype );
gdjs.TextEntryRuntimeObject.thisIsARuntimeObjectConstructor = "TextEntryObject::TextEntry";
gdjs.TextEntryRuntimeObject.prototype.onDeletedFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
gdjs.TextEntryRuntimeObject.prototype.onDestroyFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
if (this._renderer.onOwnerRemovedFromScene) {
this._renderer.onOwnerRemovedFromScene();
if (this._renderer.onDestroy) {
this._renderer.onDestroy();
}
};

View File

@@ -36,131 +36,275 @@ class TextObjectJsExtension : public gd::PlatformExtension {
GetAllActionsForObject("TextObject::Text")["TextObject::Scale"]
.SetFunctionName("setScale")
.SetGetter("getScale")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleX"]
.SetFunctionName("setScaleX")
.SetGetter("getScaleX")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleX"]
.SetFunctionName("getScaleX")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::ScaleY"]
.SetFunctionName("setScaleY")
.SetGetter("getScaleY")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::ScaleY"]
.SetFunctionName("getScaleY")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::String"]
.SetFunctionName("setString")
.SetGetter("getString")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::String"]
.SetFunctionName("getString")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::Size"]
.SetFunctionName("setCharacterSize")
.SetGetter("getCharacterSize")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::Size"]
.SetFunctionName("getCharacterSize")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::Angle"]
.SetFunctionName("setAngle")
.SetGetter("getAngle")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::Angle"]
.SetFunctionName("getAngle")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::Opacity"]
.SetFunctionName("setOpacity")
.SetGetter("getOpacity")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::Opacity"]
.SetFunctionName("getOpacity")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetBold"]
.SetFunctionName("setBold")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::IsBold"]
.SetFunctionName("isBold")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetItalic"]
.SetFunctionName("setItalic")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::IsItalic"]
.SetFunctionName("isItalic")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetWrapping"]
.SetFunctionName("setWrapping")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::IsWrapping"]
.SetFunctionName("isWrapping")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetPadding"]
.SetFunctionName("setPadding")
.SetGetter("getPadding")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::Padding"]
.SetFunctionName("getPadding")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetTextAlignment"]
.SetFunctionName("setTextAlignment")
.SetGetter("getTextAlignment")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::TextAlignment"]
.SetFunctionName("getTextAlignment")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::WrappingWidth"]
.SetFunctionName("setWrappingWidth")
.SetGetter("getWrappingWidth")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllConditionsForObject("TextObject::Text")["TextObject::WrappingWidth"]
.SetFunctionName("getWrappingWidth")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllExpressionsForObject("TextObject::Text")["Padding"]
.SetFunctionName("getPadding")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllExpressionsForObject("TextObject::Text")["ScaleX"]
.SetFunctionName("getScaleX")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllExpressionsForObject("TextObject::Text")["ScaleY"]
.SetFunctionName("getScaleY")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllExpressionsForObject("TextObject::Text")["Opacity"]
.SetFunctionName("getOpacity")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllExpressionsForObject("TextObject::Text")["Angle"]
.SetFunctionName("getAngle")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllStrExpressionsForObject("TextObject::Text")["String"]
.SetFunctionName("getString")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::ChangeColor"]
.SetFunctionName("setColor")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetGradient"]
.SetFunctionName("setGradient")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetOutline"]
.SetFunctionName("setOutline")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::SetShadow"]
.SetFunctionName("setShadow")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
GetAllActionsForObject("TextObject::Text")["TextObject::ShowShadow"]
.SetFunctionName("showShadow")
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js");
.SetIncludeFile("Extensions/TextObject/textruntimeobject.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-pixi-renderer.js")
.AddIncludeFile(
"Extensions/TextObject/textruntimeobject-cocos-renderer.js");
// Unimplemented actions and conditions:
GetAllActionsForObject("TextObject::Text")["TextObject::Font"]

View File

@@ -35,9 +35,9 @@ TextObject::TextObject(gd::String name_)
bold(false),
italic(false),
underlined(false),
colorR(255),
colorG(255),
colorB(255)
colorR(0),
colorG(0),
colorB(0)
{
}
@@ -274,7 +274,7 @@ bool RuntimeTextObject::ChangeProperty(std::size_t propertyNb,
} else if (propertyNb == 1) {
ChangeFont(newValue);
} else if (propertyNb == 2) {
SetCharacterSize(newValue.To<int>());
SetCharacterSize(std::max(1, newValue.To<int>()));
} else if (propertyNb == 3) {
gd::String r, gb, g, b;
{
@@ -297,7 +297,7 @@ bool RuntimeTextObject::ChangeProperty(std::size_t propertyNb,
SetColor(r.To<int>(), g.To<int>(), b.To<int>());
} else if (propertyNb == 4) {
SetOpacity(newValue.To<float>());
SetOpacity(std::min(std::max(0.0f, newValue.To<float>()), 255.0f));
} else if (propertyNb == 5) {
SetSmooth(!(newValue == _("No")));
}

View File

@@ -69,6 +69,9 @@ gdjs.TextRuntimeObjectPixiRenderer.prototype.updateStyle = function() {
style.dropShadowAngle = this._object._shadowAngle;
style.dropShadowDistance = this._object._shadowDistance;
style.padding = this._object._padding;
// Prevent spikey outlines by adding a miter limit
style.miterLimit = 3;
this.updatePosition();
// Manually ask the PIXI object to re-render as we changed a style property

View File

@@ -14,7 +14,7 @@ gdjs.TextRuntimeObject = function(runtimeScene, objectData)
{
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
this._characterSize = objectData.characterSize;
this._characterSize = Math.max(1, objectData.characterSize);
this._fontName = objectData.font;
this._bold = objectData.bold;
this._italic = objectData.italic;
@@ -44,6 +44,9 @@ gdjs.TextRuntimeObject = function(runtimeScene, objectData)
gdjs.TextRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
else
this._renderer = new gdjs.TextRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.TextRuntimeObject.prototype = Object.create( gdjs.RuntimeObject.prototype );
@@ -206,7 +209,7 @@ gdjs.TextRuntimeObject.prototype.getHeight = function() {
* Get scale of the text.
*/
gdjs.TextRuntimeObject.prototype.getScale = function() {
return (Math.abs(this._scaleX)+Math.abs(this._scaleY))/2.0;
return (Math.abs(this._scaleX)+Math.abs(this._scaleY))/2.0;
};
/**
@@ -413,7 +416,7 @@ gdjs.TextRuntimeObject.prototype.setGradient = function(strGradientType, strFirs
this._gradientType = strGradientType;
this._useGradient = (this._gradient.length > 1) ? true : false;
this._useGradient = (this._gradient.length > 1) ? true : false;
this._renderer.updateStyle();
};

View File

@@ -23,7 +23,7 @@ gdjs.TiledSpriteRuntimeObjectCocosRenderer = function(runtimeObject, runtimeScen
gdjs.TiledSpriteRuntimeObjectRenderer = gdjs.TiledSpriteRuntimeObjectCocosRenderer; //Register the class to let the engine use it.
gdjs.TiledSpriteRuntimeObjectCocosRenderer.prototype.onOwnerRemovedFromScene = function() {
gdjs.TiledSpriteRuntimeObjectCocosRenderer.prototype.onDestroy = function() {
if (this._shader) this._shader.release();
}

View File

@@ -24,6 +24,9 @@ gdjs.TiledSpriteRuntimeObject = function(runtimeScene, objectData)
this.setWidth(objectData.width);
this.setHeight(objectData.height);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.TiledSpriteRuntimeObject.prototype = Object.create( gdjs.RuntimeObject.prototype );
@@ -33,11 +36,11 @@ gdjs.TiledSpriteRuntimeObject.prototype.getRendererObject = function() {
return this._renderer.getRendererObject();
};
gdjs.TiledSpriteRuntimeObject.prototype.onDeletedFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
gdjs.TiledSpriteRuntimeObject.prototype.onDestroyFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
if (this._renderer.onOwnerRemovedFromScene) {
this._renderer.onOwnerRemovedFromScene();
if (this._renderer.onDestroy) {
this._renderer.onDestroy();
}
};
@@ -187,6 +190,6 @@ gdjs.TiledSpriteRuntimeObject.prototype.setColor = function(rgbColor) {
*
* @returns {string} rgbColor The color, in RGB format ("128;200;255").
*/
gdjs.SpriTiledSpriteRuntimeObjectteRuntimeObject.prototype.getColor = function() {
gdjs.TiledSpriteRuntimeObject.prototype.getColor = function() {
return this._renderer.getColor();
};
};

View File

@@ -5,7 +5,7 @@
* @param {Object} behaviorData The data to initialize the behavior
* @param {gdjs.RuntimeObject} owner The runtime object the behavior belongs to.
*/
gdjs.TweenRuntimeBehavior = function(runtimeScene, behaviorData, owner) {
gdjs.TweenRuntimeBehavior = function (runtimeScene, behaviorData, owner) {
gdjs.RuntimeBehavior.call(this, runtimeScene, behaviorData, owner);
/** @type Object.<string, gdjs.TweenRuntimeBehavior.TweenInstance > */
@@ -66,7 +66,7 @@ gdjs.TweenRuntimeBehavior.easings = [
* @param {number} startTime The time at which the tween starts
* @param {number} totalDuration The time of the whole tween
*/
gdjs.TweenRuntimeBehavior.TweenInstance = function(
gdjs.TweenRuntimeBehavior.TweenInstance = function (
instance,
hasFinished,
startTime,
@@ -79,7 +79,7 @@ gdjs.TweenRuntimeBehavior.TweenInstance = function(
this.resumeOnActivate = false;
};
gdjs.TweenRuntimeBehavior.prototype._addTween = function(
gdjs.TweenRuntimeBehavior.prototype._addTween = function (
identifier,
instance,
startTime,
@@ -93,19 +93,19 @@ gdjs.TweenRuntimeBehavior.prototype._addTween = function(
);
};
gdjs.TweenRuntimeBehavior.prototype._getTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._getTween = function (identifier) {
return this._tweens[identifier];
};
gdjs.TweenRuntimeBehavior.prototype._tweenExists = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._tweenExists = function (identifier) {
return !!this._tweens[identifier];
};
gdjs.TweenRuntimeBehavior.prototype._tweenIsPlaying = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._tweenIsPlaying = function (identifier) {
return this._tweens[identifier].instance.isPlaying();
};
gdjs.TweenRuntimeBehavior.prototype._pauseTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._pauseTween = function (identifier) {
var tween = this._tweens[identifier];
// Pause the tween, and remove it from the scene of living tweens
@@ -116,12 +116,12 @@ gdjs.TweenRuntimeBehavior.prototype._pauseTween = function(identifier) {
}
};
gdjs.TweenRuntimeBehavior.prototype._resumeTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._resumeTween = function (identifier) {
var tween = this._tweens[identifier];
// Resume the tween, and add it back to the scene of living tweens
// (the invariant is that scene only contains tweens being played).
tween.instance.resume().catch(() => {
tween.instance.resume().catch(function () {
// Do nothing if the Promise is rejected. Rejection is used
// by Shifty.js to signal that the tween was not finished.
// We catch it to avoid an uncaught promise error, and to
@@ -132,32 +132,32 @@ gdjs.TweenRuntimeBehavior.prototype._resumeTween = function(identifier) {
}
};
gdjs.TweenRuntimeBehavior.prototype._stopTween = function(
gdjs.TweenRuntimeBehavior.prototype._stopTween = function (
identifier,
jumpToDest
) {
return this._tweens[identifier].instance.stop(jumpToDest);
};
gdjs.TweenRuntimeBehavior.prototype._setTweenFinished = function(
gdjs.TweenRuntimeBehavior.prototype._setTweenFinished = function (
identifier,
hasFinished
) {
this._tweens[identifier].hasFinished = hasFinished;
};
gdjs.TweenRuntimeBehavior.prototype._tweenHasFinished = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._tweenHasFinished = function (identifier) {
return this._tweens[identifier].hasFinished;
};
gdjs.TweenRuntimeBehavior.prototype._removeObjectFromScene = function(
gdjs.TweenRuntimeBehavior.prototype._removeObjectFromScene = function (
identifier
) {
this._removeTween(identifier);
return this.owner.deleteFromScene(this._runtimeScene);
};
gdjs.TweenRuntimeBehavior.prototype._removeTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype._removeTween = function (identifier) {
if (!this._tweens[identifier]) return;
this._tweens[identifier].instance.stop();
@@ -168,23 +168,24 @@ gdjs.TweenRuntimeBehavior.prototype._removeTween = function(identifier) {
delete this._tweens[identifier];
};
gdjs.TweenRuntimeBehavior.prototype._setupTweenEnding = function(
gdjs.TweenRuntimeBehavior.prototype._setupTweenEnding = function (
identifier,
destroyObjectWhenFinished
) {
var that = this;
if (destroyObjectWhenFinished) {
this._tweens[identifier].instance
.tween()
.catch(() => {
.catch(function () {
// Do nothing if the Promise is rejected. Rejection is used
// by Shifty.js to signal that the tween was not finished.
// We catch it to avoid an uncaught promise error, and to
// ensure that the content of the "then" is always applied:
})
.then(() => {
this._removeObjectFromScene(identifier);
.then(function () {
that._removeObjectFromScene(identifier);
})
.catch(() => {
.catch(function () {
// Do nothing if the Promise is rejected. Rejection is used
// by Shifty.js to signal that the tween was not finished.
// We catch it to avoid an uncaught promise error, and to
@@ -193,18 +194,18 @@ gdjs.TweenRuntimeBehavior.prototype._setupTweenEnding = function(
} else {
this._tweens[identifier].instance
.tween()
.catch(() => {
.catch(function () {
// Do nothing if the Promise is rejected. Rejection is used
// by Shifty.js to signal that the tween was not finished.
// We catch it to avoid an uncaught promise error, and to
// ensure that the content of the "then" is always applied:
})
.then(() => {
if (this._tweens[identifier]) {
this._tweens[identifier].hasFinished = true;
.then(function () {
if (that._tweens[identifier]) {
that._tweens[identifier].hasFinished = true;
}
})
.catch(() => {
.catch(function () {
// Do nothing if the Promise is rejected. Rejection is used
// by Shifty.js to signal that the tween was not finished.
// We catch it to avoid an uncaught promise error, and to
@@ -223,7 +224,7 @@ gdjs.TweenRuntimeBehavior.prototype._setupTweenEnding = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addVariableTween = function(
gdjs.TweenRuntimeBehavior.prototype.addVariableTween = function (
identifier,
variable,
fromValue,
@@ -252,7 +253,7 @@ gdjs.TweenRuntimeBehavior.prototype.addVariableTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
step: function step(state) {
variable.setNumber(state.value);
}
});
@@ -276,7 +277,7 @@ gdjs.TweenRuntimeBehavior.prototype.addVariableTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function (
identifier,
toX,
toY,
@@ -284,6 +285,7 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function(
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
@@ -305,9 +307,9 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setX(state.x);
this.owner.setY(state.y);
step: function step(state) {
that.owner.setX(state.x);
that.owner.setY(state.y);
}
});
@@ -329,13 +331,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionXTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionXTween = function (
identifier,
toX,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
@@ -355,8 +358,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionXTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setX(state.x);
step: function step(state) {
that.owner.setX(state.x);
}
});
@@ -378,13 +381,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionXTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionYTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectPositionYTween = function (
identifier,
toY,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
@@ -404,8 +408,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionYTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setY(state.y);
step: function step(state) {
that.owner.setY(state.y);
}
});
@@ -427,13 +431,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectPositionYTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectAngleTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectAngleTween = function (
identifier,
toAngle,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!!gdjs.TweenRuntimeBehavior.easings[easingValue]) return;
@@ -453,8 +458,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectAngleTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setAngle(state.angle);
step: function step(state) {
that.owner.setAngle(state.angle);
}
});
@@ -477,7 +482,7 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectAngleTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function (
identifier,
toScaleX,
toScaleY,
@@ -485,6 +490,7 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function(
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.setScaleX || !this.owner.setScaleY) return;
@@ -511,9 +517,9 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setScaleX(state.scaleX);
this.owner.setScaleY(state.scaleY);
step: function step(state) {
that.owner.setScaleX(state.scaleX);
that.owner.setScaleY(state.scaleY);
}
});
@@ -535,13 +541,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleXTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleXTween = function (
identifier,
toScaleX,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.setScaleX) return;
@@ -563,8 +570,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleXTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setScaleX(state.scaleX);
step: function step(state) {
that.owner.setScaleX(state.scaleX);
}
});
@@ -586,13 +593,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleXTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleYTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectScaleYTween = function (
identifier,
toScaleY,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.setScaleY) return;
@@ -614,8 +622,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleYTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setScaleY(state.scaleY);
step: function step(state) {
that.owner.setScaleY(state.scaleY);
}
});
@@ -637,13 +645,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectScaleYTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectOpacityTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectOpacityTween = function (
identifier,
toOpacity,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.getOpacity || !this.owner.setOpacity) return;
@@ -665,8 +674,8 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectOpacityTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setOpacity(state.opacity);
step: function step(state) {
that.owner.setOpacity(state.opacity);
}
});
@@ -688,13 +697,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectOpacityTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addObjectColorTween = function(
gdjs.TweenRuntimeBehavior.prototype.addObjectColorTween = function (
identifier,
toColor,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.getColor || !this.owner.setColor) return;
if (
@@ -730,13 +740,13 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectColorTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setColor(
step: function step(state) {
that.owner.setColor(
Math.floor(state.red) +
";" +
Math.floor(state.green) +
";" +
Math.floor(state.blue)
";" +
Math.floor(state.green) +
";" +
Math.floor(state.blue)
);
}
});
@@ -759,13 +769,14 @@ gdjs.TweenRuntimeBehavior.prototype.addObjectColorTween = function(
* @param {number} durationValue Duration in milliseconds
* @param {boolean} destroyObjectWhenFinished Destroy this object when the tween ends
*/
gdjs.TweenRuntimeBehavior.prototype.addTextObjectCharacterSizeTween = function(
gdjs.TweenRuntimeBehavior.prototype.addTextObjectCharacterSizeTween = function (
identifier,
toSize,
easingValue,
durationValue,
destroyObjectWhenFinished
) {
var that = this;
if (!this._isActive) return;
if (!this.owner.setCharacterSize) return;
@@ -787,8 +798,8 @@ gdjs.TweenRuntimeBehavior.prototype.addTextObjectCharacterSizeTween = function(
},
duration: durationValue,
easing: easingValue,
step: state => {
this.owner.setCharacterSize(state.size);
step: function step(state) {
that.owner.setCharacterSize(state.size);
}
});
@@ -806,7 +817,7 @@ gdjs.TweenRuntimeBehavior.prototype.addTextObjectCharacterSizeTween = function(
* Tween is playing.
* @param {string} identifier Unique id to idenfify the tween
*/
gdjs.TweenRuntimeBehavior.prototype.isPlaying = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.isPlaying = function (identifier) {
if (this._tweenExists(identifier) && this._tweenIsPlaying(identifier)) {
return true;
} else {
@@ -819,7 +830,7 @@ gdjs.TweenRuntimeBehavior.prototype.isPlaying = function(identifier) {
* @param {string} identifier Unique id to idenfify the tween
* @returns {boolean} The tween exists
*/
gdjs.TweenRuntimeBehavior.prototype.exists = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.exists = function (identifier) {
return this._tweenExists(identifier);
};
@@ -827,7 +838,7 @@ gdjs.TweenRuntimeBehavior.prototype.exists = function(identifier) {
* Tween has finished.
* @param {string} identifier Unique id to idenfify the tween
*/
gdjs.TweenRuntimeBehavior.prototype.hasFinished = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.hasFinished = function (identifier) {
if (this._tweenExists(identifier)) {
return this._tweenHasFinished(identifier);
} else {
@@ -839,7 +850,7 @@ gdjs.TweenRuntimeBehavior.prototype.hasFinished = function(identifier) {
* Pause a tween.
* @param {string} identifier Unique id to idenfify the tween
*/
gdjs.TweenRuntimeBehavior.prototype.pauseTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.pauseTween = function (identifier) {
if (!this._isActive) return;
if (this._tweenExists(identifier) && this._tweenIsPlaying(identifier)) {
@@ -852,7 +863,7 @@ gdjs.TweenRuntimeBehavior.prototype.pauseTween = function(identifier) {
* @param {string} identifier Unique id to idenfify the tween
* @param {boolean} jumpToDest Move to destination
*/
gdjs.TweenRuntimeBehavior.prototype.stopTween = function(
gdjs.TweenRuntimeBehavior.prototype.stopTween = function (
identifier,
jumpToDest
) {
@@ -867,7 +878,7 @@ gdjs.TweenRuntimeBehavior.prototype.stopTween = function(
* Resume a tween.
* @param {string} identifier Unique id to idenfify the tween
*/
gdjs.TweenRuntimeBehavior.prototype.resumeTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.resumeTween = function (identifier) {
if (!this._isActive) return;
if (this._tweenExists(identifier) && !this._tweenIsPlaying(identifier)) {
@@ -879,7 +890,7 @@ gdjs.TweenRuntimeBehavior.prototype.resumeTween = function(identifier) {
* Remove a tween.
* @param {string} identifierFirst Unique id to idenfify the tween
*/
gdjs.TweenRuntimeBehavior.prototype.removeTween = function(identifier) {
gdjs.TweenRuntimeBehavior.prototype.removeTween = function (identifier) {
this._removeTween(identifier);
};
@@ -888,8 +899,8 @@ gdjs.TweenRuntimeBehavior.prototype.removeTween = function(identifier) {
* @param {string} identifier Unique id to idenfify the tween
* @returns {boolean} Progress of playing tween animation (between 0.0 and 1.0)
*/
gdjs.TweenRuntimeBehavior.prototype.getProgress = function(identifier) {
const tween = this._getTween(identifier);
gdjs.TweenRuntimeBehavior.prototype.getProgress = function (identifier) {
var tween = this._getTween(identifier);
if (tween) {
var currentTime = this._runtimeScene.getTimeManager().getTimeFromStart();
if (currentTime >= tween.startTime + tween.totalDuration) return 1;
@@ -900,12 +911,12 @@ gdjs.TweenRuntimeBehavior.prototype.getProgress = function(identifier) {
}
};
gdjs.TweenRuntimeBehavior.prototype.onDeActivate = function() {
gdjs.TweenRuntimeBehavior.prototype.onDeActivate = function () {
if (!this._isActive) return;
for (const key in this._tweens) {
for (var key in this._tweens) {
if (this._tweens.hasOwnProperty(key)) {
const tween = this._tweens[key];
var tween = this._tweens[key];
if (tween.instance.isPlaying()) {
tween.resumeOnActivate = true;
@@ -916,12 +927,12 @@ gdjs.TweenRuntimeBehavior.prototype.onDeActivate = function() {
this._isActive = false;
};
gdjs.TweenRuntimeBehavior.prototype.onActivate = function() {
gdjs.TweenRuntimeBehavior.prototype.onActivate = function () {
if (this._isActive) return;
for (const key in this._tweens) {
for (var key in this._tweens) {
if (this._tweens.hasOwnProperty(key)) {
const tween = this._tweens[key];
var tween = this._tweens[key];
if (tween.resumeOnActivate) {
tween.resumeOnActivate = false;
@@ -940,7 +951,7 @@ gdjs.TweenRuntimeBehavior.prototype.onActivate = function() {
* @param {gdjs.RuntimeScene} runtimeScene
* @returns {shifty.Tweenable} The new tweenable
*/
gdjs.TweenRuntimeBehavior.makeNewTweenable = function(runtimeScene) {
gdjs.TweenRuntimeBehavior.makeNewTweenable = function (runtimeScene) {
if (!runtimeScene.shiftyJsScene) {
runtimeScene.shiftyJsScene = new shifty.Scene();
}
@@ -956,7 +967,7 @@ gdjs.TweenRuntimeBehavior.makeNewTweenable = function(runtimeScene) {
* @param {gdjs.RuntimeScene} runtimeScene
* @param {shifty.Tweenable} tweenable
*/
gdjs.TweenRuntimeBehavior.removeFromScene = function(runtimeScene, tweenable) {
gdjs.TweenRuntimeBehavior.removeFromScene = function (runtimeScene, tweenable) {
if (!runtimeScene.shiftyJsScene) return;
runtimeScene.shiftyJsScene.remove(tweenable);
@@ -969,7 +980,7 @@ gdjs.TweenRuntimeBehavior.removeFromScene = function(runtimeScene, tweenable) {
* Stop and "destroy" all the tweens when a scene is unloaded.
* @private
*/
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneUnloaded = function(
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneUnloaded = function (
runtimeScene
) {
if (!runtimeScene.shiftyJsScene) return;
@@ -986,7 +997,7 @@ gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneUnloaded = function(
* When a scene is paused, pause all the tweens of this scene.
* @private
*/
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeScenePaused = function(
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeScenePaused = function (
runtimeScene
) {
if (!runtimeScene.shiftyJsScene) return;
@@ -998,7 +1009,7 @@ gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeScenePaused = function(
* When a scene is paused, resume all the tweens of this scene.
* @private
*/
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneResumed = function(
gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneResumed = function (
runtimeScene
) {
if (!runtimeScene.shiftyJsScene) return;
@@ -1021,7 +1032,7 @@ gdjs.TweenRuntimeBehavior.gdjsCallbackRuntimeSceneResumed = function(
gdjs.TweenRuntimeBehavior._tweensProcessed = false;
gdjs.TweenRuntimeBehavior._currentTweenTime = 0;
gdjs.TweenRuntimeBehavior.prototype.doStepPreEvents = function(runtimeScene) {
gdjs.TweenRuntimeBehavior.prototype.doStepPreEvents = function (runtimeScene) {
// Process tweens (once per frame).
if (!gdjs.TweenRuntimeBehavior._tweensProcessed) {
gdjs.TweenRuntimeBehavior._currentTweenTime = runtimeScene
@@ -1032,19 +1043,19 @@ gdjs.TweenRuntimeBehavior.prototype.doStepPreEvents = function(runtimeScene) {
}
};
gdjs.TweenRuntimeBehavior.prototype.doStepPostEvents = function(runtimeScene) {
gdjs.TweenRuntimeBehavior.prototype.doStepPostEvents = function (runtimeScene) {
gdjs.TweenRuntimeBehavior._tweensProcessed = false;
};
// Set up Shifty.js so that the processing ("tick"/updates) is handled
// by the behavior (once per frame):
shifty.Tweenable.setScheduleFunction(function() {
shifty.Tweenable.setScheduleFunction(function () {
/* Do nothing, we'll call processTweens manually. */
});
// Set up Shifty.js so that the time is handled by the behavior.
// It will be set to be the time of the current scene, and should be updated
// before any tween processing (processTweens, resume).
shifty.Tweenable.now = function() {
shifty.Tweenable.now = function () {
return gdjs.TweenRuntimeBehavior._currentTweenTime;
};

View File

@@ -17,7 +17,7 @@ gdjs.VideoRuntimeObjectCocosRenderer.prototype.getRendererObject = function() {}
/**
* To be called when the object is removed from the scene: will pause the video.
*/
gdjs.VideoRuntimeObjectCocosRenderer.prototype.onOwnerRemovedFromScene = function() {};
gdjs.VideoRuntimeObjectCocosRenderer.prototype.onDestroy = function() {};
gdjs.VideoRuntimeObjectCocosRenderer.prototype.ensureUpToDate = function() {};

View File

@@ -21,6 +21,12 @@ gdjs.VideoRuntimeObjectPixiRenderer = function(runtimeObject, runtimeScene) {
} else {
this._pixiObject._texture.baseTexture.source.currentTime = 0;
}
// Needed to avoid video not playing/crashing in Chrome/Chromium browsers.
// See https://github.com/pixijs/pixi.js/issues/5996
this._pixiObject._texture.baseTexture.source.preload = "auto";
this._pixiObject._texture.baseTexture.source.autoload = true;
this._textureWasValid = false; // Will be set to true when video texture is loaded.
runtimeScene
@@ -49,7 +55,7 @@ gdjs.VideoRuntimeObjectPixiRenderer.prototype.getRendererObject = function() {
/**
* To be called when the object is removed from the scene: will pause the video.
*/
gdjs.VideoRuntimeObjectPixiRenderer.prototype.onOwnerRemovedFromScene = function() {
gdjs.VideoRuntimeObjectPixiRenderer.prototype.onDestroy = function() {
this.pause();
};
@@ -132,7 +138,7 @@ gdjs.VideoRuntimeObjectPixiRenderer.prototype._getHTMLVideoElementSource = funct
}
return source;
}
};
/**
* Start the video
@@ -247,10 +253,7 @@ gdjs.VideoRuntimeObjectPixiRenderer.prototype.isPlayed = function() {
var source = this._getHTMLVideoElementSource();
if (!source) return false;
return (
!source.paused &&
!source.ended
);
return !source.paused && !source.ended;
};
/**

View File

@@ -30,6 +30,9 @@ gdjs.VideoRuntimeObject = function(runtimeScene, objectData) {
if (this._renderer)
gdjs.VideoRuntimeObjectRenderer.call(this._renderer, this, runtimeScene);
else this._renderer = new gdjs.VideoRuntimeObjectRenderer(this, runtimeScene);
// *ALWAYS* call `this.onCreated()` at the very end of your object constructor.
this.onCreated();
};
gdjs.VideoRuntimeObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
@@ -52,10 +55,10 @@ gdjs.VideoRuntimeObject.prototype.extraInitializationFromInitialInstance = funct
}
};
gdjs.VideoRuntimeObject.prototype.onDeletedFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
gdjs.VideoRuntimeObject.prototype.onDestroyFromScene = function(runtimeScene) {
gdjs.RuntimeObject.prototype.onDestroyFromScene.call(this, runtimeScene);
this._renderer.onOwnerRemovedFromScene();
this._renderer.onDestroy();
};
gdjs.VideoRuntimeObject.prototype.update = function(runtimeScene) {
@@ -234,7 +237,7 @@ gdjs.VideoRuntimeObject.prototype.getDuration = function() {
* Check if the video has ended.
*/
gdjs.VideoRuntimeObject.prototype.isEnded = function() {
return !this._renderer.isEnded();
return this._renderer.isEnded();
};
/**

View File

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

View File

@@ -76,6 +76,14 @@ int GD_API GetMouseWheelDelta(RuntimeScene &scene) {
return scene.GetInputManager().GetMouseWheelDelta();
}
bool GD_API IsMouseWheelScrollingUp(RuntimeScene &scene) {
return scene.GetInputManager().IsScrollingUp();
}
bool GD_API IsMouseWheelScrollingDown(RuntimeScene &scene) {
return scene.GetInputManager().IsScrollingDown();
}
bool GD_API CursorOnObject(
std::map<gd::String, std::vector<RuntimeObject *> *> objectsLists,
RuntimeScene &scene,

View File

@@ -24,6 +24,8 @@ double GD_API GetCursorYPosition(RuntimeScene &scene,
bool GD_API MouseButtonPressed(RuntimeScene &scene, const gd::String &key);
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,

View File

@@ -116,6 +116,18 @@ int InputManager::GetMouseWheelDelta() const {
return mouseWheelDelta;
}
bool InputManager::IsScrollingUp() const {
if (!windowHasFocus && disableInputWhenNotFocused) return false;
return mouseWheelDelta > 0;
}
bool InputManager::IsScrollingDown() const {
if (!windowHasFocus && disableInputWhenNotFocused) return false;
return mouseWheelDelta < 0;
}
const std::map<gd::String, int>& InputManager::GetKeyNameToSfKeyMap() {
static bool initialized = false;
static std::map<gd::String, int>* map = new std::map<gd::String, int>();

View File

@@ -130,6 +130,16 @@ class GD_API InputManager {
*/
int GetMouseWheelDelta() const;
/**
* @brief Return true is mouse wheel scroll up.
*/
bool IsScrollingUp() const;
/**
* @brief Return true is mouse wheel scroll down.
*/
bool IsScrollingDown() const;
static const std::map<gd::String, int>& GetButtonNameToSfButtonMap();
static const std::map<int, gd::String>& GetSfButtonToButtonNameMap();
///@}

View File

@@ -65,6 +65,14 @@ gd::String BehaviorCodeGenerator::GenerateRuntimeBehaviorCompleteCode(
methodFullyQualifiedName,
includeFiles,
compilationForRuntime);
// Compatibility with GD <= 5.0 beta 75
if (functionName == "onOwnerRemovedFromScene") {
runtimeBehaviorMethodsCode +=
GenerateBehaviorOnDestroyToDeprecatedOnOwnerRemovedFromScene(
eventsBasedBehavior, codeNamespace);
}
// end of compatibility code
}
return runtimeBehaviorMethodsCode;
@@ -94,8 +102,6 @@ CODE_NAMESPACE.RUNTIME_BEHAVIOR_CLASSNAME = function(runtimeScene, behaviorData,
this._behaviorData = {};
INITIALIZE_PROPERTIES_CODE
if (this.onCreated) { this.onCreated(); }
};
CODE_NAMESPACE.RUNTIME_BEHAVIOR_CLASSNAME.prototype = Object.create( gdjs.RuntimeBehavior.prototype );
@@ -174,4 +180,18 @@ gd::String BehaviorCodeGenerator::GeneratePropertyValueCode(
return "0 /* Error: property was of an unrecognized type */";
}
gd::String BehaviorCodeGenerator::
GenerateBehaviorOnDestroyToDeprecatedOnOwnerRemovedFromScene(
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& codeNamespace) {
return gd::String(R"jscode_template(
CODE_NAMESPACE.RUNTIME_BEHAVIOR_CLASSNAME.prototype.onDestroy = function() {
// Redirect call to onOwnerRemovedFromScene (the old name of onDestroy)
if (this.onOwnerRemovedFromScene) this.onOwnerRemovedFromScene();
};)jscode_template")
.FindAndReplace("RUNTIME_BEHAVIOR_CLASSNAME",
eventsBasedBehavior.GetName())
.FindAndReplace("CODE_NAMESPACE", codeNamespace);
}
} // namespace gdjs

View File

@@ -56,6 +56,7 @@ class BehaviorCodeGenerator {
return "_set" + propertyName;
}
private:
gd::String GenerateRuntimeBehaviorTemplateCode(
const gd::String& extensionName,
@@ -73,6 +74,9 @@ class BehaviorCodeGenerator {
gd::String GenerateInitializePropertyFromDefaultValueCode(
const gd::NamedPropertyDescriptor& property);
gd::String GeneratePropertyValueCode(const gd::PropertyDescriptor& property);
gd::String GenerateBehaviorOnDestroyToDeprecatedOnOwnerRemovedFromScene(
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& codeNamespace);
gd::Project& project;
};

View File

@@ -158,8 +158,9 @@ gd::String EventsCodeGenerator::GenerateBehaviorEventsFunctionCode(
// it from the behavior
gd::String("var runtimeScene = this._runtimeScene;\n") +
// By convention of Behavior Events Function, the object is accessible
// as a parameter called "Object", and thisObjectList is an array containing it
// (for faster access, without having to go through the hashmap).
// as a parameter called "Object", and thisObjectList is an array
// containing it (for faster access, without having to go through the
// hashmap).
"var thisObjectList = [this.owner];\n" +
"var Object = Hashtable.newFrom({Object: thisObjectList});\n" +
// By convention of Behavior Events Function, the behavior is accessible
@@ -249,9 +250,10 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionContext(
}
}
// If we have an object considered as the current object ("this") (usually called
// Object in behavior events function), generate a slightly more optimized getter
// for it (bypassing "Object" hashmap, and directly return the array containing it).
// If we have an object considered as the current object ("this") (usually
// called Object in behavior events function), generate a slightly more
// optimized getter for it (bypassing "Object" hashmap, and directly return
// the array containing it).
gd::String thisObjectGetterCode =
thisObjectName.empty()
? ""
@@ -275,6 +277,11 @@ gd::String EventsCodeGenerator::GenerateEventsFunctionContext(
" return objectsList ? gdjs.objectsListsToArray(objectsList) : "
"[];\n"
" },\n" +
// Function that can be used in JS code to get the lists of objects
// and filter/alter them.
" getObjectsLists: function(objectName) {\n" +
" return eventsFunctionContext._objectsMap[objectName] || null;\n"
" },\n" +
// Function that will be used to query behavior name (as behavior name
// can be different between the parameter name vs the actual behavior
// name passed as argument).

View File

@@ -65,6 +65,10 @@ CameraExtension::CameraExtension() {
GetAllActions()["SetLayerEffectParameter"].SetFunctionName(
"gdjs.evtTools.camera.setLayerEffectParameter");
GetAllActions()["EnableLayerEffect"].SetFunctionName(
"gdjs.evtTools.camera.enableLayerEffect");
GetAllConditions()["LayerEffectEnabled"].SetFunctionName(
"gdjs.evtTools.camera.layerEffectEnabled");
GetAllConditions()["LayerTimeScale"].SetFunctionName(
"gdjs.evtTools.camera.getLayerTimeScale");

View File

@@ -32,6 +32,11 @@ MouseExtension::MouseExtension() {
GetAllActions()["TouchSimulateMouse"].SetFunctionName(
"gdjs.evtTools.input.touchSimulateMouse");
GetAllConditions()["IsMouseWheelScrollingUp"].SetFunctionName(
"gdjs.evtTools.input.isScrollingUp");
GetAllConditions()["IsMouseWheelScrollingDown"].SetFunctionName(
"gdjs.evtTools.input.isScrollingDown");
GetAllConditions()["SourisSurObjet"].SetFunctionName(
"gdjs.evtTools.input.cursorOnObject");
@@ -61,6 +66,9 @@ MouseExtension::MouseExtension() {
GetAllExpressions()["LastEndedTouchId"].SetFunctionName(
"gdjs.evtTools.input.getLastEndedTouchId");
GetAllExpressions()["MouseWheelDelta"].SetFunctionName(
"gdjs.evtTools.input.getMouseWheelDelta");
StripUnimplementedInstructionsAndExpressions(); // Unimplemented things are
// listed here:
}

View File

@@ -73,15 +73,13 @@ bool Exporter::ExportWholePixiProject(
if (exportForFacebookInstantGames)
exportedProject.GetLoadingScreen().ShowGDevelopSplash(false);
wxProgressDialog* progressDialogPtr = NULL;
// Prepare the export directory
fs.MkDir(exportDir);
std::vector<gd::String> includesFiles;
// Export the resources (before generating events as some resources
// filenames may be updated)
helper.ExportResources(fs, exportedProject, exportDir, progressDialogPtr);
helper.ExportResources(fs, exportedProject, exportDir);
// Export engine libraries
helper.AddLibsInclude(true, false, false, includesFiles);
@@ -173,7 +171,7 @@ bool Exporter::ExportWholeCocos2dProject(gd::Project& project,
// Export the resources (before generating events as some resources filenames
// may be updated)
helper.ExportResources(
fs, exportedProject, exportDir + "/res", progressDialogPtr);
fs, exportedProject, exportDir + "/res");
// Export engine libraries
helper.AddLibsInclude(false, true, false, includesFiles);

View File

@@ -499,6 +499,7 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
InsertUnique(includesFiles, "libs/hshg.js");
InsertUnique(includesFiles, "libs/rbush.js");
InsertUnique(includesFiles, "inputmanager.js");
InsertUnique(includesFiles, "jsonmanager.js");
InsertUnique(includesFiles, "timemanager.js");
InsertUnique(includesFiles, "runtimeobject.js");
InsertUnique(includesFiles, "profiler.js");
@@ -693,10 +694,9 @@ bool ExporterHelper::ExportIncludesAndLibs(
void ExporterHelper::ExportResources(gd::AbstractFileSystem &fs,
gd::Project &project,
gd::String exportDir,
wxProgressDialog *progressDialog) {
gd::String exportDir) {
gd::ProjectResourcesCopier::CopyAllResourcesTo(
project, fs, exportDir, true, progressDialog, false, false);
project, fs, exportDir, true, false, false);
}
} // namespace gdjs

View File

@@ -62,8 +62,7 @@ class ExporterHelper {
*/
static void ExportResources(gd::AbstractFileSystem &fs,
gd::Project &project,
gd::String exportDir,
wxProgressDialog *progressDlg = NULL);
gd::String exportDir);
/**
* \brief Add libraries files from Pixi.js or Cocos2d to the list of includes.

View File

@@ -7,7 +7,6 @@
"version": "GDJS_GAME_VERSION",
"dependencies": {},
"devDependencies": {
"electron": "2.0.7"
"electron": "3.0.9"
}
}

View File

@@ -128,6 +128,32 @@ gdjs.evtTools.camera.setLayerEffectParameter = function(runtimeScene, layer, eff
return runtimeScene.getLayer(layer).setEffectParameter(effect, parameter, value);
}
/**
* Enable, or disable, an effect of a layer.
* @param {gdjs.RuntimeScene} runtimeScene The scene
* @param {string} layer The name of the layer
* @param {string} effect The name of the effect
* @param {boolean} enabled true to enable, false to disable.
*/
gdjs.evtTools.camera.enableLayerEffect = function(runtimeScene, layer, effect, enabled) {
if ( !runtimeScene.hasLayer(layer) ) { return; }
runtimeScene.getLayer(layer).enableEffect(effect, enabled);
}
/**
* Check if an effect is enabled.
* @param {gdjs.RuntimeScene} runtimeScene The scene
* @param {string} layer The name of the layer
* @param {string} effect The name of the effect
* @return {boolean} true if the effect is enabled, false otherwise.
*/
gdjs.evtTools.camera.layerEffectEnabled = function(runtimeScene, layer, effect) {
if ( !runtimeScene.hasLayer(layer) ) { return true; }
return runtimeScene.getLayer(layer).isEffectEnabled(effect);
}
gdjs.evtTools.camera.setLayerTimeScale = function(runtimeScene, layer, timeScale) {
if ( !runtimeScene.hasLayer(layer) ) { return; }
return runtimeScene.getLayer(layer).setTimeScale(timeScale);

View File

@@ -206,6 +206,14 @@ gdjs.evtTools.input.getMouseWheelDelta = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().getMouseWheelDelta();
};
gdjs.evtTools.input.isScrollingUp = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().isScrollingUp();
};
gdjs.evtTools.input.isScrollingDown = function(runtimeScene) {
return runtimeScene.getGame().getInputManager().isScrollingDown();
};
gdjs.evtTools.input.getMouseX = function(runtimeScene, layer, camera) {
return runtimeScene.getLayer(layer).convertCoords(
runtimeScene.getGame().getInputManager().getMouseX(),
@@ -269,6 +277,8 @@ gdjs.evtTools.input.popEndedTouch = function(runtimeScene) {
return false;
};
gdjs.evtTools.input.touchSimulateMouse = function(runtimeScene, enable) {
runtimeScene.getGame().getInputManager().touchSimulateMouse(enable);
};

View File

@@ -15,8 +15,8 @@ gdjs.evtTools.object = gdjs.evtTools.object || {};
/**
* Keep only the specified object in the lists of picked objects.
*
* @param objectsLists The lists of objects to trim
* @param runtimeObject {gdjs.RuntimeObject} The object to keep in the lists
* @param {Hashtable} objectsLists The lists of objects to trim
* @param {gdjs.RuntimeObject} runtimeObject The object to keep in the lists
*/
gdjs.evtTools.object.pickOnly = function(objectsLists, runtimeObject) {
for (var listName in objectsLists.items) {
@@ -33,9 +33,17 @@ gdjs.evtTools.object.pickOnly = function(objectsLists, runtimeObject) {
}
};
/**
* A predicate to be passed to `gdjs.evtTools.object.twoListsTest`.
* @callback gdjsTwoListsTestPredicate
* @param {gdjs.RuntimeObject} object1 First object
* @param {gdjs.RuntimeObject} object2 Second object
* @param {*} extraArg An optional extra argument
* @return {boolean} true if the pair satisfy the predicate (for example,there is a collision), meaning that the objects will be picked, false otherwise (no collision).
*/
/**
* Do a test on two tables of objects so as to pick only the pair of objects for which the test is true.
* If inverted == true, only the objects of the first table are filtered.
*
* Note that the predicate method is not called stricly for each pair: When considering a pair of objects, if
* these objects have already been marked as picked, the predicate method won't be called again.
@@ -51,9 +59,12 @@ gdjs.evtTools.object.pickOnly = function(objectsLists, runtimeObject) {
* + Cost(predicate)*(NbObjList1+NbObjList2)
* + Cost(Testing NbObjList1+NbObjList2 booleans)
*
* Note: predicate is called with the two objects to compare, and an optional argument `extraArg`.
* This should be used to avoid declaring the predicate as a closure that would be created and destroyed
* at each call to twoListsTest (potentially multiple time per frame).
*
* @param {gdjsTwoListsTestPredicate} predicate The predicate function is called with the two objects to compare, and an optional argument `extraArg`
* @param {Hashtable} objectsLists1 e.g. Hashtable.newFrom({ A: objects1 });
* @param {Hashtable} objectsLists2 e.g. Hashtable.newFrom({ B: objects2 });
* @param {boolean} inverted If `inverted` == true, only the objects of the first table are filtered.
* @param {*} extraArg (optional) This argument should be used to avoid declaring the predicate as a closure that would be created and destroyed at each call to twoListsTest (potentially multiple time per frame).
*/
gdjs.evtTools.object.twoListsTest = function(predicate, objectsLists1, objectsLists2, inverted, extraArg) {
@@ -151,11 +162,11 @@ gdjs.evtTools.object.twoListsTest = function(predicate, objectsLists1, objectsLi
*
* Objects that do not fullfil the predicate are removed from objects lists.
*
* @param predicate The function applied to each object: must return true if the object fulfill the predicate.
* @param objectsLists The lists of objects to trim
* @param negatePredicate If set to true, the result of the predicate is negated.
* @param extraArg Argument passed to the predicate (along with the object). Useful for avoiding relying on temporary closures.
* @return true if at least one object fulfill the predicate.
* @param {Function} predicate The function applied to each object: must return true if the object fulfill the predicate.
* @param {Hashtable} objectsLists The lists of objects to trim
* @param {boolean} negatePredicate If set to true, the result of the predicate is negated.
* @param {*} extraArg Argument passed to the predicate (along with the object). Useful for avoiding relying on temporary closures.
* @return {boolean} true if at least one object fulfill the predicate.
*/
gdjs.evtTools.object.pickObjectsIf = function(predicate, objectsLists, negatePredicate, extraArg) {
var isTrue = false;

File diff suppressed because one or more lines are too long

View File

@@ -299,4 +299,19 @@ gdjs.InputManager.prototype.onFrameEnded = function() {
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 true if the mouse wheel scroll to down
*/
gdjs.InputManager.prototype.isScrollingDown = function() {
return this.getMouseWheelDelta() < 0;
};

View File

@@ -0,0 +1,76 @@
/*
* GDevelop JS Platform
* Copyright 2013-present Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the MIT License.
*/
/**
* JsonManager loads json files (using XMLHttpRequest), using the "json" resources
* registered in the game resources.
*
* Contrary to audio/fonts, json files are loaded asynchronously, when requested.
* You should properly handle errors, and give the developer/player a way to know
* that loading failed.
*
* @class JsonManager
* @memberof gdjs
* @param {Object[]} resources The resources data of the game.
*/
gdjs.JsonManager = function(resources) {
this._resources = resources;
};
/**
* The callback called when a json that was requested is loaded (or an error occured).
* @callback JsonManagerRequestCallback
* @param {?Error} error The error, if any. `null` otherwise.
* @param {?Object} jsonContent The content of the json file (or null if an error occured).
* @returns {undefined} Nothing
*/
/**
* Request the json file from the given resource name.
* When loaded, the `callback` is called with the error (null if none) and the loaded
* json (string).
*
* @param {string} resourceName The resource pointing to the json file to load.
* @param {JsonManagerRequestCallback} callback The callback function called when json is loaded (or an error occured).
*/
gdjs.JsonManager.prototype.loadJson = function(resourceName, callback) {
var resource = this._resources.find(
resource => resource.kind === 'json' && resource.name === resourceName
);
if (!resource) {
callback(
new Error(
'Can\'t find resource with name: "' +
resourceName +
'" (or is not a json resource).'
),
null
);
return;
}
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET', resource.file);
xhr.onload = function() {
if (xhr.status !== 200) {
callback(
new Error('HTTP error: ' + xhr.status + '(' + xhr.statusText + ')'),
null
);
return;
}
callback(null, xhr.response);
};
xhr.onerror = function() {
callback(new Error('Network error'), null);
};
xhr.onabort = function() {
callback(new Error('Request aborted'), null);
};
xhr.send();
};

View File

@@ -216,6 +216,24 @@ gdjs.Layer.prototype.setEffectParameter = function(name, parameterIndex, value)
return this._renderer.setEffectParameter(name, parameterIndex, value);
};
/**
* Enable or disable an effect.
* @param {string} effect The name of the effect to enable or disable.
* @param {boolean} enable true to enable, false to disable
*/
gdjs.Layer.prototype.enableEffect = function(name, enable) {
this._renderer.enableEffect(name, enable);
};
/**
* Check if an effect is enabled
* @param {string} effect The name of the effect
* @return {boolean} true if the effect is enabled, false otherwise.
*/
gdjs.Layer.prototype.isEffectEnabled = function(name) {
return this._renderer.isEffectEnabled(name);
};
gdjs.Layer.prototype.setEffectsDefaultParameters = function() {
for (var i = 0; i < this._effects.length; ++i) {
var effect = this._effects[i];

View File

@@ -1,9 +1,22 @@
/**
* A generic map (key values) container.
*
* Mostly used for storing lists of objects for
* GDevelop generated events.
*
* @class Hashtable
*/
function Hashtable()
{
// console.log("New hashtable");
this.items = {};
}
/**
* Construct a Hashtable from a JS object.
* @param {Object} items The content of the Hashtable
* @returns {Hashtable} The new hashtable
* @static
*/
Hashtable.newFrom = function(items) {
var hashtable = new Hashtable();
hashtable.items = items;

View File

@@ -1,12 +1,26 @@
gdjs.LayerPixiRenderer = function(layer, runtimeSceneRenderer)
{
this._pixiContainer = new PIXI.Container();
this._filters = {};
this._layer = layer;
runtimeSceneRenderer.getPIXIContainer().addChild(this._pixiContainer);
/*
* GDevelop JS Platform
* Copyright 2013-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the MIT License.
*/
this._addFilters();
}
/**
* The renderer for a gdjs.Layer using Pixi.js.
*
* @class LayerPixiRenderer
* @memberof gdjs
* @param {gdjs.Layer} layer The layer
* @param {gdjs.RuntimeScenePixiRenderer} runtimeSceneRenderer The scene renderer
*/
gdjs.LayerPixiRenderer = function(layer, runtimeSceneRenderer) {
this._pixiContainer = new PIXI.Container();
/** @type Object.<string, gdjsPixiFiltersToolsFilter> */
this._filters = {};
this._layer = layer;
runtimeSceneRenderer.getPIXIContainer().addChild(this._pixiContainer);
this._setupFilters();
};
gdjs.LayerRenderer = gdjs.LayerPixiRenderer; //Register the class to let the engine use it.
@@ -16,53 +30,62 @@ gdjs.LayerRenderer = gdjs.LayerPixiRenderer; //Register the class to let the eng
* @private
*/
gdjs.LayerPixiRenderer.prototype.updatePosition = function() {
var angle = -gdjs.toRad(this._layer.getCameraRotation());
var zoomFactor = this._layer.getCameraZoom();
var angle = -gdjs.toRad(this._layer.getCameraRotation());
var zoomFactor = this._layer.getCameraZoom();
this._pixiContainer.rotation = angle;
this._pixiContainer.scale.x = zoomFactor;
this._pixiContainer.scale.y = zoomFactor;
this._pixiContainer.rotation = angle;
this._pixiContainer.scale.x = zoomFactor;
this._pixiContainer.scale.y = zoomFactor;
var cosValue = Math.cos(angle);
var sinValue = Math.sin(angle);
var centerX = (this._layer.getCameraX()*zoomFactor)*cosValue
- (this._layer.getCameraY()*zoomFactor)*sinValue;
var centerY = (this._layer.getCameraX()*zoomFactor)*sinValue
+ (this._layer.getCameraY()*zoomFactor)*cosValue;
var cosValue = Math.cos(angle);
var sinValue = Math.sin(angle);
var centerX =
this._layer.getCameraX() * zoomFactor * cosValue -
this._layer.getCameraY() * zoomFactor * sinValue;
var centerY =
this._layer.getCameraX() * zoomFactor * sinValue +
this._layer.getCameraY() * zoomFactor * cosValue;
this._pixiContainer.position.x = -centerX;
this._pixiContainer.position.y = -centerY;
this._pixiContainer.position.x += this._layer.getWidth()/2;
this._pixiContainer.position.y += this._layer.getHeight()/2;
this._pixiContainer.position.x = -centerX;
this._pixiContainer.position.y = -centerY;
this._pixiContainer.position.x += this._layer.getWidth() / 2;
this._pixiContainer.position.y += this._layer.getHeight() / 2;
};
gdjs.LayerPixiRenderer.prototype.updateVisibility = function(visible) {
this._pixiContainer.visible = !!visible;
}
this._pixiContainer.visible = !!visible;
};
gdjs.LayerPixiRenderer.prototype._addFilters = function() {
var effects = this._layer.getEffects();
if (effects.length === 0) {
return;
} else if (effects.length > 1) {
console.log('Only a single effect by Layer is supported for now by the Pixi renderer');
}
gdjs.LayerPixiRenderer.prototype._setupFilters = function() {
var effects = this._layer.getEffects();
if (effects.length === 0) {
return;
}
var filter = gdjs.PixiFiltersTools.getFilter(effects[0].effectName);
this._filters = {};
/** @type PIXI.Filter[] */
var pixiFilters = [];
for (var i = 0; i < effects.length; ++i) {
var effect = effects[i];
var filter = gdjs.PixiFiltersTools.getFilter(effect.effectName);
if (!filter) {
console.log('Filter \"' + effects[0].name + '\" not found');
return;
console.log('Filter "' + effect.name + '" not found');
continue;
}
/** @type gdjsPixiFiltersToolsFilter */
var theFilter = {
filter: filter.makeFilter(),
updateParameter: filter.updateParameter
filter: filter.makeFilter(),
updateParameter: filter.updateParameter,
};
this._pixiContainer.filters = [theFilter.filter];
this._filters = {};
this._filters[effects[0].name] = theFilter;
}
pixiFilters.push(theFilter.filter);
this._filters[effect.name] = theFilter;
}
this._pixiContainer.filters = pixiFilters;
};
/**
* Add a child to the pixi container associated to the layer.
@@ -72,15 +95,16 @@ gdjs.LayerPixiRenderer.prototype._addFilters = function() {
* @param zOrder The z order of the associated object.
*/
gdjs.LayerPixiRenderer.prototype.addRendererObject = function(child, zOrder) {
child.zOrder = zOrder; //Extend the pixi object with a z order.
child.zOrder = zOrder; //Extend the pixi object with a z order.
for( var i = 0, len = this._pixiContainer.children.length; i < len;++i) {
if ( this._pixiContainer.children[i].zOrder >= zOrder ) { //TODO : Dichotomic search
this._pixiContainer.addChildAt(child, i);
return;
}
}
this._pixiContainer.addChild(child);
for (var i = 0, len = this._pixiContainer.children.length; i < len; ++i) {
if (this._pixiContainer.children[i].zOrder >= zOrder) {
//TODO : Dichotomic search
this._pixiContainer.addChildAt(child, i);
return;
}
}
this._pixiContainer.addChild(child);
};
/**
@@ -89,9 +113,12 @@ gdjs.LayerPixiRenderer.prototype.addRendererObject = function(child, zOrder) {
* @param child The child (PIXI object) to be modified.
* @param newZOrder The z order of the associated object.
*/
gdjs.LayerPixiRenderer.prototype.changeRendererObjectZOrder = function(child, newZOrder) {
this._pixiContainer.removeChild(child);
this.addRendererObject(child, newZOrder);
gdjs.LayerPixiRenderer.prototype.changeRendererObjectZOrder = function(
child,
newZOrder
) {
this._pixiContainer.removeChild(child);
this.addRendererObject(child, newZOrder);
};
/**
@@ -101,12 +128,30 @@ gdjs.LayerPixiRenderer.prototype.changeRendererObjectZOrder = function(child, ne
* @param child The child (PIXI object) to be removed.
*/
gdjs.LayerPixiRenderer.prototype.removeRendererObject = function(child) {
this._pixiContainer.removeChild(child);
this._pixiContainer.removeChild(child);
};
gdjs.LayerPixiRenderer.prototype.setEffectParameter = function (name, parameterName, value) {
if (!this._filters.hasOwnProperty(name)) return;
gdjs.LayerPixiRenderer.prototype.setEffectParameter = function(
name,
parameterName,
value
) {
if (!this._filters.hasOwnProperty(name)) return;
var theFilter = this._filters[name];
theFilter.updateParameter(theFilter.filter, parameterName, value);
var theFilter = this._filters[name];
theFilter.updateParameter(theFilter.filter, parameterName, value);
};
gdjs.LayerPixiRenderer.prototype.enableEffect = function(name, value) {
if (!this._filters.hasOwnProperty(name)) return;
var theFilter = this._filters[name];
gdjs.PixiFiltersTools.enableEffect(theFilter.filter, value);
};
gdjs.LayerPixiRenderer.prototype.isEffectEnabled = function(name) {
if (!this._filters.hasOwnProperty(name)) return false;
var theFilter = this._filters[name];
return gdjs.PixiFiltersTools.isEffectEnabled(theFilter.filter);
};

View File

@@ -1,5 +1,11 @@
/**
* Contains tools related to PIXI filters handling.
*/
gdjs.PixiFiltersTools = function() {};
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.NightPixiFilter = function() {
var vertexShader = null;
var fragmentShader = [
@@ -70,7 +76,7 @@ gdjs.PixiFiltersTools._filters = {
if (parameterName !== 'intensity' &&
parameterName !== 'opacity') return;
filter.uniforms[parameterName] = value;
filter.uniforms[parameterName] = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
},
},
LightNight: {
@@ -81,7 +87,7 @@ gdjs.PixiFiltersTools._filters = {
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'opacity') return;
filter.uniforms.opacity = value;
filter.uniforms.opacity = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
},
},
Sepia: {
@@ -93,14 +99,100 @@ gdjs.PixiFiltersTools._filters = {
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'opacity') return;
filter.alpha = value;
filter.alpha = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
},
},
BlackAndWhite: {
makeFilter: function() {
var colorMatrix = new PIXI.filters.ColorMatrixFilter();
colorMatrix.blackAndWhite();
return colorMatrix;
},
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'opacity') return;
filter.alpha = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
},
},
Brightness: {
makeFilter: function() {
var brightness = new PIXI.filters.ColorMatrixFilter();
brightness.brightness();
return brightness;
},
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'brightness') return;
filter.brightness(gdjs.PixiFiltersTools.clampValue(value, 0, 1));
},
},
Noise: {
makeFilter: function() {
var noise = new PIXI.filters.NoiseFilter();
return noise;
},
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'noise') return;
filter.noise = gdjs.PixiFiltersTools.clampValue(value, 0, 1);
},
},
Blur: {
makeFilter: function() {
var blur = new PIXI.filters.BlurFilter();
return blur;
},
updateParameter: function(filter, parameterName, value) {
if (parameterName !== 'blur' &&
parameterName !== 'quality' &&
parameterName !== 'kernelSize' &&
parameterName !== 'resolution') return;
if (parameterName === 'kernelSize'){
value = gdjs.PixiFiltersTools.clampKernelSize(value);
}
filter[parameterName] = value;
},
},
};
/**
* Enable an effect.
* @param {PIXI.Filter} filter The filter to enable or disable
* @param {boolean} value Set to true to enable, false to disable
*/
gdjs.PixiFiltersTools.enableEffect = function(filter, value) {
filter.enabled = value;
}
/**
* Effect is enabled.
* @param {PIXI.Filter} filter The filter to be checked
* @return {boolean} true if the filter is enabled
*/
gdjs.PixiFiltersTools.isEffectEnabled = function(filter) {
return filter.enabled;
}
/**
* Return the filter with the given name, if any.
* @param {string} filterName The name of the filter to get
* @return {?gdjsPixiFiltersToolsFilter} The filter wrapper, if any (null otherwise).
*/
gdjs.PixiFiltersTools.getFilter = function(filterName) {
if (gdjs.PixiFiltersTools._filters.hasOwnProperty(filterName))
return gdjs.PixiFiltersTools._filters[filterName];
return null;
}
// Type definitions:
/**
* The type of a filter used to manipulate a Pixi filter.
* @typedef gdjsPixiFiltersToolsFilter
* @type {object}
* @property {PIXI.Filter} filter The PIXI filter
* @property {Function} updateParameter The function to be called to update a parameter
*/

View File

@@ -1,6 +1,13 @@
/**
* The renderer for a gdjs.SpriteRuntimeObject using Pixi.js.
* @class SpriteRuntimeObjectPixiRenderer
* @memberof gdjs
* @param {gdjs.SpriteRuntimeObject} runtimeObject The object
* @param {gdjs.RuntimeScene} runtimeScene The scene
*/
gdjs.SpriteRuntimeObjectPixiRenderer = function(runtimeObject, runtimeScene)
{
/** @type gdjs.SpriteRuntimeObject */
this._object = runtimeObject;
this._spriteDirty = true;
this._textureDirty = true;
@@ -67,13 +74,13 @@ gdjs.SpriteRuntimeObjectPixiRenderer.prototype.update = function() {
gdjs.SpriteRuntimeObjectPixiRenderer.prototype.updateX = function() {
this._sprite.position.x = this._object.x + (this._object._animationFrame.center.x - this._object._animationFrame.origin.x)*Math.abs(this._object._scaleX);
if ( this._flippedX )
if ( this._object._flippedX )
this._sprite.position.x += (this._sprite.texture.frame.width/2-this._object._animationFrame.center.x)*Math.abs(this._object._scaleX)*2;
}
gdjs.SpriteRuntimeObjectPixiRenderer.prototype.updateY = function() {
this._sprite.position.y = this._object.y + (this._object._animationFrame.center.y - this._object._animationFrame.origin.y)*Math.abs(this._object._scaleY);
if ( this._flippedY )
if ( this._object._flippedY )
this._sprite.position.y += (this._sprite.texture.frame.height/2-this._object._animationFrame.center.y)*Math.abs(this._object._scaleY)*2;
}

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