Made draggableruntimeautomatism.js working with multitouch and added tests for it

This commit is contained in:
Florian Rival
2015-03-12 13:47:24 +13:00
parent 130f5526f2
commit f29d17ec91
6 changed files with 240 additions and 27 deletions

View File

@@ -15,6 +15,9 @@ gdjs.DraggableRuntimeAutomatism = function(runtimeScene, automatismData, owner)
gdjs.RuntimeAutomatism.call(this, runtimeScene, automatismData, owner);
this._dragged = false;
this._touchId = null;
this._mouse = false;
this._xOffset = 0;
this._yOffset = 0;
};
@@ -23,46 +26,111 @@ gdjs.DraggableRuntimeAutomatism.prototype = Object.create( gdjs.RuntimeAutomatis
gdjs.DraggableRuntimeAutomatism.thisIsARuntimeAutomatismConstructor = "DraggableAutomatism::Draggable";
gdjs.DraggableRuntimeAutomatism.prototype.onDeActivate = function() {
if ( this._dragged ) gdjs.DraggableRuntimeAutomatism.draggingSomething = false;
this._dragged = false;
this._endDrag();
};
gdjs.DraggableRuntimeAutomatism.prototype.doStepPreEvents = function(runtimeScene) {
var mousePos = null;
gdjs.DraggableRuntimeAutomatism.prototype._endDrag = function() {
if ( this._dragged && this._mouse ) gdjs.DraggableRuntimeAutomatism.mouseDraggingSomething = false;
if ( this._dragged && this._touchId !== null ) gdjs.DraggableRuntimeAutomatism.touchDraggingSomething[this._touchId] = false;
//Begin drag ?
if ( !this._dragged && runtimeScene.getGame().getInputManager().isMouseButtonPressed(0) &&
this._dragged = false;
this._mouse = false;
this._touchId = null;
}
gdjs.DraggableRuntimeAutomatism.prototype._tryBeginDrag = function(runtimeScene) {
if (this._dragged) return false;
var inputManager = runtimeScene.getGame().getInputManager();
//Try mouse
if (inputManager.isMouseButtonPressed(0) &&
!gdjs.DraggableRuntimeAutomatism.leftPressedLastFrame &&
!gdjs.DraggableRuntimeAutomatism.draggingSomething ) {
!gdjs.DraggableRuntimeAutomatism.mouseDraggingSomething) {
mousePos = runtimeScene.getLayer(this.owner.getLayer()).convertCoords(
runtimeScene.getGame().getInputManager().getMouseX(),
runtimeScene.getGame().getInputManager().getMouseY());
inputManager.getMouseX(),
inputManager.getMouseY());
if (this.owner.insideObject(mousePos[0], mousePos[1])) {
this._dragged = true;
gdjs.DraggableRuntimeAutomatism.draggingSomething = true;
this._mouse = true;
this._xOffset = mousePos[0] - this.owner.getX();
this._yOffset = mousePos[1] - this.owner.getY();
gdjs.DraggableRuntimeAutomatism.mouseDraggingSomething = true;
return true;
}
} else { //Try touches
var touchIds = inputManager.getStartedTouchIdentifiers();
for(var i = 0;i<touchIds.length;++i) {
if (gdjs.DraggableRuntimeAutomatism.touchDraggingSomething[touchIds[i]])
continue;
touchPos = runtimeScene.getLayer(this.owner.getLayer()).convertCoords(
inputManager.getTouchX(touchIds[i]),
inputManager.getTouchY(touchIds[i]));
if (this.owner.insideObject(touchPos[0], touchPos[1])) {
this._dragged = true;
this._touchId = touchIds[i];
this._xOffset = touchPos[0] - this.owner.getX();
this._yOffset = touchPos[1] - this.owner.getY();
gdjs.DraggableRuntimeAutomatism.touchDraggingSomething[touchIds[i]] = true;
return true;
}
}
}
//End dragging ?
else if ( !runtimeScene.getGame().getInputManager().isMouseButtonPressed(0) ) {
this._dragged = false;
gdjs.DraggableRuntimeAutomatism.draggingSomething = false;
}
//Being dragging ?
if ( this._dragged ) {
if ( mousePos === null ) {
mousePos = runtimeScene.getLayer(this.owner.getLayer()).convertCoords(
runtimeScene.getGame().getInputManager().getMouseX(),
runtimeScene.getGame().getInputManager().getMouseY());
}
return false;
}
gdjs.DraggableRuntimeAutomatism.prototype._shouldEndDrag = function(runtimeScene) {
if (!this._dragged) return false;
var inputManager = runtimeScene.getGame().getInputManager();
if (this._mouse)
return !inputManager.isMouseButtonPressed(0);
else if (this._touchId !== null) {
return inputManager.getAllTouchIdentifiers().indexOf(this._touchId) === -1;
}
return false;
}
gdjs.DraggableRuntimeAutomatism.prototype._updateObjectPosition = function(runtimeScene) {
if (!this._dragged) return false;
var inputManager = runtimeScene.getGame().getInputManager();
if (this._mouse) {
mousePos = runtimeScene.getLayer(this.owner.getLayer()).convertCoords(
inputManager.getMouseX(),
inputManager.getMouseY());
this.owner.setX(mousePos[0] - this._xOffset);
this.owner.setY(mousePos[1] - this._yOffset);
}
else if (this._touchId !== null) {
touchPos = runtimeScene.getLayer(this.owner.getLayer()).convertCoords(
inputManager.getTouchX(this._touchId),
inputManager.getTouchY(this._touchId));
this.owner.setX(touchPos[0] - this._xOffset);
this.owner.setY(touchPos[1] - this._yOffset);
}
return true;
}
gdjs.DraggableRuntimeAutomatism.prototype.doStepPreEvents = function(runtimeScene) {
this._tryBeginDrag(runtimeScene);
if (this._shouldEndDrag(runtimeScene)) {
this._endDrag();
}
this._updateObjectPosition(runtimeScene);
};
gdjs.DraggableRuntimeAutomatism.prototype.doStepPostEvents = function(runtimeScene) {
@@ -75,7 +143,10 @@ gdjs.DraggableRuntimeAutomatism.prototype.isDragged = function(runtimeScene) {
};
//Static property used to avoid start dragging an object while another is dragged.
gdjs.DraggableRuntimeAutomatism.draggingSomething = false;
gdjs.DraggableRuntimeAutomatism.mouseDraggingSomething = false;
//Static property used to avoid start dragging an object while another is dragged by the same touch.
gdjs.DraggableRuntimeAutomatism.touchDraggingSomething = [];
//Static property used to only start dragging when clicking.
gdjs.DraggableRuntimeAutomatism.leftPressedLastFrame = false;

View File

@@ -0,0 +1,117 @@
describe('gdjs.DraggableRuntimeAutomatism', function() {
var runtimeGame = new gdjs.RuntimeGame({variables: [], properties: {windowWidth: 800, windowHeight: 600}});
var runtimeScene = new gdjs.RuntimeScene(runtimeGame, null);
runtimeScene.loadFromScene({
layers:[{name:"", visibility: true}],
variables: [],
automatismsSharedData: [],
objects: [],
instances: []
});
var object = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", automatisms: [{type: "DraggableAutomatism::Draggable"}]});
var object2 = new gdjs.RuntimeObject(runtimeScene, {name: "obj1", type: "", automatisms: [{type: "DraggableAutomatism::Draggable"}]});
runtimeScene.addObject(object);
runtimeScene.addObject(object2);
it('should handle mouse', function() {
object.setPosition(450, 500);
//Drag'n'drop
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onMouseMove(450, 500);
runtimeGame.getInputManager().onMouseButtonPressed(0);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onMouseButtonReleased(0);
runtimeScene.renderAndStep();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
//Mouse move with dragging
runtimeGame.getInputManager().onMouseMove(600, 600);
runtimeScene.renderAndStep();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
//Start dragging again
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeGame.getInputManager().onMouseButtonPressed(0);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onMouseMove(850, 700);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onMouseButtonReleased(0);
runtimeScene.renderAndStep();
expect(object.getX()).to.be(850);
expect(object.getY()).to.be(700);
});
it('should handle touches', function() {
object.setPosition(450, 500);
//Drag'n'drop
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchStart(1, 10, 20);
runtimeGame.getInputManager().onTouchStart(0, 450, 500);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchMove(0, 750, 600);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(0);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
//Move another unrelated touch
runtimeGame.getInputManager().onTouchMove(1, 750, 600);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchMove(1, 850, 700);
runtimeScene.renderAndStep();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
//Start drag'n'drop with another touch
runtimeGame.getInputManager().onTouchEnd(1);
runtimeGame.getInputManager().onFrameEnded();
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchStart(1, 750, 600);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchMove(1, 850, 700);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchEnd(1);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(850);
expect(object.getY()).to.be(700);
});
it('should handle multitouch', function() {
object.setPosition(450, 500);
object2.setPosition(650, 600);
//Drag'n'drop
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onTouchStart(2, 450, 500);
runtimeGame.getInputManager().onTouchStart(1, 650, 600);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchMove(2, 750, 700);
runtimeGame.getInputManager().onTouchMove(1, 100, 200);
runtimeScene.renderAndStep();
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(2);
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(700);
expect(object2.getX()).to.be(100);
expect(object2.getY()).to.be(200);
});
});

View File

@@ -191,7 +191,12 @@ gdjs.InputManager.prototype.getTouchY = function(identifier) {
* @method getAllTouchIdentifiers
*/
gdjs.InputManager.prototype.getAllTouchIdentifiers = function() {
return this._touches.keys();
var touchIds = this._touches.keys();
for(var i = 0;i<touchIds.length;++i) {
touchIds[i] = parseInt(touchIds[i], 10);
}
return touchIds;
};
gdjs.InputManager.prototype.onTouchStart = function(identifier, x, y) {
@@ -212,6 +217,10 @@ gdjs.InputManager.prototype.onTouchEnd = function(identifier, x, y) {
this._touches.remove(identifier);
};
gdjs.InputManager.prototype.getStartedTouchIdentifiers = function() {
return this._startedTouches;
}
gdjs.InputManager.prototype.popStartedTouch = function() {
return this._startedTouches.shift();
}

View File

@@ -127,7 +127,11 @@ gdjs.RuntimeScene.prototype.loadFromScene = function(sceneData) {
//Set up the function to be executed at each tick
var module = gdjs[sceneData.mangledName+"Code"];
if ( module && module.func ) this._eventsFunction = module.func;
if ( module && module.func )
this._eventsFunction = module.func;
else
this._eventsFunction = (function() {});
this._eventsContext = new gdjs.EventsContext();
//Call global callback
@@ -211,7 +215,9 @@ gdjs.RuntimeScene.prototype.renderAndStep = function() {
* Render the PIXI stage associated to the runtimeScene.
* @method render
*/
gdjs.RuntimeScene.prototype.render = function(){
gdjs.RuntimeScene.prototype.render = function() {
if (!this._pixiRenderer) return;
// render the PIXI stage
this._pixiRenderer.render(this._pixiStage);
};

View File

@@ -4,6 +4,8 @@ module.exports = function(config) {
files: [
'node_modules/expect.js/index.js',
//GDJS game engine files: (Order is important)
'../Runtime/libs/pixi.js',
'../Runtime/libs/jshashtable.js',
'../Runtime/gd.js',
@@ -34,7 +36,13 @@ module.exports = function(config) {
'../Runtime/storagetools.js',
'../Runtime/stringtools.js',
'../Runtime/windowtools.js',
//Extensions:
'../../Extensions/DraggableAutomatism/draggableruntimeautomatism.js',
//All tests files:
'../../Extensions/**/tests/**.spec.js',
'tests/**/*.js'
]
});
};
};

View File

@@ -95,6 +95,7 @@ describe('gdjs.InputManager', function() {
it('should handle touch events', function(){
inputManager.onTouchStart(46, 510, 610);
inputManager.onTouchStart(10, 510, 610);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(2);
expect(inputManager.getTouchX(46)).to.be(510);
expect(inputManager.getTouchY(46)).to.be(610);
@@ -104,6 +105,7 @@ describe('gdjs.InputManager', function() {
inputManager.onFrameEnded();
inputManager.onTouchEnd(10);
expect(inputManager.getStartedTouchIdentifiers()).to.have.length(0);
expect(inputManager.popStartedTouch()).to.be(undefined);
expect(inputManager.popEndedTouch()).to.be(10);
});