Compare commits

...

89 Commits

Author SHA1 Message Date
Florian Rival
5f916903ab Bump newIDE version 2018-04-27 15:14:21 +01:00
Florian Rival
60fe29660d Add missing images for points 2018-04-27 15:12:31 +01:00
Florian Rival
596e0087e5 Bump newIDE version 2018-04-26 15:31:29 +01:00
Todor Imreorov
8034247494 Fix scrolling issue (#483) 2018-04-26 14:37:06 +01:00
Florian Rival
73b60e6da8 Fix harmless error in import-libGD.js 2018-04-26 14:27:33 +01:00
Florian Rival
57e00a7ce0 Bump newIDE version 2018-04-26 13:43:25 +01:00
Florian Rival
1a6aa3b7ab Enable again menu in LocalPreviewLauncher preview windows 2018-04-26 13:38:58 +01:00
Florian Rival
e6eb05ce22 Fix TextEditor not resized when text is entered 2018-04-25 22:26:25 +01:00
Florian Rival
ddf63637fe Bump newIDE version 2018-04-25 17:38:06 +01:00
Florian Rival
c02aec0f6b Merge pull request #478 from 4ian/feature/gdjs-ws-debugger
Add basic Debugger for GDevelop 5/GDJS games
2018-04-25 15:41:16 +01:00
Florian Rival
280eebbccd Add HelpButton in DebuggerContent 2018-04-25 15:34:06 +01:00
Florian Rival
48611c2c38 Add Debugger menu item in EventsSheet toolbar 2018-04-24 23:48:42 +01:00
Florian Rival
5dbbc25b2b Fix warning in ScenePropertiesDialog 2018-04-24 23:40:09 +01:00
Florian Rival
23c85d8a75 Enhance RuntimeSceneInspector to allow to create new instances of objects 2018-04-24 23:23:59 +01:00
Florian Rival
cdd0f72266 Refactor *Inspector to use mapValues 2018-04-24 22:53:44 +01:00
Florian Rival
68189bf720 Add RuntimeSceneInspector showing layers information and timescale to Debugger 2018-04-24 20:59:09 +01:00
Florian Rival
376c2cc5c5 Fix Debugger opening from an ExternalLayoutEditor 2018-04-24 20:30:14 +01:00
Florian Rival
38b587cdd4 Set initial split percentage in DebuggerContent to increase inspectors list readability 2018-04-24 17:44:13 +01:00
Florian Rival
dd65aaf086 Make Debugger inspectors more resilient to bad values 2018-04-24 17:14:36 +01:00
Florian Rival
db7604ee88 Ask for getting a subscription to regularly use the Debugger 2018-04-24 17:11:29 +01:00
Florian Rival
d94749177b Lightly fade buttons to add child to a non-structure variable 2018-04-24 17:10:49 +01:00
Florian Rival
d061be627b Ensure Debugger toolbar is not shown if DebuggerEditor is not active 2018-04-24 17:10:18 +01:00
Florian Rival
3dede19f1f Add note about Debugger working only on Electron runtime 2018-04-24 15:43:17 +01:00
Florian Rival
916d2eb99e Fix storybook DebuggerContent stories 2018-04-24 12:53:26 +01:00
Florian Rival
9fadc0faab Add item in menu to open Debugger 2018-04-24 11:00:04 +01:00
Florian Rival
ba6c7ec78d Add a message when no debugger is launched 2018-04-24 10:57:55 +01:00
Florian Rival
0b4fc055bf [WIP] Enable debugger to listen to multiple game previews 2018-04-24 00:14:38 +01:00
Florian Rival
8a841fa68f Fix a flow type error 2018-04-23 22:15:21 +01:00
Florian Rival
f71983679c Enhance README and fix linter errors + add warning about RawContentInspector usage 2018-04-23 22:15:21 +01:00
Florian Rival
be3cc48e32 Add RuntimeObject/VariablesContainerInspector for Debugger with live editing 2018-04-23 22:15:21 +01:00
Florian Rival
956656236b Move InstancesFullEditor to SceneEditor 2018-04-23 22:15:20 +01:00
Florian Rival
a53de69c4e [WIP] Implement a basic client/server debugger for GDJS games 2018-04-23 22:15:20 +01:00
Florian Rival
a7abbda061 Fix an incorrectly parsed color warning in DefaultTheme 2018-04-23 22:09:48 +01:00
Florian Rival
c267d14348 Merge pull request #452 from Lizard-13/skeleton-runtime-object
Add Skeleton object extension (still in Beta)
2018-04-23 21:50:09 +01:00
Todor Imreorov
7db2709ff0 Improve scrolling and add mouse middle button support to Scene editor (#472)
* Add mouse middle button input support to Scene editor, using standard navigation design present in other software (Gimp, Krita, Inkscape, blender, etc):
- Scrolling to zoom in and out the view
- Mid click to pan the view

* Middle mouse navigation is only for windows and Linux, but not macOS.
* Add support for natural scrolling in both X and Y directions
2018-04-23 21:36:19 +01:00
Lizard-13
86a3614f89 Added an example and improve response on missing resources 2018-04-23 12:52:30 -03:00
Lizard-13
b8e0b5d8e3 Update comments 2018-04-20 08:22:18 -03:00
Lizard-13
c7a8df3d5a Clean some code 2018-04-16 12:31:11 -03:00
Florian Rival
3be8966132 Remove menu of BrowserWindow showing the preview of games in newIDE 2018-04-15 22:34:33 +02:00
Florian Rival
61cefa6cd7 Merge branch 'master' of github.com:4ian/GD 2018-04-15 22:33:47 +02:00
Florian Rival
e1dd41bb32 Fix debouncing of HelpFinder analytics 2018-04-15 12:29:06 +02:00
Ryan Jentzsch
24466ca653 Add note about NPM watcher error for Linux (#468)
See #467
2018-04-14 10:40:02 +02:00
Florian Rival
1c9497dc92 Remove useless file 2018-04-13 23:45:26 +02:00
Florian Rival
5dd3ed43cf Merge pull request #466 from 4ian/feature/help-finder
Add HelpFinder with search in documentation powered by Algolia DocSearch.
2018-04-13 17:06:11 +02:00
Florian Rival
368cdebd78 Fix primary RaisedButton text color in DarkTheme 2018-04-13 17:03:43 +02:00
Florian Rival
3d7279144b Add Search powered by Algolia in HelpFinder 2018-04-13 16:53:54 +02:00
Florian Rival
18682eccfa Fix DocSearch width on large screens 2018-04-13 16:45:41 +02:00
Florian Rival
f70c565e7d Ensure opening a link in the Electron app will open an external browser 2018-04-13 16:38:34 +02:00
Florian Rival
b9035efc9e Fix StartPage tests 2018-04-13 16:29:40 +02:00
Florian Rival
493fc7b6f9 Send analytics from HelpFinder to know if it's being used 2018-04-13 16:28:04 +02:00
Florian Rival
52db6e15ee Add work-in-progress HelpFinder dialog 2018-04-13 16:19:39 +02:00
Florian Rival
28de2b179b Merge pull request #465 from Lizard-13/improve-particles
Improve particles
2018-04-13 15:12:11 +02:00
Lizard-13
4a6c37f502 Fix Cocos particles size 2018-04-13 06:50:51 -03:00
Lizard-13
9ce734e204 More particles fixes 2018-04-13 06:27:37 -03:00
Florian Rival
fb3a0edfac Fix AudioResourceField not properly shown in ExternalEvents editor 2018-04-10 18:38:46 +02:00
Florian Rival
e613c7d546 Merge pull request #464 from Lizard-13/improve-particles
Improve/Fix particles
2018-04-10 10:44:21 +02:00
Lizard-13
6db6455bb6 Improve particles 2018-04-09 22:38:47 -03:00
Florian Rival
86e928724a Add ObjectName string expression 2018-04-09 17:53:48 +02:00
Florian Rival
f31d8f88c2 Update Particles - Various effects example for HTML5 games 2018-04-08 23:57:39 +02:00
Florian Rival
940eac6bc4 Fix Pixi and Cocos2d-JS particles flow/tank support and adapt Explosion example 2018-04-08 23:28:51 +02:00
Florian Rival
6908f51b4a Fix hasStarted method of ParticleEmitterObject (Pixi.js and Cocos2d-JS renderers) 2018-04-08 22:34:01 +02:00
Florian Rival
a537f678fb Merge pull request #462 from Lizard-13/js-particles
Add support for particles in HTML5 games (both Pixi.js and Cocos2d-JS renderers)

Thanks @Lizard-13 for this great work!
2018-04-08 21:33:37 +02:00
Lizard-13
1019aaba5f Update exporter and improve readability 2018-04-08 11:48:28 -03:00
Lizard-13
5770ac6396 Add support for particles in web platform 2018-04-07 23:51:28 -03:00
Florian Rival
7171f691a3 Display global groups in italic 2018-04-05 20:20:18 +02:00
Florian Rival
0ad7b71cf2 Bump newIDE version 2018-04-04 17:08:52 +02:00
Florian Rival
006d7296a2 Fix AudioResourceField not properly shown when editing it inline in EventsSheet 2018-04-04 17:07:44 +02:00
Florian Rival
443c49f83e Fix regression due to broken Variable and VariablesContainer copy ctor and assignement operator 2018-04-04 15:10:08 +02:00
Florian Rival
9884965595 Merge pull request #458 from 4ian/audio-resource-support
Audio resource support
2018-04-04 13:15:59 +02:00
Florian Rival
e0379466e0 Add more flowtype coverage 2018-04-04 11:54:58 +02:00
Florian Rival
622cba4642 Move ResourceSelectorWithThumbnail and add ResourceThumbnail 2018-04-04 11:46:14 +02:00
Florian Rival
50c7a582ef Add AudioPreview 2018-04-04 11:23:49 +02:00
Florian Rival
e501fd4a09 Add AudioResourceField 2018-04-04 10:36:59 +02:00
Lizard-13
50746b3c75 Still trying to fix Travis CI 2018-03-30 23:25:11 -03:00
Lizard-13
1c5364f917 Trying to fix the Travis CI compiling error 2018-03-30 21:51:50 -03:00
Lizard-13
89d099ff7d Add Cocos renderer support 2018-03-30 21:20:01 -03:00
Lizard-13
ca1721ef9a Load skeletal data file only once through shared data
Now each file is readed only once, multiple instances will share static data as default values and animation keys.

Also converted all tabs into spaces :)
2018-03-29 19:25:43 -03:00
Lizard-13
ddcf51a2b7 Add custom hitbox action and fix polygons draw 2018-03-14 22:09:25 -03:00
Lizard-13
46279e7762 Add JS events functions and hitboxes debug draw 2018-03-10 14:54:17 -03:00
Lizard-13
557af32cc9 Add custom icons 2018-02-27 21:51:15 -03:00
Lizard-13
729a85a9a9 Add extension conditions/actions/expressions 2018-02-27 19:10:36 -03:00
Lizard-13
34146c2f18 Added gdjs.sk namespace for better organization 2018-02-27 19:10:23 -03:00
Lizard-13
00146bb8f8 Add animation and animation blending system 2018-02-27 19:10:11 -03:00
Lizard-13
6026d79ebb Support for armatures, meshes* and polygons
*Meshes needs PIXI lib update
2018-02-27 19:10:07 -03:00
Lizard-13
fc28f272b3 Images color, alpha, visible, z support 2018-02-27 19:10:02 -03:00
Lizard-13
9702db06a5 Basic images working 2018-02-27 19:09:55 -03:00
Lizard-13
209f83d697 Basic classes setup 2018-02-27 19:09:47 -03:00
Lizard-13
0ef8eb32a5 Base extension info and files tree
Files named Ax, By, Cz... as a temporal fix for include order
2018-02-27 19:09:42 -03:00
Lizard-13
8115b8181e Empty working object 2018-02-27 19:09:31 -03:00
151 changed files with 11484 additions and 821 deletions

View File

@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project firstLayout="">
<gdVersion build="84" major="3" minor="6" revision="0" />
<properties linuxExecutableFilename="" macExecutableFilename="" useExternalSourceFiles="false" winExecutableFilename="" winExecutableIconFile="">
<gdVersion build="97" major="4" minor="0" revision="0" />
<properties folderProject="false" linuxExecutableFilename="" macExecutableFilename="" orientation="default" packageName="" projectFile="C:\Users\Maciel\Programacion\gits\GD\Binaries\Output\Release_Windows\Examples\Particles - Explosions.gdg" useExternalSourceFiles="false" winExecutableFilename="" winExecutableIconFile="">
<name>Explosions</name>
<author></author>
<windowWidth>800</windowWidth>
<windowHeight>600</windowHeight>
<latestCompilationDirectory></latestCompilationDirectory>
<latestCompilationDirectory>C:\Users\Maciel\AppData\Local\Temp\GDTemporaries\JSCocosExportParticles</latestCompilationDirectory>
<maxFPS>60</maxFPS>
<minFPS>10</minFPS>
<verticalSync>false</verticalSync>
<platformSpecificAssets />
<loadingScreen showGDevelopSplash="true" />
<extensions>
<extension name="BuiltinObject" />
<extension name="BuiltinAudio" />
@@ -34,6 +36,7 @@
</extensions>
<platforms>
<platform name="GDevelop C++ platform" />
<platform name="GDevelop JS platform" />
</platforms>
<currentPlatform>GDevelop C++ platform</currentPlatform>
</properties>
@@ -48,40 +51,40 @@
<variables />
<layouts>
<layout b="0" disableInputWhenNotFocused="true" mangledName="New_32scene" name="New scene" oglFOV="90.000000" oglZFar="500.000000" oglZNear="1.000000" r="0" standardSortMethod="true" stopSoundsOnStartup="true" title="" v="0">
<uiSettings associatedLayout="" grid="false" gridB="255" gridG="180" gridHeight="32" gridOffsetX="0" gridOffsetY="0" gridR="158" gridWidth="32" snap="true" windowMask="false" zoomFactor="1.000000" />
<uiSettings grid="false" gridB="255" gridG="180" gridHeight="32" gridOffsetX="0" gridOffsetY="0" gridR="158" gridWidth="32" snap="true" windowMask="false" zoomFactor="1.000000" />
<objectsGroups />
<variables />
<instances />
<objects>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Mutable" destroyWhenNoParticles="true" emissionEditionSimpleMode="false" emitterAngleA="180.000000" emitterAngleB="160.000000" emitterForceMax="40.000000" emitterForceMin="5.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="-1.000000" friction="2.000000" gravityEditionSimpleMode="false" greenParam="Mutable" maxParticleNb="5000" name="Explosion" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="50.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="20.000000" particleGreen1="128.000000" particleGreen2="50.000000" particleLifeTimeMax="1.500000" particleLifeTimeMin="0.700000" particleRed1="255.000000" particleRed2="50.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Mutable" rendererParam1="20.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Random" tank="1000.000000" textureParticleName="ExplosionTexture.png" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Mutable" destroyWhenNoParticles="true" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="360.000000" emitterForceMax="70.000000" emitterForceMin="30.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="-1.000000" friction="2.000000" gravityEditionSimpleMode="false" greenParam="Mutable" maxParticleNb="100" name="Explosion" particleAlpha1="225.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="50.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="20.000000" particleGreen1="128.000000" particleGreen2="50.000000" particleLifeTimeMax="1.500000" particleLifeTimeMin="0.700000" particleRed1="255.000000" particleRed2="50.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Mutable" rendererParam1="20.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Random" tank="100.000000" textureParticleName="ExplosionTexture.png" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Mutable" destroyWhenNoParticles="true" emissionEditionSimpleMode="false" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="130.000000" emitterForceMin="50.000000" emitterXDirection="1.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="-1.000000" friction="2.000000" gravityEditionSimpleMode="false" greenParam="Mutable" maxParticleNb="5000" name="Explosion2" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="75.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="30.000000" particleGreen1="76.000000" particleGreen2="180.000000" particleLifeTimeMax="1.500000" particleLifeTimeMin="0.700000" particleRed1="153.000000" particleRed2="1.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="0.050000" rendererParam2="1.000000" rendererType="Line" sizeParam="Random" tank="350.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Mutable" destroyWhenNoParticles="true" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="360.000000" emitterForceMax="130.000000" emitterForceMin="130.000000" emitterXDirection="1.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="-1.000000" friction="2.000000" gravityEditionSimpleMode="false" greenParam="Mutable" maxParticleNb="151" name="Explosion2" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="75.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="30.000000" particleGreen1="76.000000" particleGreen2="180.000000" particleLifeTimeMax="1.000000" particleLifeTimeMin="0.700000" particleRed1="153.000000" particleRed2="1.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="3.000000" rendererParam2="6.000000" rendererType="Line" sizeParam="Random" tank="40.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Enabled" destroyWhenNoParticles="true" emissionEditionSimpleMode="false" emitterAngleA="45.000000" emitterAngleB="180.000000" emitterForceMax="10.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="400.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Enabled" maxParticleNb="5000" name="ExplosionSmoke" particleAlpha1="153.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="0.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="30.000000" particleGreen1="25.000000" particleGreen2="0.800000" particleLifeTimeMax="1.200000" particleLifeTimeMin="0.700000" particleRed1="25.000000" particleRed2="0.100000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="20.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Random" tank="500.000000" textureParticleName="ExplosionTexture.png" type="ParticleSystem::ParticleEmitter" zoneRadius="20.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Enabled" destroyWhenNoParticles="true" emissionEditionSimpleMode="false" emitterAngleA="45.000000" emitterAngleB="180.000000" emitterForceMax="10.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="400.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Enabled" maxParticleNb="50" name="ExplosionSmoke" particleAlpha1="153.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="25.000000" particleBlue2="0.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="30.000000" particleGreen1="25.000000" particleGreen2="0.800000" particleLifeTimeMax="2.000000" particleLifeTimeMin="0.700000" particleRed1="25.000000" particleRed2="0.100000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="20.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Random" tank="50.000000" textureParticleName="ExplosionTexture.png" type="ParticleSystem::ParticleEmitter" zoneRadius="20.000000">
<variables />
<automatisms />
<behaviors />
</object>
</objects>
<events>
<event disabled="false" folded="false">
<type>BuiltinCommonInstructions::Standard</type>
<conditions>
<condition>
<instruction>
<type inverted="false" value="Timer" />
<parameters>
<parameter></parameter>
<parameter>Random(0.3)+0.2</parameter>
<parameter>&quot;Creating&quot;</parameter>
</parameters>
<subConditions />
</condition>
<subInstructions />
</instruction>
</conditions>
<actions>
<action>
<instruction>
<type inverted="false" value="Create" />
<parameters>
<parameter></parameter>
@@ -90,9 +93,9 @@
<parameter>Random(600)</parameter>
<parameter></parameter>
</parameters>
<subActions />
</action>
<action>
<subInstructions />
</instruction>
<instruction>
<type inverted="false" value="Create" />
<parameters>
<parameter></parameter>
@@ -101,9 +104,9 @@
<parameter>Explosion.Y()</parameter>
<parameter></parameter>
</parameters>
<subActions />
</action>
<action>
<subInstructions />
</instruction>
<instruction>
<type inverted="false" value="Create" />
<parameters>
<parameter></parameter>
@@ -112,16 +115,16 @@
<parameter>Explosion.Y()</parameter>
<parameter></parameter>
</parameters>
<subActions />
</action>
<action>
<subInstructions />
</instruction>
<instruction>
<type inverted="false" value="ResetTimer" />
<parameters>
<parameter></parameter>
<parameter>&quot;Creating&quot;</parameter>
</parameters>
<subActions />
</action>
<subInstructions />
</instruction>
</actions>
<events />
</event>
@@ -131,9 +134,10 @@
<cameras>
<camera defaultSize="true" defaultViewport="true" height="0.000000" viewportBottom="1.000000" viewportLeft="0.000000" viewportRight="1.000000" viewportTop="0.000000" width="0.000000" />
</cameras>
<effects />
</layer>
</layers>
<automatismsSharedData />
<behaviorsSharedData />
</layout>
</layouts>
<externalEvents />

View File

@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<project firstLayout="">
<gdVersion build="84" major="3" minor="6" revision="0" />
<properties linuxExecutableFilename="" macExecutableFilename="" useExternalSourceFiles="false" winExecutableFilename="" winExecutableIconFile="">
<gdVersion build="97" major="4" minor="0" revision="0" />
<properties folderProject="false" linuxExecutableFilename="" macExecutableFilename="" orientation="default" packageName="" projectFile="C:\Users\Maciel\Programacion\gits\GD\Binaries\Output\Release_Windows\Examples\Particles - Various effects.gdg" useExternalSourceFiles="false" winExecutableFilename="" winExecutableIconFile="">
<name>Project</name>
<author></author>
<windowWidth>800</windowWidth>
<windowHeight>600</windowHeight>
<latestCompilationDirectory></latestCompilationDirectory>
<latestCompilationDirectory>C:\Users\Maciel\AppData\Local\Temp\GDTemporaries\JSCocosExportParticles</latestCompilationDirectory>
<maxFPS>60</maxFPS>
<minFPS>10</minFPS>
<verticalSync>false</verticalSync>
<platformSpecificAssets />
<loadingScreen showGDevelopSplash="true" />
<extensions>
<extension name="BuiltinObject" />
<extension name="BuiltinAudio" />
@@ -34,6 +36,7 @@
</extensions>
<platforms>
<platform name="GDevelop C++ platform" />
<platform name="GDevelop JS platform" />
</platforms>
<currentPlatform>GDevelop C++ platform</currentPlatform>
</properties>
@@ -47,8 +50,8 @@
<objectsGroups />
<variables />
<layouts>
<layout b="0" disableInputWhenNotFocused="true" mangledName="Nouvelle_32sc_232ne" name="Nouvelle scène" oglFOV="90.000000" oglZFar="500.000000" oglZNear="1.000000" r="0" standardSortMethod="true" stopSoundsOnStartup="true" title="" v="0">
<uiSettings associatedLayout="" grid="false" gridB="255" gridG="180" gridHeight="32" gridOffsetX="0" gridOffsetY="0" gridR="158" gridWidth="32" snap="true" windowMask="false" zoomFactor="1.000000" />
<layout b="0" disableInputWhenNotFocused="true" mangledName="Scene" name="Scene" oglFOV="90.000000" oglZFar="500.000000" oglZNear="1.000000" r="0" standardSortMethod="true" stopSoundsOnStartup="true" title="" v="0">
<uiSettings grid="false" gridB="255" gridG="180" gridHeight="32" gridOffsetX="0" gridOffsetY="0" gridR="158" gridWidth="32" snap="true" windowMask="false" zoomFactor="1.000000" />
<objectsGroups />
<variables />
<instances>
@@ -99,47 +102,47 @@
</instance>
</instances>
<objects>
<object additive="true" alphaParam="Mutable" angleParam="Mutable" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="10.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="300.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Fire" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="30.000000" particleBlue1="50.000000" particleBlue2="0.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="-100.000000" particleGravityZ="0.000000" particleGreen1="50.000000" particleGreen2="204.000000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="240.000000" particleRed2="1.000000" particleSize1="100.000000" particleSize2="0.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="10.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Mutable" tank="-1.000000" textureParticleName="Fire" type="ParticleSystem::ParticleEmitter" zoneRadius="5.000000">
<object additive="true" alphaParam="Mutable" angleParam="Mutable" blueParam="Mutable" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="10.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="30.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Mutable" maxParticleNb="200" name="Fire" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="30.000000" particleBlue1="50.000000" particleBlue2="0.000000" particleEditionSimpleMode="true" particleGravityX="0.000000" particleGravityY="-100.000000" particleGravityZ="0.000000" particleGreen1="50.000000" particleGreen2="191.000000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="240.000000" particleRed2="255.000000" particleSize1="100.000000" particleSize2="0.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Mutable" rendererParam1="10.000000" rendererParam2="20.000000" rendererType="Quad" sizeParam="Mutable" tank="-1.000000" textureParticleName="Fire" type="ParticleSystem::ParticleEmitter" zoneRadius="5.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="false" alphaParam="Mutable" angleParam="Random" blueParam="Enabled" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="0.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="200.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Enabled" maxParticleNb="5000" name="Smoke" particleAlpha1="160.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="360.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="50.000000" particleBlue2="0.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="-100.000000" particleGravityZ="0.000000" particleGreen1="50.000000" particleGreen2="0.800000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="50.000000" particleRed2="1.000000" particleSize1="20.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="30.000000" rendererParam2="30.000000" rendererType="Quad" sizeParam="Mutable" tank="-1.000000" textureParticleName="Fire" type="ParticleSystem::ParticleEmitter" zoneRadius="7.000000">
<object additive="false" alphaParam="Mutable" angleParam="Random" blueParam="Mutable" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="360.000000" emitterForceMax="0.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="150.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Mutable" maxParticleNb="150" name="Smoke" particleAlpha1="160.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="360.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="255.000000" particleBlue2="149.000000" particleEditionSimpleMode="true" particleGravityX="0.000000" particleGravityY="-100.000000" particleGravityZ="0.000000" particleGreen1="250.000000" particleGreen2="144.000000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="253.000000" particleRed2="135.000000" particleSize1="20.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Mutable" rendererParam1="30.000000" rendererParam2="30.000000" rendererType="Quad" sizeParam="Mutable" tank="-1.000000" textureParticleName="Fire" type="ParticleSystem::ParticleEmitter" zoneRadius="15.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="65.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="200.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Particles" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="125.000000" particleBlue2="204.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="250.000000" particleGreen1="125.000000" particleGreen2="204.000000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="204.000000" particleRed2="255.000000" particleSize1="0.000000" particleSize2="0.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="8.000000" rendererParam2="1.000000" rendererType="Point" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="65.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="200.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Particles" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="125.000000" particleBlue2="204.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="250.000000" particleGreen1="125.000000" particleGreen2="204.000000" particleLifeTimeMax="2.500000" particleLifeTimeMin="0.500000" particleRed1="204.000000" particleRed2="255.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="8.000000" rendererParam2="1.000000" rendererType="Point" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="2.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="false" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="0.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="100.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Beam" particleAlpha1="250.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="204.000000" particleBlue2="255.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="0.000000" particleGravityZ="500.000000" particleGreen1="127.000000" particleGreen2="230.000000" particleLifeTimeMax="2.000000" particleLifeTimeMin="0.500000" particleRed1="153.000000" particleRed2="180.000000" particleSize1="0.000000" particleSize2="0.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="3.000000" rendererParam2="1.000000" rendererType="Line" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="3.000000">
<object additive="false" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="false" emitterAngleA="-55.000000" emitterAngleB="-35.000000" emitterForceMax="5.000000" emitterForceMin="0.000000" emitterXDirection="0.000000" emitterYDirection="1.000000" emitterZDirection="0.000000" flow="100.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="151" name="Beam" particleAlpha1="250.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="204.000000" particleBlue2="255.000000" particleEditionSimpleMode="false" particleGravityX="100.000000" particleGravityY="0.000000" particleGravityZ="500.000000" particleGreen1="127.000000" particleGreen2="230.000000" particleLifeTimeMax="2.000000" particleLifeTimeMin="0.500000" particleRed1="153.000000" particleRed2="180.000000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="100.000000" rendererParam2="3.000000" rendererType="Line" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="20.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="0.000000" emitterForceMax="65.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="0.000000" flow="300.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Beam2" particleAlpha1="125.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="255.000000" particleBlue2="204.000000" particleEditionSimpleMode="false" particleGravityX="-500.000000" particleGravityY="0.000000" particleGravityZ="0.000000" particleGreen1="204.000000" particleGreen2="125.000000" particleLifeTimeMax="5.000000" particleLifeTimeMin="0.500000" particleRed1="127.000000" particleRed2="0.500000" particleSize1="0.000000" particleSize2="0.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="0.500000" rendererParam2="2.000000" rendererType="Line" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="3.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="false" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="0.000000" emitterForceMax="65.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="0.000000" flow="50.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Random" maxParticleNb="5000" name="Beam2" particleAlpha1="125.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="255.000000" particleBlue2="204.000000" particleEditionSimpleMode="false" particleGravityX="-500.000000" particleGravityY="0.000000" particleGravityZ="0.000000" particleGreen1="204.000000" particleGreen2="125.000000" particleLifeTimeMax="5.000000" particleLifeTimeMin="0.500000" particleRed1="127.000000" particleRed2="0.500000" particleSize1="100.000000" particleSize2="100.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Enabled" rendererParam1="10.000000" rendererParam2="3.000000" rendererType="Line" sizeParam="Random" tank="-1.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="10.000000">
<variables />
<automatisms />
<behaviors />
</object>
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="true" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="180.000000" emitterForceMax="100.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="400.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Enabled" maxParticleNb="5000" name="Pyro" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="204.000000" particleBlue2="255.000000" particleEditionSimpleMode="false" particleGravityX="0.000000" particleGravityY="-100.000000" particleGravityZ="0.000000" particleGreen1="127.000000" particleGreen2="1.000000" particleLifeTimeMax="1.000000" particleLifeTimeMin="0.500000" particleRed1="127.000000" particleRed2="230.000000" particleSize1="100.000000" particleSize2="1.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="0.060000" rendererParam2="3.000000" rendererType="Line" sizeParam="Mutable" tank="600.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="7.000000">
<object additive="true" alphaParam="Mutable" angleParam="Random" blueParam="Random" destroyWhenNoParticles="true" emissionEditionSimpleMode="true" emitterAngleA="0.000000" emitterAngleB="360.000000" emitterForceMax="100.000000" emitterForceMin="25.000000" emitterXDirection="0.000000" emitterYDirection="0.000000" emitterZDirection="1.000000" flow="70.000000" friction="2.000000" gravityEditionSimpleMode="true" greenParam="Enabled" maxParticleNb="151" name="Pyro" particleAlpha1="204.000000" particleAlpha2="0.000000" particleAlphaRandomness1="0.000000" particleAlphaRandomness2="0.000000" particleAngle1="0.000000" particleAngle2="0.000000" particleAngleRandomness1="0.000000" particleAngleRandomness2="0.000000" particleBlue1="204.000000" particleBlue2="255.000000" particleEditionSimpleMode="false" particleGravityX="-0.000080" particleGravityY="-200.000000" particleGravityZ="0.000000" particleGreen1="127.000000" particleGreen2="1.000000" particleLifeTimeMax="1.000000" particleLifeTimeMin="0.500000" particleRed1="127.000000" particleRed2="230.000000" particleSize1="100.000000" particleSize2="1.000000" particleSizeRandomness1="0.000000" particleSizeRandomness2="0.000000" redParam="Random" rendererParam1="8.000000" rendererParam2="8.000000" rendererType="Line" sizeParam="Mutable" tank="80.000000" textureParticleName="" type="ParticleSystem::ParticleEmitter" zoneRadius="25.000000">
<variables />
<automatisms />
<behaviors />
</object>
</objects>
<events>
<event disabled="false" folded="false">
<type>BuiltinCommonInstructions::Standard</type>
<conditions>
<condition>
<instruction>
<type inverted="false" value="Timer" />
<parameters>
<parameter></parameter>
<parameter>Random(0.3)+1</parameter>
<parameter>1</parameter>
<parameter>&quot;Creating&quot;</parameter>
</parameters>
<subConditions />
</condition>
<subInstructions />
</instruction>
</conditions>
<actions>
<action>
<instruction>
<type inverted="false" value="Create" />
<parameters>
<parameter></parameter>
@@ -148,16 +151,16 @@
<parameter>100+Random(300)</parameter>
<parameter></parameter>
</parameters>
<subActions />
</action>
<action>
<subInstructions />
</instruction>
<instruction>
<type inverted="false" value="ResetTimer" />
<parameters>
<parameter></parameter>
<parameter>&quot;Creating&quot;</parameter>
</parameters>
<subActions />
</action>
<subInstructions />
</instruction>
</actions>
<events />
</event>
@@ -167,9 +170,10 @@
<cameras>
<camera defaultSize="true" defaultViewport="true" height="0.000000" viewportBottom="1.000000" viewportLeft="0.000000" viewportRight="1.000000" viewportTop="0.000000" width="0.000000" />
</cameras>
<effects />
</layer>
</layers>
<automatismsSharedData />
<behaviorsSharedData />
</layout>
</layouts>
<externalEvents />

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"SubTexture":[{"frameY":0,"y":234,"frameWidth":112,"frameX":0,"frameHeight":210,"width":111,"height":209,"name":"parts/tailTip","x":456},{"width":112,"y":234,"height":86,"name":"parts/armUpperL","x":340},{"width":48,"y":859,"height":80,"name":"parts/armL","x":373},{"width":96,"y":922,"height":78,"name":"parts/handL","x":1},{"frameY":0,"y":677,"frameWidth":204,"frameX":0,"frameHeight":180,"width":203,"height":180,"name":"parts/legL","x":238},{"frameY":0,"y":397,"frameWidth":236,"frameX":0,"frameHeight":348,"width":235,"height":347,"name":"parts/body","x":1},{"width":216,"y":397,"height":278,"name":"parts/tail","x":238},{"width":208,"y":746,"height":174,"name":"parts/clothes1","x":1},{"width":124,"y":677,"height":282,"name":"parts/hair","x":443},{"frameY":0,"y":1,"frameWidth":338,"frameX":0,"frameHeight":394,"width":337,"height":394,"name":"parts/head","x":1},{"width":28,"y":961,"height":46,"name":"parts/eyeL","x":459},{"frameY":0,"y":961,"frameWidth":38,"frameX":0,"frameHeight":58,"width":37,"height":58,"name":"parts/eyeR","x":420},{"frameY":0,"y":1,"frameWidth":180,"frameX":0,"frameHeight":232,"width":180,"height":231,"name":"parts/legR","x":340},{"width":160,"y":859,"height":94,"name":"parts/armUpperR","x":211},{"frameY":0,"y":941,"frameWidth":46,"frameX":0,"frameHeight":78,"width":45,"height":77,"name":"parts/armR","x":373},{"width":98,"y":322,"height":58,"name":"parts/handR","x":340},{"frameY":0,"y":955,"frameWidth":120,"frameX":0,"frameHeight":36,"width":119,"height":36,"name":"parts/beardL","x":237},{"width":136,"y":955,"height":36,"name":"parts/beardR","x":99}],"width":1024,"height":1024,"name":"dragon","imagePath":"dragon_tex.png"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

View File

@@ -167,7 +167,7 @@ private:
/**
* Initialize from another list of events, copying events. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const gd::EventsList & other);
};

View File

@@ -879,6 +879,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(gd:
extension.AddExpression("Count", _("Number of objects"), _("Count the number of the specified objects currently picked"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"));
obj.AddStrExpression("ObjectName", _("Object name"), _("Return the name of the object"), _("Objects"), "res/conditions/text.png")
.AddParameter("object", _("Object"));
#endif
}

View File

@@ -102,7 +102,7 @@ private:
/**
* Initialize from another ExternalEvents. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const ExternalEvents & externalEvents);
};

View File

@@ -493,7 +493,7 @@ private:
/**
* Initialize from another layout. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const gd::Layout & other);
};

View File

@@ -321,7 +321,7 @@ protected:
/**
* Initialize object using another object. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const gd::Object & object);
};

View File

@@ -742,7 +742,7 @@ private:
/**
* Initialize from another game. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const gd::Project & project);

View File

@@ -210,4 +210,34 @@ void Variable::RemoveRecursively(const gd::Variable& variableToRemove)
}
}
}
Variable::Variable(const Variable& other) :
value(other.value),
str(other.str),
isNumber(other.isNumber),
isStructure(other.isStructure)
{
CopyChildren(other);
}
Variable& Variable::operator=(const Variable& other)
{
if (this != &other) {
value = other.value;
str = other.str;
isNumber = other.isNumber;
isStructure = other.isStructure;
CopyChildren(other);
}
return *this;
}
void Variable::CopyChildren(const gd::Variable& other)
{
children.clear();
for (auto& it : other.children) {
children[it.first] = std::make_shared<gd::Variable>(*it.second);
}
}
}

View File

@@ -30,8 +30,11 @@ public:
* \brief Default constructor creating a variable with 0 as value.
*/
Variable() : value(0), isNumber(true), isStructure(false) {};
Variable(const Variable&);
virtual ~Variable() {};
Variable& operator=(const Variable & rhs);
/** \name Number or string
* Methods and operators used when the variable is considered as a number or a string.
*/
@@ -207,6 +210,11 @@ private:
mutable bool isNumber; ///< True if the type of the variable is a number.
mutable bool isStructure; ///< False when the variable is a primitive ( i.e: Number or String ), true when it is a structure and has may have children.
mutable std::map<gd::String, std::shared_ptr<Variable>> children; ///<Children, when the variable is considered as a structure.
/**
* Initialize children by copying them from another variable. Used by copy-ctor and assign-op.
*/
void CopyChildren(const Variable & other);
};
}

