Merge pull request #452 from Lizard-13/skeleton-runtime-object
Add Skeleton object extension (still in Beta)
1864
Binaries/Output/Release_Windows/Examples/SkeletonTest.gdg
Normal file
1
Binaries/Output/Release_Windows/Examples/skeleton.json
Normal 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"}
|
BIN
Binaries/Output/Release_Windows/Examples/skeleton_texture.png
Normal file
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 464 B |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 550 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 469 B |
After Width: | Height: | Size: 600 B |
@@ -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()
|
||||
|
398
Extensions/SkeletonObject/Ask.js
Normal 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;
|
||||
};
|
@@ -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);
|
||||
};
|
@@ -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;
|
||||
};
|
20
Extensions/SkeletonObject/CMakeLists.txt
Normal 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)
|
131
Extensions/SkeletonObject/Cskbone.js
Normal 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;
|
||||
}
|
||||
};
|
456
Extensions/SkeletonObject/Dskslot.js
Normal 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);
|
||||
};
|
317
Extensions/SkeletonObject/Eskarmature.js
Normal 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();
|
||||
}
|
||||
};
|
678
Extensions/SkeletonObject/Extension.cpp
Normal 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();
|
||||
}
|
1394
Extensions/SkeletonObject/Fskanimation.js
Normal file
451
Extensions/SkeletonObject/Gskeletonruntimeobject.js
Normal 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;
|
||||
};
|
53
Extensions/SkeletonObject/Hskmanager.js
Normal 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;
|
||||
};
|
57
Extensions/SkeletonObject/Isk-tools.js
Normal 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;
|
||||
};
|
159
Extensions/SkeletonObject/JsExtension.cpp
Normal 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
|
151
Extensions/SkeletonObject/SkeletonObject.cpp
Normal 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);
|
||||
}
|
68
Extensions/SkeletonObject/SkeletonObject.h
Normal 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
|