(function(){ this.FIRST_TILE = null; // Global position of the first tile (1a) this.TILE_SIZE = null; // Size of one tile this.wantDebug = false; this.active = false; this.entityID = null; this.properties = null; this.boardID = null; this.boardUserData = null; this.sound = null; this.startingTile = null; this.pieces = new Array(); // All callbacks start by updating the properties this.updateProperties = function(entityID) { // Piece ID if (this.entityID === null) { this.entityID = entityID; } // Piece Properties this.properties = Entities.getEntityProperties(this.entityID); // Board ID if (this.boardID === null) { // Read user data string and update boardID var userData = JSON.parse(this.properties.userData); this.boardID = userData.boardID; } // Board User Data this.updateUserData(); } // Get an entity's user data this.getEntityUserData = function(entityID) { var properties = Entities.getEntityProperties(entityID); if (properties && properties.userData){ return JSON.parse(properties.userData); } else { print("No user data found."); return null; } } // Updates user data related objects this.updateUserData = function() { // Get board's user data if (this.boardID !== null) { this.boardUserData = this.getEntityUserData(this.boardID); if (!(this.boardUserData && this.boardUserData.firstTile && this.boardUserData.tileSize)) { print("Incomplete boardUserData " + this.boardID); } else { this.FIRST_TILE = this.boardUserData.firstTile; this.TILE_SIZE = this.boardUserData.tileSize; this.active = true; } } else { print("Missing boardID:" + JSON.stringify(this.boardID)); } } // Returns whether pos is inside the grid or not this.isOutsideGrid = function(pos) { return !(pos.i >= 0 && pos.j >= 0 && pos.i < 8 && pos.j < 8); } // Returns the tile coordinate this.getIndexPosition = function(position) { var halfTile = this.TILE_SIZE / 2.0; var corner = Vec3.sum(this.FIRST_TILE, { x: -halfTile, y: 0.0, z: -halfTile }); var relative = Vec3.subtract(position, corner); return { i: Math.floor(relative.x / this.TILE_SIZE), j: Math.floor(relative.z / this.TILE_SIZE) } } // Returns the world position this.getAbsolutePosition = function(pos, halfHeight) { var relative = { x: pos.i * this.TILE_SIZE, y: halfHeight, z: pos.j * this.TILE_SIZE } return Vec3.sum(this.FIRST_TILE, relative); } // Pr, Vr are respectively the Ray's Point of origin and Vector director // Pp, Np are respectively the Plane's Point of origin and Normal vector this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) { var d = -Vec3.dot(Pp, Np); var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np); return Vec3.sum(Pr, Vec3.multiply(t, Vr)); } // Download sound if needed this.maybeDownloadSound = function() { if (this.sound === null) { this.sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav"); } } // Play drop sound this.playSound = function() { if (this.sound && this.sound.downloaded) { Audio.playSound(this.sound, { position: this.properties.position }); } } // updates the piece position based on mouse input this.updatePosition = function(mouseEvent) { var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) var upVector = { x: 0, y: 1, z: 0 }; var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, this.properties.position, upVector); // if piece outside grid then send it back to the starting tile if (this.isOutsideGrid(this.getIndexPosition(intersection))) { intersection = this.getAbsolutePosition(this.startingTile, this.properties.dimensions.y / 2.0); } Entities.editEntity(this.entityID, { position: intersection }); } // Snap piece to the center of the tile it is on this.snapToGrid = function() { var pos = this.getIndexPosition(this.properties.position); var finalPos = this.getAbsolutePosition((this.isOutsideGrid(pos)) ? this.startingTile : pos, this.properties.dimensions.y / 2.0); Entities.editEntity(this.entityID, { position: finalPos }); } this.moveDeadPiece = function() { var myPos = this.getIndexPosition(this.properties.position); var others = Entities.findEntities(this.properties.position, this.properties.dimensions.y); for (var i = 0; i < others.length; i++) { var pieceID = others[i]; if (pieceID != this.entityID) { var properties = Entities.getEntityProperties(pieceID); var isWhite = properties.modelURL.search("White") !== -1; var type = (properties.modelURL.search("King") !== -1) ? 4 : (properties.modelURL.search("Queen") !== -1) ? 3 : (properties.modelURL.search("Rook") !== -1) ? 2 : (properties.modelURL.search("Knight") !== -1) ? 1 : (properties.modelURL.search("Bishop") !== -1) ? 0 : (properties.modelURL.search("Pawn") !== -1) ? -1 : -2; var piecePos = this.getIndexPosition(properties.position); if (myPos.i === piecePos.i && myPos.j === piecePos.j && type !== -2) { var position = this.getAbsolutePosition((isWhite) ? { i: type, j: -1 } : { i: 7 - type, j: 8 }, properties.dimensions.y / 2.0); Entities.editEntity(pieceID, { position: position }); break; } } } } this.grab = function(mouseEvent) { if (this.active) { this.startingTile = this.getIndexPosition(this.properties.position); this.updatePosition(mouseEvent); } } this.move = function(mouseEvent) { if (this.active) { this.updatePosition(mouseEvent); } } this.release = function(mouseEvent) { if (this.active) { this.updatePosition(mouseEvent); this.snapToGrid(); this.moveDeadPiece(); this.playSound(); } } this.preload = function(entityID) { this.updateProperties(entityID); // All callbacks start by updating the properties this.maybeDownloadSound(); } this.clickDownOnEntity = function(entityID, mouseEvent) { this.preload(entityID); // TODO : remove this.updateProperties(entityID); // All callbacks start by updating the properties this.grab(mouseEvent); }; this.holdingClickOnEntity = function(entityID, mouseEvent) { this.updateProperties(entityID); // All callbacks start by updating the properties this.move(mouseEvent); }; this.clickReleaseOnEntity = function(entityID, mouseEvent) { this.updateProperties(entityID); // All callbacks start by updating the properties this.release(mouseEvent); };})
(function(){
this.FIRST_TILE = null; // Global position of the first tile (1a)
this.TILE_SIZE = null; // Size of one tile
this.wantDebug = false;
this.active = false;
this.entityID = null;
this.properties = null;
this.boardID = null;
this.boardUserData = null;
this.sound = null;
this.startingTile = null;
this.pieces = new Array();
// All callbacks start by updating the properties
this.updateProperties = function(entityID) {
// Piece ID
if (this.entityID === null) {
this.entityID = entityID;
}
// Piece Properties
this.properties = Entities.getEntityProperties(this.entityID);
// Board ID
if (this.boardID === null) {
// Read user data string and update boardID
var userData = JSON.parse(this.properties.userData);
this.boardID = userData.boardID;
}
// Board User Data
this.updateUserData();
}
// Get an entity's user data
this.getEntityUserData = function(entityID) {
var properties = Entities.getEntityProperties(entityID);
if (properties && properties.userData){
return JSON.parse(properties.userData);
} else {
print("No user data found.");
return null;
}
}
// Updates user data related objects
this.updateUserData = function() {
// Get board's user data
if (this.boardID !== null) {
this.boardUserData = this.getEntityUserData(this.boardID);
if (!(this.boardUserData &&
this.boardUserData.firstTile &&
this.boardUserData.tileSize)) {
print("Incomplete boardUserData " + this.boardID);
} else {
this.FIRST_TILE = this.boardUserData.firstTile;
this.TILE_SIZE = this.boardUserData.tileSize;
this.active = true;
}
} else {
print("Missing boardID:" + JSON.stringify(this.boardID));
}
}
// Returns whether pos is inside the grid or not
this.isOutsideGrid = function(pos) {
return !(pos.i >= 0 && pos.j >= 0 && pos.i < 8 && pos.j < 8);
}
// Returns the tile coordinate
this.getIndexPosition = function(position) {
var halfTile = this.TILE_SIZE / 2.0;
var corner = Vec3.sum(this.FIRST_TILE, { x: -halfTile, y: 0.0, z: -halfTile });
var relative = Vec3.subtract(position, corner);
return {
i: Math.floor(relative.x / this.TILE_SIZE),
j: Math.floor(relative.z / this.TILE_SIZE)
}
}
// Returns the world position
this.getAbsolutePosition = function(pos, halfHeight) {
var relative = {
x: pos.i * this.TILE_SIZE,
y: halfHeight,
z: pos.j * this.TILE_SIZE
}
return Vec3.sum(this.FIRST_TILE, relative);
}
// Pr, Vr are respectively the Ray's Point of origin and Vector director
// Pp, Np are respectively the Plane's Point of origin and Normal vector
this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) {
var d = -Vec3.dot(Pp, Np);
var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np);
return Vec3.sum(Pr, Vec3.multiply(t, Vr));
}
// Download sound if needed
this.maybeDownloadSound = function() {
if (this.sound === null) {
this.sound = SoundCache.getSound("http://public.highfidelity.io/sounds/Footsteps/FootstepW3Left-12db.wav");
}
}
// Play drop sound
this.playSound = function() {
if (this.sound && this.sound.downloaded) {
Audio.playSound(this.sound, { position: this.properties.position });
}
}
// updates the piece position based on mouse input
this.updatePosition = function(mouseEvent) {
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
var upVector = { x: 0, y: 1, z: 0 };
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
this.properties.position, upVector);
// if piece outside grid then send it back to the starting tile
if (this.isOutsideGrid(this.getIndexPosition(intersection))) {
intersection = this.getAbsolutePosition(this.startingTile, this.properties.dimensions.y / 2.0);
}
Entities.editEntity(this.entityID, { position: intersection });
}
// Snap piece to the center of the tile it is on
this.snapToGrid = function() {
var pos = this.getIndexPosition(this.properties.position);
var finalPos = this.getAbsolutePosition((this.isOutsideGrid(pos)) ? this.startingTile : pos,
this.properties.dimensions.y / 2.0);
Entities.editEntity(this.entityID, { position: finalPos });
}
this.moveDeadPiece = function() {
var myPos = this.getIndexPosition(this.properties.position);
var others = Entities.findEntities(this.properties.position, this.properties.dimensions.y);
for (var i = 0; i < others.length; i++) {
var pieceID = others[i];
if (pieceID != this.entityID) {
var properties = Entities.getEntityProperties(pieceID);
var isWhite = properties.modelURL.search("White") !== -1;
var type = (properties.modelURL.search("King") !== -1) ? 4 :
(properties.modelURL.search("Queen") !== -1) ? 3 :
(properties.modelURL.search("Rook") !== -1) ? 2 :
(properties.modelURL.search("Knight") !== -1) ? 1 :
(properties.modelURL.search("Bishop") !== -1) ? 0 :
(properties.modelURL.search("Pawn") !== -1) ? -1 : -2;
var piecePos = this.getIndexPosition(properties.position);
if (myPos.i === piecePos.i && myPos.j === piecePos.j && type !== -2) {
var position = this.getAbsolutePosition((isWhite) ? { i: type, j: -1 } : { i: 7 - type, j: 8 },
properties.dimensions.y / 2.0);
Entities.editEntity(pieceID, {
position: position
});
break;
}
}
}
}
this.grab = function(mouseEvent) {
if (this.active) {
this.startingTile = this.getIndexPosition(this.properties.position);
this.updatePosition(mouseEvent);
}
}
this.move = function(mouseEvent) {
if (this.active) {
this.updatePosition(mouseEvent);
}
}
this.release = function(mouseEvent) {
if (this.active) {
this.updatePosition(mouseEvent);
this.snapToGrid();
this.moveDeadPiece();
this.playSound();
}
}
this.preload = function(entityID) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.maybeDownloadSound();
}
this.clickDownOnEntity = function(entityID, mouseEvent) {
this.preload(entityID); // TODO : remove
this.updateProperties(entityID); // All callbacks start by updating the properties
this.grab(mouseEvent);
};
this.holdingClickOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.move(mouseEvent);
};
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.release(mouseEvent);
};
})