View File

@@ -63,7 +63,7 @@ const Variable& VariablesContainer::Get(const gd::String& name) const
return badVariable;
}
Variable & VariablesContainer::Get(std::size_t index)
Variable& VariablesContainer::Get(std::size_t index)
{
if (index < variables.size())
return *variables[index].second;
@@ -71,7 +71,7 @@ Variable & VariablesContainer::Get(std::size_t index)
return badVariable;
}
const Variable & VariablesContainer::Get(std::size_t index) const
const Variable& VariablesContainer::Get(std::size_t index) const
{
if (index < variables.size())
return *variables[index].second;
@@ -79,7 +79,7 @@ const Variable & VariablesContainer::Get(std::size_t index) const
return badVariable;
}
const gd::String & VariablesContainer::GetNameAt(std::size_t index) const
const gd::String& VariablesContainer::GetNameAt(std::size_t index) const
{
if (index < variables.size())
return variables[index].first;
@@ -191,4 +191,27 @@ void VariablesContainer::UnserializeFrom(const SerializerElement& element)
Insert(variableElement.GetStringAttribute("name", "", "Name"), variable, -1);
}
}
VariablesContainer::VariablesContainer(const VariablesContainer& other)
{
Init(other);
}
VariablesContainer& VariablesContainer::operator=(const VariablesContainer& other)
{
if (this != &other)
Init(other);
return *this;
}
void VariablesContainer::Init(const gd::VariablesContainer& other)
{
variables.clear();
for (auto& it : other.variables) {
variables.push_back(std::make_pair(
it.first,
std::make_shared<gd::Variable>(*it.second)));
}
}
}

View File

@@ -30,8 +30,11 @@ class GD_CORE_API VariablesContainer
{
public:
VariablesContainer();
VariablesContainer(const VariablesContainer&);
virtual ~VariablesContainer() {};
VariablesContainer& operator=(const VariablesContainer & rhs);
/** \name Variables management
* Members functions related to variables management.
*/
@@ -149,6 +152,12 @@ private:
std::vector < std::pair<gd::String, std::shared_ptr<gd::Variable>> > variables;
static gd::Variable badVariable;
static gd::String badName;
/**
* Initialize from another variables container, copying elements. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed!
*/
void Init(const VariablesContainer & other);
};
}

View File

@@ -143,7 +143,7 @@ protected:
/**
* Initialize from another list of elements, copying elements. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed !
* Don't forget to update me if members were changed!
*/
void Init(const SPtrList<T> & other);
};

View File

@@ -26,48 +26,6 @@ TEST_CASE( "Project", "[common]" ) {
REQUIRE( project.GetName() == "myname" );
}
}
TEST_CASE( "Variable", "[common]" ) {
SECTION("Basics") {
gd::Variable variable;
variable.SetValue(50);
REQUIRE( variable.GetValue() == 50 );
REQUIRE( variable == 50 );
REQUIRE( variable.IsNumber() == true );
REQUIRE( variable.IsStructure() == false );
variable.SetString("MyString");
REQUIRE( variable.GetString() == "MyString" );
REQUIRE( variable == "MyString" );
REQUIRE( variable.IsNumber() == false );
REQUIRE( variable.IsStructure() == false );
}
SECTION("Conversions") {
gd::Variable variable;
variable.SetValue(50);
REQUIRE( variable.GetString() == "50" ); //Used as a string...
REQUIRE( variable.IsNumber() == false ); //...so consider as a string
variable.SetString("MyString");
REQUIRE( variable.GetValue() == 0 ); //Used as a number...
REQUIRE( variable.IsNumber() == true ); //...so consider as a number
}
SECTION("Use with int and string like semantics") {
gd::Variable variable;
variable = 50;
REQUIRE( variable.GetValue() == 50 );
REQUIRE( variable.IsNumber() == true );
variable = "MyString";
REQUIRE( variable.GetString() == "MyString" );
REQUIRE( variable.IsNumber() == false );
variable = "MyRealStdString";
REQUIRE( variable.GetString() == "MyRealStdString" );
REQUIRE( variable.IsNumber() == false );
}
}
TEST_CASE( "EventsList", "[common][events]" ) {
SECTION("Basics") {
gd::EventsList list;

89
Core/tests/Variable.cpp Normal file
View File

@@ -0,0 +1,89 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the MIT License.
*/
/**
* @file Tests covering events of GDevelop Core.
*/
#include "catch.hpp"
#include <algorithm>
#include <initializer_list>
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/Project/VariablesContainer.h"
TEST_CASE( "Variable", "[common][variables]" ) {
SECTION("Basics") {
gd::Variable variable;
variable.SetValue(50);
REQUIRE( variable.GetValue() == 50 );
REQUIRE( variable == 50 );
REQUIRE( variable.IsNumber() == true );
REQUIRE( variable.IsStructure() == false );
variable.SetString("MyString");
REQUIRE( variable.GetString() == "MyString" );
REQUIRE( variable == "MyString" );
REQUIRE( variable.IsNumber() == false );
REQUIRE( variable.IsStructure() == false );
}
SECTION("Conversions") {
gd::Variable variable;
variable.SetValue(50);
REQUIRE( variable.GetString() == "50" ); //Used as a string...
REQUIRE( variable.IsNumber() == false ); //...so consider as a string
variable.SetString("MyString");
REQUIRE( variable.GetValue() == 0 ); //Used as a number...
REQUIRE( variable.IsNumber() == true ); //...so consider as a number
}
SECTION("Use with int and string like semantics") {
gd::Variable variable;
variable = 50;
REQUIRE( variable.GetValue() == 50 );
REQUIRE( variable.IsNumber() == true );
variable = "MyString";
REQUIRE( variable.GetString() == "MyString" );
REQUIRE( variable.IsNumber() == false );
variable = "MyRealStdString";
REQUIRE( variable.GetString() == "MyRealStdString" );
REQUIRE( variable.IsNumber() == false );
}
SECTION("Copy and assignment") {
gd::Variable variable1;
gd::Variable variable2;
variable1.GetChild("Child1").SetString("Hello World");
variable1.GetChild("Child2").SetValue(42);
gd::Variable variable3(variable1);
variable2 = variable1;
REQUIRE( variable2.HasChild("Child1") == true );
REQUIRE( variable2.HasChild("Child2") == true );
REQUIRE( variable3.HasChild("Child1") == true );
REQUIRE( variable3.HasChild("Child2") == true );
REQUIRE( variable1.GetChild("Child1").GetString() == "Hello World" );
REQUIRE( variable1.GetChild("Child2").GetValue() == 42 );
REQUIRE( variable2.GetChild("Child1").GetString() == "Hello World" );
REQUIRE( variable2.GetChild("Child2").GetValue() == 42 );
REQUIRE( variable3.GetChild("Child1").GetString() == "Hello World" );
REQUIRE( variable3.GetChild("Child2").GetValue() == 42 );
variable2.GetChild("Child1").SetString("Hello copied World");
variable2.GetChild("Child2").SetValue(43);
variable3.GetChild("Child1").SetString("Hello second copied World");
variable3.GetChild("Child2").SetValue(44);
REQUIRE( variable1.GetChild("Child1").GetString() == "Hello World" );
REQUIRE( variable1.GetChild("Child2").GetValue() == 42 );
REQUIRE( variable2.GetChild("Child1").GetString() == "Hello copied World" );
REQUIRE( variable2.GetChild("Child2").GetValue() == 43 );
REQUIRE( variable3.GetChild("Child1").GetString() == "Hello second copied World" );
REQUIRE( variable3.GetChild("Child2").GetValue() == 44 );
}
}

View File

@@ -0,0 +1,52 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the MIT License.
*/
/**
* @file Tests covering events of GDevelop Core.
*/
#include "catch.hpp"
#include <algorithm>
#include <initializer_list>
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/Project/VariablesContainer.h"
TEST_CASE( "VariablesContainer", "[common][variables]" ) {
SECTION("Copy and assignment") {
gd::VariablesContainer container1;
gd::VariablesContainer container2;
container1.InsertNew("Variable1", 0).SetString("Hello World");
container1.InsertNew("Variable2", 0).SetValue(42);
gd::VariablesContainer container3(container1);
container2 = container1;
REQUIRE( container2.Has("Variable1") == true );
REQUIRE( container2.Has("Variable2") == true );
REQUIRE( container3.Has("Variable1") == true );
REQUIRE( container3.Has("Variable2") == true );
REQUIRE( container1.Get("Variable1").GetString() == "Hello World" );
REQUIRE( container1.Get("Variable2").GetValue() == 42 );
REQUIRE( container2.Get("Variable1").GetString() == "Hello World" );
REQUIRE( container2.Get("Variable2").GetValue() == 42 );
REQUIRE( container3.Get("Variable1").GetString() == "Hello World" );
REQUIRE( container3.Get("Variable2").GetValue() == 42 );
container2.Get("Variable1").SetString("Hello copied World");
container2.Get("Variable2").SetValue(43);
container3.Get("Variable1").SetString("Hello second copied World");
container3.Get("Variable2").SetValue(44);
REQUIRE( container1.Get("Variable1").GetString() == "Hello World" );
REQUIRE( container1.Get("Variable2").GetValue() == 42 );
REQUIRE( container2.Get("Variable1").GetString() == "Hello copied World" );
REQUIRE( container2.Get("Variable2").GetValue() == 43 );
REQUIRE( container3.Get("Variable1").GetString() == "Hello second copied World" );
REQUIRE( container3.Get("Variable2").GetValue() == 44 );
}
}

View File

@@ -41,6 +41,7 @@ ADD_SUBDIRECTORY(PhysicsBehavior)
ADD_SUBDIRECTORY(PlatformBehavior)
ADD_SUBDIRECTORY(PrimitiveDrawing)
ADD_SUBDIRECTORY(Shopify)
ADD_SUBDIRECTORY(SkeletonObject)
IF (NOT EMSCRIPTEN)
ADD_SUBDIRECTORY(SoundObject)
ENDIF()

View File

@@ -15,37 +15,162 @@ This project is released under the MIT License.
#include "Extension.h"
/**
* Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
Extension::Extension()
void DeclareParticleSystemExtension(gd::PlatformExtension & extension)
{
SetExtensionInformation("ParticleSystem",
_("Particle system"),
_("This Extension can display a large number of small particles."),
"Florian Rival",
"Open source (MIT License)");
extension.SetExtensionInformation("ParticleSystem",
_("Particle system"),
_("This Extension can display a large number of small particles."),
"Florian Rival",
"Open source (MIT License)");
//Declaration of all objects available
{
gd::ObjectMetadata & obj = AddObject<ParticleEmitterObject>(
"ParticleEmitter",
_("Particles emitter"),
_("Displays a large number of small particles to create visual effects."),
"CppPlatform/Extensions/particleSystemicon.png");
gd::ObjectMetadata & obj = extension.AddObject<ParticleEmitterObject>(
"ParticleEmitter",
_("Particles emitter"),
_("Displays a large number of small particles to create visual effects."),
"CppPlatform/Extensions/particleSystemicon.png");
AddRuntimeObject<ParticleEmitterObject, RuntimeParticleEmitterObject>(
obj, "RuntimeParticleEmitterObject");
#if defined(GD_IDE_ONLY)
#if defined(GD_IDE_ONLY)
obj.SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
//Declaration is too big to be compiled by GCC in one file, unless you have 4GB+ ram. :/
ExtensionSubDeclaration1(obj);
ExtensionSubDeclaration2(obj);
ExtensionSubDeclaration3(obj);
#endif
#endif
}
}
/**
* Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
ParticleSystemCppExtension::ParticleSystemCppExtension()
{
DeclareParticleSystemExtension(*this);
AddRuntimeObject<ParticleEmitterObject, RuntimeParticleEmitterObject>(
GetObjectMetadata("ParticleSystem::ParticleEmitter"),
"RuntimeParticleEmitterObject");
#if defined(GD_IDE_ONLY)
auto & actions = GetAllActionsForObject("ParticleSystem::ParticleEmitter");
auto & conditions = GetAllConditionsForObject("ParticleSystem::ParticleEmitter");
auto & expressions = GetAllExpressionsForObject("ParticleSystem::ParticleEmitter");
auto & strExpressions = GetAllStrExpressionsForObject("ParticleSystem::ParticleEmitter");
actions["ParticleSystem::EmitterForceMin"].SetFunctionName("SetEmitterForceMin").SetGetter("GetEmitterForceMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterForceMax"].SetFunctionName("SetEmitterForceMax").SetGetter("GetEmitterForceMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterXDirection"].SetFunctionName("SetEmitterXDirection").SetGetter("GetEmitterXDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterXDirection"].SetFunctionName("GetEmitterXDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterYDirection"].SetFunctionName("SetEmitterYDirection").SetGetter("GetEmitterYDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterYDirection"].SetFunctionName("GetEmitterYDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterZDirection"].SetFunctionName("SetEmitterZDirection").SetGetter("GetEmitterZDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterZDirection"].SetFunctionName("GetEmitterZDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterAngle"].SetFunctionName("SetAngle").SetGetter("GetAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterAngle"].SetFunctionName("GetAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterAngleA"].SetFunctionName("SetEmitterAngleA").SetGetter("GetEmitterAngleA").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterAngleA"].SetFunctionName("GetEmitterAngleA").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::EmitterAngleB"].SetFunctionName("SetEmitterAngleB").SetGetter("GetEmitterAngleB").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::EmitterAngleB"].SetFunctionName("GetEmitterAngleB").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ConeSprayAngle"].SetFunctionName("SetConeSprayAngle").SetGetter("GetConeSprayAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ConeSprayAngle"].SetFunctionName("GetConeSprayAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::Friction"].SetFunctionName("SetFriction").SetGetter("GetFriction").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::Friction"].SetFunctionName("GetFriction").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ZoneRadius"].SetFunctionName("SetZoneRadius").SetGetter("GetZoneRadius").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ZoneRadius"].SetFunctionName("GetZoneRadius").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleLifeTimeMin"].SetFunctionName("SetParticleLifeTimeMin").SetGetter("GetParticleLifeTimeMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleLifeTimeMin"].SetFunctionName("GetParticleLifeTimeMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleLifeTimeMax"].SetFunctionName("SetParticleLifeTimeMax").SetGetter("GetParticleLifeTimeMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleLifeTimeMax"].SetFunctionName("GetParticleLifeTimeMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGravityX"].SetFunctionName("SetParticleGravityX").SetGetter("GetParticleGravityX").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGravityX"].SetFunctionName("GetParticleGravityX").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGravityY"].SetFunctionName("SetParticleGravityY").SetGetter("GetParticleGravityY").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGravityY"].SetFunctionName("GetParticleGravityY").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGravityZ"].SetFunctionName("SetParticleGravityZ").SetGetter("GetParticleGravityZ").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGravityZ"].SetFunctionName("GetParticleGravityZ").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGravityAngle"].SetFunctionName("SetParticleGravityAngle").SetGetter("GetParticleGravityAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGravityAngle"].SetFunctionName("GetParticleGravityAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGravityLength"].SetFunctionName("SetParticleGravityLength").SetGetter("GetParticleGravityLength").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGravityLength"].SetFunctionName("GetParticleGravityLength").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleColor1"].SetFunctionName("SetParticleColor1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleColor2"].SetFunctionName("SetParticleColor2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleRed1"].SetFunctionName("SetParticleRed1").SetGetter("GetParticleRed1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleRed1"].SetFunctionName("GetParticleRed1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleRed2"].SetFunctionName("SetParticleRed2").SetGetter("GetParticleRed2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleRed2"].SetFunctionName("GetParticleRed2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleBlue1"].SetFunctionName("SetParticleBlue1").SetGetter("GetParticleBlue1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleBlue1"].SetFunctionName("GetParticleBlue1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleBlue2"].SetFunctionName("SetParticleBlue2").SetGetter("GetParticleBlue2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleBlue2"].SetFunctionName("GetParticleBlue2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGreen1"].SetFunctionName("SetParticleGreen1").SetGetter("GetParticleGreen1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGreen1"].SetFunctionName("GetParticleGreen1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleGreen2"].SetFunctionName("SetParticleGreen2").SetGetter("GetParticleGreen2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleGreen2"].SetFunctionName("GetParticleGreen2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleSize1"].SetFunctionName("SetParticleSize1").SetGetter("GetParticleSize1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleSize1"].SetFunctionName("GetParticleSize1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleSize2"].SetFunctionName("SetParticleSize2").SetGetter("GetParticleSize2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleSize2"].SetFunctionName("GetParticleSize2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleAngle1"].SetFunctionName("SetParticleAngle1").SetGetter("GetParticleAngle1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleAngle1"].SetFunctionName("GetParticleAngle1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleAngle2"].SetFunctionName("SetParticleAngle2").SetGetter("GetParticleAngle2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleAngle2"].SetFunctionName("GetParticleAngle2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleAlpha1"].SetFunctionName("SetParticleAlpha1").SetGetter("GetParticleAlpha1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleAlpha1"].SetFunctionName("GetParticleAlpha1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::ParticleAlpha2"].SetFunctionName("SetParticleAlpha2").SetGetter("GetParticleAlpha2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::ParticleAlpha2"].SetFunctionName("GetParticleAlpha2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::NoMoreParticles"].SetFunctionName("NoMoreParticles").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::RecreateParticleSystem"].SetFunctionName("RecreateParticleSystem").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::RendererParam1"].SetFunctionName("SetRendererParam1").SetGetter("GetRendererParam1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::RendererParam1"].SetFunctionName("GetRendererParam1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::RendererParam2"].SetFunctionName("SetRendererParam2").SetGetter("GetRendererParam2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::RendererParam2"].SetFunctionName("GetRendererParam2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::Tank"].SetFunctionName("SetTank").SetGetter("GetTank").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::Tank"].SetFunctionName("GetTank").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::Flow"].SetFunctionName("SetFlow").SetGetter("GetFlow").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::Flow"].SetFunctionName("GetFlow").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
actions["ParticleSystem::Texture"].SetFunctionName("SetTexture").SetGetter("GetTexture").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
conditions["ParticleSystem::Texture"].SetFunctionName("GetTexture").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
strExpressions["Texture"].SetFunctionName("GetTexture").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["NbParticles"].SetFunctionName("GetNbParticles").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["RendererParam1"].SetFunctionName("GetRendererParam1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["RendererParam2"].SetFunctionName("GetRendererParam2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["Tank"].SetFunctionName("GetTank").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["Flow"].SetFunctionName("GetFlow").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterForceMin"].SetFunctionName("GetEmitterForceMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterForceMax"].SetFunctionName("GetEmitterForceMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterXDirection"].SetFunctionName("GetEmitterXDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterYDirection"].SetFunctionName("GetEmitterYDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterZDirection"].SetFunctionName("GetEmitterZDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterAngle"].SetFunctionName("GetAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterAngleA"].SetFunctionName("GetEmitterAngleA").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["EmitterAngleB"].SetFunctionName("GetEmitterAngleB").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ZoneRadius"].SetFunctionName("GetZoneRadius").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGravityX"].SetFunctionName("GetParticleGravityX").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGravityY"].SetFunctionName("GetParticleGravityY").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGravityZ"].SetFunctionName("GetParticleGravityZ").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGravityAngle"].SetFunctionName("GetParticleGravityAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGravityLength"].SetFunctionName("GetParticleGravityLength").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["Friction"].SetFunctionName("GetFriction").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleLifeTimeMin"].SetFunctionName("GetParticleLifeTimeMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleLifeTimeMax"].SetFunctionName("GetParticleLifeTimeMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleRed1"].SetFunctionName("GetParticleRed1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleRed2"].SetFunctionName("GetParticleRed2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleBlue1"].SetFunctionName("GetParticleBlue1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleBlue2"].SetFunctionName("GetParticleBlue2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGreen1"].SetFunctionName("GetParticleGreen1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleGreen2"].SetFunctionName("GetParticleGreen2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleAlpha1"].SetFunctionName("GetParticleAlpha1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleAlpha2"].SetFunctionName("GetParticleAlpha2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleSize1"].SetFunctionName("GetParticleSize1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleSize2"].SetFunctionName("GetParticleSize2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleAngle1"].SetFunctionName("GetParticleAngle1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
expressions["ParticleAngle2"].SetFunctionName("GetParticleAngle2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
StripUnimplementedInstructionsAndExpressions();
#endif
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
@@ -55,5 +180,5 @@ Extension::Extension()
* -- Do not need to be modified. --
*/
extern "C" ExtensionBase * GD_EXTENSION_API CreateGDExtension() {
return new Extension;
return new ParticleSystemCppExtension;
}

View File

@@ -8,20 +8,18 @@ This project is released under the MIT License.
#ifndef EXTENSION_H_INCLUDED
#define EXTENSION_H_INCLUDED
namespace gd { class ObjectMetadata; }
namespace gd { class PlatformExtension; }
void DeclareParticleSystemExtension(gd::PlatformExtension & extension);
/**
* \brief This class declares information about the extension.
*/
class Extension : public ExtensionBase
class ParticleSystemCppExtension : public ExtensionBase
{
public:
Extension();
virtual ~Extension() {};
private:
void ExtensionSubDeclaration1(gd::ObjectMetadata & objInfos);
void ExtensionSubDeclaration2(gd::ObjectMetadata & objInfos);
void ExtensionSubDeclaration3(gd::ObjectMetadata & objInfos);
ParticleSystemCppExtension();
virtual ~ParticleSystemCppExtension() {};
};
#endif // EXTENSION_H_INCLUDED

View File

@@ -9,12 +9,11 @@ This project is released under the MIT License.
#include "Extension.h"
#include "ParticleEmitterObject.h"
#include "ParticleEmitterObject.h"
/**
* Declare some actions and conditions of the particle emitter
*/
void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
void ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
{
#if defined(GD_IDE_ONLY)
obj.AddAction("EmitterForceMin",
@@ -27,8 +26,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterForceMin").SetManipulatedType("number").SetGetter("GetEmitterForceMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterForceMax",
_("Emission maximal force"),
@@ -40,8 +38,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterForceMax").SetManipulatedType("number").SetGetter("GetEmitterForceMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterXDirection",
_("Emission X direction"),
@@ -53,8 +50,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterXDirection").SetManipulatedType("number").SetGetter("GetEmitterXDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("EmitterXDirection",
_("Emission X direction"),
@@ -66,8 +62,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetEmitterXDirection").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterYDirection",
@@ -80,8 +75,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterYDirection").SetManipulatedType("number").SetGetter("GetEmitterYDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("EmitterYDirection",
_("Emission Y direction"),
@@ -93,8 +87,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetEmitterYDirection").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterZDirection",
@@ -107,8 +100,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterZDirection").SetManipulatedType("number").SetGetter("GetEmitterZDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("EmitterZDirection",
@@ -121,8 +113,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetEmitterZDirection").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterAngle",
@@ -135,7 +126,6 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetAngle").SetManipulatedType("number").SetGetter("GetAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
@@ -149,8 +139,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetAngle").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterAngleA",
_("Emission angle 1"),
@@ -162,8 +151,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterAngleA").SetManipulatedType("number").SetGetter("GetEmitterAngleA").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("EmitterAngleA",
@@ -176,8 +164,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetEmitterAngleA").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("EmitterAngleB",
@@ -190,8 +177,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetEmitterAngleB").SetManipulatedType("number").SetGetter("GetEmitterAngleB").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("EmitterAngleB",
@@ -204,8 +190,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetEmitterAngleB").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ConeSprayAngle",
@@ -218,8 +203,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetConeSprayAngle").SetManipulatedType("number").SetGetter("GetConeSprayAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ConeSprayAngle",
_("Angle of the spray cone"),
@@ -231,8 +215,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetConeSprayAngle").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("Friction",
_("Friction"),
@@ -244,8 +227,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetFriction").SetManipulatedType("number").SetGetter("GetFriction").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number").SetGetter("GetFriction");
obj.AddCondition("Friction",
@@ -259,8 +241,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetFriction").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ZoneRadius",
@@ -273,8 +254,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetZoneRadius").SetManipulatedType("number").SetGetter("GetZoneRadius").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ZoneRadius",
@@ -287,8 +267,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetZoneRadius").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleLifeTimeMin",
@@ -301,8 +280,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleLifeTimeMin").SetManipulatedType("number").SetGetter("GetParticleLifeTimeMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleLifeTimeMin",
_("Minimum lifetime"),
@@ -314,8 +292,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleLifeTimeMin").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleLifeTimeMax",
_("Maximum lifetime"),
@@ -327,8 +304,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleLifeTimeMax").SetManipulatedType("number").SetGetter("GetParticleLifeTimeMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleLifeTimeMax",
@@ -341,8 +317,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleLifeTimeMax").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGravityX",
@@ -355,8 +330,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGravityX").SetManipulatedType("number").SetGetter("GetParticleGravityX").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGravityX",
@@ -369,8 +343,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGravityX").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGravityY",
@@ -383,8 +356,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGravityY").SetManipulatedType("number").SetGetter("GetParticleGravityY").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGravityY",
@@ -397,8 +369,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGravityY").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGravityZ",
@@ -411,8 +382,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGravityZ").SetManipulatedType("number").SetGetter("GetParticleGravityZ").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGravityZ",
@@ -425,8 +395,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGravityZ").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGravityAngle",
_("Gravity angle"),
@@ -438,8 +407,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGravityAngle").SetManipulatedType("number").SetGetter("GetParticleGravityAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGravityAngle",
_("Gravity angle"),
@@ -451,8 +419,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGravityAngle").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGravityLength",
_("Gravity"),
@@ -464,8 +431,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGravityLength").SetManipulatedType("number").SetGetter("GetParticleGravityLength").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGravityLength",
_("Gravity"),
@@ -477,8 +443,7 @@ void Extension::ExtensionSubDeclaration1(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGravityLength").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
#endif
}

View File

@@ -1,8 +1,8 @@
#ifndef EXTENSIONSUBDECLARATION1_H
#define EXTENSIONSUBDECLARATION1_H
class ExtensionObjectInfos;
void ExtensionSubDeclaration1(ExtensionObjectInfos & objInfos);
namespace gd { class ObjectMetadata; }
void ExtensionSubDeclaration1(gd::ObjectMetadata & objInfos);
#endif // EXTENSIONSUBDECLARATION1_H

View File

@@ -13,7 +13,7 @@ This project is released under the MIT License.
/**
* Declare some actions and conditions of the particle emitter
*/
void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
void ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
{
#if defined(GD_IDE_ONLY)
obj.AddAction("ParticleColor1",
@@ -24,9 +24,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("color", _("Initial color"))
.SetFunctionName("SetParticleColor1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("color", _("Initial color"));
obj.AddAction("ParticleColor2",
_("Final color"),
@@ -36,9 +34,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("color", _("Final color"))
.SetFunctionName("SetParticleColor2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("color", _("Final color"));
obj.AddAction("ParticleRed1",
_("Red color, parameter 1"),
@@ -50,8 +46,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleRed1").SetManipulatedType("number").SetGetter("GetParticleRed1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleRed1",
_("Red color, parameter 1"),
@@ -63,8 +58,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleRed1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleRed2",
_("Red color, parameter 2"),
@@ -76,8 +70,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleRed2").SetManipulatedType("number").SetGetter("GetParticleRed2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleRed2",
_("Red color, parameter 2"),
@@ -89,8 +82,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleRed2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleBlue1",
_("Blue color, parameter 1"),
@@ -102,8 +94,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleBlue1").SetManipulatedType("number").SetGetter("GetParticleBlue1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleBlue1",
_("Blue color, parameter 1"),
@@ -115,8 +106,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleBlue1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleBlue2",
_("Blue color, parameter 2"),
@@ -128,8 +118,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleBlue2").SetManipulatedType("number").SetGetter("GetParticleBlue2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleBlue2",
_("Blue color, parameter 2"),
@@ -141,8 +130,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleBlue2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGreen1",
_("Green color, parameter 1"),
@@ -154,8 +142,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGreen1").SetManipulatedType("number").SetGetter("GetParticleGreen1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGreen1",
_("Green color, parameter 1"),
@@ -167,8 +154,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGreen1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleGreen2",
@@ -181,8 +167,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleGreen2").SetManipulatedType("number").SetGetter("GetParticleGreen2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleGreen2",
_("Green color, parameter 2"),
@@ -194,8 +179,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleGreen2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleSize1",
@@ -208,8 +192,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleSize1").SetManipulatedType("number").SetGetter("GetParticleSize1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleSize1",
_("SIze, parameter 1"),
@@ -221,8 +204,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleSize1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleSize2",
_("Size, parameter 2"),
@@ -234,8 +216,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleSize2").SetManipulatedType("number").SetGetter("GetParticleSize2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleSize2",
_("Size, parameter 2"),
@@ -247,8 +228,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleSize2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleAngle1",
_("Angle, parameter 1"),
@@ -260,8 +240,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleAngle1").SetManipulatedType("number").SetGetter("GetParticleAngle1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleAngle1",
_("Angle, parameter 1"),
@@ -273,8 +252,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleAngle1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleAngle2",
_("Angle, parameter 2"),
@@ -286,8 +264,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleAngle2").SetManipulatedType("number").SetGetter("GetParticleAngle2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleAngle2",
_("Angle, parameter 2"),
@@ -299,8 +276,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleAngle2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleAlpha1",
_("Transparency, parameter 1"),
@@ -312,8 +288,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleAlpha1").SetManipulatedType("number").SetGetter("GetParticleAlpha1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleAlpha1",
_("Transparency, parameter 1"),
@@ -325,8 +300,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleAlpha1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("ParticleAlpha2",
_("Transparency, parameter 2"),
@@ -338,8 +312,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetParticleAlpha2").SetManipulatedType("number").SetGetter("GetParticleAlpha2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("ParticleAlpha2",
@@ -352,8 +325,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetParticleAlpha2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("NoMoreParticles",
@@ -363,9 +335,7 @@ void Extension::ExtensionSubDeclaration2(gd::ObjectMetadata & obj)
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.SetFunctionName("NoMoreParticles").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter");
#endif
}

View File

@@ -1,10 +1,10 @@
#ifndef EXTENSIONSUBDECLARATION1_H
#define EXTENSIONSUBDECLARATION1_H
#ifndef EXTENSIONSUBDECLARATION2_H
#define EXTENSIONSUBDECLARATION2_H
class ExtensionObjectInfos;
void ExtensionSubDeclaration2(ExtensionObjectInfos & objInfos);
namespace gd { class ObjectMetadata; }
void ExtensionSubDeclaration2(gd::ObjectMetadata & objInfos);
#endif // EXTENSIONSUBDECLARATION1_H
#endif // EXTENSIONSUBDECLARATION2_H

View File

@@ -13,7 +13,7 @@ This project is released under the MIT License.
/**
* Declare some actions, conditions and expressions of the particle emitter
*/
void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
void ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
{
#if defined(GD_IDE_ONLY)
obj.AddAction("RecreateParticleSystem",
@@ -23,9 +23,7 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.SetFunctionName("RecreateParticleSystem").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter");
obj.AddAction("RendererParam1",
_("Rendering first parameter"),
@@ -37,11 +35,10 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetRendererParam1").SetManipulatedType("number").SetGetter("GetRendererParam1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("RendererParam1",
_("Direction of gravity on Z axis"),
_("Rendering first parameter"),
_("Test the first parameter of rendering ( Size/Length )."),
_("The 1nd rendering parameter of _PARAM0_ is _PARAM1__PARAM2_"),
_("Setup"),
@@ -51,8 +48,7 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetRendererParam1").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("RendererParam2",
_("Rendering second parameter"),
@@ -64,8 +60,7 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetRendererParam2").SetManipulatedType("number").SetGetter("GetRendererParam2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("RendererParam2",
_("Rendering second parameter"),
@@ -77,8 +72,7 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetRendererParam2").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("Tank",
@@ -91,8 +85,7 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetTank").SetManipulatedType("number").SetGetter("GetTank").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("Tank",
_("Capacity"),
@@ -104,22 +97,20 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetTank").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("Flow",
_("Flow"),
_("Change the flow of the emitter."),
_("Do _PARAM1__PARAM2_ to flow of _PARAM0_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
_("Flow"),
_("Change the flow of the emitter."),
_("Do _PARAM1__PARAM2_ to flow of _PARAM0_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetFunctionName("SetFlow").SetManipulatedType("number").SetGetter("GetFlow").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddCondition("Flow",
@@ -132,21 +123,18 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value to test"))
.SetFunctionName("GetFlow").SetManipulatedType("number").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("number");
obj.AddAction("Texture",
_("Image"),
_("Change the image of particles ( if displayed )."),
_("Change the image of particles of _PARAM0_ to _PARAM1_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
_("Image"),
_("Change the image of particles ( if displayed )."),
_("Change the image of particles of _PARAM0_ to _PARAM1_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("string", _("New image"))
.SetFunctionName("SetTexture").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("string", _("New image"));
obj.AddCondition("Texture",
_("Image"),
@@ -158,123 +146,87 @@ void Extension::ExtensionSubDeclaration3(gd::ObjectMetadata & obj)
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("string", _("Text to test"))
.SetFunctionName("GetTexture").SetManipulatedType("string").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.SetManipulatedType("string");
obj.AddStrExpression("Texture", _("Particles image"), _("Name of the image displayed by particles"), _("Particles"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetTexture").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("NbParticles", _("Particles number"), _("Particles number"), _("Particles"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetNbParticles").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("RendererParam1", _("Rendering first parameter"), _("Rendering first parameter"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetRendererParam1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("RendererParam2", _("Rendering second parameter"), _("Rendering second parameter"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetRendererParam2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("Tank", _("Capacity"), _("Capacity"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetTank").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("Flow", _("Flow"), _("Flow"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetFlow").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterForceMin", _("Emission minimal force"), _("Emission minimal force"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterForceMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterForceMax", _("Emission maximal force"), _("Emission maximal force"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterForceMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterXDirection", _("Emission X direction"), _("Emission X direction"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterXDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterYDirection", _("Emission Y direction"), _("Emission Y direction"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterYDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterZDirection", _("Emission Z direction"), _("Emission Z direction"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterZDirection").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterAngle", _("Emission angle"), _("Emission angle"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterAngleA", _("Emission angle A"), _("Emission angle A"), _("Advanced"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterAngleA").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterAngleB", _("Emission angle B"), _("Emission angle B"), _("Advanced"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetEmitterAngleB").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ZoneRadius", _("Radius of the emission zone"), _("Radius of the emission zone"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetZoneRadius").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityX", _("X Gravity of particles"), _("X Gravity of particles"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGravityX").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityY", _("Y Gravity of particles"), _("Y Gravity of particles"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGravityY").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityZ", _("Z Gravity of particles"), _("Z Gravity of particles"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGravityZ").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityAngle", _("Gravity angle"), _("Gravity angle"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGravityAngle").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityLength", _("Gravity"), _("Gravity value"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGravityLength").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("Friction", _("Particles friction"), _("Particles friction"), _("Common"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetFriction").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleLifeTimeMin", _("Minimum lifetime of particles"), _("Minimum lifetime of particles"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleLifeTimeMin").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleLifeTimeMax", _("Maximum lifetime of particles"), _("Maximum lifetime of particles"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleLifeTimeMax").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleRed1", _("Parameter 1 of red color"), _("Parameter 1 of red color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleRed1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleRed2", _("Parameter 2 of red color"), _("Parameter 2 of red color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleRed2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleBlue1", _("Parameter 1 of blue color"), _("Parameter 1 of blue color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleBlue1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleBlue2", _("Parameter 2 of blue color"), _("Parameter 2 of blue color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleBlue2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGreen1", _("Parameter 1 of green color"), _("Parameter 1 of green color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGreen1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGreen2", _("Parameter 2 of green color"), _("Parameter 2 of green color"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleGreen2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAlpha1", _("Parameter 1 of transparency"), _("Parameter 1 of transparency"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleAlpha1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAlpha2", _("Parameter 2 of transparency"), _("Parameter 2 of transparency"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleAlpha2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleSize1", _("Parameter 1 of size"), _("Parameter 1 of size"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleSize1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleSize2", _("Parameter 2 of size"), _("Parameter 2 of size"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleSize2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAngle1", _("Parameter 1 of angle"), _("Parameter 1 of angle"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleAngle1").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAngle2", _("Parameter 2 of angle"), _("Parameter 2 of angle"), _("Setup"), "CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false)
.SetFunctionName("GetParticleAngle2").SetIncludeFile("ParticleSystem/ParticleEmitterObject.h");
.AddParameter("object", _("Object"), "ParticleEmitter", false);
#endif
}

View File

@@ -1,10 +1,10 @@
#ifndef EXTENSIONSUBDECLARATION1_H
#define EXTENSIONSUBDECLARATION1_H
#ifndef EXTENSIONSUBDECLARATION3_H
#define EXTENSIONSUBDECLARATION3_H
class ExtensionObjectInfos;
void ExtensionSubDeclaration3(ExtensionObjectInfos & objInfos);
namespace gd { class ObjectMetadata; }
void ExtensionSubDeclaration3(gd::ObjectMetadata & objInfos);
#endif // EXTENSIONSUBDECLARATION1_H
#endif // EXTENSIONSUBDECLARATION3_H

View File

@@ -0,0 +1,138 @@
/**
GDevelop - Particle System Extension
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/Extensions/PlatformExtension.h"
#include "ParticleEmitterObject.h"
void DeclareParticleSystemExtension(gd::PlatformExtension & extension);
/**
* Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
class ParticleSystemJsExtension : public gd::PlatformExtension
{
public:
/**
* Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
ParticleSystemJsExtension()
{
DeclareParticleSystemExtension(*this);
GetObjectMetadata("ParticleSystem::ParticleEmitter")
.SetIncludeFile("Extensions/ParticleSystem/particleemitterobject.js")
.AddIncludeFile("Extensions/ParticleSystem/particleemitterobject-pixi-renderer.js")
.AddIncludeFile("Extensions/ParticleSystem/pixi-particles-pixi-renderer.min.js")
.AddIncludeFile("Extensions/ParticleSystem/particleemitterobject-cocos-renderer.js");
auto & actions = GetAllActionsForObject("ParticleSystem::ParticleEmitter");
auto & conditions = GetAllConditionsForObject("ParticleSystem::ParticleEmitter");
auto & expressions = GetAllExpressionsForObject("ParticleSystem::ParticleEmitter");
auto & strExpressions = GetAllStrExpressionsForObject("ParticleSystem::ParticleEmitter");
actions["ParticleSystem::EmitterForceMin"].SetFunctionName("setEmitterForceMin").SetGetter("getEmitterForceMin");
actions["ParticleSystem::EmitterForceMax"].SetFunctionName("setEmitterForceMax").SetGetter("getEmitterForceMax");
actions["ParticleSystem::EmitterAngle"].SetFunctionName("setAngle").SetGetter("getAngle");
conditions["ParticleSystem::EmitterAngle"].SetFunctionName("getAngle");
actions["ParticleSystem::EmitterAngleA"].SetFunctionName("setEmitterAngleA").SetGetter("getEmitterAngleA");
conditions["ParticleSystem::EmitterAngleA"].SetFunctionName("getEmitterAngleA");
actions["ParticleSystem::EmitterAngleB"].SetFunctionName("setEmitterAngleB").SetGetter("getEmitterAngleB");
conditions["ParticleSystem::EmitterAngleB"].SetFunctionName("getEmitterAngleB");
actions["ParticleSystem::ConeSprayAngle"].SetFunctionName("setConeSprayAngle").SetGetter("getConeSprayAngle");
conditions["ParticleSystem::ConeSprayAngle"].SetFunctionName("getConeSprayAngle");
actions["ParticleSystem::ZoneRadius"].SetFunctionName("setZoneRadius").SetGetter("getZoneRadius");
conditions["ParticleSystem::ZoneRadius"].SetFunctionName("getZoneRadius");
actions["ParticleSystem::ParticleLifeTimeMin"].SetFunctionName("setParticleLifeTimeMin").SetGetter("getParticleLifeTimeMin");
conditions["ParticleSystem::ParticleLifeTimeMin"].SetFunctionName("getParticleLifeTimeMin");
actions["ParticleSystem::ParticleLifeTimeMax"].SetFunctionName("setParticleLifeTimeMax").SetGetter("getParticleLifeTimeMax");
conditions["ParticleSystem::ParticleLifeTimeMax"].SetFunctionName("getParticleLifeTimeMax");
actions["ParticleSystem::ParticleGravityX"].SetFunctionName("setParticleGravityX").SetGetter("getParticleGravityX");
conditions["ParticleSystem::ParticleGravityX"].SetFunctionName("getParticleGravityX");
actions["ParticleSystem::ParticleGravityY"].SetFunctionName("setParticleGravityY").SetGetter("getParticleGravityY");
conditions["ParticleSystem::ParticleGravityY"].SetFunctionName("getParticleGravityY");
actions["ParticleSystem::ParticleGravityAngle"].SetFunctionName("setParticleGravityAngle").SetGetter("getParticleGravityAngle");
conditions["ParticleSystem::ParticleGravityAngle"].SetFunctionName("getParticleGravityAngle");
actions["ParticleSystem::ParticleGravityLength"].SetFunctionName("setParticleGravityLength").SetGetter("getParticleGravityLength");
conditions["ParticleSystem::ParticleGravityLength"].SetFunctionName("getParticleGravityLength");
actions["ParticleSystem::ParticleColor1"].SetFunctionName("setParticleColor1");
actions["ParticleSystem::ParticleColor2"].SetFunctionName("setParticleColor2");
actions["ParticleSystem::ParticleRed1"].SetFunctionName("setParticleRed1").SetGetter("getParticleRed1");
conditions["ParticleSystem::ParticleRed1"].SetFunctionName("getParticleRed1");
actions["ParticleSystem::ParticleRed2"].SetFunctionName("setParticleRed2").SetGetter("getParticleRed2");
conditions["ParticleSystem::ParticleRed2"].SetFunctionName("getParticleRed2");
actions["ParticleSystem::ParticleBlue1"].SetFunctionName("setParticleBlue1").SetGetter("getParticleBlue1");
conditions["ParticleSystem::ParticleBlue1"].SetFunctionName("getParticleBlue1");
actions["ParticleSystem::ParticleBlue2"].SetFunctionName("setParticleBlue2").SetGetter("getParticleBlue2");
conditions["ParticleSystem::ParticleBlue2"].SetFunctionName("getParticleBlue2");
actions["ParticleSystem::ParticleGreen1"].SetFunctionName("setParticleGreen1").SetGetter("getParticleGreen1");
conditions["ParticleSystem::ParticleGreen1"].SetFunctionName("getParticleGreen1");
actions["ParticleSystem::ParticleGreen2"].SetFunctionName("setParticleGreen2").SetGetter("getParticleGreen2");
conditions["ParticleSystem::ParticleGreen2"].SetFunctionName("getParticleGreen2");
actions["ParticleSystem::ParticleSize1"].SetFunctionName("setParticleSize1").SetGetter("getParticleSize1");
conditions["ParticleSystem::ParticleSize1"].SetFunctionName("getParticleSize1");
actions["ParticleSystem::ParticleSize2"].SetFunctionName("setParticleSize2").SetGetter("getParticleSize2");
conditions["ParticleSystem::ParticleSize2"].SetFunctionName("getParticleSize2");
actions["ParticleSystem::ParticleAlpha1"].SetFunctionName("setParticleAlpha1").SetGetter("getParticleAlpha1");
conditions["ParticleSystem::ParticleAlpha1"].SetFunctionName("getParticleAlpha1");
actions["ParticleSystem::ParticleAlpha2"].SetFunctionName("setParticleAlpha2").SetGetter("getParticleAlpha2");
conditions["ParticleSystem::ParticleAlpha2"].SetFunctionName("getParticleAlpha2");
conditions["ParticleSystem::NoMoreParticles"].SetFunctionName("noMoreParticles");
actions["ParticleSystem::RecreateParticleSystem"].SetFunctionName("recreateParticleSystem");
actions["ParticleSystem::Tank"].SetFunctionName("setTank").SetGetter("getTank");
conditions["ParticleSystem::Tank"].SetFunctionName("getTank");
actions["ParticleSystem::Flow"].SetFunctionName("setFlow").SetGetter("getFlow");
conditions["ParticleSystem::Flow"].SetFunctionName("getFlow");
actions["ParticleSystem::Texture"].AddCodeOnlyParameter("currentScene", "").SetFunctionName("setTexture").SetGetter("getTexture");
conditions["ParticleSystem::Texture"].SetFunctionName("getTexture");
strExpressions["Texture"].SetFunctionName("getTexture");
expressions["NbParticles"].SetFunctionName("getNbParticles");
expressions["RendererParam1"].SetFunctionName("getRendererParam1");
expressions["RendererParam2"].SetFunctionName("getRendererParam2");
expressions["Tank"].SetFunctionName("getTank");
expressions["Flow"].SetFunctionName("getFlow");
expressions["EmitterForceMin"].SetFunctionName("getEmitterForceMin");
expressions["EmitterForceMax"].SetFunctionName("getEmitterForceMax");
expressions["EmitterAngle"].SetFunctionName("getAngle");
expressions["EmitterAngleA"].SetFunctionName("getEmitterAngleA");
expressions["EmitterAngleB"].SetFunctionName("getEmitterAngleB");
expressions["ZoneRadius"].SetFunctionName("getZoneRadius");
expressions["ParticleGravityX"].SetFunctionName("getParticleGravityX");
expressions["ParticleGravityY"].SetFunctionName("getParticleGravityY");
expressions["ParticleGravityAngle"].SetFunctionName("getParticleGravityAngle");
expressions["ParticleGravityLength"].SetFunctionName("getParticleGravityLength");
expressions["ParticleLifeTimeMin"].SetFunctionName("getParticleLifeTimeMin");
expressions["ParticleLifeTimeMax"].SetFunctionName("getParticleLifeTimeMax");
expressions["ParticleRed1"].SetFunctionName("getParticleRed1");
expressions["ParticleRed2"].SetFunctionName("getParticleRed2");
expressions["ParticleBlue1"].SetFunctionName("getParticleBlue1");
expressions["ParticleBlue2"].SetFunctionName("getParticleBlue2");
expressions["ParticleGreen1"].SetFunctionName("getParticleGreen1");
expressions["ParticleGreen2"].SetFunctionName("getParticleGreen2");
expressions["ParticleAlpha1"].SetFunctionName("getParticleAlpha1");
expressions["ParticleAlpha2"].SetFunctionName("getParticleAlpha2");
expressions["ParticleSize1"].SetFunctionName("getParticleSize1");
expressions["ParticleSize2"].SetFunctionName("getParticleSize2");
StripUnimplementedInstructionsAndExpressions();
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
};
/**
* Used by GDevelop to create the extension class
* -- Do not need to be modified. --
*/
extern "C" gd::PlatformExtension * GD_EXTENSION_API CreateGDJSExtension() {
return new ParticleSystemJsExtension;
}
#endif

View File

@@ -0,0 +1,301 @@
/**
GDevelop - Particle System Extension
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
gdjs.ParticleEmitterObjectCocosRenderer = function(runtimeScene, runtimeObject, objectData){
var drawer = new cc.DrawNode();
var renderTexture = null;
this.originalSize = Math.max(objectData.rendererParam1, objectData.rendererParam2);
if(objectData.rendererType === "Point"){
drawer.drawDot(cc.p(objectData.rendererParam1, objectData.rendererParam1),
objectData.rendererParam1, cc.color(255,255,255,255));
this.originalSize = 2 * objectData.rendererParam1;
renderTexture = new cc.RenderTexture(this.originalSize, this.originalSize);
}
else if(objectData.rendererType === "Line"){
this.originalSize = Math.max(2*objectData.rendererParam1, objectData.rendererParam2);
drawer.drawRect(cc.p(this.originalSize/2.0,
(this.originalSize - objectData.rendererParam2)/2.0),
cc.p(this.originalSize/2.0 + objectData.rendererParam1,
(this.originalSize + objectData.rendererParam2)/2.0),
cc.color(255,255,255,255), 0.01 , cc.color(255,255,255,0));
renderTexture = new cc.RenderTexture(this.originalSize, this.originalSize);
}
else{
if(objectData.textureParticleName){
var imageManager = runtimeScene.getGame().getImageManager();
var sprite = new cc.Sprite(imageManager.getTexture(objectData.textureParticleName));
this.originalSize = Math.max(sprite.width, sprite.height);
sprite.setPosition( this.originalSize/2.0, this.originalSize/2.0);
drawer.addChild(sprite);
renderTexture = new cc.RenderTexture( this.originalSize, this.originalSize);
}
else{
drawer.drawRect(cc.p((this.originalSize - objectData.rendererParam1)/2.0,
(this.originalSize - objectData.rendererParam2)/2.0),
cc.p((this.originalSize + objectData.rendererParam1)/2.0,
(this.originalSize + objectData.rendererParam2)/2.0),
cc.color(255,255,255,255), 0.01 , cc.color(255,255,255,255));
renderTexture = new cc.RenderTexture(this.originalSize, this.originalSize);
}
}
renderTexture.begin();
drawer.visit();
renderTexture.end();
var texture = renderTexture.getSprite().getTexture();
var plist = {
duration: -1,
emitterType: 0,
gravityx: objectData.particleGravityX,
gravityy:-objectData.particleGravityY,
particleLifespan: (objectData.particleLifeTimeMin + objectData.particleLifeTimeMax)/2.0,
particleLifespanVariance: Math.abs(objectData.particleLifeTimeMax - objectData.particleLifeTimeMin)/2.0,
sourcePositionVariancex: objectData.zoneRadius,
sourcePositionVariancey: objectData.zoneRadius,
speed: (objectData.emitterForceMin + objectData.emitterForceMax)/2.0,
speedVariance: Math.abs(objectData.emitterForceMax - objectData.emitterForceMin)/2.0,
tangentialAccelVariance: 0.0,
tangentialAcceleration: 1,
rotationIsDir: "true",
// We are forced to use a texture name / base64 string, it's a one-pixel base64 image
textureImageData: "H4sIAAAAAAAAA+sM8HPn5ZLiYmBg4PX0cAkC0owgzMEEJCeUB98DUpwFHpHFDAzcwiDMyDBrjgRQkL3E09eV/RELu4CFwaX8heVAIdnMkIgS5/zc3NS8EgYQcC5KTSxJTVEozyzJUHD39A1I0UtlB4rzeLo4hnBcT/7x/789A+s/pn93zkQ+B2nwdPVzWeeU0AQAwMwOBZYAAAA="
};
if(objectData.emissionEditionSimpleMode){
plist.angle = 0;
plist.angleVariance = objectData.emitterAngleB/2.0;
}
else{
plist.angle = -(objectData.emitterAngleA + objectData.emitterAngleB)/2.0;
plist.angleVariance = Math.abs(plist.angle + objectData.emitterAngleB);
}
if(objectData.redParam === "Mutable"){
plist.startColorVarianceRed = plist.finishColorVarianceRed = 0.0;
plist.startColorRed = objectData.particleRed1/255.0;
plist.finishColorRed = objectData.particleRed2/255.0;
}
else if(objectData.redParam === "Random"){
plist.startColorRed = plist.finishColorRed = (objectData.particleRed1 + objectData.particleRed2)/(2.0*255.0);
plist.startColorVarianceRed = Math.abs(plist.startColorRed - objectData.particleRed2/255.0);
plist.finishColorVarianceRed = plist.startColorVarianceRed;
}
else{
plist.startColorVarianceRed = plist.finishColorVarianceRed = 0.0;
plist.startColorRed = objectData.particleRed1/255.0;
plist.finishColorRed = plist.startColorRed;
}
if(objectData.greenParam === "Mutable"){
plist.startColorVarianceGreen = plist.finishColorVarianceGreen = 0.0;
plist.startColorGreen = objectData.particleGreen1/255.0;
plist.finishColorGreen = objectData.particleGreen2/255.0;
}
else if(objectData.greenParam === "Random"){
plist.startColorGreen = plist.finishColorGreen = (objectData.particleGreen1 + objectData.particleGreen2)/(2.0*255.0);
plist.startColorVarianceGreen = Math.abs(plist.startColorGreen - objectData.particleGreen2/255.0);
plist.finishColorVarianceGreen = plist.startColorVarianceGreen;
}
else{
plist.startColorVarianceGreen = plist.finishColorVarianceGreen = 0.0;
plist.startColorGreen = objectData.particleGreen1/255.0;
plist.finishColorGreen = plist.startColorGreen;
}
if(objectData.blueParam === "Mutable"){
plist.startColorVarianceBlue = plist.finishColorVarianceBlue = 0.0;
plist.startColorBlue = objectData.particleBlue1/255.0;
plist.finishColorBlue = objectData.particleBlue2/255.0;
}
else if(objectData.blueParam === "Random"){
plist.startColorBlue = plist.finishColorBlue = (objectData.particleBlue1 + objectData.particleBlue2)/(2.0*255.0);
plist.startColorVarianceBlue = Math.abs(plist.startColorBlue - objectData.particleBlue2/255.0);
plist.finishColorVarianceBlue = plist.startColorVarianceBlue;
}
else{
plist.startColorVarianceBlue = plist.finishColorVarianceBlue = 0.0;
plist.startColorBlue = objectData.particleBlue1/255.0;
plist.finishColorBlue = plist.startColorBlue;
}
if(objectData.alphaParam === "Mutable"){
var alphaInit = (objectData.particleAlpha1 + objectData.particleAlphaRandomness1)/255.0;
var alphaEnd = (objectData.particleAlpha1 + objectData.particleAlphaRandomness2)/255.0;
plist.startColorAlpha = (alphaInit + alphaEnd)/2.0;
plist.startColorVarianceAlpha = alphaEnd - plist.startColorAlpha;
alphaInit = (objectData.particleAlpha2 + objectData.particleAlphaRandomness1)/255.0;
alphaEnd = (objectData.particleAlpha2 + objectData.particleAlphaRandomness2)/255.0;
plist.finishColorAlpha = (alphaInit + alphaEnd)/2.0;
plist.finishColorVarianceAlpha = alphaEnd - plist.finishColorAlpha;
}
else{
var alphaMid = (objectData.particleAlphaRandomness1 + objectData.particleAlphaRandomness2)/(2.0*255.0);
plist.startColorAlpha = plist.endColorAlpha = alphaMid;
plist.startColorVarianceAlpha = Math.abs(alphaMid - objectData.particleAlphaRandomness1);
plist.startColorVarianceAlpha = plist.finishColorVarianceAlpha;
}
if(objectData.sizeParam === "Mutable"){
var minSizeVariance = Math.min(objectData.particleSizeRandomness1, objectData.particleSizeRandomness2)/100.0;
var maxSizeVariance = Math.max(objectData.particleSizeRandomness1, objectData.particleSizeRandomness2)/100.0;
var midSizeVariance = (maxSizeVariance + minSizeVariance)/2.0;
plist.startParticleSizeVariance = this.originalSize*objectData.particleSize1/100.0*(maxSizeVariance - minSizeVariance)/2.0;
plist.finishParticleSizeVariance = this.originalSize*objectData.particleSize2/100.0*(maxSizeVariance - minSizeVariance)/2.0;
plist.startParticleSize = this.originalSize*objectData.particleSize1/100.0 - plist.startParticleSizeVariance;
plist.finishParticleSize = this.originalSize*objectData.particleSize2/100.0 - plist.finishParticleSizeVariance;
}
else{
var sizeMid = (objectData.particleSize1 + objectData.particleSize2)/(2.0*100.0);
plist.startParticleSize = plist.finishParticleSize = this.originalSize*sizeMid;
plist.startParticleSizeVariance = this.originalSize*Math.abs(sizeMid - objectData.particleSizeRandomness1/100.0);
plist.finishParticleSizeVariance = plist.startParticleSizeVariance;
}
if(objectData.angleParam === "Mutable"){
plist.rotationStart = objectData.particleAngle1 + (objectData.particleAngleRandomness1 + objectData.particleAngleRandomness2)/2.0;
plist.rotationEnd = objectData.particleAngle2 + (objectData.particleAngleRandomness1 + objectData.particleAngleRandomness2)/2.0;
plist.rotationStartVariance = Math.abs(objectData.particleAngleRandomness2 - objectData.particleAngleRandomness1)/2.0;
plist.rotationEndVariance = plist.rotationStartVariance;
}
else{
plist.rotationStart = plist.rotationEnd = (objectData.particleAngleRandomness1 + objectData.particleAngleRandomness2)/2.0;
plist.rotationStartVariance = Math.abs(objectData.particleAngleRandomness2 - objectData.particleAngleRandomness1)/2.0;
plist.rotationEndVariance = plist.rotationStartVariance;
}
this.renderer = new cc.ParticleSystem(plist);
this.renderer.setTexture(texture);
this.renderer.setPosition(0, 0);
this.renderer.init();
this.renderer.setBlendFunc(cc.SRC_ALPHA, cc.ONE_MINUS_SRC_ALPHA);
if(objectData.additive) this.renderer.setBlendAdditive(true);
this.renderer.setTotalParticles(objectData.maxParticleNb); // Some particle systems don't work for max particles <= 150
this.renderer.setEmissionRate(objectData.flow);
this.renderer.setDuration(objectData.tank < 0 ? -1 :
(objectData.flow < 0 ? 0.001 : objectData.tank / objectData.flow));
this.totalParticles = 0;
var that = this;
this.renderer.addParticle = function(){
cc.ParticleSystem.prototype.addParticle.call(that.renderer);
++that.totalParticles;
};
this.started = false;
var renderer = runtimeScene.getLayer("").getRenderer();
renderer.addRendererObject(this.renderer, runtimeObject.getZOrder());
this._convertYPosition = renderer.convertYPosition;
};
gdjs.ParticleEmitterObjectRenderer = gdjs.ParticleEmitterObjectCocosRenderer;
gdjs.ParticleEmitterObjectCocosRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.update = function(delta){
this.renderer.update(delta);
if(!this.started && this.getParticleCount() > 0){
this.started = true;
}
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setPosition = function(x, y){
this.renderer.setPosition(cc.p(x, this._convertYPosition(y)));
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setAngle = function(angle1, angle2){
this.renderer.setAngle(-(angle1 + angle2)/2.0);
this.renderer.setAngleVar(Math.abs(angle2 - angle1)/2.0);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setForce = function(min, max){
this.renderer.setSpeed((min + max)/2.0);
this.renderer.setSpeedVar(Math.abs(max - min)/2.0);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setZoneRadius = function(radius){
this.renderer.setPosVar(cc.p(radius, radius));
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setLifeTime = function(min, max){
this.renderer.setLife((min + max)/2.0);
this.renderer.setLifeVar(Math.abs(max - min)/2.0);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setGravity = function(x, y){
this.renderer.setGravity(cc.p(x, -y));
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setColor = function(r1, g1, b1, r2, g2, b2){
var a = this.renderer.getStartColor().a;
this.renderer.setStartColor(cc.color(r1, g1, b1, a));
a = this.renderer.getEndColor().a;
this.renderer.setEndColor(cc.color(r2, g2, b2, a));
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setAlpha = function(alpha1, alpha2){
var color = this.renderer.getStartColor();
color.a = alpha1;
this.renderer.setStartColor(color);
color = this.renderer.getEndColor();
color.a = alpha2;
this.renderer.setEndColor(color);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setSize = function(size1, size2){
this.renderer.setStartSize(this.originalSize*size1/100.0);
this.renderer.setEndSize(this.originalSize*size2/100.0);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setFlow = function(flow){
this.renderer.setEmissionRate(flow);
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.isTextureValid = function(texture, runtimeScene){
return runtimeScene.getGame().getImageManager().getTexture(texture)._textureLoaded;
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.setTexture = function(texture, runtimeScene){
var texture = runtimeScene.getGame().getImageManager().getTexture(texture);
if(texture._textureLoaded){
this.renderer.setTexture(texture);
}
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.getTotalParticleCount = function(){
return this.totalParticles;
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.getParticleCount = function(){
return this.renderer.getParticleCount();
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.stop = function(){
this.renderer.stopSystem();
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.recreate = function(){
this.renderer.resetSystem();
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.destroy = function(){
this.renderer.destroyParticleSystem();
};
gdjs.ParticleEmitterObjectCocosRenderer.prototype.hasStarted = function(){
return this.started;
};

View File

@@ -0,0 +1,260 @@
/**
GDevelop - Particle System Extension
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
gdjs.ParticleEmitterObjectPixiRenderer = function(runtimeScene, runtimeObject, objectData){
var texture = null;
var graphics = new PIXI.Graphics();
graphics.lineStyle(0, 0, 0);
graphics.beginFill(gdjs.rgbToHexNumber(255,255,255), 1);
if(objectData.rendererType === "Point")
graphics.drawCircle(0, 0, objectData.rendererParam1);
else if(objectData.rendererType === "Line"){
graphics.drawRect(objectData.rendererParam1, 0, objectData.rendererParam1, objectData.rendererParam2);
// Draw an almost-invisible rectangle in the left hand to force PIXI to take a full texture with our line at the right hand
graphics.beginFill(gdjs.rgbToHexNumber(255,255,255), 0.001);
graphics.drawRect(0, 0, objectData.rendererParam1, objectData.rendererParam2);
}
else{
if(objectData.textureParticleName){
var sprite = new PIXI.Sprite(runtimeScene.getGame().getImageManager().getPIXITexture(objectData.textureParticleName));
sprite.width = objectData.rendererParam1;
sprite.height = objectData.rendererParam2;
graphics.addChild(sprite);
}
else{
graphics.drawRect(0, 0, objectData.rendererParam1, objectData.rendererParam2);
}
}
graphics.endFill();
texture = graphics.generateTexture();
var config = {
color: {
list: [
{
value: gdjs.rgbToHexNumber(objectData.particleRed1,
objectData.particleGreen1,
objectData.particleBlue1).toString(16),
time: 0
},
{
value: gdjs.rgbToHexNumber(objectData.particleRed2,
objectData.particleGreen2,
objectData.particleBlue2).toString(16),
time: 1
}
],
isStepped: false
},
acceleration: {
x: objectData.particleGravityX,
y: objectData.particleGravityY
},
lifetime: {
min: objectData.particleLifeTimeMin,
max: objectData.particleLifeTimeMax
},
// A negative flow is "infinite flow" (all particles burst)
frequency: objectData.flow < 0 ? 0.0001 : 1.0/objectData.flow,
spawnChance: 1,
particlesPerWave: objectData.flow < 0 ? objectData.maxParticleNb : 1,
maxParticles: objectData.maxParticleNb,
// Lifetime can be computed from the tank (the number of particles available)
// and the flow (number of particles emitted per seconds)
emitterLifetime:
objectData.tank < 0 ? -1 :
(objectData.flow < 0 ? 0.001 : objectData.tank / objectData.flow),
pos: {
x: 0,
y: 0
},
addAtBack: false,
spawnType: "circle",
spawnCircle: {
x: 0,
y: 0,
r: objectData.zoneRadius
}
};
config.speed = { list: [{time: 0, value: objectData.emitterForceMax}],
minimumSpeedMultiplier: objectData.emitterForceMax !== 0 ?
objectData.emitterForceMin / objectData.emitterForceMax : 1,
isStepped: false };
if(objectData.alphaParam === "Mutable"){
config.alpha = { list: [{time: 0, value: objectData.particleAlpha1/255.0},
{time: 1, value: objectData.particleAlpha2/255.0}],
isStepped: false };
}
else{
config.alpha = { list: [{time: 0, value: objectData.particleAlpha1/255.0}],
isStepped: false };
}
if(objectData.sizeParam === "Mutable"){
var size1 = objectData.particleSize1/100;
var size2 = objectData.particleSize2/100;
var sizeRandom1 = objectData.particleSizeRandomness1/100;
var sizeRandom2 = objectData.particleSizeRandomness2/100;
var m = sizeRandom2 !== 0 ? (1 + sizeRandom1)/(1 + sizeRandom2) : 1;
config.scale = { list: [{time: 0, value: size1*(1 + sizeRandom1)},
{time: 1, value: size2*(1 + sizeRandom2)}],
minimumScaleMultiplier: m,
isStepped: false };
}
else{
var size1 = objectData.particleSize1/100;
var size2 = objectData.particleSize2/100;
var mult = size2 !== 0 ? (1 + size1)/(1 + size2) : 1;
if(size2 === 0 && size1 > size2){
mult = (1 + size2)/(1 + size1);
size2 = size1;
}
config.scale = { list: [{time: 0, value: size2}],
minimumScaleMultiplier: mult,
isStepped: false };
}
if(objectData.emissionEditionSimpleMode){
config.startRotation = { min:-objectData.emitterAngleB/2.0,
max: objectData.emitterAngleB/2.0 };
}
else{
config.startRotation = { min: objectData.emitterAngleA,
max: objectData.emitterAngleB };
}
if(objectData.angleParam === "Mutable"){
var mediumLifetime = (objectData.particleLifeTimeMin + objectData.particleLifeTimeMax)/2;
config.rotationSpeed = { min: objectData.particleAngle1/mediumLifetime,
max: objectData.particleAngle2/mediumLifetime };
}
else{
config.startRotation = { min: objectData.particleAngle1,
max: objectData.particleAngle2 };
config.rotationSpeed = { min: 0, max: 0 };
}
config.blendMode = objectData.additive ? "ADD" : "NORMAL";
this.renderer = new PIXI.Container();
this.emitter = new PIXI.particles.Emitter(this.renderer, texture, config);
this.emitter.emit = true;
this.started = false;
var layer = runtimeScene.getLayer("");
if (layer) layer.getRenderer().addRendererObject(this.renderer, runtimeObject.getZOrder());
};
gdjs.ParticleEmitterObjectRenderer = gdjs.ParticleEmitterObjectPixiRenderer;
gdjs.ParticleEmitterObjectPixiRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.update = function(delta){
this.emitter.update(delta);
if(!this.started && this.getParticleCount() > 0){
this.started = true;
}
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setPosition = function(x, y){
this.emitter.spawnPos.x = x;
this.emitter.spawnPos.y = y;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setAngle = function(angle1, angle2){
this.emitter.minStartRotation = angle1;
this.emitter.maxStartRotation = angle2;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setForce = function(min, max){
this.emitter.startSpeed.value = max;
this.emitter.minimumSpeedMultiplier = max !== 0 ? min/max : 1;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setZoneRadius = function(radius){
this.emitter.spawnCircle.radius = radius;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setLifeTime = function(min, max){
this.emitter.minLifetime = min;
this.emitter.maxLifetime = max;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setGravity = function(x, y){
this.emitter.acceleration.x = x;
this.emitter.acceleration.y = y;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setColor = function(r1, g1, b1, r2, g2, b2){
this.emitter.startColor.value.r = r1;
this.emitter.startColor.value.g = g1;
this.emitter.startColor.value.b = b1;
this.emitter.startColor.next.value.r = r2;
this.emitter.startColor.next.value.g = g2;
this.emitter.startColor.next.value.b = b2;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setSize = function(size1, size2){
this.emitter.startScale.value = size1/100.0;
if(this.emitter.startScale.next){
this.emitter.startScale.next.value = size2/100.0;
}
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setAlpha = function(alpha1, alpha2){
this.emitter.startAlpha.value = alpha1/255.0;
if(this.emitter.startAlpha.next){
this.emitter.startAlpha.next.value = alpha2/255.0;
}
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setFlow = function(flow, tank){
this.emitter.frequency = flow < 0 ? 0.0001 : 1.0/flow;
this.emitterLifetime = tank < 0 ? -1 :
(flow < 0 ? 0.001 : (tank - this.emitter.totalParticleCount) / flow);
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.isTextureValid = function(texture, runtimeScene){
return runtimeScene.getGame().getImageManager().getPIXITexture(texture).valid;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.setTexture = function(texture, runtimeScene){
var pixiTexture = runtimeScene.getGame().getImageManager().getPIXITexture(texture);
if(pixiTexture.valid){
this.emitter.particleImages[0] = pixiTexture;
}
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.getTotalParticleCount = function(){
return this.emitter.totalParticleCount;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.getParticleCount = function(){
return this.emitter.particleCount;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.stop = function(){
this.emitter.emit = false;
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.recreate = function(){
this.emitter.cleanup();
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.destroy = function(){
this.emitter.destroy();
};
gdjs.ParticleEmitterObjectPixiRenderer.prototype.hasStarted = function(){
return this.started;
};

View File

@@ -0,0 +1,468 @@
/**
GDevelop - Particle System Extension
Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
gdjs.ParticleEmitterObject = function(runtimeScene, objectData){
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
this.renderer = new gdjs.ParticleEmitterObjectRenderer(runtimeScene, this, objectData);
this.singleAngle = objectData.emissionEditionSimpleMode;
this.angleA = objectData.emitterAngleA;
this.angleB = objectData.emitterAngleB;
this.forceMin = objectData.emitterForceMin;
this.forceMax = objectData.emitterForceMax;
this.zoneRadius = objectData.zoneRadius;
this.lifeTimeMin = objectData.particleLifeTimeMin;
this.lifeTimeMax = objectData.particleLifeTimeMax;
this.gravityX = objectData.particleGravityX;
this.gravityY = objectData.particleGravityY;
this.colorR1 = objectData.particleRed1;
this.colorR2 = objectData.particleRed2;
this.colorG1 = objectData.particleGreen1;
this.colorG2 = objectData.particleGreen2;
this.colorB1 = objectData.particleBlue1;
this.colorB2 = objectData.particleBlue2;
this.size1 = objectData.particleSize1;
this.size2 = objectData.particleSize2;
this.sizeParam = objectData.sizeParam;
this.alpha1 = objectData.particleAlpha1;
this.alpha2 = objectData.particleAlpha2;
this.rendererType = objectData.rendererType;
this.rendererParam1 = objectData.rendererParam1;
this.rendererParam2 = objectData.rendererParam2;
this.texture = objectData.textureParticleName;
this.flow = objectData.flow;
this.tank = objectData.tank;
this.destroyWhenNoParticles = objectData.destroyWhenNoParticles;
this._posDirty = true;
this._angleDirty = true;
this._forceDirty = true;
this._zoneRadiusDirty = true;
this._lifeTimeDirty = true;
this._gravityDirty = true;
this._colorDirty = true;
this._sizeDirty = true;
this._alphaDirty = true;
this._textureDirty = true;
this._flowDirty = true;
};
gdjs.ParticleEmitterObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
gdjs.ParticleEmitterObject.thisIsARuntimeObjectConstructor = "ParticleSystem::ParticleEmitter";
gdjs.ParticleEmitterObject.prototype.setX = function(x){
if(this.x !== x) this._posDirty = true;
gdjs.RuntimeObject.prototype.setX.call(this, x);
};
gdjs.ParticleEmitterObject.prototype.setY = function(y){
if(this.y !== y) this._posDirty = true;
gdjs.RuntimeObject.prototype.setY.call(this, y);
};
gdjs.ParticleEmitterObject.prototype.setAngle = function(angle){
if(this.angle !== angle) this._angleDirty = true;
gdjs.RuntimeObject.prototype.setAngle.call(this, angle);
};
gdjs.ParticleEmitterObject.prototype.getRendererObject = function(){
return this.renderer.getRendererObject();
};
gdjs.ParticleEmitterObject.prototype.update = function(runtimeScene){
if(this._posDirty){
this.renderer.setPosition(this.getX(), this.getY());
}
if(this._angleDirty){
var angle = this.getAngle();
if(this.singleAngle) this.renderer.setAngle(this.angle - this.angleB/2.0, this.angle + this.angleB/2.0);
else this.renderer.setAngle(this.angle + this.angleA, this.angle + this.angleB);
}
if(this._forceDirty){
this.renderer.setForce(this.forceMin, this.forceMax);
}
if(this._zoneRadiusDirty){
this.renderer.setZoneRadius(this.zoneRadius);
}
if(this._lifeTimeDirty){
this.renderer.setLifeTime(this.lifeTimeMin, this.lifeTimeMax);
}
if(this._gravityDirty){
this.renderer.setGravity(this.gravityX, this.gravityY);
}
if(this._colorDirty){
this.renderer.setColor(this.colorR1, this.colorG1, this.colorB1,
this.colorR2, this.colorG2, this.colorB2);
}
if(this._sizeDirty && this.sizeParam === "Mutable"){
this.renderer.setSize(this.size1, this.size2);
}
if(this._alphaDirty){
this.renderer.setAlpha(this.alpha1, this.alpha2);
}
if(this._flowDirty){
this.renderer.setFlow(this.flow, this.tank);
}
if(this._textureDirty){
this.renderer.setTexture(this.texture, runtimeScene);
}
this._posDirty = this._angleDirty = this._forceDirty = this._zoneRadiusDirty = false;
this._lifeTimeDirty = this._gravityDirty = this._colorDirty = this._sizeDirty = false;
this._alphaDirty = this._flowDirty = this._textureDirty = false;
this.renderer.update(this.getElapsedTime(runtimeScene)/1000.0);
if(this.tank > 0 && this.renderer.getTotalParticleCount() > this.tank){
this.renderer.stop();
}
if(this.renderer.hasStarted() && this.renderer.getParticleCount() === 0 && this.destroyWhenNoParticles){
this.deleteFromScene(runtimeScene);
}
};
gdjs.ParticleEmitterObject.prototype.onDeletedFromScene = function(runtimeScene){
this.renderer.destroy();
gdjs.RuntimeObject.prototype.onDeletedFromScene.call(this, runtimeScene);
};
gdjs.ParticleEmitterObject.prototype.getEmitterForceMin = function(){
return this.forceMin;
};
gdjs.ParticleEmitterObject.prototype.setEmitterForceMin = function(force){
if(force < 0) force = 0;
if(this.forceMin !== force){
this._forceDirty = true;
this.forceMin = force;
}
};
gdjs.ParticleEmitterObject.prototype.getEmitterForceMax = function(){
return this.forceMax;
};
gdjs.ParticleEmitterObject.prototype.setEmitterForceMax = function(force){
if(force < 0) force = 0;
if(this.forceMax !== force){
this._forceDirty = true;
this.forceMax = force;
}
};
gdjs.ParticleEmitterObject.prototype.getEmitterAngle = function(){
return (this.angleA + this.angleB)/2.0;
};
gdjs.ParticleEmitterObject.prototype.setEmitterAngle = function(angle){
var oldAngle = this.getEmitterAngle();
if(angle !== oldAngle){
this._angleDirty = true;
this.angleA += angle - oldAngle;
this.angleB += angle - oldAngle;
}
};
gdjs.ParticleEmitterObject.prototype.getEmitterAngleA = function(){
return this.angleA;
};
gdjs.ParticleEmitterObject.prototype.setEmitterAngleA = function(angle){
if(this.angleA !== angle){
this._angleDirty = true;
this.angleA = angle;
}
};
gdjs.ParticleEmitterObject.prototype.getEmitterAngleB = function(){
return this.angleB;
};
gdjs.ParticleEmitterObject.prototype.setEmitterAngleB = function(angle){
if(this.angleB !== angle){
this._angleDirty = true;
this.angleB = angle;
}
};
gdjs.ParticleEmitterObject.prototype.getConeSprayAngle = function(){
return Math.abs(this.angleB - this.angleA);
};
gdjs.ParticleEmitterObject.prototype.setConeSprayAngle = function(angle){
var oldCone = this.getConeSprayAngle();
if(oldCone !== angle){
this._angleDirty = true;
var midAngle = this.getEmitterAngle();
this.angleA = midAngle - angle/2.0;
this.angleB = midAngle + angle/2.0;
}
};
gdjs.ParticleEmitterObject.prototype.getZoneRadius = function(){
return this.zoneRadius;
};
gdjs.ParticleEmitterObject.prototype.setZoneRadius = function(radius){
if(radius < 0) radius = 0;
if(this.zoneRadius !== radius && radius > 0){
this._zoneRadiusDirty = true;
this.zoneRadius = radius;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleLifeTimeMin = function(){
return this.lifeTimeMin;
};
gdjs.ParticleEmitterObject.prototype.setParticleLifeTimeMin = function(lifeTime){
if(lifeTime < 0) lifeTime = 0;
if(this.lifeTimeMin !== lifeTime){
this._lifeTimeDirty = true;
this.lifeTimeMin = lifeTime;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleLifeTimeMax = function(){
return this.lifeTimeMax;
};
gdjs.ParticleEmitterObject.prototype.setParticleLifeTimeMax = function(lifeTime){
if(lifeTime < 0) lifeTime = 0;
if(this.lifeTimeMax !== lifeTime){
this._lifeTimeDirty = true;
this.lifeTimeMax = lifeTime;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGravityX = function(){
return this.gravityX;
};
gdjs.ParticleEmitterObject.prototype.setParticleGravityX = function(x){
if(this.gravityX !== x){
this._gravityDirty = true;
this.gravityX = x;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGravityY = function(){
return this.gravityY;
};
gdjs.ParticleEmitterObject.prototype.setParticleGravityY = function(y){
if(this.gravityY !== y){
this._gravityDirty = true;
this.gravityY = y;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGravityAngle = function(){
return Math.atan2(this.gravityY, this.gravityX)*180.0/Math.PI;
};
gdjs.ParticleEmitterObject.prototype.setParticleGravityAngle = function(angle){
var oldAngle = this.getParticleGravityAngle();
if(oldAngle !== angle){
this._gravityDirty = true;
var length = this.getParticleGravityLength();
this.gravityX = length*Math.cos(angle*Math.PI/180.0);
this.gravityY = length*Math.sin(angle*Math.PI/180.0);
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGravityLength = function(){
return Math.sqrt(this.gravityX*this.gravityX + this.gravityY*this.gravityY);
};
gdjs.ParticleEmitterObject.prototype.setParticleGravityLength = function(length){
if(length < 0) length = 0;
var oldLength = this.getParticleGravityLength();
if(oldLength !== length){
this._gravityDirty = true;
this.gravityX *= length/oldLength;
this.gravityY *= length/oldLength;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleRed1 = function(){
return this.colorR1;
};
gdjs.ParticleEmitterObject.prototype.setParticleRed1 = function(red){
if(red < 0) red = 0;
if(red > 255) red = 255;
if(this.colorR1 !== red){
this._colorDirty = true;
this.colorR1 = red;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleRed2 = function(){
return this.colorR2;
};
gdjs.ParticleEmitterObject.prototype.setParticleRed2 = function(red){
if(red < 0) red = 0;
if(red > 255) red = 255;
if(this.colorR2 !== red){
this._colorDirty = true;
this.colorR2 = red;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGreen1 = function(){
return this.colorG1;
};
gdjs.ParticleEmitterObject.prototype.setParticleGreen1 = function(green){
if(green < 0) green = 0;
if(green > 255) green = 255;
if(this.colorG1 !== green){
this._colorDirty = true;
this.colorG1 = green;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleGreen2 = function(){
return this.colorG2;
};
gdjs.ParticleEmitterObject.prototype.setParticleGreen2 = function(green){
if(green < 0) green = 0;
if(green > 255) green = 255;
if(this.colorG2 !== green){
this._colorDirty = true;
this.colorG2 = green;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleBlue1 = function(){
return this.colorB1;
};
gdjs.ParticleEmitterObject.prototype.setParticleBlue1 = function(blue){
if(blue < 0) blue = 0;
if(blue > 255) blue = 255;
if(this.colorB1 !== blue){
this._colorDirty = true;
this.colorB1 = blue;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleBlue2 = function(){
return this.colorB2;
};
gdjs.ParticleEmitterObject.prototype.setParticleBlue2 = function(blue){
if(blue < 0) blue = 0;
if(blue > 255) blue = 255;
if(this.colorB2 !== blue){
this._colorDirty = true;
this.colorB2 = blue;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleSize1 = function(){
return this.size1;
};
gdjs.ParticleEmitterObject.prototype.setParticleSize1 = function(size){
if(size < 0) size = 0;
if(this.size1 !== size){
this._sizeDirty = true;
this.size1 = size;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleSize2 = function(){
return this.size2;
};
gdjs.ParticleEmitterObject.prototype.setParticleSize2 = function(size){
if(this.size2 !== size){
this._sizeDirty = true;
this.size2 = size;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleAlpha1 = function(){
return this.alpha1;
};
gdjs.ParticleEmitterObject.prototype.setParticleAlpha1 = function(alpha){
if(this.alpha1 !== alpha){
this._alphaDirty = true;
this.alpha1 = alpha;
}
};
gdjs.ParticleEmitterObject.prototype.getParticleAlpha2 = function(){
return this.alpha2;
};
gdjs.ParticleEmitterObject.prototype.setParticleAlpha2 = function(alpha){
if(this.alpha2 !== alpha){
this._alphaDirty = true;
this.alpha2 = alpha;
}
};
gdjs.ParticleEmitterObject.prototype.noMoreParticles = function(){
this.renderer.stop();
};
gdjs.ParticleEmitterObject.prototype.recreateParticleSystem = function(){
this.renderer.recreate();
};
gdjs.ParticleEmitterObject.prototype.getFlow = function(){
return this.flow;
};
gdjs.ParticleEmitterObject.prototype.setFlow = function(flow){
if(this.flow !== flow){
this.flow = flow;
this._flowDirty = true;
}
};
gdjs.ParticleEmitterObject.prototype.getTank = function(){
return this.tank;
};
gdjs.ParticleEmitterObject.prototype.setTank = function(tank){
this.tank = tank;
};
gdjs.ParticleEmitterObject.prototype.getTexture = function(){
return this.texture;
};
gdjs.ParticleEmitterObject.prototype.setTexture = function(texture, runtimeScene){
if(this.texture !== texture){
if(this.renderer.isTextureValid(texture, runtimeScene)){
this.texture = texture;
this._textureDirty = true;
}
}
};

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,398 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
/**
* @namespace gdjs.sk
*/
gdjs.sk = gdjs.sk || {
// Some useful constants
SLOT_UNDEFINED: -1,
SLOT_IMAGE: 0,
SLOT_MESH: 1,
SLOT_POLYGON: 2,
SLOT_ARMATURE: 3,
EASING_CONST: 0,
EASING_LINEAR: 1,
EASING_CURVE: 2,
EVENT_STOP: 0,
EVENT_PLAY: 1,
EVENT_PLAYSINGLE: 2
};
/**
* The Matrix holds the basic transformation data in a matrix form.
*
* @namespace gdjs.sk
* @class Matrix
*/
gdjs.sk.Matrix = function(a=1, b=0, tx=0, c=0, d=1, ty=0){
this.a = a; this.b = b; this.tx = tx;
this.c = c; this.d = d; this.ty = ty;
this.u = 0; this.v = 0; this.w = 1;
};
gdjs.sk.Matrix.prototype.translation = function(x, y){
this.tx = x;
this.ty = y;
return this;
};
gdjs.sk.Matrix.prototype.rotation = function(angle){
this.a = Math.cos(angle); this.b = -Math.sin(angle);
this.c = Math.sin(angle); this.d = Math.cos(angle);
return this;
};
gdjs.sk.Matrix.prototype.scale = function(sx, sy){
this.a = sx;
this.d = sy;
return this;
};
gdjs.sk.Matrix.prototype.clone = function(){
return new gdjs.sk.Matrix(this.a, this.b, this.tx,
this.c, this.d, this.ty,
this.u, this.v, this.w );
};
gdjs.sk.Matrix.prototype.mul = function(m){
return new gdjs.sk.Matrix(this.a*m.a + this.b*m.c,
this.a*m.b + this.b*m.d,
this.a*m.tx + this.b*m.ty + this.tx,
this.c*m.a + this.d*m.c,
this.c*m.b + this.d*m.d,
this.c*m.tx + this.d*m.ty + this.ty);
};
gdjs.sk.Matrix.prototype.mulVec = function(v){
return [this.a*v[0] + this.b*v[1] + this.tx,
this.c*v[0] + this.d*v[1] + this.ty];
};
gdjs.sk.Matrix.prototype.invert = function(){
var det_inv = 1.0 / (this.a*this.d - this.b*this.c);
var a = this.a;
var tx = this.tx;
this.tx = (this.b*this.ty - this.d*tx)*det_inv;
this.ty = (this.c*tx - this.a*this.ty)*det_inv;
this.a = this.d*det_inv;
this.b =-this.b*det_inv;
this.c =-this.c*det_inv;
this.d = a*det_inv;
return this;
};
gdjs.sk.Matrix.prototype.inverse = function(){
var det_inv = 1.0 / (this.a*this.d - this.b*this.c);
return new gdjs.sk.Matrix( this.d*det_inv,
-this.b*det_inv,
(this.b*this.ty - this.d*this.tx)*det_inv,
-this.c*det_inv,
this.a*det_inv,
(this.c*this.tx - this.a*this.ty)*det_inv);
};
gdjs.sk.Matrix.prototype.str = function(){
return "|" + this.a.toFixed(2) + ", " + this.b.toFixed(2) + ", " + this.tx.toFixed(2) + "|\n" +
"|" + this.c.toFixed(2) + ", " + this.d.toFixed(2) + ", " + this.ty.toFixed(2) + "|\n" +
"|" + this.u.toFixed(2) + ", " + this.v.toFixed(2) + ", " + this.w.toFixed(2) + "|\n";
};
/**
* The Transform is the basic class for transformable objects as bones, slots and armatures.
*
* @namespace gdjs.sk
* @class Transform
*/
gdjs.sk.Transform = function(x=0, y=0, rot=0, sx=1, sy=1){
this.parent = null;
this.children = [];
this.x = x;
this.y = y;
this.rot = rot * Math.PI / 180.0;
this.sx = sx;
this.sy = sy;
this.matrix = new gdjs.sk.Matrix();
this.worldMatrix = new gdjs.sk.Matrix();
this._updateMatrix = true;
this._updateWorldMatrix = false;
this.inheritTranslation = true;
this.inheritRotation = true;
this.inheritScale = true;
};
gdjs.sk.Transform.prototype.addChild = function(child){
this.children.push(child);
child.reparent(this);
};
gdjs.sk.Transform.prototype.reparent = function(parent){
if(this.parent){
this.parent.removeChild(this);
}
this.parent = parent;
this._updateWorldMatrix = true;
};
gdjs.sk.Transform.prototype.removeChild = function(child){
var index = this.children.indexOf(child);
if(index > -1){
this.children.splice(index, 1);
}
};
gdjs.sk.Transform.prototype.getX = function(){
return this.x;
};
gdjs.sk.Transform.prototype.setX = function(x){
if(this.x !== x){
this.x = x;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.getGlobalX = function(){
this.updateParentsTransform();
return this.worldMatrix.tx;
};
gdjs.sk.Transform.prototype.setGlobalX = function(x){
var globalY = this.getGlobalY(); // Also updates parent transforms
var localPos = this.parent.worldMatrix.inverse().mulVec([x, globalY, 1.0]);
this.x = localPos[0];
this.y = localPos[1];
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.getY = function(){
return this.y;
};
gdjs.sk.Transform.prototype.setY = function(y){
if(this.y !== y){
this.y = y;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.getGlobalY = function(){
this.updateParentsTransform();
return this.worldMatrix.ty;
};
gdjs.sk.Transform.prototype.setGlobalY = function(y){
var globalX = this.getGlobalX(); // Also updates parent transforms
var localPos = this.parent.worldMatrix.inverse().mulVec([globalX, y, 1.0]);
this.x = localPos[0];
this.y = localPos[1];
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.setPos = function(x, y){
if(this.x !== x || this.y !== y){
this.x = x;
this.y = y;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.getRot = function(){
return this.rot * 180.0 / Math.PI;
};
gdjs.sk.Transform.prototype.setRot = function(angle){
angle *= Math.PI / 180.0;
if(this.rot !== angle){
this.rot = angle;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.getGlobalRot = function(){
this.updateParentsTransform();
var sx = Math.sqrt(this.worldMatrix.a * this.worldMatrix.a +
this.worldMatrix.c * this.worldMatrix.c );
var sy = Math.sqrt(this.worldMatrix.b * this.worldMatrix.b +
this.worldMatrix.d * this.worldMatrix.d );
return Math.atan2(-this.worldMatrix.b/sy, this.worldMatrix.a/sx) * 180.0 / Math.PI;
};
gdjs.sk.Transform.prototype.setGlobalRot = function(rot){
var parentGlobalRot = this.parent ? this.parent.getGlobalRot() : 0;
this.rot = (rot - parentGlobalRot)*Math.PI/180.0;
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.getSx = function(){
return this.sx;
};
gdjs.sk.Transform.prototype.getSy = function(){
return this.sy;
};
gdjs.sk.Transform.prototype.setSx = function(sx){
if(this.sx !== sx){
this.sx = sx;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.setSy = function(sy){
if(this.sy !== sy){
this.sy = sy;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.setScale = function(sx, sy){
if(this.sx !== sx || this.sy !== sy){
this.sx = sx;
this.sy = sy;
this._updateMatrix = true;
}
};
gdjs.sk.Transform.prototype.move = function(x, y){
this.x += x;
this.y += y;
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.rotate = function(angle){
this.rot += angle * Math.PI / 180.0;
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.scale = function(sx, sy){
this.sx *= sx;
this.sy *= sy;
this._updateMatrix = true;
};
gdjs.sk.Transform.prototype.update = function(){
this.updateTransform();
for(var i=0; i<this.children.length; i++){
this.children[i].update();
}
};
gdjs.sk.Transform.prototype.updateTransform = function(){
var sin_rot, cos_rot;
if(this._updateMatrix || this._updateWorldMatrix){
sin_rot = Math.sin(this.rot);
cos_rot = Math.cos(this.rot);
}
if(this._updateMatrix){
this.matrix = new gdjs.sk.Matrix(this.sx*cos_rot,-this.sy*sin_rot, this.x,
this.sx*sin_rot, this.sy*cos_rot, this.y,
0, 0, 1);
}
if(this._updateMatrix || this._updateWorldMatrix){
if(!this.parent){
this.worldMatrix = this.matrix.clone();
}
else{
this.worldMatrix = this.parent.worldMatrix.mul(this.matrix);
if(!this.inheritRotation || !this.inheritScale){
if(this.inheritScale){ // Non iherited rotation
var worldSx = Math.sqrt(this.worldMatrix.a*this.worldMatrix.a +
this.worldMatrix.c*this.worldMatrix.c);
var worldSy = Math.sqrt(this.worldMatrix.b*this.worldMatrix.b +
this.worldMatrix.d*this.worldMatrix.d);
this.worldMatrix.a = worldSx*cos_rot;
this.worldMatrix.b = -worldSy*sin_rot;
this.worldMatrix.c = worldSx*sin_rot;
this.worldMatrix.d = worldSy*cos_rot;
}
else if(this.inheritRotation){ // Non inherited scale
var worldSx = Math.sqrt(this.worldMatrix.a*this.worldMatrix.a +
this.worldMatrix.c*this.worldMatrix.c);
var worldSy = Math.sqrt(this.worldMatrix.b*this.worldMatrix.b +
this.worldMatrix.d*this.worldMatrix.d);
this.worldMatrix.a *= this.sx / worldSx;
this.worldMatrix.b *= this.sy / worldSy;
this.worldMatrix.c *= this.sx / worldSx;
this.worldMatrix.d *= this.sy / worldSy;
}
else{ // Non inherited rotation nor scale
this.worldMatrix.a = this.sx*cos_rot;
this.worldMatrix.b = -this.sy*sin_rot;
this.worldMatrix.c = this.sx*sin_rot;
this.worldMatrix.d = this.sy*cos_rot;
}
}
if(!this.inheritTranslation){
this.worldMatrix.tx = this.x;
this.worldMatrix.ty = this.y;
}
}
for(var i=0; i<this.children.length; i++){
this.children[i]._updateWorldMatrix = true;
}
}
this._updateMatrix = false;
this._updateWorldMatrix = false;
};
gdjs.sk.Transform.prototype.updateParentsTransform = function(){
if(this.parent){
this.parent.updateParentsTransform();
}
this.updateTransform();
};
gdjs.sk.Transform.prototype.transformPolygon = function(vertices){
this.updateParentsTransform();
var worldPoly = new gdjs.Polygon();
for(var i=0; i<vertices.length; i++){
worldPoly.vertices.push(this.worldMatrix.mulVec(vertices[i]));
}
return worldPoly;
};
gdjs.sk.Transform._statics = {
transform: {
x: 0,
y: 0,
sx: 1,
sy: 1,
skx: 0,
sky: 0,
rot: 0
}
};
gdjs.sk.Transform.decomposeMatrix = function(matrix){
var transform = gdjs.sk.Transform._statics.transform;
transform.x = matrix.tx
transform.y = matrix.ty;
var sx = Math.sqrt(matrix.a*matrix.a + matrix.c*matrix.c);
var sy = Math.sqrt(matrix.b*matrix.b + matrix.d*matrix.d);
transform.sx = sx;
transform.sy = sy;
transform.skx = -Math.atan2(matrix.d, matrix.b) + Math.PI/2.0;
transform.sky = Math.atan2(matrix.c, matrix.a);
transform.rot = Math.atan2(-matrix.b/sy, matrix.a/sx);
return transform;
};

View File

@@ -0,0 +1,174 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
gdjs.sk.CocosDataLoader = function()
{
this.textures = {};
};
gdjs.sk.DataLoader = gdjs.sk.CocosDataLoader;
gdjs.sk.CocosDataLoader.prototype.getData = function(dataName){
return cc.loader.getRes("res/"+dataName);
};
gdjs.sk.CocosDataLoader.prototype.loadDragonBones = function(runtimeScene, objectData){
var textureData = this.getData(objectData.textureDataFilename);
var texture = runtimeScene.getGame().getImageManager().getTexture(objectData.textureName);
if(!textureData || !texture._textureLoaded) return;
for(var i=0; i<textureData.SubTexture.length; i++){
var subTex = textureData.SubTexture[i];
var frame = new cc.rect(subTex.x, subTex.y, subTex.width, subTex.height);
if(subTex.hasOwnProperty("frameWidth")){
frame.width = subTex.frameWidth;
}
if (subTex.hasOwnProperty("frameHeight")){
frame.height = subTex.frameHeight;
}
this.textures[subTex.name] = {"texture": texture, "frame": frame};
}
};
gdjs.sk.ArmatureCocosRenderer = function()
{
this.layer = new cc.Layer();
this.slotsRenderers = new cc.Layer();
this.layer.addChild(this.slotsRenderers);
this.debugRenderers = new cc.Layer();
this.layer.addChild(this.debugRenderers);
this._convertYPosition = function(y){ return y; };
};
gdjs.sk.ArmatureRenderer = gdjs.sk.ArmatureCocosRenderer;
gdjs.sk.ArmatureCocosRenderer.prototype.putInScene = function(runtimeObject, runtimeScene){
var layerRenderer = runtimeScene.getLayer("").getRenderer();
layerRenderer.addRendererObject(this.layer, runtimeObject.getZOrder());
this._convertYPosition = layerRenderer.convertYPosition;
};
gdjs.sk.ArmatureCocosRenderer.prototype.getRendererObject = function(){
return this.layer;
};
gdjs.sk.ArmatureCocosRenderer.prototype.addRenderer = function(renderer){
this.slotsRenderers.addChild(renderer.getRendererObject());
renderer._convertYPosition = this._convertYPosition;
};
gdjs.sk.ArmatureCocosRenderer.prototype.sortRenderers = function(){
this.slotsRenderers.children.sort(function(a, b){ return a.z - b.z; });
};
gdjs.sk.ArmatureCocosRenderer.prototype.addDebugRenderer = function(renderer){
this.debugRenderers.addChild(renderer.getRendererObject());
renderer._convertYPosition = this._convertYPosition;
};
gdjs.sk.ArmatureCocosRenderer.prototype.extraInitialization = function(parentArmatureRenderer){
this._convertYPosition = parentArmatureRenderer._convertYPosition;
};
gdjs.sk.SlotCocosRenderer = function()
{
this.renderer = null;
this._convertYPosition = function(y){ return y; };
};
gdjs.sk.SlotRenderer = gdjs.sk.SlotCocosRenderer;
gdjs.sk.SlotCocosRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.sk.SlotCocosRenderer.prototype.loadAsSprite = function(texture){
if(!texture)
this.renderer = new cc.Sprite();
else
this.renderer = new cc.Sprite.createWithTexture(texture.texture, texture.frame);
this.renderer.z = 0;
};
gdjs.sk.SlotCocosRenderer.prototype.loadAsMesh = function(texture, vertices, uvs, triangles){
// Meshes not supported, load as sprites
this.loadAsSprite(texture);
};
gdjs.sk.SlotCocosRenderer.prototype.getWidth = function(){
return this.renderer.width;
};
gdjs.sk.SlotCocosRenderer.prototype.getHeight = function(){
return this.renderer.height;
};
gdjs.sk.SlotCocosRenderer.prototype.setTransform = function(transform){
this.renderer.setPositionX(transform.x);
this.renderer.setPositionY(this._convertYPosition(transform.y));
this.renderer.setScaleX(transform.sx);
this.renderer.setScaleY(transform.sy);
this.renderer.setRotationX(-transform.skx*180.0/Math.PI);
this.renderer.setRotationY( transform.sky*180.0/Math.PI);
};
gdjs.sk.SlotCocosRenderer.prototype.setZ = function(z){
this.renderer.z = z;
};
gdjs.sk.SlotCocosRenderer.prototype.setColor = function(color){
this.renderer.setColor(cc.color(color[0], color[1], color[2]));
};
gdjs.sk.SlotCocosRenderer.prototype.setAlpha = function(alpha){
this.renderer.setOpacity(255*alpha);
};
gdjs.sk.SlotCocosRenderer.prototype.setVisible = function(visible){
this.renderer.setVisible(visible);
};
// Meshes not supported
gdjs.sk.SlotCocosRenderer.prototype.setVertices = function(vertices, updateList){
};
gdjs.sk.DebugCocosRenderer = function()
{
this.renderer = new cc.DrawNode();
this._convertYPosition = function(y){ return y; };
};
gdjs.sk.DebugRenderer = gdjs.sk.DebugCocosRenderer;
gdjs.sk.DebugCocosRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.sk.DebugCocosRenderer.prototype.loadVertices = function(verts, color, fill){
var fillAlpha = fill ? 100 : 0;
var fillColor = new cc.Color(color[0], color[1], color[2], fillAlpha);
var lineColor = new cc.Color(color[0], color[1], color[2], 225);
for(var i=0; i<verts.length; i++){
var vertices = [];
for(var i=0; i<verts.length; i++){
vertices.push(cc.p(verts[i][0], -verts[i][1]));
}
this.renderer.drawPoly(vertices, fillColor, 3, lineColor);
}
};
gdjs.sk.DebugCocosRenderer.prototype.setTransform = function(transform){
this.renderer.setPositionX(transform.x);
this.renderer.setPositionY(this._convertYPosition(transform.y));
this.renderer.setScaleX(transform.sx);
this.renderer.setScaleY(transform.sy);
this.renderer.setRotationX(-transform.skx*180.0/Math.PI);
this.renderer.setRotationY( transform.sky*180.0/Math.PI);
};

View File

@@ -0,0 +1,187 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
gdjs.sk.PixiDataLoader = function()
{
this.textures = {};
};
gdjs.sk.DataLoader = gdjs.sk.PixiDataLoader;
gdjs.sk.PixiDataLoader.prototype.getData = function(dataName){
if(PIXI.loader.resources[dataName]){
return PIXI.loader.resources[dataName].data;
}
return null;
};
gdjs.sk.PixiDataLoader.prototype.loadDragonBones = function(runtimeScene, objectData){
var textureData = this.getData(objectData.textureDataFilename);
var texture = runtimeScene.getGame().getImageManager().getPIXITexture(objectData.textureName);
if(!textureData || !texture.valid) return;
for(var i=0; i<textureData.SubTexture.length; i++){
var subTex = textureData.SubTexture[i];
var frame = new PIXI.Rectangle(subTex.x, subTex.y, subTex.width, subTex.height);
if(subTex.hasOwnProperty("frameWidth")){
frame.width = subTex.frameWidth;
}
if (subTex.hasOwnProperty("frameHeight")){
frame.height = subTex.frameHeight;
}
// Fix the frame size, in case texture is not loaded
if(frame.x > texture.width) frame.x = 0;
if(frame.y > texture.height) frame.y = 0;
if(frame.x + frame.width > texture.width) frame.width = texture.width - frame.x;
if(frame.y + frame.height > texture.height) frame.height = texture.height - frame.y;
this.textures[subTex.name] = new PIXI.Texture(texture.baseTexture, frame=frame);
}
};
gdjs.sk.ArmaturePixiRenderer = function()
{
this.container = new PIXI.Container();
this.slotsRenderers = new PIXI.Container();
this.container.addChild(this.slotsRenderers);
this.debugRenderers = new PIXI.Container();
this.container.addChild(this.debugRenderers);
};
gdjs.sk.ArmatureRenderer = gdjs.sk.ArmaturePixiRenderer;
gdjs.sk.ArmaturePixiRenderer.prototype.putInScene = function(runtimeObject, runtimeScene){
runtimeScene.getLayer("").getRenderer().addRendererObject(this.container, runtimeObject.getZOrder());
};
gdjs.sk.ArmaturePixiRenderer.prototype.getRendererObject = function(){
return this.container;
};
gdjs.sk.ArmaturePixiRenderer.prototype.addRenderer = function(renderer){
this.slotsRenderers.addChild(renderer.getRendererObject());
};
gdjs.sk.ArmaturePixiRenderer.prototype.sortRenderers = function(){
this.slotsRenderers.children.sort(function(a, b){ return a.z - b.z; });
};
gdjs.sk.ArmaturePixiRenderer.prototype.addDebugRenderer = function(renderer){
this.debugRenderers.addChild(renderer.getRendererObject());
};
gdjs.sk.ArmaturePixiRenderer.prototype.extraInitialization = function(parentArmatureRenderer){
};
gdjs.sk.SlotPixiRenderer = function()
{
this.renderer = null;
};
gdjs.sk.SlotRenderer = gdjs.sk.SlotPixiRenderer;
gdjs.sk.SlotPixiRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.sk.SlotPixiRenderer.prototype.loadAsSprite = function(texture){
this.renderer = new PIXI.Sprite(texture);
this.renderer.pivot = new PIXI.Point(this.renderer.width/2.0, this.renderer.height/2.0);
this.renderer.z = 0;
};
gdjs.sk.SlotPixiRenderer.prototype.loadAsMesh = function(texture, vertices, uvs, triangles){
this.renderer = new PIXI.mesh.Mesh(texture,
new Float32Array(vertices),
new Float32Array(uvs),
new Uint16Array(triangles),
PIXI.mesh.Mesh.DRAW_MODES.TRIANGLES);
this.renderer.uploadUvTransform = true;
this.renderer.z = 0;
};
gdjs.sk.SlotPixiRenderer.prototype.getWidth = function(){
return this.renderer.width;
};
gdjs.sk.SlotPixiRenderer.prototype.getHeight = function(){
return this.renderer.height;
};
gdjs.sk.SlotPixiRenderer.prototype.setTransform = function(transform){
this.renderer.x = transform.x;
this.renderer.y = transform.y;
this.renderer.scale.x = transform.sx;
this.renderer.scale.y = transform.sy;
this.renderer.skew.x = transform.skx;
this.renderer.skew.y = transform.sky;
};
gdjs.sk.SlotPixiRenderer.prototype.setZ = function(z){
this.renderer.z = z;
};
gdjs.sk.SlotPixiRenderer.prototype.setColor = function(color){
this.renderer.tint = (color[0] << 16) + (color[1] << 8) + color[2];
};
gdjs.sk.SlotPixiRenderer.prototype.setAlpha = function(alpha){
this.renderer.alpha = alpha;
};
gdjs.sk.SlotPixiRenderer.prototype.setVisible = function(visible){
this.renderer.visible = visible;
};
// Mesh only
gdjs.sk.SlotPixiRenderer.prototype.setVertices = function(vertices, updateList){
for(var i=0; i<updateList.length; i++){
this.renderer.vertices[2*updateList[i]] = vertices[i][0];
this.renderer.vertices[2*updateList[i] + 1] = vertices[i][1];
}
};
gdjs.sk.DebugPixiRenderer = function()
{
this.renderer = new PIXI.Graphics();
};
gdjs.sk.DebugRenderer = gdjs.sk.DebugPixiRenderer;
gdjs.sk.DebugPixiRenderer.prototype.getRendererObject = function(){
return this.renderer;
};
gdjs.sk.DebugPixiRenderer.prototype.loadVertices = function(verts, color, fill){
color = color[2] | (color[1] << 8) | (color[0] << 16);
if(fill){
this.renderer.beginFill(color, 0.1);
}
this.renderer.lineStyle(3, color, 0.8);
for(var i=0; i<verts.length; i++){
this.renderer.drawPolygon(verts.reduce(function(a, b){ return a.concat(b); }).concat(verts[0]));
}
if(fill){
this.renderer.endFill();
}
};
gdjs.sk.DebugPixiRenderer.prototype.setTransform = function(transform){
this.renderer.x = transform.x;
this.renderer.y = transform.y;
this.renderer.scale.x = transform.sx;
this.renderer.scale.y = transform.sy;
this.renderer.skew.x = transform.skx;
this.renderer.skew.y = transform.sky;
};
gdjs.sk.DebugPixiRenderer.prototype.skewSupported = function(){
return true;
};

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
project(SkeletonObject)
gd_add_extension_includes()
#Defines
###
gd_add_extension_definitions(SkeletonObject)
#The targets
###
include_directories(.)
file(GLOB source_files *)
gd_add_extension_target(SkeletonObject "${source_files}" "JsPlatform")
#Linker files for the IDE extension
###
gd_extension_link_libraries(SkeletonObject)

View File

@@ -0,0 +1,131 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
/**
* @namespace gdjs.sk
* @class SharedBone
*/
gdjs.sk.SharedBone = function(){
this.x = 0;
this.y = 0;
this.rot = 0;
this.sx = 1;
this.sy = 1;
this.name = "";
this.length = 0;
this.parent = -1;
this.childBones = [];
this.childSlots = [];
this.restX = 0;
this.restY = 0;
this.restRot = 0;
this.restSx = 1;
this.restSy = 1;
};
gdjs.sk.SharedBone.prototype.loadDragonBones = function(boneData){
this.name = boneData.name;
this.length = boneData.hasOwnProperty("length") ? boneData.length : 0;
var transformData = boneData.transform;
this.restX = transformData.hasOwnProperty("x") ? transformData.x : 0;
this.restY = transformData.hasOwnProperty("y") ? transformData.y : 0;
this.restRot = transformData.hasOwnProperty("skX") ? transformData.skX * Math.PI / 180.0 : 0;
this.restSx = transformData.hasOwnProperty("scX") ? transformData.scX : 1;
this.restSy = transformData.hasOwnProperty("scY") ? transformData.scY : 1;
this.inheritRotation = boneData.hasOwnProperty("inheritRotation") ? transformData.inheritRotation : true;
this.inheritScale = boneData.hasOwnProperty("inheritScale") ? transformData.inheritScale : true;
};
/**
* The Bone holds basic transform data in a hierarchy tree.
*
* @namespace gdjs.sk
* @class Bone
* @extends gdjs.sk.Transform
*/
gdjs.sk.Bone = function(armature){
gdjs.sk.Transform.call(this);
this.shared = null;
this.armature = armature;
};
gdjs.sk.Bone.prototype = Object.create(gdjs.sk.Transform.prototype);
gdjs.sk.Bone.prototype.loadData = function(boneData){
this.shared = boneData;
this.resetState();
};
gdjs.sk.Bone.prototype.resetState = function(){
this.setPos(0, 0);
this.setRot(0);
this.setScale(1, 1);
};
gdjs.sk.Bone.prototype.setX = function(x){
var prevX = this.x;
this.x = this.shared.restX + x;
if(this.x !== prevX){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setY = function(y){
var prevY = this.y;
this.y = this.shared.restY + y;
if(this.y !== prevY){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setPos = function(x, y){
var prevX = this.x;
var prevY = this.y;
this.x = this.shared.restX + x;
this.y = this.shared.restY + y;
if(this.x !== prevX || this.y !== prevY){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setRot = function(angle){
var prevRot = this.rot;
this.rot = this.shared.restRot + angle*Math.PI/180.0;
if(this.rot !== prevRot){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setSx = function(sx){
var prevSx = this.sx;
this.sx = this.shared.restSx * sx;
if(this.sx !== prevSx){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setSy = function(sy){
var prevSy = this.sy;
this.sy = this.shared.restSy * sy;
if(this.sy !== prevSy){
this._updateMatrix = true;
}
};
gdjs.sk.Bone.prototype.setScale = function(sx, sy){
var prevSx = this.sx;
var prevSy = this.sy;
this.sx = this.shared.restSx * sx;
this.sy = this.shared.restSy * sy;
if(this.sx !== prevSx || this.sy !== prevSy){
this._updateMatrix = true;
}
};

View File

@@ -0,0 +1,456 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
/**
* @namespace gdjs.sk
* @class SharedSlot
*/
gdjs.sk.SharedSlot = function(){
// Transform
this.x = 0;
this.y = 0;
this.rot = 0;
this.sx = 1;
this.sy = 1;
// Slot
this.name = "";
this.type = gdjs.sk.SLOT_UNDEFINED;
this.path = "";
this.parent = -1;
this.defaultZ = 0;
this.defaultR = 255;
this.defaultG = 255;
this.defaultB = 255;
this.defaultAlpha = 1.0;
this.defaultVisible = true;
this.aabb = null;
// Polygon
this.polygons = [];
// Mesh
this.rawVertices = [];
this.rawUVs = [];
this.rawTriangles = [];
this.defaultVertices = [];
this.skinned = false;
this.skinBones = [];
this.skinBonesMatricesInverses = [];
this.vertexBones = [];
this.vertexWeights = [];
// Armature
this.armature = "";
};
gdjs.sk.SharedSlot.prototype.loadDragonBonesSlotData = function(slotData){
this.name = slotData.name;
this.defaultZ = slotData.hasOwnProperty("z") ? slotData.z : 0;
this.defaultR = slotData.color.hasOwnProperty("rM") ? Math.ceil(slotData.color.rM * 255 / 100) : 255;
this.defaultG = slotData.color.hasOwnProperty("gM") ? Math.ceil(slotData.color.gM * 255 / 100) : 255;
this.defaultB = slotData.color.hasOwnProperty("bM") ? Math.ceil(slotData.color.bM * 255 / 100) : 255;
this.defaultAlpha = slotData.color.hasOwnProperty("aM") ? slotData.color.aM / 100.0 : 1.0;
this.defaultVisible = slotData.hasOwnProperty("displayIndex") ? (slotData.displayIndex + 1) / 2 : 1; // {-1, 1} -> {0, 1}
};
gdjs.sk.SharedSlot.prototype.loadDragonBonesSkinData = function(skinDatas, index){
var skinData = skinDatas[index];
var transformData = skinData.display[0].transform;
this.x = transformData.hasOwnProperty("x") ? transformData.x : 0;
this.y = transformData.hasOwnProperty("y") ? transformData.y : 0;
this.rot = transformData.hasOwnProperty("skX") ? transformData.skX * Math.PI / 180.0 : 0;
this.sx = transformData.hasOwnProperty("scX") ? transformData.scX : 1;
this.sy = transformData.hasOwnProperty("scY") ? transformData.scY : 1;
// If another slot is already using the same image path we have to search for it
if(!skinData.display[0].hasOwnProperty("path")){
for(var i=0; i<skinDatas.length; i++){
if(skinDatas[i].display[0].name === skinData.display[0].name && skinDatas[i].display[0].path){
this.path = skinDatas[i].display[0].path;
break;
}
}
}
else{
this.path = skinData.display[0].path;
}
if(skinData.display[0].type === "image"){
this.type = gdjs.sk.SLOT_IMAGE;
}
else if(skinData.display[0].type === "armature"){
this.type = gdjs.sk.SLOT_ARMATURE;
}
else if(skinData.display[0].type === "boundingBox"){
this.type = gdjs.sk.SLOT_POLYGON;
var polygon = [];
var verts = skinData.display[0].vertices;
for(var i=0; i<verts.length; i+=2){
polygon.push([verts[i], verts[i+1]]);
}
this.polygons.push(polygon);
}
else if(skinData.display[0].type === "mesh"){
this.type = gdjs.sk.SLOT_MESH;
for(var i=0; i<skinData.display[0].vertices.length; i+=2){
this.defaultVertices.push([skinData.display[0].vertices[i],
skinData.display[0].vertices[i+1]]);
}
this.rawVertices = skinData.display[0].vertices;
this.rawUVs = skinData.display[0].uvs;
this.rawTriangles = skinData.display[0].triangles;
if(skinData.display[0].hasOwnProperty("weights")){
this.skinned = true;
var slotPose = skinData.display[0].slotPose;
var worldMatrixInverse = new gdjs.sk.Matrix( slotPose[0],-slotPose[1], slotPose[4],
-slotPose[2], slotPose[3], slotPose[5]);
worldMatrixInverse.invert();
// maps Armature.bones index -> skinBones index
var boneMap = {};
for(var i=0, j=0; i<skinData.display[0].bonePose.length; i+=7, j++){
var bonePose = skinData.display[0].bonePose;
var boneWorldMatrix = new gdjs.sk.Matrix( bonePose[i+1],-bonePose[i+2], bonePose[i+5],
-bonePose[i+3], bonePose[i+4], bonePose[i+6]);
boneMap[bonePose[i]] = j;
this.skinBones.push(bonePose[i]);
this.skinBonesMatricesInverses.push(worldMatrixInverse.mul(boneWorldMatrix).invert());
}
for(var i=0; i<skinData.display[0].weights.length;){
var boneCount = skinData.display[0].weights[i];
var vertexWeights = [];
var vertexBones = [];
for(var k=0; k<boneCount; k++){
var boneId = skinData.display[0].weights[i + 2*k + 1];
vertexBones.push(boneMap[boneId]);
var boneWeight = skinData.display[0].weights[i + 2*k + 2];
vertexWeights.push(boneWeight);
}
this.vertexBones.push(vertexBones);
this.vertexWeights.push(vertexWeights);
i += 2 * boneCount + 1;
}
}
}
};
/**
* The Slot display images transformed by animations itself and bones.
*
* @namespace gdjs.sk
* @class Slot
* @extends gdjs.sk.Transform
*/
gdjs.sk.Slot = function(armature){
gdjs.sk.Transform.call(this);
this.shared = null;
this.armature = armature;
this.z = 0;
this.r = 0;
this.g = 0;
this.b = 0;
this.alpha = 0;
this.visible = false;
this.renderer = new gdjs.sk.SlotRenderer();
this._updateRender = false;
// Mesh only
this.vertices = []; // same as this.shared.defaultVertices, but modified on animations
this.skinBones = [];
// Armature only
this.childArmature = null;
// Debug only
this.debugRenderer = null;
}
gdjs.sk.Slot.prototype = Object.create(gdjs.sk.Transform.prototype);
gdjs.sk.Slot.prototype.loadData = function(slotData, skeletalData, textures, debugPolygons){
this.shared = slotData;
this.z = this.shared.defaultZ;
this.r = this.shared.defaultR;
this.g = this.shared.defaultG;
this.b = this.shared.defaultB;
this.alpha = this.shared.defaultAlpha;
this.visible = this.shared.defaultVisible;
this.x = this.shared.x;
this.y = this.shared.y;
this.rot = this.shared.rot;
this.sx = this.shared.sx;
this.sy = this.shared.sy;
this._updateMatrix = true;
this._updateWorldMatrix = true;
if(this.shared.type === gdjs.sk.SLOT_IMAGE){
this.renderer.loadAsSprite(textures[this.shared.path]);
if(!this.shared.aabb){
this.shared.aabb = [];
this.shared.aabb.push([-this.renderer.getWidth()/2.0,-this.renderer.getHeight()/2.0]);
this.shared.aabb.push([ this.renderer.getWidth()/2.0,-this.renderer.getHeight()/2.0]);
this.shared.aabb.push([ this.renderer.getWidth()/2.0, this.renderer.getHeight()/2.0]);
this.shared.aabb.push([-this.renderer.getWidth()/2.0, this.renderer.getHeight()/2.0]);
}
if(debugPolygons){
this.debugRenderer = new gdjs.sk.DebugRenderer();
this.debugRenderer.loadVertices(this.shared.aabb, [255, 100, 100], false);
}
}
else if(this.shared.type === gdjs.sk.SLOT_MESH){
for(var i=0; i<this.shared.defaultVertices.length; i++){
this.vertices.push([this.shared.defaultVertices[i][0], this.shared.defaultVertices[i][1]]);
}
for(var i=0; i<this.shared.skinBones.length; i++){
this.skinBones.push(this.armature.bones[this.shared.skinBones[i]]);
}
this.renderer.loadAsMesh(textures[this.shared.path],
this.shared.rawVertices,
this.shared.rawUVs,
this.shared.rawTriangles);
if(!this.shared.aabb){
this.shared.aabb = [];
this.shared.aabb.push([-this.renderer.getWidth()/2.0,-this.renderer.getHeight()/2.0]);
this.shared.aabb.push([ this.renderer.getWidth()/2.0,-this.renderer.getHeight()/2.0]);
this.shared.aabb.push([ this.renderer.getWidth()/2.0, this.renderer.getHeight()/2.0]);
this.shared.aabb.push([-this.renderer.getWidth()/2.0, this.renderer.getHeight()/2.0]);
}
if(debugPolygons){
this.debugRenderer = new gdjs.sk.DebugRenderer();
this.debugRenderer.loadVertices(this.shared.aabb, [255, 100, 100], false);
}
}
else if(this.shared.type === gdjs.sk.SLOT_POLYGON){
if(debugPolygons){
this.debugRenderer = new gdjs.sk.DebugRenderer();
this.debugRenderer.loadVertices(this.shared.polygons[0], [100, 255, 100], true);
}
}
else if(this.shared.type === gdjs.sk.SLOT_ARMATURE){
for(var i=0; i<skeletalData.armatures.length; i++){
if(skeletalData.armatures[i].name === this.shared.path){
this.childArmature = new gdjs.sk.Armature(this.armature.skeleton, this.armature, this);
this.childArmature.getRenderer().extraInitialization(this.armature.getRenderer());
this.childArmature.loadData(skeletalData.armatures[i], skeletalData, debugPolygons);
this.addChild(this.childArmature);
if(!this.shared.aabb){
this.shared.aabb = [];
var verts = this.childArmature.getAABB().vertices;
for(var j=0; j<verts.length; j++){
this.shared.aabb.push([verts[j][0], verts[j][1]]);
}
}
}
}
}
this.updateRendererColor();
this.updateRendererAlpha();
this.updateRendererVisible();
};
gdjs.sk.Slot.prototype.resetState = function(){
this.setZ(this.shared.defaultZ);
this.setColor(this.shared.defaultR, this.shared.defaultG, this.shared.defaultB);
this.setAlpha(this.shared.defaultAlpha);
this.setVisible(this.shared.defaultVisible);
if(this.shared.type === gdjs.sk.SLOT_MESH){
var verts = [];
var updateList = [];
for(var i=0; i<this.shared.defaultVertices.length; i++){
verts.push([0, 0]);
updateList.push(i);
}
this.setVertices(verts, updateList);
}
if(this.shared.type === gdjs.sk.SLOT_ARMATURE){
this.childArmature.resetState();
}
};
gdjs.sk.Slot.prototype.getZ = function(){
return this.z;
};
gdjs.sk.Slot.prototype.setZ = function(z){
this.z = z;
if(this.shared.type === gdjs.sk.SLOT_IMAGE || this.shared.type === gdjs.sk.SLOT_MESH){
this.renderer.setZ(z);
}
};
gdjs.sk.Slot.prototype.getColor = function(){
if(!this.armature.parentSlot){
return [this.r, this.g, this.b];
}
var armatureColor = this.armature.parentSlot.getColor();
return [this.r * armatureColor[0] / 255,
this.g * armatureColor[1] / 255,
this.b * armatureColor[2] / 255];
};
gdjs.sk.Slot.prototype.setColor = function(r, g, b){
if(this.r !== r || this.g !== g || this.b !== b){
this.r = r;
this.g = g;
this.b = b;
this.updateRendererColor();
}
};
gdjs.sk.Slot.prototype.updateRendererColor = function(){
if(this.shared.type === gdjs.sk.SLOT_IMAGE || this.shared.type === gdjs.sk.SLOT_MESH){
this.renderer.setColor(this.getColor());
}
else if(this.shared.type === gdjs.sk.SLOT_ARMATURE && this.childArmature){
for(var i=0; i<this.childArmature.slots.length; i++){
this.childArmature.slots[i].updateRendererColor();
}
}
};
gdjs.sk.Slot.prototype.getAlpha = function(){
if(!this.armature.parentSlot){
return this.alpha;
}
var armatureAlpha = this.armature.parentSlot.getAlpha();
return (this.alpha * armatureAlpha);
};
gdjs.sk.Slot.prototype.setAlpha = function(alpha){
if(this.alpha !== alpha){
this.alpha = alpha;
this.updateRendererAlpha();
}
};
gdjs.sk.Slot.prototype.updateRendererAlpha = function(){
if(this.shared.type === gdjs.sk.SLOT_IMAGE || this.shared.type === gdjs.sk.SLOT_MESH){
this.renderer.setAlpha(this.getAlpha());
}
else if(this.shared.type === gdjs.sk.SLOT_ARMATURE && this.childArmature){
for(var i=0; i<this.childArmature.slots.length; i++){
this.childArmature.slots[i].updateRendererAlpha();
}
}
};
gdjs.sk.Slot.prototype.getVisible = function(){
if(!this.armature.parentSlot){
return this.visible;
}
return (this.visible && this.armature.parentSlot.getVisible());
};
gdjs.sk.Slot.prototype.setVisible = function(visible){
if(this.visible !== visible){
this.visible = visible;
this.updateRendererVisible();
}
};
gdjs.sk.Slot.prototype.updateRendererVisible = function(){
if(this.shared.type === gdjs.sk.SLOT_IMAGE || this.shared.type === gdjs.sk.SLOT_MESH){
this.renderer.setVisible(this.getVisible());
}
else if(this.shared.type === gdjs.sk.SLOT_ARMATURE && this.childArmature){
for(var i=0; i<this.childArmature.slots.length; i++){
this.childArmature.slots[i].updateRendererVisible();
}
}
};
// Mesh only
gdjs.sk.Slot.prototype.setVertices = function(vertices, updateList){
var verts = [];
for(var i=0; i<updateList.length; i++){
this.vertices[updateList[i]] = [vertices[i][0] + this.shared.defaultVertices[updateList[i]][0],
vertices[i][1] + this.shared.defaultVertices[updateList[i]][1]];
verts.push(this.vertices[updateList[i]]);
}
this.renderer.setVertices(verts, updateList);
}
// Mesh only
gdjs.sk.Slot.prototype.updateSkinning = function(){
var verts = [];
var updateList = [];
var boneMatrices = [];
var inverseWorldMatrix = this.worldMatrix.inverse();
for(var i=0; i<this.skinBones.length; i++){
var localBoneMatrix = inverseWorldMatrix.mul(this.skinBones[i].worldMatrix);
boneMatrices.push(localBoneMatrix.mul(this.shared.skinBonesMatricesInverses[i]));
}
for(var i=0; i<this.shared.vertexWeights.length; i++){
var vx = 0.0;
var vy = 0.0;
for(var j=0; j<this.shared.vertexWeights[i].length; j++){
var v = boneMatrices[this.shared.vertexBones[i][j]].mulVec(this.vertices[i]);
vx += this.shared.vertexWeights[i][j] * v[0];
vy += this.shared.vertexWeights[i][j] * v[1];
}
verts.push([vx, vy]);
updateList.push(i);
}
this.renderer.setVertices(verts, updateList);
};
gdjs.sk.Slot.prototype.getPolygons = function(){
if(this.shared.type === gdjs.sk.SLOT_POLYGON){
var worldPolygons = [];
for(var i=0; i<this.shared.polygons.length; i++){
worldPolygons.push(this.transformPolygon(this.shared.polygons[i]));
}
return worldPolygons;
}
return [this.transformPolygon(this.shared.aabb)];
};
gdjs.sk.Slot.prototype.update = function(){
gdjs.sk.Transform.prototype.update.call(this);
if(this._updateRender && (this.shared.type === gdjs.sk.SLOT_IMAGE || this.shared.type === gdjs.sk.SLOT_MESH)){
var transform = gdjs.sk.Transform.decomposeMatrix(this.worldMatrix);
this.renderer.setTransform(transform);
}
if(this._updateRender && this.debugRenderer){
var transform = gdjs.sk.Transform.decomposeMatrix(this.worldMatrix);
this.debugRenderer.setTransform(transform);
}
this._updateRender = false;
};
gdjs.sk.Slot.prototype.updateTransform = function(){
if(this._updateMatrix || this._updateWorldMatrix){
this._updateRender = true;
}
gdjs.sk.Transform.prototype.updateTransform.call(this);
};

View File

@@ -0,0 +1,317 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
/**
* @namespace gdjs.sk
* @class SharedArmature
*/
gdjs.sk.SharedArmature = function(){
this.name = "";
this.bones = [];
this.bonesMap = {};
this.rootBone = -1;
this.slots = [];
this.slotsMap = {};
this.animations = [];
this.animationsMap = {};
this.aabb = [];
};
gdjs.sk.SharedArmature.prototype.loadDragonBones = function(armatureData, textures){
this.name = armatureData.name;
var aabb = armatureData.aabb;
this.aabb.push([aabb.x, aabb.y ]);
this.aabb.push([aabb.x + aabb.width, aabb.y ]);
this.aabb.push([aabb.x + aabb.width, aabb.y + aabb.height]);
this.aabb.push([aabb.x, aabb.y + aabb.height]);
// Get all the bones
for(var i=0; i<armatureData.bone.length; i++){
var bone = new gdjs.sk.SharedBone();
bone.loadDragonBones(armatureData.bone[i]);
this.bones.push(bone);
this.bonesMap[armatureData.bone[i].name] = i;
}
// Set bone parents
for(var i=0; i<armatureData.bone.length; i++){
if(armatureData.bone[i].hasOwnProperty("parent")){ // Child bone
this.bones[i].parent = this.bonesMap[armatureData.bone[i].parent];
this.bones[this.bones[i].parent].childBones.push(i);
}
else{ // Root bone
this.rootBone = i;
}
}
// Get all the slots
for(var i=0; i<armatureData.slot.length; i++){
var slot = new gdjs.sk.SharedSlot()
slot.loadDragonBonesSlotData(armatureData.slot[i]);
this.slots.push(slot);
this.slotsMap[armatureData.slot[i].name] = i;
this.slots[i].parent = this.bonesMap[armatureData.slot[i].parent];
this.bones[this.slots[i].parent].childSlots.push(i);
}
// Generate displayers
for(var i=0; i<armatureData.skin[0].slot.length; i++){
var skinData = armatureData.skin[0].slot[i];
var slot = this.slots[this.slotsMap[skinData.name]];
slot.loadDragonBonesSkinData(armatureData.skin[0].slot, i);
}
// Get all the animations
for(var i=0; i<armatureData.animation.length; i++){
var animation = new gdjs.sk.SharedAnimation();
animation.loadDragonBones(armatureData.animation[i], armatureData.frameRate, this.slots);
this.animations.push(animation);
this.animationsMap[animation.name] = i;
}
};
/**
* The Armature holds the bones and slots/attachments as well as its animations.
*
* @namespace gdjs.sk
* @class Armature
* @extends gdjs.sk.Transform
*/
gdjs.sk.Armature = function(skeleton, parentArmature=null, parentSlot=null){
gdjs.sk.Transform.call(this);
this.shared = null;
this.skeleton = skeleton;
this.parentArmature = parentArmature;
this.parentSlot = parentSlot;
this.bones = [];
this.bonesMap = {};
this.slots = [];
this.slotsMap = {};
this.animations = [];
this.animationsMap = {};
this.currentAnimation = -1;
this.renderer = new gdjs.sk.ArmatureRenderer();
this.debugRenderer = null;
this.isRoot = false;
};
gdjs.sk.Armature.prototype = Object.create(gdjs.sk.Transform.prototype);
gdjs.sk.Armature.prototype.loadData = function(armatureData, skeletalData, debugPolygons){
this.shared = armatureData;
if(debugPolygons){
this.debugRenderer = new gdjs.sk.DebugRenderer();
this.debugRenderer.loadVertices(this.shared.aabb, [100, 100, 255], false);
}
// Get all the bones
for(var i=0; i<this.shared.bones.length; i++){
var bone = new gdjs.sk.Bone(this);
bone.loadData(this.shared.bones[i]);
this.bones.push(bone);
this.bonesMap[bone.shared.name] = bone;
}
// With all the bones loaded, set parents
for(var i=0; i<this.shared.bones.length; i++){
if(this.shared.bones[i].parent !== -1){ // Child bone
this.bones[this.shared.bones[i].parent].addChild(this.bones[i]);
}
else{ // Root bone
this.addChild(this.bones[i]);
}
}
// Get all the slots
for(var i=0; i<this.shared.slots.length; i++){
var slot = new gdjs.sk.Slot(this);
this.bones[this.shared.slots[i].parent].addChild(slot);
slot.loadData(this.shared.slots[i], skeletalData, skeletalData.loader.textures, debugPolygons);
this.slots.push(slot);
this.slotsMap[slot.shared.name] = slot;
}
// Get all the animations
for(var i=0; i<this.shared.animations.length; i++){
var animation = new gdjs.sk.Animation(this);
animation.loadData(this.shared.animations[i]);
this.animations.push(animation);
this.animationsMap[animation.shared.name] = animation;
}
this.setRenderers();
};
gdjs.sk.Armature.prototype.setAsRoot = function(){
this.isRoot = true;
// Create an empty shared data, in case nothing is loaded
this.shared = new gdjs.sk.SharedArmature();
this.shared.aabb = [[0,0], [0,0], [0,0], [0,0]];
};
gdjs.sk.Armature.prototype.getRenderer = function(){
return this.renderer;
};
gdjs.sk.Armature.prototype.getRendererObject = function(){
return this.renderer.getRendererObject();
};
gdjs.sk.Armature.prototype.setRenderers = function(){
for(var i=0; i<this.slots.length; i++){
if(this.slots[i].shared.type === gdjs.sk.SLOT_IMAGE || this.slots[i].shared.type === gdjs.sk.SLOT_MESH){
this.renderer.addRenderer(this.slots[i].renderer);
if(this.slots[i].debugRenderer){
this.renderer.addDebugRenderer(this.slots[i].debugRenderer);
}
}
else if(this.slots[i].shared.type === gdjs.sk.SLOT_ARMATURE){
this.renderer.addRenderer(this.slots[i].childArmature.renderer);
if(this.slots[i].childArmature.debugRenderer){
this.renderer.addDebugRenderer(this.slots[i].childArmature.debugRenderer);
}
}
else if(this.slots[i].shared.type === gdjs.sk.SLOT_POLYGON){
if(this.slots[i].debugRenderer){
this.renderer.addDebugRenderer(this.slots[i].debugRenderer);
}
}
}
if(this.isRoot){
this.renderer.addDebugRenderer(this.debugRenderer);
}
};
gdjs.sk.Armature.prototype.getAABB = function(){
return this.transformPolygon(this.shared.aabb);
};
gdjs.sk.Armature.prototype.getDefaultWidth = function(){
return this.shared.aabb[1][0] - this.shared.aabb[0][0];
};
gdjs.sk.Armature.prototype.getDefaultHeight = function(){
return this.shared.aabb[2][1] - this.shared.aabb[1][1];
};
gdjs.sk.Armature.prototype.resetState = function(){
for(var i=0; i<this.bones.length; i++){
this.bones[i].resetState();
}
for(var i=0; i<this.slots.length; i++){
this.slots[i].resetState();
}
this.renderer.sortRenderers();
};
gdjs.sk.Armature.prototype.updateZOrder = function(){
this.renderer.sortRenderers();
};
gdjs.sk.Armature.prototype.update = function(){
gdjs.sk.Transform.prototype.update.call(this);
if(this.debugRenderer){
var transform = gdjs.sk.Transform.decomposeMatrix(this.worldMatrix);
this.debugRenderer.setTransform(transform);
}
};
gdjs.sk.Armature.prototype.getCurrentAnimation = function(){
if(this.currentAnimation >= 0 && this.currentAnimation < this.animations.length){
return this.animations[this.currentAnimation];
}
return null;
};
gdjs.sk.Armature.prototype.updateAnimation = function(delta){
var animation = this.getCurrentAnimation();
if(animation){
animation.update(delta);
}
};
gdjs.sk.Armature.prototype.isAnimationFinished = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.isFinished() : false;
};
gdjs.sk.Armature.prototype.getAnimationTime = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.getTime() : 0;
};
gdjs.sk.Armature.prototype.setAnimationTime = function(time){
var animation = this.getCurrentAnimation();
if(animation){
animation.setTime(time);
}
};
gdjs.sk.Armature.prototype.getAnimationTimeLength = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.getTimeLength() : 0;
};
gdjs.sk.Armature.prototype.getAnimationFrame = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.getFrame() : 0;
};
gdjs.sk.Armature.prototype.setAnimationFrame = function(frame){
var animation = this.getCurrentAnimation();
if(animation){
animation.setFrame(frame);
}
};
gdjs.sk.Armature.prototype.getAnimationFrameLength = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.getFrameLength() : 0;
};
gdjs.sk.Armature.prototype.getAnimationIndex = function(){
return this.currentAnimation;
};
gdjs.sk.Armature.prototype.setAnimationIndex = function(newAnimation, blendTime, loops){
if(newAnimation >= 0 && newAnimation < this.animations.length && newAnimation !== this.currentAnimation){
this.resetState();
var oldAnimation = this.currentAnimation;
this.currentAnimation = newAnimation;
this.animations[this.currentAnimation].reset(loops);
if(blendTime > 0 && oldAnimation >= 0 && oldAnimation < this.animations.length){
this.animations[this.currentAnimation].blendFrom(this.animations[oldAnimation], blendTime);
}
var armatureAnimators = this.animations[this.currentAnimation].armatureAnimators;
for(var i=0; i<armatureAnimators.length; i++){
armatureAnimators[i].setFirstFrameAnimation(blendTime);
}
this.animations[this.currentAnimation].update(0);
}
};
gdjs.sk.Armature.prototype.getAnimationName = function(){
var animation = this.getCurrentAnimation();
return animation ? animation.shared.name : "";
};
gdjs.sk.Armature.prototype.setAnimationName = function(newAnimation, blendTime, loops){
if(newAnimation in this.animationsMap){
this.setAnimationIndex(this.animations.indexOf(this.animationsMap[newAnimation]), blendTime, loops);
}
};
gdjs.sk.Armature.prototype.resetAnimation = function(){
var animation = this.getCurrentAnimation();
if(animation){
animation.reset();
}
};

View File

@@ -0,0 +1,678 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include "SkeletonObject.h"
void DeclareSkeletonObjectExtension(gd::PlatformExtension & extension)
{
extension.SetExtensionInformation("SkeletonObject",
_("Skeleton"),
_("Enables the use of animated skeleton objects.\nCurrently supported formats:\n *DragonBones"),
"Franco Maciel",
"Open source (MIT License)");
gd::ObjectMetadata & obj = extension.AddObject<SkeletonObject>(
"Skeleton",
_("Skeleton"),
_("Object animated through bones"),
"JsPlatform/Extensions/skeletonicon.png");
#if !defined(GD_NO_WX_GUI)
SkeletonObject::LoadEdittimeIcon();
#endif
// Object instructions
obj.AddCondition("ScaleX",
_("Scale X"),
_("Check the object scale X."),
_("Current scale X of _PARAM0_ is _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetScaleX",
_("Scale X"),
_("Change the object scale X."),
_("Set _PARAM0_ scale X _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("ScaleX", _("Scale X"), _("Object scale X"), _("Size"), "JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("ScaleY",
_("Scale Y"),
_("Check the object scale Y."),
_("Current scale Y of _PARAM0_ is _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetScaleY",
_("Scale Y"),
_("Change the object scale Y."),
_("Set _PARAM0_ scale Y _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("ScaleY", _("Scale Y"), _("Object scale Y"), _("Size"), "JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("Width",
_("Width"),
_("Check the object width."),
_("Current width of _PARAM0_ is _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetWidth",
_("Width"),
_("Change the object width."),
_("Set _PARAM0_ width _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("Width", _("Width"), _("Object width"), _("Size"), "JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("Height",
_("Height"),
_("Check the object height."),
_("Current height of _PARAM0_ is _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetHeight",
_("Height"),
_("Change the object height."),
_("Set _PARAM0_ height _PARAM1__PARAM2_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("Height", _("Height"), _("Object height"), _("Size"), "JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddAction("SetDefaultHitbox",
_("Default hitbox"),
_("Change the object default hitbox to be used by other conditions and behaviors."),
_("Set _PARAM0_ default hitbox to _PARAM1_"),
_("Size"),
"JsPlatform/Extensions/skeletonicon24.png",
"JsPlatform/Extensions/skeletonicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"");
// Animation instructions
obj.AddCondition("AnimationPaused",
_("Paused"),
_("Test if the animation for the skeleton is paused"),
_("Animation of _PARAM0_ is paused"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddAction("PauseAnimation",
_("Pause"),
_("Pauses animation for the skeleton"),
_("Pause animation for _PARAM0_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddCodeOnlyParameter("yesorno", "").SetDefaultValue("true");
obj.AddAction("UnpauseAnimation",
_("Unpause"),
_("Unpauses animation for the skeleton"),
_("Unpause animation for _PARAM0_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddCodeOnlyParameter("yesorno", "").SetDefaultValue("false");
obj.AddCondition("AnimationFinished",
_("Finished"),
_("Test if the animation has finished on this frame"),
_("Animation of _PARAM0_ has finished"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("AnimationTime",
_("Current time"),
_("Check the current animation elapsed time."),
_("Current animation time of _PARAM0_ is _PARAM1_ _PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetAnimationTime",
_("Current time"),
_("Change the current animation elapsed time."),
_("Set _PARAM0_ current animation time _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("AnimationTime", _("Current time"), _("Current animation elapsed time"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddExpression("AnimationTimeLength", _("Animation time length"), _("Current animation time length"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("AnimationFrame",
_("Current frame"),
_("Check the current animation frame.\nIf the animation is set as smooth, a float can be (and probably will be) returned."),
_("Current animation frame of _PARAM0_ is _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetAnimationFrame",
_("Current frame"),
_("Change the current animation frame"),
_("Set _PARAM0_ current animation frame _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("AnimationFrame", _("Current frame"), _("Current animation frame"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddExpression("AnimationFrameLength", _("Animation frame length"), _("Current animation frame length"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("AnimationIndex",
_("Animation index"),
_("Check the current animation index.\nIf not sure about the index, you can use the \"by name\" action"),
_("Current animation of _PARAM0_ is _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetAnimationIndex",
_("Animation index"),
_("Change the current animation from the animation index.\nIf not sure about the index, you can use the \"by name\" action"),
_("Set _PARAM0_ animation _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.AddParameter("expression", _("Blend time (0 for automatic blending)"), "", true).SetDefaultValue("0")
.AddParameter("expression", _("Loops (0 for infinite loops)"), "", true).SetDefaultValue("-1")
.SetManipulatedType("number");
obj.AddExpression("AnimationIndex", _("Animation index"), _("Current animation index"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("AnimationName",
_("Animation name"),
_("Check the current animation name."),
_("Current animation of _PARAM0_ is _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("string", _("Text"))
.SetManipulatedType("string");
obj.AddAction("SetAnimationName",
_("Animation name"),
_("Change the current animation from the animation name."),
_("Set _PARAM0_ animation to _PARAM1_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Text"))
.AddParameter("expression", _("Blend time (0 for automatic blending)"), "", true).SetDefaultValue("0")
.AddParameter("expression", _("Loops (0 for infinite loops)"), "", true).SetDefaultValue("-1");
obj.AddStrExpression("AnimationName", _("Animation name"), _("Current animation name"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddCondition("AnimationSmooth",
_("Smooth"),
_("Check if the object animation interpolator is smooth."),
_("Animation mode of _PARAM0_ is smooth"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddAction("SetAnimationSmooth",
_("Smooth"),
_("Change the object animation interpolator."),
_("Set animation mode of _PARAM0_ as smooth: _PARAM1_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("yesorno", _("Smooth"));
obj.AddCondition("AnimationTimeScale",
_("Time scale"),
_("Check the animation time scale."),
_("Animation time scale of _PARAM0_ is _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetAnimationTimeScale",
_("Time scale"),
_("Change the animation time scale"),
_("Set _PARAM0_ animation time scale _PARAM1__PARAM2_"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("AnimationTimeScale", _("Time scale"), _("Animation time scale"), _("Animation"), "JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
obj.AddAction("ResetAnimation",
_("Reset"),
_("Reset current animation"),
_("Reset _PARAM0_ current animation"),
_("Animation"),
"JsPlatform/Extensions/skeletonanimationicon24.png",
"JsPlatform/Extensions/skeletonanimationicon16.png")
.AddParameter("object", _("Object"), "Skeleton");
// Bone instructions
obj.AddCondition("BonePositionX",
_("Position X"),
_("Check the bone position X."),
_("Current position X of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetBonePositionX",
_("Position X"),
_("Change the bone position X."),
_("Set _PARAM0_:_PARAM1_ position X _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("BonePositionX", _("Position X"), _("Bone position X"), _("Bone"), "JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
obj.AddCondition("BonePositionY",
_("Position Y"),
_("Check the bone position Y."),
_("Current position Y of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetBonePositionY",
_("Position Y"),
_("Change the bone position Y."),
_("Set _PARAM0_:_PARAM1_ position Y _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("BonePositionY", _("Position Y"), _("Bone position Y"), _("Bone"), "JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
obj.AddAction("SetBonePosition",
_("Position"),
_("Change the bone position."),
_("Set _PARAM0_:_PARAM1_ position X _PARAM2__PARAM3_; Y _PARAM4__PARAM5_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Position X"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Position Y"));
obj.AddCondition("BoneAngle",
_("Angle"),
_("Check the bone angle (in degrees)."),
_("Current angle of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetBoneAngle",
_("Angle"),
_("Change the bone angle (in degrees)."),
_("Set _PARAM0_:_PARAM1_ angle _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("BoneAngle", _("Angle"), _("Slot angle (in degrees)"), _("Bone"), "JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
obj.AddCondition("BoneScaleX",
_("Scale X"),
_("Check the bone scale X."),
_("Current scale X of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetBoneScaleX",
_("Scale X"),
_("Change the bone scale X."),
_("Set _PARAM0_:_PARAM1_ scale X _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("BoneScaleX", _("Scale X"), _("Slot scale X"), _("Bone"), "JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
obj.AddCondition("BoneScaleY",
_("Scale Y"),
_("Check the bone scale Y."),
_("Current scale Y of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetBoneScaleY",
_("Scale Y"),
_("Change the bone scale Y."),
_("Set _PARAM0_:_PARAM1_ scale Y _PARAM2__PARAM3_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("BoneScaleY", _("Scale Y"), _("Slot scale Y"), _("Bone"), "JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
obj.AddAction("SetBoneScale",
_("Scale"),
_("Change the bone scale."),
_("Set _PARAM0_:_PARAM1_ scale X _PARAM2__PARAM3_; Y _PARAM4__PARAM5_"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Scale X"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Scale Y"));
obj.AddAction("ResetBone",
_("Reset"),
_("Reset the bone transformation."),
_("Reset _PARAM0_:_PARAM1_ transformation"),
_("Bone"),
"JsPlatform/Extensions/skeletonboneicon24.png",
"JsPlatform/Extensions/skeletonboneicon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Bone path")).SetDefaultValue("\"\"");
// Slot instructions
obj.AddAction("SetSlotColor",
_("Color"),
_("Change the slot color."),
_("Set _PARAM0_:_PARAM1_ color to _PARAM2_"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddParameter("color", _("Color"));
obj.AddCondition("SlotVisible",
_("Visible"),
_("Check the slot visibility."),
_("_PARAM0_:_PARAM1_ is visible"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"");
obj.AddAction("ShowSlot",
_("Show"),
_("Show the slot, making it visible."),
_("Show _PARAM0_:_PARAM1_"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"")
.AddCodeOnlyParameter("yesorno", "").SetDefaultValue("true");
obj.AddAction("HideSlot",
_("Hide"),
_("Hide the slot, making it invisible."),
_("Hide _PARAM0_:_PARAM1_"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"")
.AddCodeOnlyParameter("yesorno", "").SetDefaultValue("false");
obj.AddCondition("SlotZOrder",
_("Z-order"),
_("Check the slot Z-order."),
_("Z-order of _PARAM0_:_PARAM1_ is _PARAM2__PARAM3_"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"")
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddAction("SetSlotZOrder",
_("Z-order"),
_("Change the slot Z-order."),
_("Set _PARAM0_:_PARAM1_ Z-order _PARAM2__PARAM3_"),
_("Slot"),
"JsPlatform/Extensions/skeletonsloticon24.png",
"JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Slot path")).SetDefaultValue("\"\"")
.AddParameter("operator", _("Modification's sign"))
.AddParameter("expression", _("Value"))
.SetManipulatedType("number");
obj.AddExpression("SlotZOrder", _("Z-order"), _("Slot Z-order"), _("Slot"), "JsPlatform/Extensions/skeletonsloticon16.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"");
obj.AddCondition("PointInsideSlot",
_("Point inside slot"),
_("Check if the point is inside the slot"),
_("The point _PARAM2_;_PARAM3_ is inside _PARAM0_:_PARAM1_"),
_("Collision"),
"res/conditions/collisionPoint24.png",
"res/conditions/collisionPoint.png")
.AddParameter("object", _("Object"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddParameter("expression", _("Point X"))
.AddParameter("expression", _("Point Y"));
// Extension instructions
extension.AddCondition("SlotCollidesWithObject",
_("Slot collides with object"),
_("Check if the slot collides with an object"),
_("_PARAM0_:_PARAM1_ collides with _PARAM2_"),
_("Collision"),
"res/conditions/collision24.png",
"res/conditions/collision.png")
.AddParameter("objectList", _("Skeleton"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddParameter("objectList", _("Object"))
.AddCodeOnlyParameter("conditionInverted", "");
extension.AddCondition("SlotCollidesWithSlot",
_("Slot collides with slot"),
_("Check if the slot collides with another skeleton slot"),
_("_PARAM0_:_PARAM1_ collides with _PARAM2_:_PARAM3_"),
_("Collision"),
"res/conditions/collision24.png",
"res/conditions/collision.png")
.AddParameter("objectList", _("Skeleton"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddParameter("objectList", _("Other skeleton"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddCodeOnlyParameter("conditionInverted", "");
extension.AddCondition("RaycastSlot",
_("Raycast slot"),
_("Same as Raycast, but intersects specific slots instead."),
_("Raycast _PARAM0_:_PARAM1_ from _PARAM2_;_PARAM3_"),
_("Collision"),
"res/conditions/collision24.png",
"res/conditions/collision.png")
.AddParameter("objectList", _("Skeleton to test against the ray"), "Skeleton")
.AddParameter("string", _("Sloth path")).SetDefaultValue("\"\"")
.AddParameter("expression", _("Ray source X position"))
.AddParameter("expression", _("Ray source Y position"))
.AddParameter("expression", _("Ray angle (in degrees)"))
.AddParameter("expression", _("Ray maximum distance (in pixels)"))
.AddParameter("scenevar", _("Variable where to store the X position of the intersection"))
.AddParameter("scenevar", _("Variable where to store the Y position of the intersection"))
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,451 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
/**
* The SkeletonRuntimeObject imports and displays skeletal animations files.
*
* @namespace gdjs
* @class SkeletonRuntimeObject
* @extends RuntimeObject
*/
gdjs.SkeletonRuntimeObject = function(runtimeScene, objectData){
gdjs.RuntimeObject.call(this, runtimeScene, objectData);
this.rootArmature = new gdjs.sk.Armature(this);
this.rootArmature.getRenderer().putInScene(this, runtimeScene);
this.rootArmature.setAsRoot();
this.animationPlaying = true;
this.animationSmooth = true;
this.timeScale = 1.0;
this.scaleX = 1.0;
this.scaleY = 1.0;
this.hitboxSlot = null;
this.manager = gdjs.SkeletonObjectsManager.getManager(runtimeScene);
this.getSkeletonData(runtimeScene, objectData);
};
gdjs.SkeletonRuntimeObject.prototype = Object.create(gdjs.RuntimeObject.prototype);
gdjs.SkeletonRuntimeObject.thisIsARuntimeObjectConstructor = "SkeletonObject::Skeleton";
gdjs.SkeletonRuntimeObject.prototype.extraInitializationFromInitialInstance = function(initialInstanceData) {
if(initialInstanceData.customSize){
this.setWidth(initialInstanceData.width);
this.setHeight(initialInstanceData.height);
}
};
gdjs.SkeletonRuntimeObject.prototype.getSkeletonData = function(runtimeScene, objectData){
var skeletonData = this.manager.getSkeleton(runtimeScene, this.name, objectData);
if(skeletonData.armatures.length > 0){
this.rootArmature.loadData(skeletonData.armatures[skeletonData.rootArmature],
skeletonData,
objectData.debugPolygons);
this.rootArmature.resetState();
}
};
// RuntimeObject overwrites
gdjs.SkeletonRuntimeObject.prototype.setX = function(x){
this.x = x;
this.rootArmature.setX(x);
};
gdjs.SkeletonRuntimeObject.prototype.setY = function(y){
this.y = y;
this.rootArmature.setY(y);
};
gdjs.SkeletonRuntimeObject.prototype.setAngle = function(angle){
this.angle = angle;
this.rootArmature.setRot(angle);
};
gdjs.SkeletonRuntimeObject.prototype.getRendererObject = function(){
return this.rootArmature.getRendererObject();
};
gdjs.SkeletonRuntimeObject.prototype.getHitBoxes = function(){
if(this.hitboxSlot){
return this.hitboxSlot.getPolygons();
}
return [this.rootArmature.getAABB()];
};
gdjs.SkeletonRuntimeObject.prototype.stepBehaviorsPreEvents = function(runtimeScene){
var delta = this.getElapsedTime(runtimeScene) / 1000.0;
if(this.animationPlaying){
this.rootArmature.updateAnimation(delta*this.timeScale);
}
gdjs.RuntimeObject.prototype.stepBehaviorsPreEvents.call(this, runtimeScene);
};
gdjs.SkeletonRuntimeObject.prototype.update = function(runtimeScene){
this.rootArmature.update();
};
gdjs.SkeletonRuntimeObject.prototype.getDrawableX = function(){
return this.getX() - this.rootArmature.shared.aabb[0][0] * Math.abs(this.scaleX);
};
gdjs.SkeletonRuntimeObject.prototype.getDrawableY = function(){
return this.getY() - this.rootArmature.shared.aabb[0][1] * Math.abs(this.scaleY);
};
// Object instructions
gdjs.SkeletonRuntimeObject.prototype.getScaleX = function(){
return this.scaleX;
};
gdjs.SkeletonRuntimeObject.prototype.setScaleX = function(scaleX){
this.scaleX = scaleX;
this.rootArmature.setSx(scaleX);
};
gdjs.SkeletonRuntimeObject.prototype.getScaleY = function(){
return this.scaleY;
};
gdjs.SkeletonRuntimeObject.prototype.setScaleY = function(scaleY){
this.scaleY = scaleY;
this.rootArmature.setSy(scaleY);
};
gdjs.SkeletonRuntimeObject.prototype.getWidth = function(){
return this.rootArmature.getDefaultWidth() * Math.abs(this.scaleX);
};
gdjs.SkeletonRuntimeObject.prototype.setWidth = function(width){
if(width < 0) width = 0;
this.setScaleX(width / this.rootArmature.getDefaultWidth());
};
gdjs.SkeletonRuntimeObject.prototype.getHeight = function(){
return this.rootArmature.getDefaultHeight() * Math.abs(this.scaleY);
};
gdjs.SkeletonRuntimeObject.prototype.setHeight = function(height){
if(height < 0) height = 0;
this.setScaleY(height / this.rootArmature.getDefaultHeight());
};
gdjs.SkeletonRuntimeObject.prototype.setDefaultHitbox = function(slotPath){
if(slotPath === ""){
this.hitboxSlot = null;
return;
}
var slot = this.getSlot(slotPath);
if(slot){
this.hitboxSlot = slot;
}
};
// Animation instructions
gdjs.SkeletonRuntimeObject.prototype.isAnimationPaused = function(){
return !this.animationPlaying;
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationPaused = function(paused){
this.animationPlaying = !paused;
};
gdjs.SkeletonRuntimeObject.prototype.isAnimationFinished = function(){
return this.rootArmature.isAnimationFinished();
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationTime = function(){
return this.rootArmature.getAnimationTime();
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationTime = function(time){
this.rootArmature.setAnimationTime(time);
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationTimeLength = function(){
return this.rootArmature.getAnimationTimeLength();
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationFrame = function(){
return this.rootArmature.getAnimationFrame();
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationFrame = function(frame){
this.rootArmature.setAnimationFrame(frame);
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationFrameLength = function(){
return this.rootArmature.getAnimationFrameLength();
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationIndex = function(){
return this.rootArmature.getAnimationIndex();
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationIndex = function(newAnimation, blendTime=0, loops=-1){
this.rootArmature.setAnimationIndex(newAnimation, blendTime, loops);
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationName = function(){
return this.rootArmature.getAnimationName();
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationName = function(newAnimation, blendTime=0, loops=-1){
this.rootArmature.setAnimationName(newAnimation, blendTime, loops);
};
gdjs.SkeletonRuntimeObject.prototype.isAnimationSmooth = function(){
return this.animationSmooth;
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationSmooth = function(smooth){
this.animationSmooth = smooth;
};
gdjs.SkeletonRuntimeObject.prototype.getAnimationTimeScale = function(){
return this.timeScale;
};
gdjs.SkeletonRuntimeObject.prototype.setAnimationTimeScale = function(timeScale){
if(timeScale < 0) timeScale = 0; // Support negative timeScale (backward animation) ?
this.timeScale = timeScale;
};
gdjs.SkeletonRuntimeObject.prototype.resetAnimation = function(){
this.rootArmature.resetAnimation();
};
// Bone instructions
gdjs.SkeletonRuntimeObject.prototype.getBoneX = function(bonePath){
var bone = this.getBone(bonePath);
return bone ? bone.getGlobalX() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setBoneX = function(bonePath, x){
var bone = this.getBone(bonePath);
if(bone){
bone.setGlobalX(x);
bone.update();
}
};
gdjs.SkeletonRuntimeObject.prototype.getBoneY = function(bonePath){
var bone = this.getBone(bonePath);
return bone ? bone.getGlobalY() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setBoneY = function(bonePath, y){
var bone = this.getBone(bonePath);
if(bone){
bone.setGlobalY(y);
bone.update();
}
};
gdjs.SkeletonRuntimeObject.prototype.getBoneAngle = function(bonePath){
var bone = this.getBone(bonePath);
return bone ? bone.getGlobalRot() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setBoneAngle = function(bonePath, angle){
var bone = this.getBone(bonePath);
if(bone){
bone.setGlobalRot(angle);
bone.update();
}
};
gdjs.SkeletonRuntimeObject.prototype.getBoneScaleX = function(bonePath){
var bone = this.getBone(bonePath);
return bone ? bone.getSx() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setBoneScaleX = function(bonePath, scaleX){
var bone = this.getBone(bonePath);
if(bone){
bone.setSx(scaleX);
bone.update();
}
};
gdjs.SkeletonRuntimeObject.prototype.getBoneScaleY = function(bonePath){
var bone = this.getBone(bonePath);
return bone ? bone.getSy() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setBoneScaleY = function(bonePath, scaleY){
var bone = this.getBone(bonePath);
if(bone){
bone.setSy(scaleY);
bone.update();
}
};
gdjs.SkeletonRuntimeObject.prototype.resetBone = function(bonePath){
var bone = this.getBone(bonePath);
if(bone){
bone.resetState();
}
};
// Slot instructions
gdjs.SkeletonRuntimeObject.prototype.setSlotColor = function(slotPath, color){
var slot = this.getSlot(slotPath);
if(slot){
var rgb = color.split(";");
if(rgb.length < 3) return;
slot.setColor(...rgb);
}
};
gdjs.SkeletonRuntimeObject.prototype.isSlotVisible = function(slotPath){
var slot = this.getSlot(slotPath);
return slot ? slot.getVisible() : false;
};
gdjs.SkeletonRuntimeObject.prototype.setSlotVisible = function(slotPath, visible){
var slot = this.getSlot(slotPath);
if(slot){
slot.setVisible(visible);
}
};
gdjs.SkeletonRuntimeObject.prototype.getSlotZOrder = function(slotPath){
var slot = this.getSlot(slotPath);
return slot ? slot.getZ() : 0;
};
gdjs.SkeletonRuntimeObject.prototype.setSlotZOrder = function(slotPath, z){
var slot = this.getSlot(slotPath);
if(slot){
slot.setZ(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;
}
return false;
};
// Extension instructions
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;
var hitBoxes = this.getPolygons(slotPath);
if(!hitBoxes) return result;
for(var i=0; i<hitBoxes.length; i++){
var res = gdjs.Polygon.raycastTest(hitBoxes[i], x, y, endX, endY);
if ( res.collision ) {
if ( closest && (res.closeSqDist < testSqDist) ) {
testSqDist = res.closeSqDist;
result = res;
}
else if ( !closest && (res.farSqDist > testSqDist) && (res.farSqDist <= dist*dist) ) {
testSqDist = res.farSqDist;
result = res;
}
}
}
return result;
};
// Warning!, assuming gdjs.evtTools.object.twoListsTest calls the predicate
// respecting the given objects lists paramenters order
gdjs.SkeletonRuntimeObject.slotObjectCollisionTest = function(skl, obj, slotPath){
var hitBoxes1 = skl.getPolygons(slotPath);
if(!hitBoxes1) return false;
var hitBoxes2 = obj.getHitBoxes();
for(var k=0, lenBoxes1=hitBoxes1.length; k<lenBoxes1; ++k){
for(var l=0, lenBoxes2=hitBoxes2.length; l<lenBoxes2; ++l){
if (gdjs.Polygon.collisionTest(hitBoxes1[k], hitBoxes2[l]).collision){
return true;
}
}
}
return false;
};
gdjs.SkeletonRuntimeObject.slotSlotCollisionTest = function(skl1, skl2, slotPaths){
var hitBoxes1 = skl1.getPolygons(slotPaths[0]);
var hitBoxes2 = skl2.getPolygons(slotPaths[1]);
if(!hitBoxes1 || !hitBoxes2) return false;
for(var k=0, lenBoxes1=hitBoxes1.length; k<lenBoxes1; ++k){
for(var l=0, lenBoxes2=hitBoxes2.length; l<lenBoxes2; ++l){
if (gdjs.Polygon.collisionTest(hitBoxes1[k], hitBoxes2[l]).collision){
return true;
}
}
}
return false;
};
// Helpers
gdjs.SkeletonRuntimeObject.prototype.getSlot = function(slotPath){
var slotArray = slotPath.split("/");
var currentSlot = null;
if(slotArray[0] in this.rootArmature.slotsMap){
currentSlot = this.rootArmature.slotsMap[slotArray[0]];
for(var i=1; i<slotArray.length; i++){
if(currentSlot.type === gdjs.sk.SLOT_ARMATURE &&
slotArray[i] in currentSlot.childArmature.slotsMap){
currentSlot = currentSlot.childArmature.slotsMap[slotArray[i]];
}
else{
return null
}
}
}
return currentSlot;
};
gdjs.SkeletonRuntimeObject.prototype.getBone = function(bonePath){
var slotArray = bonePath.split("/");
var boneName = slotArray.pop();
if(slotArray.length === 0 && boneName in this.rootArmature.bonesMap){
return this.rootArmature.bonesMap[boneName];
}
var slot = this.getSlot(slotArray.join("/"));
if(slot && slot.type === gdjs.sk.SLOT_ARMATURE && boneName in slot.childArmature.bonesMap){
return slot.childArmature.bonesMap[boneName];
}
return null;
};
gdjs.SkeletonRuntimeObject.prototype.getPolygons = function(slotPath){
if(slotPath === ""){
return this.rootArmature.getHitBoxes();
}
var slot = this.getSlot(slotPath);
if(slot){
return slot.getPolygons();
}
return null;
};

View File

@@ -0,0 +1,53 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
gdjs.SkeletonObjectsManager = function(){
// List of loaded skeletons per object type
this.loadedObjects = {};
};
gdjs.SkeletonObjectsManager.getManager = function(runtimeScene){
if( !runtimeScene.skeletonObjectsManager ){
runtimeScene.skeletonObjectsManager = new gdjs.SkeletonObjectsManager();
}
return runtimeScene.skeletonObjectsManager;
};
gdjs.SkeletonObjectsManager.prototype.getSkeleton = function(runtimeScene, objectName, objectData){
if( !(objectName in this.loadedObjects) ){
this.loadedObjects[objectName] = this.loadSkeleton(runtimeScene, objectData);
}
return this.loadedObjects[objectName];
};
gdjs.SkeletonObjectsManager.prototype.loadSkeleton = function(runtimeScene, objectData){
var loader = new gdjs.sk.DataLoader();
var skeletalData = loader.getData(objectData.skeletalDataFilename);
var skeleton = {"loader": loader,
"armatures": [],
"rootArmature": 0};
if(!skeletalData) return skeleton;
if(objectData.apiName === "DragonBones"){
// Load sub-textures
loader.loadDragonBones(runtimeScene, objectData);
// Load the root armature with the given name
for(var i=0; i<skeletalData.armature.length; i++){
var armature = new gdjs.sk.SharedArmature();
armature.loadDragonBones(skeletalData.armature[i]);
skeleton.armatures.push(armature);
if(armature.name === objectData.rootArmatureName){
skeleton.rootArmature = i;
}
}
}
return skeleton;
};

View File

@@ -0,0 +1,57 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
gdjs.sk.slotObjectCollision = function(objectsLists1, slotPath, objectsLists2, inverted){
return gdjs.evtTools.object.twoListsTest(gdjs.SkeletonRuntimeObject.slotObjectCollisionTest,
objectsLists1, objectsLists2, inverted, slotPath);
};
gdjs.sk.slotSlotCollision = function(objectsLists1, slotPath1, objectsLists2, slotPath2, inverted){
return gdjs.evtTools.object.twoListsTest(gdjs.SkeletonRuntimeObject.slotSlotCollisionTest,
objectsLists1, objectsLists2, inverted, [slotPath1, slotPath2]);
};
gdjs.sk.raycastSlot = function(objectsLists, slotPath, x, y, angle, dist, varX, varY, inverted){
var matchObject = null;
var testSqDist = inverted ? 0 : dist*dist;
var resultX = 0;
var resultY = 0;
var lists = gdjs.staticArray(gdjs.sk.raycastSlot);
objectsLists.values(lists);
for (var i = 0; i < lists.length; i++) {
var list = lists[i];
for (var j = 0; j < list.length; j++) {
var object = list[j];
var result = object.raycastSlot(slotPath, x, y, angle, dist, !inverted);
if( result.collision ) {
if ( !inverted && (result.closeSqDist <= testSqDist) ) {
testSqDist = result.closeSqDist;
matchObject = object;
resultX = result.closeX;
resultY = result.closeY;
}
else if ( inverted && (result.farSqDist >= testSqDist) ) {
testSqDist = result.farSqDist;
matchObject = object;
resultX = result.farX;
resultY = result.farY;
}
}
}
}
if ( !matchObject )
return false;
gdjs.evtTools.object.pickOnly(objectsLists, matchObject);
varX.setNumber(resultX);
varY.setNumber(resultY);
return true;
};

View File

@@ -0,0 +1,159 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/Extensions/PlatformExtension.h"
#include "SkeletonObject.h"
#include <iostream>
void DeclareSkeletonObjectExtension(gd::PlatformExtension & extension);
/**
* \brief This class declares information about the JS extension.
*/
class SkeletonObjectJsExtension : public gd::PlatformExtension
{
public:
/**
* Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions.
*/
SkeletonObjectJsExtension()
{
DeclareSkeletonObjectExtension(*this);
GetObjectMetadata("SkeletonObject::Skeleton")
.SetIncludeFile("Extensions/SkeletonObject/Isk-tools.js")
.AddIncludeFile("Extensions/SkeletonObject/Hskmanager.js")
.AddIncludeFile("Extensions/SkeletonObject/Gskeletonruntimeobject.js")
.AddIncludeFile("Extensions/SkeletonObject/Fskanimation.js")
.AddIncludeFile("Extensions/SkeletonObject/Eskarmature.js")
.AddIncludeFile("Extensions/SkeletonObject/Dskslot.js")
.AddIncludeFile("Extensions/SkeletonObject/Cskbone.js")
.AddIncludeFile("Extensions/SkeletonObject/Bskeletonruntimeobject-cocos-renderer.js")
.AddIncludeFile("Extensions/SkeletonObject/Bskeletonruntimeobject-pixi-renderer.js")
.AddIncludeFile("Extensions/SkeletonObject/Ask.js");
auto & actions = GetAllActionsForObject("SkeletonObject::Skeleton");
auto & conditions = GetAllConditionsForObject("SkeletonObject::Skeleton");
auto & expressions = GetAllExpressionsForObject("SkeletonObject::Skeleton");
auto & strExpressions = GetAllStrExpressionsForObject("SkeletonObject::Skeleton");
// Object instructions
conditions["SkeletonObject::ScaleX"].SetFunctionName("getScaleX");
actions["SkeletonObject::SetScaleX"].SetFunctionName("setScaleX").SetGetter("getScaleX");
expressions["ScaleX"].SetFunctionName("getScaleX");
conditions["SkeletonObject::ScaleY"].SetFunctionName("getScaleY");
actions["SkeletonObject::SetScaleY"].SetFunctionName("setScaleY").SetGetter("getScaleY");
expressions["ScaleY"].SetFunctionName("getScaleY");
conditions["SkeletonObject::Width"].SetFunctionName("getWidth");
actions["SkeletonObject::SetWidth"].SetFunctionName("setWidth").SetGetter("getWidth");
expressions["Width"].SetFunctionName("getWidth");
conditions["SkeletonObject::Height"].SetFunctionName("getHeight");
actions["SkeletonObject::SetHeight"].SetFunctionName("setHeight").SetGetter("getHeight");
expressions["Height"].SetFunctionName("getHeight");
actions["SkeletonObject::SetDefaultHitbox"].SetFunctionName("setDefaultHitbox");
// Animation instructions
conditions["SkeletonObject::AnimationPaused"].SetFunctionName("isAnimationPaused");
actions["SkeletonObject::PauseAnimation"].SetFunctionName("setAnimationPaused");
actions["SkeletonObject::UnpauseAnimation"].SetFunctionName("setAnimationPaused");
conditions["SkeletonObject::AnimationFinished"].SetFunctionName("isAnimationFinished");
conditions["SkeletonObject::AnimationTime"].SetFunctionName("getAnimationTime");
actions["SkeletonObject::SetAnimationTime"].SetFunctionName("setAnimationTime").SetGetter("getAnimationTime");
expressions["AnimationTime"].SetFunctionName("getAnimationTime");
expressions["AnimationTimeLength"].SetFunctionName("getAnimationTimeLength");
conditions["SkeletonObject::AnimationFrame"].SetFunctionName("getAnimationFrame");
actions["SkeletonObject::SetAnimationFrame"].SetFunctionName("setAnimationFrame").SetGetter("getAnimationFrame");
expressions["AnimationFrame"].SetFunctionName("getAnimationFrame");
expressions["AnimationFrameLength"].SetFunctionName("getAnimationFrameLength");
conditions["SkeletonObject::AnimationIndex"].SetFunctionName("getAnimationIndex");
actions["SkeletonObject::SetAnimationIndex"].SetFunctionName("setAnimationIndex").SetGetter("getAnimationIndex");
expressions["AnimationIndex"].SetFunctionName("getAnimationIndex");
conditions["SkeletonObject::AnimationName"].SetFunctionName("getAnimationName");
actions["SkeletonObject::SetAnimationName"].SetFunctionName("setAnimationName").SetGetter("getAnimationName");
strExpressions["AnimationName"].SetFunctionName("getAnimationName");
conditions["SkeletonObject::AnimationSmooth"].SetFunctionName("isAnimationSmooth");
actions["SkeletonObject::SetAnimationSmooth"].SetFunctionName("setAnimationSmooth");
conditions["SkeletonObject::AnimationTimeScale"].SetFunctionName("getAnimationTimeScale");
actions["SkeletonObject::SetAnimationTimeScale"].SetFunctionName("setAnimationTimeScale").SetGetter("getAnimationTimeScale");
expressions["AnimationTimeScale"].SetFunctionName("getAnimationTimeScale");
actions["SkeletonObject::ResetAnimation"].SetFunctionName("resetAnimation");
// Bone instructions
conditions["SkeletonObject::BonePositionX"].SetFunctionName("getBoneX");
actions["SkeletonObject::SetBonePositionX"].SetFunctionName("setBoneX").SetGetter("getBoneX");
expressions["BonePositionX"].SetFunctionName("getBoneX");
conditions["SkeletonObject::BonePositionY"].SetFunctionName("getBoneY");
actions["SkeletonObject::SetBonePositionY"].SetFunctionName("setBoneY").SetGetter("getBoneY");
expressions["BonePositionY"].SetFunctionName("getBoneY");
conditions["SkeletonObject::BoneAngle"].SetFunctionName("getBoneAngle");
actions["SkeletonObject::SetBoneAngle"].SetFunctionName("setBoneAngle").SetGetter("getBoneAngle");
expressions["BoneAngle"].SetFunctionName("getBoneAngle");
conditions["SkeletonObject::BoneScaleX"].SetFunctionName("getBoneScaleX");
actions["SkeletonObject::SetBoneScaleX"].SetFunctionName("setBoneScaleX").SetGetter("getBoneScaleX");
expressions["BoneScaleX"].SetFunctionName("getBoneScaleX");
conditions["SkeletonObject::BoneScaleY"].SetFunctionName("getBoneScaleY");
actions["SkeletonObject::SetBoneScaleY"].SetFunctionName("setBoneScaleY").SetGetter("getBoneScaleY");
expressions["BoneScaleY"].SetFunctionName("getBoneScaleY");
actions["SkeletonObject::ResetBone"].SetFunctionName("resetBone");
// Slot instructions
actions["SkeletonObject::SetSlotColor"].SetFunctionName("setSlotColor");
conditions["SkeletonObject::SlotVisible"].SetFunctionName("isSlotVisible");
actions["SkeletonObject::ShowSlot"].SetFunctionName("setSlotVisible");
actions["SkeletonObject::HideSlot"].SetFunctionName("setSlotVisible");
conditions["SkeletonObject::SlotZOrder"].SetFunctionName("getSlotZOrder");
actions["SkeletonObject::SetSlotZOrder"].SetFunctionName("setSlotZOrder").SetGetter("getSlotZOrder");
expressions["SlotZOrder"].SetFunctionName("getSlotZOrder");
conditions["SkeletonObject::PointInsideSlot"].SetFunctionName("isPointInsideSlot");
// Extension instructions
GetAllConditions()["SkeletonObject::SlotCollidesWithObject"].SetFunctionName("gdjs.sk.slotObjectCollision");
GetAllConditions()["SkeletonObject::SlotCollidesWithSlot"].SetFunctionName("gdjs.sk.slotSlotCollision");
GetAllConditions()["SkeletonObject::RaycastSlot"].SetFunctionName("gdjs.sk.raycastSlot");
GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION();
};
};
#if defined(EMSCRIPTEN)
extern "C" gd::PlatformExtension * CreateGDJSSkeletonObjectExtension() {
return new SkeletonObjectJsExtension;
}
#else
/**
* Used by GDevelop to create the extension class
* -- Do not need to be modified. --
*/
extern "C" gd::PlatformExtension * GD_EXTENSION_API CreateGDJSExtension() {
return new SkeletonObjectJsExtension;
}
#endif
#endif

View File

@@ -0,0 +1,151 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
#include <SFML/Graphics.hpp>
#include "GDCpp/Runtime/Project/Project.h"
#include "GDCpp/Runtime/Project/Object.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/IDE/Dialogs/PropertyDescriptor.h"
#include "GDCpp/Runtime/ImageManager.h"
#include "GDCpp/Runtime/Serialization/SerializerElement.h"
#include "GDCpp/Runtime/Serialization/Serializer.h"
#include "GDCpp/Runtime/Project/InitialInstance.h"
#include "GDCpp/Runtime/CommonTools.h"
#include "SkeletonObject.h"
#include "GDCore/String.h"
#include "GDCpp/Runtime/ResourcesLoader.h"
#include <iostream>
#if defined(GD_IDE_ONLY)
#if !defined(GD_NO_WX_GUI)
#include <wx/bitmap.h>
#include <wx/filename.h>
#endif
sf::Texture SkeletonObject::edittimeIconImage;
sf::Sprite SkeletonObject::edittimeIcon;
#endif
SkeletonObject::SkeletonObject(gd::String name_) :
Object(name_)
{
#if defined(GD_IDE_ONLY)
originalSize = sf::Vector2f(32.0f, 32.0f),
originOffset = sf::Vector2f(16.0f, 16.0f),
sizeDirty = true;
#endif
}
void SkeletonObject::DoUnserializeFrom(gd::Project & project, const gd::SerializerElement & element)
{
skeletalDataFilename = element.GetStringAttribute("skeletalDataFilename");
rootArmatureName = element.GetStringAttribute("rootArmatureName");
textureDataFilename = element.GetStringAttribute("textureDataFilename");
textureName = element.GetStringAttribute("textureName");
apiName = element.GetStringAttribute("apiName");
debugPolygons = element.GetBoolAttribute("debugPolygons", false);
}
#if defined(GD_IDE_ONLY)
void SkeletonObject::DoSerializeTo(gd::SerializerElement & element) const
{
element.SetAttribute("skeletalDataFilename", skeletalDataFilename);
element.SetAttribute("rootArmatureName", rootArmatureName);
element.SetAttribute("textureDataFilename", textureDataFilename);
element.SetAttribute("textureName", textureName);
element.SetAttribute("apiName", apiName);
element.SetAttribute("debugPolygons", debugPolygons);
}
std::map<gd::String, gd::PropertyDescriptor> SkeletonObject::GetProperties(gd::Project & project) const
{
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Skeletal data filename")].SetValue(skeletalDataFilename);
properties[_("Main armature name")].SetValue(rootArmatureName);
properties[_("Texture data filename")].SetValue(textureDataFilename);
properties[_("Texture")].SetValue(textureName);
properties[_("API")]
.SetValue(apiName)
.SetType("Choice")
.AddExtraInfo("DragonBones");
properties[_("Debug Polygons")].SetValue(debugPolygons ? "true" : "false").SetType("Boolean");
return properties;
}
bool SkeletonObject::UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project)
{
if (name == _("Skeletal data filename")) {
skeletalDataFilename = value;
sizeDirty = true;
}
if (name == _("Main armature name")) {
rootArmatureName = value;
sizeDirty = true;
}
if (name == _("Texture data filename")) textureDataFilename = value;
if (name == _("Texture")) textureName = value;
if (name == _("API")) apiName = value;
if (name == _("Debug Polygons")) debugPolygons = value == "1";
return true;
}
void SkeletonObject::LoadEdittimeIcon()
{
edittimeIconImage.loadFromFile("JsPlatform/Extensions/skeletonicon.png");
edittimeIcon.setTexture(edittimeIconImage);
}
#if !defined(GD_NO_WX_GUI)
bool SkeletonObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) const
{
thumbnail = wxBitmap("JsPlatform/Extensions/skeletonicon24.png", wxBITMAP_TYPE_ANY);
return true;
}
#endif
void SkeletonObject::DrawInitialInstance(gd::InitialInstance & instance, sf::RenderTarget & renderTarget, gd::Project & project, gd::Layout & layout)
{
#if !defined(GD_NO_WX_GUI)
if(sizeDirty) UpdateSize(project);
#endif
edittimeIcon.setPosition(instance.GetX() - originalSize.x/2.0f, instance.GetY() - originalSize.y/2.0f);
renderTarget.draw(edittimeIcon);
}
sf::Vector2f SkeletonObject::GetInitialInstanceOrigin(gd::InitialInstance & instance, gd::Project & project, gd::Layout & layout) const
{
return originOffset;
}
#if !defined(GD_NO_WX_GUI)
void SkeletonObject::UpdateSize(gd::Project & project)
{
sizeDirty = false;
// Force the path as relative
wxString projectDir = wxFileName::FileName(project.GetProjectFile()).GetPath();
wxFileName fileName(skeletalDataFilename.ToWxString());
fileName.SetPath(projectDir);
// Can't unserialize from JSON's with empty arrays/objects ?
// gd::String fileContent = gd::ResourcesLoader::Get()->LoadPlainText(gd::String::FromWxString(fileName.GetFullPath()));
// gd::SerializerElement element = gd::Serializer::FromJSON(fileContent);
}
#endif
#endif
gd::Object * CreateSkeletonObject(gd::String name)
{
return new SkeletonObject(name);
}

View File

@@ -0,0 +1,68 @@
/**
GDevelop - Skeleton Object Extension
Copyright (c) 2017-2018 Franco Maciel (francomaciel10@gmail.com)
This project is released under the MIT License.
*/
#ifndef SKELETONOBJECT_H
#define SKELETONOBJECT_H
#include "GDCpp/Runtime/Project/Object.h"
#include "GDCpp/Runtime/String.h"
namespace gd { class InitialInstance; }
namespace gd { class Project; }
namespace sf { class Texture; }
namespace sf { class Sprite; }
class wxBitmap;
class GD_EXTENSION_API SkeletonObject : public gd::Object
{
public:
SkeletonObject(gd::String name_);
virtual ~SkeletonObject() {};
virtual std::unique_ptr<gd::Object> Clone() const { return gd::make_unique<SkeletonObject>(*this); }
#if defined(GD_IDE_ONLY)
static void LoadEdittimeIcon();
#if !defined(GD_NO_WX_GUI)
bool GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) const override;
#endif
void DrawInitialInstance(gd::InitialInstance & instance, sf::RenderTarget & renderTarget, gd::Project & project, gd::Layout & layout) override;
sf::Vector2f GetInitialInstanceOrigin(gd::InitialInstance & instance, gd::Project & project, gd::Layout & layout) const override;
#if !defined(GD_NO_WX_GUI)
void UpdateSize(gd::Project & project);
#endif
std::map<gd::String, gd::PropertyDescriptor> GetProperties(gd::Project & project) const override;
bool UpdateProperty(const gd::String & name, const gd::String & value, gd::Project & project) override;
#endif
private:
void DoUnserializeFrom(gd::Project & project, const gd::SerializerElement & element) override;
#if defined(GD_IDE_ONLY)
void DoSerializeTo(gd::SerializerElement & element) const override;
#endif
gd::String skeletalDataFilename;
gd::String rootArmatureName;
gd::String textureDataFilename;
gd::String textureName;
gd::String apiName;
bool debugPolygons;
#if defined(GD_IDE_ONLY)
static sf::Texture edittimeIconImage;
static sf::Sprite edittimeIcon;
sf::Vector2f originalSize;
sf::Vector2f originOffset;
bool sizeDirty;
#endif
};
gd::Object * CreateSkeletonObject(gd::String name);
#endif // SKELETONOBJECT_H

View File

@@ -91,6 +91,7 @@ BaseObjectExtension::BaseObjectExtension()
objectExpressions["Variable"].SetFunctionName("GetVariableValue").SetStatic();
objectStrExpressions["VariableString"].SetFunctionName("GetVariableString").SetStatic();
objectExpressions["VariableChildCount"].SetFunctionName("GetVariableChildCount");
objectStrExpressions["ObjectName"].SetFunctionName("GetName");
GetAllActions()["Create"].SetFunctionName("CreateObjectOnScene").SetIncludeFile("GDCpp/Extensions/Builtin/RuntimeSceneTools.h");
GetAllActions()["CreateByName"].SetFunctionName("CreateObjectFromGroupOnScene").SetIncludeFile("GDCpp/Extensions/Builtin/RuntimeSceneTools.h");

View File

@@ -92,6 +92,7 @@ BaseObjectExtension::BaseObjectExtension()
objectExpressions["Longueur"].SetFunctionName("getAverageForce().getLength"); //Deprecated
objectExpressions["Distance"].SetFunctionName("getDistanceToObject");
objectExpressions["SqDistance"].SetFunctionName("getSqDistanceToObject");
objectStrExpressions["ObjectName"].SetFunctionName("getName");
GetAllActions()["Create"].SetFunctionName("gdjs.evtTools.object.createObjectOnScene");

View File

@@ -120,13 +120,15 @@ bool Exporter::ExportWholePixiProject(gd::Project & project, gd::String exportDi
progressDialog.Update(50, _("Exporting events..."));
#endif
//Export engine libraries
helper.AddLibsInclude(true, false, false, includesFiles);
//Export events
if ( !helper.ExportEventsCode(exportedProject, codeOutputDir, includesFiles) )
{
gd::LogError(_("Error during exporting! Unable to export events:\n")+lastError);
return false;
}
helper.AddLibsInclude(true, false, includesFiles);
//Export source files
if ( !helper.ExportExternalSourceFiles(exportedProject, codeOutputDir, includesFiles) )
@@ -222,13 +224,15 @@ bool Exporter::ExportWholeCocos2dProject(gd::Project & project, bool debugMode,
progressDialog.Update(50, _("Exporting events..."));
#endif
//Export engine libraries
helper.AddLibsInclude(false, true, false, includesFiles);
//Export events
if ( !helper.ExportEventsCode(exportedProject, codeOutputDir, includesFiles) )
{
gd::LogError(_("Error during exporting! Unable to export events:\n")+lastError);
return false;
}
helper.AddLibsInclude(false, true, includesFiles);
//Export source files
if ( !helper.ExportExternalSourceFiles(exportedProject, codeOutputDir, includesFiles) )

View File

@@ -85,12 +85,14 @@ bool ExporterHelper::ExportLayoutForPixiPreview(gd::Project & project, gd::Layou
//Export resources (*before* generating events as some resources filenames may be updated)
ExportResources(fs, exportedProject, exportDir);
//Export engine libraries
AddLibsInclude(true, false, true, includesFiles);
//Generate events code
if ( !ExportEventsCode(exportedProject, codeOutputDir, includesFiles) )
return false;
AddLibsInclude(true, false, includesFiles);
//Export source files
if ( !ExportExternalSourceFiles(exportedProject, codeOutputDir, includesFiles) )
{
@@ -312,8 +314,48 @@ bool ExporterHelper::CompleteIndexFile(gd::String & str, gd::String customCss, g
return true;
}
void ExporterHelper::AddLibsInclude(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles)
void ExporterHelper::AddLibsInclude(bool pixiRenderers, bool cocosRenderers, bool websocketDebuggerClient, std::vector<gd::String> & includesFiles)
{
//First, do not forget common includes (they must be included before events generated code files).
InsertUnique(includesFiles, "libs/jshashtable.js");
InsertUnique(includesFiles, "gd.js");
InsertUnique(includesFiles, "gd-splash-image.js");
InsertUnique(includesFiles, "libs/hshg.js");
InsertUnique(includesFiles, "libs/rbush.js");
InsertUnique(includesFiles, "inputmanager.js");
InsertUnique(includesFiles, "timemanager.js");
InsertUnique(includesFiles, "runtimeobject.js");
InsertUnique(includesFiles, "profiler.js");
InsertUnique(includesFiles, "runtimescene.js");
InsertUnique(includesFiles, "scenestack.js");
InsertUnique(includesFiles, "polygon.js");
InsertUnique(includesFiles, "force.js");
InsertUnique(includesFiles, "layer.js");
InsertUnique(includesFiles, "timer.js");
InsertUnique(includesFiles, "runtimegame.js");
InsertUnique(includesFiles, "variable.js");
InsertUnique(includesFiles, "variablescontainer.js");
InsertUnique(includesFiles, "eventscontext.js");
InsertUnique(includesFiles, "runtimebehavior.js");
InsertUnique(includesFiles, "spriteruntimeobject.js");
//Common includes for events only.
InsertUnique(includesFiles, "events-tools/commontools.js");
InsertUnique(includesFiles, "events-tools/runtimescenetools.js");
InsertUnique(includesFiles, "events-tools/inputtools.js");
InsertUnique(includesFiles, "events-tools/objecttools.js");
InsertUnique(includesFiles, "events-tools/cameratools.js");
InsertUnique(includesFiles, "events-tools/soundtools.js");
InsertUnique(includesFiles, "events-tools/storagetools.js");
InsertUnique(includesFiles, "events-tools/stringtools.js");
InsertUnique(includesFiles, "events-tools/windowtools.js");
InsertUnique(includesFiles, "events-tools/networktools.js");
if (websocketDebuggerClient)
{
InsertUnique(includesFiles, "websocket-debugger-client/websocket-debugger-client.js");
}
if (pixiRenderers)
{
InsertUnique(includesFiles, "pixi-renderers/pixi.js");
@@ -370,41 +412,6 @@ bool ExporterHelper::ExportEventsCode(gd::Project & project, gd::String outputDi
{
fs.MkDir(outputDir);
//First, do not forget common includes (they must be included before events generated code files).
InsertUnique(includesFiles, "libs/jshashtable.js");
InsertUnique(includesFiles, "gd.js");
InsertUnique(includesFiles, "gd-splash-image.js");
InsertUnique(includesFiles, "libs/hshg.js");
InsertUnique(includesFiles, "libs/rbush.js");
InsertUnique(includesFiles, "inputmanager.js");
InsertUnique(includesFiles, "timemanager.js");
InsertUnique(includesFiles, "runtimeobject.js");
InsertUnique(includesFiles, "profiler.js");
InsertUnique(includesFiles, "runtimescene.js");
InsertUnique(includesFiles, "scenestack.js");
InsertUnique(includesFiles, "polygon.js");
InsertUnique(includesFiles, "force.js");
InsertUnique(includesFiles, "layer.js");
InsertUnique(includesFiles, "timer.js");
InsertUnique(includesFiles, "runtimegame.js");
InsertUnique(includesFiles, "variable.js");
InsertUnique(includesFiles, "variablescontainer.js");
InsertUnique(includesFiles, "eventscontext.js");
InsertUnique(includesFiles, "runtimebehavior.js");
InsertUnique(includesFiles, "spriteruntimeobject.js");
//Common includes for events only.
InsertUnique(includesFiles, "events-tools/commontools.js");
InsertUnique(includesFiles, "events-tools/runtimescenetools.js");
InsertUnique(includesFiles, "events-tools/inputtools.js");
InsertUnique(includesFiles, "events-tools/objecttools.js");
InsertUnique(includesFiles, "events-tools/cameratools.js");
InsertUnique(includesFiles, "events-tools/soundtools.js");
InsertUnique(includesFiles, "events-tools/storagetools.js");
InsertUnique(includesFiles, "events-tools/stringtools.js");
InsertUnique(includesFiles, "events-tools/windowtools.js");
InsertUnique(includesFiles, "events-tools/networktools.js");
for (std::size_t i = 0;i<project.GetLayoutsCount();++i)
{
std::set<gd::String> eventsIncludes;

View File

@@ -64,11 +64,10 @@ public:
static void ExportResources(gd::AbstractFileSystem & fs, gd::Project & project, gd::String exportDir,
wxProgressDialog * progressDlg = NULL);
/**
* \brief Add libraries files from Pixi.js or Cocos2d to the list of includes.
*/
void AddLibsInclude(bool pixiRenderers, bool cocosRenderers, std::vector<gd::String> & includesFiles);
void AddLibsInclude(bool pixiRenderers, bool cocosRenderers, bool websocketDebuggerClient, std::vector<gd::String> & includesFiles);
/**
* \brief Remove include files that are Pixi or Cocos2d renderers.

View File

@@ -40,12 +40,18 @@ gdjs.RuntimeGame = function(data, spec) {
//Game loop management (see startGameLoop method)
this._sceneStack = new gdjs.SceneStack(this);
this._notifySceneForResize = false; //When set to true, the current scene is notified that canvas size changed.
this._paused = false;
//Inputs :
this._inputManager = new gdjs.InputManager();
//Allow to specify an external layout to insert in the first scene:
this._injectExternalLayout = spec.injectExternalLayout || '';
//Optional client to connect to a debugger:
this._debuggerClient = gdjs.DebuggerClient
? new gdjs.DebuggerClient(this)
: null;
};
gdjs.RuntimeGame.prototype.getRenderer = function() {
@@ -239,6 +245,16 @@ gdjs.RuntimeGame.prototype.getMinimalFramerate = function() {
return this._minFPS;
};
/**
* Set or unset the game as paused.
* When paused, the game won't step and will be freezed. Useful for debugging.
* @method pause
* @param enable {Boolean} true to pause the game, false to unpause
*/
gdjs.RuntimeGame.prototype.pause = function(enable) {
this._paused = enable;
}
/**
* Load all assets, displaying progress in renderer.
* @method loadAllAssets
@@ -299,6 +315,8 @@ gdjs.RuntimeGame.prototype.startGameLoop = function() {
//The standard game loop
var that = this;
this._renderer.startGameLoop(function(elapsedTime) {
if (that._paused) return true;
//Manage resize events.
if (that._notifySceneForResize) {
that._sceneStack.onRendererResized();

View File

@@ -0,0 +1,226 @@
/**
* This DebuggerClient connects to a websocket server and can dump
* the data of the current game, and receive message to change a field or
* call a function on an object of the specified runtimeGame.
* @param {*} runtimegame
*/
gdjs.WebsocketDebuggerClient = function(runtimegame) {
this._runtimegame = runtimegame;
if (typeof WebSocket !== 'undefined') {
var that = this;
var ws = (this._ws = new WebSocket('ws://127.0.0.1:3030/'));
ws.onopen = function open() {
console.info('Debugger connection open');
};
ws.onclose = function close() {
console.info('Debugger connection closed');
};
ws.onerror = function errored(error) {
console.warn('Debugger client error:', error);
};
ws.onmessage = function incoming(message) {
var data = null;
try {
data = JSON.parse(message.data);
} catch (e) {
console.info('Debugger received a badly formatted message');
}
if (data && data.command) {
if (data.command === 'play') {
runtimegame.pause(false);
} else if (data.command === 'pause') {
runtimegame.pause(true);
that.sendRuntimeGameDump();
} else if (data.command === 'refresh') {
that.sendRuntimeGameDump();
} else if (data.command === 'set') {
that.set(data.path, data.newValue);
} else if (data.command === 'call') {
that.call(data.path, data.args);
} else {
console.info(
'Unknown command "' + data.command + '" received by the debugger.'
);
}
} else {
console.info('Debugger received a message with badly formatted data.');
}
};
} else {
console.log("WebSocket is not defined, debugger won't work");
}
};
gdjs.DebuggerClient = gdjs.WebsocketDebuggerClient; //Register the class to let the engine use it.
gdjs.WebsocketDebuggerClient.prototype.set = function(path, newValue) {
if (!path || !path.length) {
console.warn('No path specified, set operation from debugger aborted');
return false;
}
var object = this._runtimegame;
var currentIndex = 0;
while (currentIndex < path.length - 1) {
var key = path[currentIndex];
if (!object || !object[key]) {
console.error('Incorrect path specified. No ' + key + ' in ', object);
return false;
}
object = object[key];
currentIndex++;
}
// Ensure the newValue is properly typed to avoid breaking anything in
// the game engine.
var currentValue = object[path[currentIndex]];
if (typeof currentValue === 'number') {
newValue = parseFloat(newValue);
} else if (typeof currentValue === 'string') {
newValue = '' + newValue;
}
console.log('Updating', path, 'to', newValue);
object[path[currentIndex]] = newValue;
return true;
};
gdjs.WebsocketDebuggerClient.prototype.call = function(path, args) {
if (!path || !path.length) {
console.warn('No path specified, call operation from debugger aborted');
return false;
}
var object = this._runtimegame;
var currentIndex = 0;
while (currentIndex < path.length - 1) {
var key = path[currentIndex];
if (!object || !object[key]) {
console.error('Incorrect path specified. No ' + key + ' in ', object);
return false;
}
object = object[key];
currentIndex++;
}
if (!object[path[currentIndex]]) {
console.error('Unable to call', path);
return false;
}
console.log('Calling', path, 'with', args);
object[path[currentIndex]].apply(object, args);
return true;
};
gdjs.WebsocketDebuggerClient.prototype.sendRuntimeGameDump = function() {
if (!this._ws) {
console.warn('No connection to debugger opened to send RuntimeGame dump');
return;
}
var that = this;
var message = {
command: 'dump',
payload: this._runtimegame,
};
var serializationStartTime = Date.now();
// This is an alternative to JSON.stringify that ensure that circular reference
// are replaced by a placeholder.
function circularSafeStringify(obj, replacer, spaces, cycleReplacer) {
return JSON.stringify(
obj,
depthLimitedSerializer(replacer, cycleReplacer, 18),
spaces
);
}
function depthLimitedSerializer(replacer, cycleReplacer, maxDepth) {
var stack = [],
keys = [];
if (cycleReplacer == null)
cycleReplacer = function(key, value) {
if (stack[0] === value) return '[Circular ~]';
return (
'[Circular ~.' + keys.slice(0, stack.indexOf(value)).join('.') + ']'
);
};
return function(key, value) {
if (stack.length > 0) {
var thisPos = stack.indexOf(this);
~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
if (thisPos > maxDepth) {
return '[Max depth reached]';
} else if (~stack.indexOf(value))
value = cycleReplacer.call(this, key, value);
} else stack.push(value);
return replacer == null ? value : replacer.call(this, key, value);
};
}
// Stringify the message, excluding some known data that are big and/or not
// useful for the debugger.
var excludedValues = [that._runtimegame.getGameData()];
var excludedKeys = [
// Exclude some RuntimeScene fields:
'_allInstancesList',
'_initialObjectsData',
// Exclude circular references to parent runtimeGame or runtimeScene:
'_runtimeGame',
'_runtimeScene',
// Exclude some runtimeObject duplicated data:
'_behaviorsTable',
// Exclude some objects data:
'_animations',
'_animationFrame',
// Exclude some behaviors data:
'_platformRBush',
// Exclude rendering related objects:
'_renderer',
'_imageManager',
// Exclude PIXI textures:
'baseTexture',
'_baseTexture',
'_invalidTexture',
];
var stringifiedMessage = circularSafeStringify(message, function(key, value) {
if (
excludedValues.indexOf(value) !== -1 ||
excludedKeys.indexOf(key) !== -1
)
return '[Removed from the debugger]';
return value;
});
var serializationDuration = Date.now() - serializationStartTime;
console.log('RuntimeGame serialization took ' + serializationDuration + 'ms');
if (serializationDuration > 500) {
console.warn(
'Serialization took a long time: please check if there is a need to remove some objects from serialization'
);
}
this._ws.send(stringifiedMessage);
};

View File

@@ -26,6 +26,9 @@ This will open the app in your web browser.
Images resources, GDJS Runtime, extensions will be copied in resources, and [libGD.js](https://github.com/4ian/GDevelop.js) will be downloaded automatically. If you wish, you can
[build libGD.js by yourself](https://github.com/4ian/GDevelop.js) (useful if you modified GDevelop native code like extensions).
Note for Linux: If you get an error message that looks like this:
`Error: watch GD/newIDE/app/some/file ENOSPC` then follow the instructions [here](https://stackoverflow.com/questions/22475849/node-js-error-enospc) to fix.
### Development of the standalone app
You can run the app with Electron. **Make sure that you've run `yarn start` in `app` folder before** (see above).
@@ -55,17 +58,24 @@ yarn storybook #or npm run storybook
### Tests
Unit tests can be launched with this command:
Unit tests and type checking can be launched with this command:
```bash
cd newIDE/app
yarn test #or npm run test
yarn flow #or npm run flow
```
### Theming
It's possible to create new themes for the UI. See [this file](https://github.com/4ian/GD/blob/master/newIDE/app/src/UI/Theme/index.js) to declare a new theme. You can take a look at the [default theme](https://github.com/4ian/GD/blob/master/newIDE/app/src/UI/Theme/DefaultTheme/index.js), including the [styling of the Events Sheets](https://github.com/4ian/GD/blob/master/newIDE/app/src/UI/Theme/DefaultTheme/EventsSheet.css).
### Recommended tools for development
Any text editor is fine, but it's a good idea to have one with *Prettier* (code formatting), *ESLint* (code linting) and *Flow* (type checking) integration.
👉 You can use [Visual Studio Code](https://code.visualstudio.com) with these extensions: [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode), [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [Flow Language Support](https://github.com/flowtype/flow-for-vscode).
## Building and deploying the standalone app
### Desktop version

View File

@@ -1,2 +1,6 @@
<!-- GDevelop.js core -->
<script src="/libGD.js"></script
<script src="/libGD.js"></script>
<!-- DocSearch support -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>

View File

@@ -15,6 +15,7 @@ declare type gdInitialInstance = EmscriptenObject;
declare type gdBaseEvent = EmscriptenObject;
declare type gdResource = EmscriptenObject;
declare type gdObject = EmscriptenObject;
declare type gdResourcesManager = EmscriptenObject;
declare type gdInstruction = EmscriptenObject;
declare type gdInstructionMetadata = EmscriptenObject;

View File

@@ -40,6 +40,7 @@
"react-dom": "^16.2.0",
"react-error-boundary": "^1.2.0",
"react-i18next": "6.2.0",
"react-json-view": "^1.16.1",
"react-measure": "1.4.7",
"react-mosaic-component": "1.0.3",
"react-sortable-hoc": "0.6.8",

View File

@@ -28,6 +28,8 @@
<!-- Stripe.com Checkout -->
<script src="https://checkout.stripe.com/checkout.js"></script>
<!-- DocSearch support -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" />
</head>
<body>
<!-- Root div used for React `App` component rendering-->
@@ -48,5 +50,8 @@
global.gd = require(name)();
}
</script>
<!-- DocSearch support -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
</body>
</html>

View File

@@ -5,7 +5,7 @@ var fs = require('fs');
var sourceFile = '../../../Binaries/Output/libGD.js/Release/libGD.js';
var destinationTestDirectory = '../node_modules/libGD.js-for-tests-only';
if (!shell.mkdir(destinationTestDirectory)) {
if (!shell.mkdir('-p', destinationTestDirectory)) {
shell.echo('❌ Error while creating node_modules folder for libGD.js');
}

View File

@@ -0,0 +1,151 @@
// @flow
import * as React from 'react';
import EditorMosaic, { MosaicWindow } from '../UI/EditorMosaic';
import Paper from 'material-ui/Paper';
import get from 'lodash/get';
import RaisedButton from 'material-ui/RaisedButton';
import { Column, Line } from '../UI/Grid';
import InspectorsList from './InspectorsList';
import {
getInspectorDescriptions,
type InspectorDescription,
type EditFunction,
type CallFunction,
} from './GDJSInspectorDescriptions';
import RawContentInspector from './Inspectors/RawContentInspector';
import EmptyMessage from '../UI/EmptyMessage';
import Checkbox from 'material-ui/Checkbox';
import Flash from 'material-ui/svg-icons/image/flash-on';
import FlashOff from 'material-ui/svg-icons/image/flash-off';
import HelpButton from '../UI/HelpButton';
type Props = {|
gameData: ?any,
onEdit: EditFunction,
onCall: CallFunction,
onPlay: () => void,
onPause: () => void,
onRefresh: () => void,
|};
type State = {|
selectedInspector: ?InspectorDescription,
selectedInspectorFullPath: Array<string>,
rawMode: boolean,
|};
const styles = {
container: { flex: 1, display: 'flex' },
};
/**
* The debugger interface: show the list of inspectors for a game, along with the
* currently selected inspector.
*/
export default class DebuggerContent extends React.Component<Props, State> {
state = {
selectedInspector: null,
selectedInspectorFullPath: [],
rawMode: false,
};
render() {
const { gameData, onRefresh, onCall, onEdit } = this.props;
const {
selectedInspector,
selectedInspectorFullPath,
rawMode,
} = this.state;
return (
<EditorMosaic
editors={{
inspectors: (
<MosaicWindow
title="Inspectors"
toolbarControls={[]}
gameData={gameData}
>
<Paper style={styles.container}>
<Column expand noMargin>
<Line justifyContent="center">
<RaisedButton label="Refresh" onClick={onRefresh} primary />
</Line>
<Line expand noMargin>
<InspectorsList
gameData={gameData}
getInspectorDescriptions={getInspectorDescriptions}
onChooseInspector={(
selectedInspector,
selectedInspectorFullPath
) =>
this.setState({
selectedInspector,
selectedInspectorFullPath,
})}
/>
</Line>
</Column>
</Paper>
</MosaicWindow>
),
'selected-inspector': (
<Column expand noMargin>
{' '}
{selectedInspector ? (
rawMode ? (
<RawContentInspector
gameData={get(gameData, selectedInspectorFullPath, null)}
onEdit={(path, newValue) =>
onEdit(selectedInspectorFullPath.concat(path), newValue)}
/>
) : (
selectedInspector.renderInspector(
get(gameData, selectedInspectorFullPath, null),
{
onCall: (path, args) =>
onCall(selectedInspectorFullPath.concat(path), args),
onEdit: (path, newValue) =>
onEdit(
selectedInspectorFullPath.concat(path),
newValue
),
}
) || (
<EmptyMessage>
No inspector, choose another element in the list or toggle
the raw data view.
</EmptyMessage>
)
)
) : (
<EmptyMessage>
{gameData
? 'Choose an element to inspect in the list'
: 'Pause the game (from the toolbar) or hit refresh (on the left) to inspect the game'}
</EmptyMessage>
)}
<Column>
<Line justifyContent="space-between" alignItems="center">
<HelpButton helpPagePath="/interface/debugger" />
<div>
<Checkbox
checkedIcon={<Flash />}
uncheckedIcon={<FlashOff />}
checked={rawMode}
onCheck={(e, enabled) =>
this.setState({
rawMode: enabled,
})}
/>
</div>
</Line>
</Column>
</Column>
),
}}
initialEditorNames={['inspectors', 'selected-inspector']}
initialSplitPercentage={32}
/>
);
}
}

View File

@@ -0,0 +1,40 @@
// @flow
import * as React from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import { Column } from '../UI/Grid';
import { type DebuggerId } from '.';
type Props = {|
selectedId: DebuggerId,
debuggerIds: Array<DebuggerId>,
onChooseDebugger: DebuggerId => void,
|};
export default class DebuggerSelector extends React.Component<Props, void> {
render() {
const hasDebuggers = !!this.props.debuggerIds.length;
return (
<Column>
<SelectField
fullWidth
value={hasDebuggers ? this.props.selectedId : 0}
onChange={(e, i, value) => this.props.onChooseDebugger(value)}
disabled={!hasDebuggers}
>
{this.props.debuggerIds.map(id => (
<MenuItem value={id} key={id} primaryText={'Game preview #' + id} />
))}
{!hasDebuggers && (
<MenuItem
value={0}
primaryText={
'No preview running. Run a preview and you will be able to inspect it with the debugger'
}
/>
)}
</SelectField>
</Column>
);
}
}

View File

@@ -0,0 +1,129 @@
// @flow
import * as React from 'react';
import RuntimeObjectInspector from './Inspectors/RuntimeObjectInspector';
import VariablesContainerInspector from './Inspectors/VariablesContainerInspector';
import RuntimeSceneInspector from './Inspectors/RuntimeSceneInspector';
export type GameData = any;
export type EditFunction = (path: Array<string>, newValue: any) => boolean;
export type CallFunction = (path: Array<string>, args: Array<any>) => boolean;
export type InspectorDescriptionsGetter = (
gameData: GameData
) => Array<InspectorDescription>; //eslint-disable-line
export type InspectorDescription = {|
label: string,
key: string | Array<string>,
renderInspector: (
gameData: GameData,
{
onCall: CallFunction,
onEdit: EditFunction,
}
) => React.Node,
getSubInspectors?: InspectorDescriptionsGetter,
initiallyOpen?: boolean,
|};
/**
* Returns the list of inspectors, given the data coming from a GDJS RuntimeGame.
* @param {*} gdjsRuntimeGame
*/
export const getInspectorDescriptions = (
gdjsRuntimeGame: GameData
): Array<InspectorDescription> => {
return [
{
label: 'Global variables',
key: '_variables',
renderInspector: (gameData, { onCall, onEdit }) => (
<VariablesContainerInspector
variablesContainer={gameData}
onCall={onCall}
onEdit={onEdit}
/>
),
},
{
label: 'Scenes',
key: ['_sceneStack', '_stack'],
renderInspector: () => null,
initiallyOpen: true,
getSubInspectors: gdjsStack => {
if (!gdjsStack) return [];
return gdjsStack.map((runtimeScene, index) => ({
label: runtimeScene._name,
key: index,
renderInspector: (gameData, { onCall, onEdit }) => (
<RuntimeSceneInspector
runtimeScene={gameData}
onCall={onCall}
onEdit={onEdit}
/>
),
initiallyOpen: true,
getSubInspectors: runtimeScene => [
{
label: 'Scene variables',
key: `_variables`,
renderInspector: (gameData, { onCall, onEdit }) => (
<VariablesContainerInspector
variablesContainer={gameData}
onCall={onCall}
onEdit={onEdit}
/>
),
},
{
label: 'Instances',
key: `_instances`,
renderInspector: () => null,
initiallyOpen: true,
getSubInspectors: instances => {
if (!instances || !instances.items) return [];
return Object.keys(instances.items).map(objectName => {
if (
!instances.items[objectName] ||
typeof instances.items[objectName].length === undefined
)
return null;
return {
label: `${objectName} (${instances.items[objectName]
.length})`,
key: ['items', objectName],
renderInspector: () => null,
getSubInspectors: instancesList =>
instancesList
? instancesList
.filter(runtimeObject => !!runtimeObject)
.map((runtimeObject, index) => {
return {
label: `#${runtimeObject.id}`,
key: index,
renderInspector: (
gameData,
{ onCall, onEdit }
) => (
<RuntimeObjectInspector
runtimeObject={gameData}
onCall={onCall}
onEdit={onEdit}
/>
),
};
})
: [],
};
});
},
},
],
}));
},
},
];
};

View File

@@ -0,0 +1,37 @@
// @flow
import * as React from 'react';
import ReactJsonView from 'react-json-view';
import { type GameData } from '../GDJSInspectorDescriptions';
import EmptyMessage from '../../UI/EmptyMessage';
type Props = {|
gameData: GameData,
onEdit: (path: Array<string>, newValue: any) => boolean,
|};
const styles = {
container: {
flex: 1,
overflowY: 'scroll',
},
};
/**
* A very simple inspector that display the raw information given by the gameData
* object.
*/
export default ({ gameData, onEdit }: Props) => (
<div style={styles.container}>
<EmptyMessage>You are in raw mode. You can edit the fields, but be aware that this can lead to unexpected results or even crash the debugged game!</EmptyMessage>
<ReactJsonView
collapsed={1}
name={false}
src={gameData}
onEdit={edit => {
return onEdit(edit.namespace.concat(edit.name), edit.new_value);
}}
groupArraysAfterLength={50}
theme="monokai"
/>
</div>
);

View File

@@ -0,0 +1,80 @@
// @flow
import * as React from 'react';
import ReactJsonView from 'react-json-view';
import {
type GameData,
type EditFunction,
type CallFunction,
} from '../GDJSInspectorDescriptions';
import VariablesContainerInspector from './VariablesContainerInspector';
type Props = {|
runtimeObject: GameData,
onCall: CallFunction,
onEdit: EditFunction,
|};
const styles = {
container: {
flex: 1,
overflowY: 'scroll',
},
};
const transform = runtimeObject => {
if (!runtimeObject) return null;
return {
'X position': runtimeObject.x,
'Y position': runtimeObject.y,
Angle: runtimeObject.angle,
Layer: runtimeObject.layer,
'Z order': runtimeObject.zOrder,
'Is hidden?': runtimeObject.hidden,
};
};
const handleEdit = (edit, { onCall, onEdit }: Props) => {
if (edit.name === 'X position') {
onCall(['setX'], [parseFloat(edit.new_value)]);
} else if (edit.name === 'Y position') {
onCall(['setY'], [parseFloat(edit.new_value)]);
} else if (edit.name === 'Angle') {
onCall(['setAngle'], [parseFloat(edit.new_value)]);
} else if (edit.name === 'Layer') {
onCall(['setLayer'], [edit.new_value]);
} else if (edit.name === 'Z order') {
onCall(['setZOrder'], [parseFloat(edit.new_value)]);
} else if (edit.name === 'Is hidden?') {
onCall(['hide'], [!!edit.new_value]);
} else return false;
return true;
};
export default (props: Props) => (
<div style={styles.container}>
<p>General:</p>
<ReactJsonView
collapsed={false}
name={false}
src={transform(props.runtimeObject)}
enableClipboard={false}
displayDataTypes={false}
displayObjectSize={false}
onEdit={edit => handleEdit(edit, props)}
groupArraysAfterLength={50}
theme="monokai"
/>
<p>Instance variables:</p>
<VariablesContainerInspector
variablesContainer={
props.runtimeObject ? props.runtimeObject._variables : null
}
// TODO: onEdit and onCall could benefit from a "forward" utility function
// (can also be applied in DebuggerContent.js)
onEdit={(path, newValue) =>
props.onEdit(['_variables'].concat(path), newValue)}
onCall={(path, args) => props.onCall(['_variables'].concat(path), args)}
/>
</div>
);

View File

@@ -0,0 +1,172 @@
// @flow
import * as React from 'react';
import ReactJsonView from 'react-json-view';
import {
type GameData,
type EditFunction,
type CallFunction,
} from '../GDJSInspectorDescriptions';
import { Line } from '../../UI/Grid';
import mapValues from 'lodash/mapValues';
import AutoComplete from 'material-ui/AutoComplete';
import RaisedButton from 'material-ui/RaisedButton';
type Props = {|
runtimeScene: GameData,
onCall: CallFunction,
onEdit: EditFunction,
|};
type State = {|
newObjectName: string,
|};
const styles = {
container: {
flex: 1,
overflowY: 'scroll',
},
};
const transformLayer = layer => {
if (!layer) return null;
return {
'Camera rotation (in deg)': layer._cameraRotation,
'Camera zoom': layer._zoomFactor,
'Layer is hidden': !!layer._hidden,
'Camera X position': layer._cameraX,
'Camera Y position': layer._cameraY,
'Time scale': layer._timeScale,
};
};
const transform = runtimeScene => {
if (!runtimeScene) return null;
return {
'Time scale': runtimeScene._timeManager
? runtimeScene._timeManager._timeScale
: null,
Layers:
runtimeScene._layers && runtimeScene._layers.items
? mapValues(runtimeScene._layers.items, transformLayer)
: null,
};
};
const handleEdit = (edit, { onCall, onEdit }: Props) => {
if (edit.namespace.length === 0 && edit.name === 'Time scale') {
onCall(['_timeManager', 'setTimeScale'], [parseFloat(edit.new_value)]);
} else if (edit.namespace.length >= 2) {
if (edit.namespace[0] === 'Layers') {
if (edit.name === 'Camera rotation (in deg)') {
onCall(
['_layers', 'items', edit.namespace[1], 'setCameraRotation'],
[parseFloat(edit.new_value)]
);
} else if (edit.name === 'Camera zoom') {
onCall(
['_layers', 'items', edit.namespace[1], 'setCameraZoom'],
[parseFloat(edit.new_value)]
);
} else if (edit.name === 'Layer is hidden') {
onCall(
['_layers', 'items', edit.namespace[1], 'show'],
[!edit.new_value]
);
} else if (edit.name === 'Camera X position') {
onCall(
['_layers', 'items', edit.namespace[1], 'setCameraX'],
[parseFloat(edit.new_value)]
);
} else if (edit.name === 'Camera Y position') {
onCall(
['_layers', 'items', edit.namespace[1], 'setCameraY'],
[parseFloat(edit.new_value)]
);
} else if (edit.name === 'Time scale') {
onCall(
['_layers', 'items', edit.namespace[1], 'setTimeScale'],
[parseFloat(edit.new_value)]
);
}
}
} else return false;
return true;
};
export default class RuntimeSceneInspector extends React.Component<
Props,
State
> {
state = {
newObjectName: '',
};
render() {
const { runtimeScene, onCall } = this.props;
if (!runtimeScene) return null;
return (
<div style={styles.container}>
<p>Layers:</p>
<ReactJsonView
collapsed={false}
name={false}
src={transform(runtimeScene)}
enableClipboard={false}
displayDataTypes={false}
displayObjectSize={false}
onEdit={edit => handleEdit(edit, this.props)}
groupArraysAfterLength={50}
theme="monokai"
/>
<p>Create a new instance on the scene (will be at position 0;0):</p>
{runtimeScene._objects &&
runtimeScene._objects.items && (
<Line noMargin alignItems="baseline">
<AutoComplete
hintText="Enter the name of the object"
fullWidth
menuProps={{
maxHeight: 250,
}}
searchText={this.state.newObjectName}
onUpdateInput={value => {
this.setState({
newObjectName: value,
});
}}
onNewRequest={data => {
// Note that data may be a string or a {text, value} object.
if (typeof data === 'string') {
this.setState({
newObjectName: data,
});
} else if (typeof data.value === 'string') {
this.setState({
newObjectName: data.value,
});
}
}}
dataSource={Object.keys(
runtimeScene._objects.items
).map(objectName => ({
text: objectName,
value: objectName,
}))}
filter={AutoComplete.fuzzyFilter}
/>
<RaisedButton
label="Create"
primary
onClick={() =>
onCall(['createObject'], [this.state.newObjectName])}
/>
</Line>
)}
</div>
);
}
}

View File

@@ -0,0 +1,80 @@
// @flow
import * as React from 'react';
import ReactJsonView from 'react-json-view';
import {
type GameData,
type EditFunction,
type CallFunction,
} from '../GDJSInspectorDescriptions';
import mapValues from 'lodash/mapValues';
type Props = {|
variablesContainer: GameData,
onCall: CallFunction,
onEdit: EditFunction,
|};
const styles = {
container: {
flex: 1,
overflowY: 'scroll',
},
};
const transformVariable = variable => {
if (!variable) return null;
if (!variable._isStructure) {
return variable._stringDirty ? variable._value : variable._str;
} else {
if (!variable._children) return null;
return mapValues(variable._children, transformVariable);
}
};
const transform = variablesContainer => {
if (!variablesContainer || !variablesContainer._variables || !variablesContainer._variables.items)
return null;
return mapValues(variablesContainer._variables.items, transformVariable);
};
const handleEdit = (edit, { onCall, onEdit }: Props) => {
// Reconstruct the path to the variable to edit
const path = ['_variables', 'items'];
edit.namespace.forEach(variableName => {
path.push(variableName);
path.push('_children');
});
path.push(edit.name);
// Guess the type of the new value (number or string)
if (parseFloat(edit.new_value).toString() === edit.new_value) {
path.push('setNumber');
onCall(path, [parseFloat(edit.new_value)]);
} else {
path.push('setString');
onCall(path, ['' + edit.new_value]);
}
return true;
};
export default (props: Props) => (
<div style={styles.container}>
<ReactJsonView
collapsed={false}
name={false}
src={
props.variablesContainer ? transform(props.variablesContainer) : null
}
enableClipboard={false}
displayDataTypes={false}
displayObjectSize={false}
onEdit={edit => handleEdit(edit, props)}
groupArraysAfterLength={50}
theme="monokai"
/>
</div>
);

View File

@@ -0,0 +1,81 @@
// @flow
import * as React from 'react';
import { List, ListItem } from 'material-ui/List';
import get from 'lodash/get';
import {
type InspectorDescription,
type InspectorDescriptionsGetter,
type GameData,
} from './GDJSInspectorDescriptions';
type Props = {|
gameData: GameData,
getInspectorDescriptions: InspectorDescriptionsGetter,
onChooseInspector: (
InspectorDescription,
fullInspectorPath: Array<string>
) => void,
|};
const styles = {
container: {
flex: 1,
display: 'flex',
},
list: {
overflowY: 'scroll',
flex: 1,
},
};
/**
* Generate a visual list of inspectors, using gameData and getInspectorDescriptions
*/
export default class InspectorsList extends React.Component<Props, void> {
_renderInspectorList(
gameData: GameData,
getInspectorDescriptions: InspectorDescriptionsGetter,
path: Array<string>
) {
return getInspectorDescriptions(gameData).map(inspectorDescription => {
if (!inspectorDescription) return null;
const fullInspectorPath = path.concat(inspectorDescription.key);
const getSubInspectors = inspectorDescription.getSubInspectors;
const nestedItems = getSubInspectors
? this._renderInspectorList(
get(gameData, inspectorDescription.key, null),
getSubInspectors,
fullInspectorPath
)
: undefined;
return (
<ListItem
key={fullInspectorPath.join('.')}
primaryText={inspectorDescription.label}
initiallyOpen={!!inspectorDescription.initiallyOpen}
onClick={() =>
this.props.onChooseInspector(
inspectorDescription,
fullInspectorPath
)}
nestedItems={nestedItems}
primaryTogglesNestedList
/>
);
});
}
render() {
return this.props.gameData ? (
<List style={styles.list}>
{this._renderInspectorList(
this.props.gameData,
this.props.getInspectorDescriptions,
[]
)}
</List>
) : null;
}
}

View File

@@ -0,0 +1,41 @@
// @flow
import React, { PureComponent } from 'react';
import { translate, type TranslatorProps } from 'react-i18next';
import { ToolbarGroup } from 'material-ui/Toolbar';
import ToolbarIcon from '../UI/ToolbarIcon';
import ToolbarSeparator from '../UI/ToolbarSeparator';
type Props = {|
onPlay: () => void,
canPlay: boolean,
onPause: () => void,
canPause: boolean,
|} & TranslatorProps;
type State = {||};
export class Toolbar extends PureComponent<Props, State> {
render() {
const { t, onPlay, onPause, canPlay, canPause } = this.props;
return (
<ToolbarGroup lastChild>
<ToolbarIcon
onClick={onPlay}
src="res/ribbon_default/preview32.png"
disabled={!canPlay}
tooltip={t('Play the game')}
/>
<ToolbarSeparator />
<ToolbarIcon
onClick={onPause}
src="res/ribbon_default/pause32.png"
disabled={!canPause}
tooltip={t('Pause the game')}
/>
</ToolbarGroup>
);
}
}
export default translate()(Toolbar);

View File

@@ -0,0 +1,298 @@
// @flow
import * as React from 'react';
import Toolbar from './Toolbar';
import DebuggerContent from './DebuggerContent';
import DebuggerSelector from './DebuggerSelector';
import { Column } from '../UI/Grid';
import PlaceholderLoader from '../UI/PlaceholderLoader';
import PlaceholderMessage from '../UI/PlaceholderMessage';
import Paper from 'material-ui/Paper';
import optionalRequire from '../Utils/OptionalRequire';
import EmptyMessage from '../UI/EmptyMessage';
const electron = optionalRequire('electron');
const ipcRenderer = electron ? electron.ipcRenderer : null;
//Each game connected to the debugger server is identified by a unique number
export type DebuggerId = number;
type Props = {|
project: gdProject,
setToolbar: React.Node => void,
isActive: boolean,
|};
type State = {|
debuggerServerStarted: boolean,
debuggerServerError: ?any,
debuggerIds: Array<DebuggerId>,
debuggerGameData: { [number]: any },
selectedId: DebuggerId,
|};
const styles = {
container: { flex: 1, display: 'flex' },
};
/**
* Start the debugger server, listen to commands received and issue commands to it.
* This is only supported on Electron runtime for now.
*/
export default class Debugger extends React.Component<Props, State> {
state = {
debuggerServerStarted: false,
debuggerServerError: null,
debuggerIds: [],
debuggerGameData: {},
selectedId: 0,
};
updateToolbar() {
if (!this.props.isActive) return;
this.props.setToolbar(
<Toolbar
onPlay={() => this._play(this.state.selectedId)}
onPause={() => this._pause(this.state.selectedId)}
canPlay={this._hasSelectedDebugger()}
canPause={this._hasSelectedDebugger()}
/>
);
}
componentDidMount() {
if (this.props.isActive) {
this._startServer();
}
}
componentWillReceiveProps(nextProps: Props) {
if (nextProps.isActive && !this.props.isActive) {
this._startServer();
}
}
componentWillUnmount() {
this._removeServerListeners();
}
_removeServerListeners = () => {
if (!ipcRenderer) return;
ipcRenderer.removeAllListeners('debugger-send-message-done');
ipcRenderer.removeAllListeners('debugger-error-received');
ipcRenderer.removeAllListeners('debugger-connection-closed');
ipcRenderer.removeAllListeners('debugger-connection-opened');
ipcRenderer.removeAllListeners('debugger-start-server-done');
ipcRenderer.removeAllListeners('debugger-message-received');
};
_startServer = () => {
if (!ipcRenderer) return;
this.setState({
debuggerServerStarted: false,
});
this._removeServerListeners();
ipcRenderer.on('debugger-error-received', (event, err) => {
this.setState(
{
debuggerServerError: err,
},
() => this.updateToolbar()
);
});
ipcRenderer.on('debugger-connection-closed', (event, { id }) => {
const { debuggerIds, selectedId } = this.state;
const remainingDebuggerIds = debuggerIds.filter(
debuggerId => debuggerId !== id
);
this.setState(
{
debuggerIds: remainingDebuggerIds,
selectedId:
selectedId !== id
? selectedId
: remainingDebuggerIds.length
? remainingDebuggerIds[remainingDebuggerIds.length - 1]
: selectedId,
},
() => this.updateToolbar()
);
});
ipcRenderer.on('debugger-connection-opened', (event, { id }) => {
this.setState(
{
debuggerIds: [...this.state.debuggerIds, id],
selectedId: id,
},
() => this.updateToolbar()
);
});
ipcRenderer.on('debugger-start-server-done', event => {
this.setState(
{
debuggerServerStarted: true,
},
() => this.updateToolbar()
);
});
ipcRenderer.on('debugger-message-received', (event, { id, message }) => {
console.log('Processing message received for debugger');
try {
const data = JSON.parse(message);
this._handleMessage(id, data);
} catch (e) {
console.warn(
'Error while parsing message received from debugger client:',
e
);
}
});
ipcRenderer.send('debugger-start-server');
};
_handleMessage = (id: DebuggerId, data: any) => {
if (data.command === 'dump') {
this.setState({
debuggerGameData: {
...this.state.debuggerGameData,
[id]: data.payload,
},
});
} else {
console.warn(
'Unknown command received from debugger client:',
data.command
);
}
};
_play = (id: DebuggerId) => {
if (!ipcRenderer) return;
ipcRenderer.send('debugger-send-message', {
id,
message: '{"command": "play"}',
});
};
_pause = (id: DebuggerId) => {
if (!ipcRenderer) return;
ipcRenderer.send('debugger-send-message', {
id,
message: '{"command": "pause"}',
});
};
_refresh = (id: DebuggerId) => {
if (!ipcRenderer) return;
ipcRenderer.send('debugger-send-message', {
id,
message: '{"command": "refresh"}',
});
};
_edit = (id: DebuggerId, path: Array<string>, newValue: any) => {
if (!ipcRenderer) return false;
ipcRenderer.send('debugger-send-message', {
id,
message: JSON.stringify({
command: 'set',
path,
newValue,
}),
});
setTimeout(() => this._refresh(id), 100);
return true;
};
_call = (id: DebuggerId, path: Array<string>, args: Array<any>) => {
if (!ipcRenderer) return false;
ipcRenderer.send('debugger-send-message', {
id,
message: JSON.stringify({
command: 'call',
path,
args,
}),
});
setTimeout(() => this._refresh(id), 100);
return true;
};
_hasSelectedDebugger = () => {
const { selectedId, debuggerIds } = this.state;
return debuggerIds.indexOf(selectedId) !== -1;
};
render() {
const {
debuggerServerError,
debuggerServerStarted,
selectedId,
debuggerIds,
debuggerGameData,
} = this.state;
return (
<Paper style={styles.container}>
{!debuggerServerStarted &&
!debuggerServerError && (
<PlaceholderMessage>
<PlaceholderLoader />
<p>Debugger is starting...</p>
</PlaceholderMessage>
)}
{!debuggerServerStarted &&
debuggerServerError && (
<PlaceholderMessage>
<p>
Unable to start the debugger server! Make sure that you are
authorized to run servers on this computer.
</p>
</PlaceholderMessage>
)}
{debuggerServerStarted && (
<Column expand noMargin>
<DebuggerSelector
selectedId={selectedId}
debuggerIds={debuggerIds}
onChooseDebugger={id =>
this.setState({
selectedId: id,
})}
/>
{this._hasSelectedDebugger() && (
<DebuggerContent
gameData={debuggerGameData[selectedId]}
onPlay={() => this._play(selectedId)}
onPause={() => this._pause(selectedId)}
onRefresh={() => this._refresh(selectedId)}
onEdit={(path, args) => this._edit(selectedId, path, args)}
onCall={(path, args) => this._call(selectedId, path, args)}
/>
)}
{!this._hasSelectedDebugger() && (
<EmptyMessage>
Run a preview and you will be able to inspect it with the
debugger.
</EmptyMessage>
)}
</Column>
)}
</Paper>
);
}
}

View File

@@ -1,15 +1,49 @@
import React, { Component } from 'react';
// @flow
import * as React from 'react';
import InlinePopover from './InlinePopover';
import ParameterRenderingService from './InstructionEditor/ParameterRenderingService';
import {
type ResourceSource,
type ChooseResourceFunction,
} from '../ResourcesList/ResourceSource.flow';
const gd = global.gd;
export default class InlineParameterEditor extends Component {
type Props = {|
project: gdProject,
layout: gdLayout,
open: boolean,
onRequestClose: () => void,
onChange: (string) => void,
instruction: gdInstruction,
isCondition: boolean,
parameterIndex: number,
anchorEl: ?any,
resourceSources: Array<ResourceSource>,
onChooseResource: ChooseResourceFunction,
|};
type State = {|
isValid: boolean,
parameterMetadata: ?gdParameterMetadata,
instruction: ?gdInstruction,
ParameterComponent: ?any,
|};
export default class InlineParameterEditor extends React.Component<Props, State> {
state = {
isValid: false,
parameterMetadata: null,
ParameterComponent: null,
instruction: null,
};
componentWillReceiveProps(newProps) {
_field: ?any;
componentWillReceiveProps(newProps: Props) {
if (
(newProps.open && !this.props.open) ||
newProps.instruction !== this.props.instruction
@@ -26,7 +60,7 @@ export default class InlineParameterEditor extends Component {
});
}
_loadComponentFromInstruction(props) {
_loadComponentFromInstruction(props: Props) {
const { project, isCondition, instruction, parameterIndex } = props;
if (!instruction) return this._unload();
@@ -81,6 +115,8 @@ export default class InlineParameterEditor extends Component {
ref={field => (this._field = field)}
parameterRenderingService={ParameterRenderingService}
isInline
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
</InlinePopover>
);

View File

@@ -114,6 +114,8 @@ export default class InstructionParametersEditor extends Component {
this.forceUpdate();
}}
parameterRenderingService={ParameterRenderingService}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
);
})}

View File

@@ -0,0 +1,35 @@
// @flow
import React, { Component } from 'react';
import ResourceSelector from '../../../ResourcesList/ResourceSelector';
import { type ParameterFieldProps } from './ParameterFieldProps.flow';
export default class AudioResourceField extends Component<
ParameterFieldProps,
void
> {
focus() {
// TODO
}
render() {
if (!this.props.resourceSources || !this.props.onChooseResource) {
console.error(
'Missing resourceSources or onChooseResource for AudioResourceField'
);
return null;
}
return (
<ResourceSelector
project={this.props.project}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
resourceKind="audio"
fullWidth
initialResourceName={this.props.value}
onChange={this.props.onChange}
floatingLabelText="Choose the audio file to use"
/>
);
}
}

View File

@@ -1,4 +1,10 @@
// @flow
import {
type ResourceSource,
type ChooseResourceFunction,
} from '../../../ResourcesList/ResourceSource.flow';
export type ParameterFieldProps = {|
parameterMetadata?: gdParameterMetadata,
project: gdProject,
@@ -10,4 +16,6 @@ export type ParameterFieldProps = {|
components: any,
getParameterComponent: (type: string) => any,
},
resourceSources?: Array<ResourceSource>,
onChooseResource?: ChooseResourceFunction,
|};

View File

@@ -14,6 +14,7 @@ import SceneVariableField from './ParameterFields/SceneVariableField';
import GlobalVariableField from './ParameterFields/GlobalVariableField';
import ObjectVariableField from './ParameterFields/ObjectVariableField';
import LayerField from './ParameterFields/LayerField';
import AudioResourceField from './ParameterFields/AudioResourceField';
const gd = global.gd;
const components = {
@@ -33,8 +34,8 @@ const components = {
layer: LayerField,
key: KeyField,
file: DefaultField, //TODO
musicfile: DefaultField, //TODO
soundfile: DefaultField, //TODO
musicfile: AudioResourceField,
soundfile: AudioResourceField,
color: DefaultField, //TODO
police: DefaultField, //TODO
joyaxis: DefaultField, //TODO

View File

@@ -42,6 +42,8 @@ export default class InstructionEditor extends Component {
layout={layout}
isCondition={isCondition}
instruction={instruction}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
</Paper>
</div>

View File

@@ -47,12 +47,26 @@ export class Toolbar extends PureComponent {
/>
)}
{this.props.showNetworkPreviewButton && (
<ToolbarIcon
onClick={this.props.onNetworkPreview}
src="res/ribbon_default/networkpreview32.png"
tooltip={t('Preview the scene on a mobile or tablet connected to your wifi')}
/>
)}
<IconMenu
iconButtonElement={
<ToolbarIcon
src="res/ribbon_default/bug32.png"
tooltip={t('Advanced preview options (debugger, network preview...)')}
/>
}
buildMenuTemplate={() => [
{
label: 'Network preview (Preview over WiFi/LAN)',
click: () => this.props.onNetworkPreview(),
},
{ type: 'separator' },
{
label: 'Preview with debugger',
click: () => this.props.onOpenDebugger(),
},
]}
/>)
}
{this.props.showPreviewButton && <ToolbarSeparator />}
<ToolbarIcon
onClick={this.props.onAddStandardEvent}

View File

@@ -105,6 +105,10 @@ export default class EventsSheet extends Component {
showNetworkPreviewButton={this.props.showNetworkPreviewButton}
onPreview={() => this.props.onPreview({})}
onNetworkPreview={() => this.props.onPreview({networkPreview: true})}
onOpenDebugger={() => {
this.props.onOpenDebugger();
this.props.onPreview({});
}}
canUndo={canUndo(this.state.history)}
canRedo={canRedo(this.state.history)}
undo={this.undo}
@@ -516,6 +520,8 @@ export default class EventsSheet extends Component {
inlineEditingChangesMade: true,
});
}}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
<ContextMenu
ref={eventContextMenu => (this.eventContextMenu = eventContextMenu)}
@@ -654,6 +660,8 @@ export default class EventsSheet extends Component {
this.closeInstructionEditor(true);
this._eventsTree.forceEventsUpdate();
}}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
)}
</div>

View File

@@ -0,0 +1,90 @@
// @flow
import * as React from 'react';
import TextField from 'material-ui/TextField';
import FlatButton from 'material-ui/FlatButton';
import Window from '../Utils/Window';
import './DocSearchOverrides.css';
import { Column } from '../UI/Grid';
const styles = {
dropdownMenuContainer: {
maxHeight: 300,
overflowY: 'scroll',
},
poweredByText: {
textAlign: 'right',
opacity: 0.8,
},
};
export default class DocSearchArea extends React.Component<*, *> {
componentDidMount() {
if (!global.docsearch) {
console.warn("docsearch not found - DocSearchArea won't work");
return;
}
try {
global.docsearch({
apiKey: '69c73fc1a710bb79543d4b91f6b81c08',
indexName: 'gdevelop',
inputSelector: '#help-finder-search-bar',
debug: true, // Set debug to true if you want to inspect the dropdown
handleSelected: (input, event, suggestion) => {
Window.openExternalURL(suggestion.url);
this.props.onChange('');
},
autocompleteOptions: {
appendTo: true,
hint: false,
dropdownMenuContainer: '#help-finder-dropdown-menu-container',
},
});
} catch (e) {
console.error('Error while loading docsearch:', e);
}
}
render() {
return (
<div>
<TextField
id={'help-finder-search-bar'}
fullWidth
hintText={'Enter what you want to build.'}
value={this.props.value}
onChange={(e, text) => this.props.onChange(text)}
/>
<div
id="help-finder-dropdown-menu-container"
className="algolia-autocomplete"
style={{
...styles.dropdownMenuContainer,
visibility: !this.props.value ? 'hidden' : undefined,
}}
/>
{!this.props.value && (
<React.Fragment>
<p>Examples:</p>
<Column expand>
<p>
Coins in platformer<br />
Export on Android<br />
Add a score<br />
Move enemies<br />
...<br />
</p>
</Column>
<p style={styles.poweredByText}>
This search is powered by{' '}
<FlatButton
onClick={() => Window.openExternalURL('http://algolia.com/')}
label="Algolia"
/>
</p>
</React.Fragment>
)}
</div>
);
}
}

View File

@@ -0,0 +1,6 @@
/* The dropdown is inserted into a container and should always take the width
of this container. */
.algolia-autocomplete .ds-dropdown-menu {
min-width: 0 !important;
max-width: initial !important;
}

View File

@@ -0,0 +1,88 @@
// @flow
import * as React from 'react';
import Dialog from '../UI/Dialog';
import FlatButton from 'material-ui/FlatButton';
import Window from '../Utils/Window';
import DocSearchArea from './DocSearchArea';
import debounce from 'lodash/debounce';
import {
sendHelpFinderOpened,
sendHelpSearch,
} from '../Utils/Analytics/EventSender';
type Props = {|
open: boolean,
onClose: () => void,
|};
type State = {|
searchText: string,
|};
export default class HelpFinder extends React.Component<Props, State> {
state = {
searchText: '',
};
componentWillReceiveProps(newProps: Props) {
if (newProps.open && !this.props.open) {
sendHelpFinderOpened();
}
}
_handleSearchTextChange = (searchText: string) => {
this.setState({
searchText,
});
this._sendHelpSearch();
};
_sendHelpSearch = debounce(() => {
if (this.state.searchText) sendHelpSearch(this.state.searchText.trim());
}, 1300);
render() {
const { open, onClose } = this.props;
return (
<Dialog
title="Help!"
onRequestClose={onClose}
actions={[
<FlatButton
label="Close"
key="close"
primary={false}
onClick={onClose}
/>,
]}
secondaryActions={[
<FlatButton
key="forum"
primary={false}
onClick={() => {
Window.openExternalURL('http://forum.compilgames.net');
}}
label="Community forum"
/>,
<FlatButton
key="wiki"
primary={false}
onClick={() => {
Window.openExternalURL(
'http://wiki.compilgames.net/doku.php/gdevelop5/start'
);
}}
label="Wiki"
/>,
]}
open={open}
>
<DocSearchArea
value={this.state.searchText}
onChange={this._handleSearchTextChange}
/>
</Dialog>
);
}
}

View File

@@ -52,9 +52,9 @@ export default class InstancesEditorContainer extends Component {
if (this.keyboardShortcuts.shouldZoom()) {
this.zoomBy(event.wheelDelta / 5000);
} else if (this.keyboardShortcuts.shouldScrollHorizontally()) {
this.viewPosition.scrollBy(-event.wheelDelta / 20, 0);
this.viewPosition.scrollBy(-event.wheelDelta / 10, 0);
} else {
this.viewPosition.scrollBy(0, -event.wheelDelta / 20);
this.viewPosition.scrollBy(event.deltaX / 10, event.deltaY / 10);
}
if (this.props.onViewPositionChanged) {
@@ -69,6 +69,12 @@ export default class InstancesEditorContainer extends Component {
this.pixiRenderer.view.addEventListener('blur', e => {
this.keyboardShortcuts.blur();
});
this.pixiRenderer.view.addEventListener('mouseover', e => {
this.keyboardShortcuts.focus();
});
this.pixiRenderer.view.addEventListener('mouseout', e => {
this.keyboardShortcuts.blur();
});
this.pixiContainer = new PIXI.Container();
@@ -113,7 +119,6 @@ export default class InstancesEditorContainer extends Component {
});
this.pixiContainer.addChild(this.grid.getPixiObject());
// TODO: This should probably be moved up in the InstancesFullEditor component.
this.keyboardShortcuts = new KeyboardShortcuts({
onDelete: this.props.onDeleteSelection,
onMove: this.moveSelection,
@@ -506,12 +511,12 @@ export default class InstancesEditorContainer extends Component {
pauseSceneRendering = () => {
if (this.nextFrame) cancelAnimationFrame(this.nextFrame);
this._renderingPaused = true;
}
};
restartSceneRendering = () => {
this._renderingPaused = false;
this._renderScene();
}
};
render() {
if (!this.props.project) return null;

View File

@@ -3,6 +3,7 @@ import * as React from 'react';
import { serializeToJSObject } from '../../Utils/Serializer';
import { rgbToHexNumber } from '../../Utils/ColorTransformer';
//TODO: try BaseEditor<Props,State>
export default class BaseEditor extends React.Component<*,*> {
static defaultProps = {
setToolbar: () => {},

View File

@@ -0,0 +1,56 @@
// @flow
import * as React from 'react';
import Debugger from '../../Debugger';
import BaseEditor from './BaseEditor';
import SubscriptionChecker from '../../Profile/SubscriptionChecker';
export default class DebuggerEditor extends BaseEditor {
editor: ?Debugger;
_subscriptionChecker: ?SubscriptionChecker;
state = {
subscriptionChecked: false,
};
updateToolbar() {
if (this.editor) this.editor.updateToolbar();
}
componentWillReceiveProps() {
this._checkHasSubscription();
}
componentDidMount() {
this._checkHasSubscription();
}
_checkHasSubscription() {
if (
this._subscriptionChecker &&
this.props.isActive &&
!this.state.subscriptionChecked
) {
this._subscriptionChecker.checkHasSubscription();
this.setState({
subscriptionChecked: true,
});
}
}
render() {
return (
<React.Fragment>
<Debugger {...this.props} ref={editor => (this.editor = editor)} />
<SubscriptionChecker
ref={subscriptionChecker =>
(this._subscriptionChecker = subscriptionChecker)}
onChangeSubscription={() => {
if (this.props.onChangeSubscription)
this.props.onChangeSubscription();
}}
title="Debugger"
mode="try"
/>
</React.Fragment>
);
}
}

View File

@@ -5,7 +5,7 @@ import { serializeToJSObject } from '../../Utils/Serializer';
import BaseEditor from './BaseEditor';
export default class EventsEditor extends BaseEditor {
editor: ?typeof EventsSheet;
editor: ?EventsSheet;
updateToolbar() {
if (this.editor) this.editor.updateToolbar();
@@ -45,6 +45,8 @@ export default class EventsEditor extends BaseEditor {
events={layout.getEvents()}
onPreview={(options) => this.props.onPreview(project, layout, options)}
onOpenExternalEvents={this.props.onOpenExternalEvents}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
);
}

View File

@@ -98,6 +98,8 @@ export default class ExternalEventsEditor extends BaseEditor {
onPreview={() => this.props.onPreview(project, layout)}
onOpenSettings={this.openLayoutChooser}
onOpenExternalEvents={this.props.onOpenExternalEvents}
resourceSources={this.props.resourceSources}
onChooseResource={this.props.onChooseResource}
/>
)}
{!layout && (

View File

@@ -1,7 +1,7 @@
// @flow
import * as React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import InstancesFullEditor from '../../SceneEditor/InstancesFullEditor';
import SceneEditor from '../../SceneEditor';
import { serializeToJSObject } from '../../Utils/Serializer';
import PlaceholderMessage from '../../UI/PlaceholderMessage';
import BaseEditor from './BaseEditor';
@@ -15,7 +15,7 @@ const styles = {
};
export default class ExternalLayoutEditor extends BaseEditor {
editor: ?typeof InstancesFullEditor;
editor: ?typeof SceneEditor;
state = {
layoutChooserOpen: false,
};
@@ -89,7 +89,7 @@ export default class ExternalLayoutEditor extends BaseEditor {
return (
<div style={styles.container}>
{layout && (
<InstancesFullEditor
<SceneEditor
{...this.props}
ref={editor => (this.editor = editor)}
project={project}
@@ -100,6 +100,7 @@ export default class ExternalLayoutEditor extends BaseEditor {
)}
onPreview={options =>
this.props.onPreview(project, layout, externalLayout, options)}
onOpenDebugger={this.props.onOpenDebugger}
onOpenMoreSettings={this.openLayoutChooser}
isActive={isActive}
/>

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