overte-HifiExperiments/tutorial/tutorial.js
2016-10-07 10:30:18 -07:00

545 lines
18 KiB
JavaScript

Script.include("entityData.js");
//
// var FAR_GRAB_INPUTS = [
// Controller.Standard.RT
// Controller.Standard.RTClick
// Controller.Standard.LT
// Controller.Standard.LTClick
// ];
//
// var TELEPORT_INPUTS = [
// Controller.Standard.LeftPrimaryThumb
// Controller.Standard.RightPrimaryThumb
// ];
//
// function noop(value) { }
// var FAR_GRAB_MAPPING_NAME = "com.highfidelity.farGrab.disable";
// var farGrabMapping = Controller.newMapping(FAR_GRAB_MAPPING_NAME);
// for (var i = 0; i < FAR_GRAB_INPUTS.length; ++i) {
// mapping.from([FAR_GRAB_INPUTS[i]]).to(noop);
// }
//
// var TELEPORT_MAPPING_NAME = "com.highfidelity.teleport.disable";
// var teleportMapping = Controller.newMapping(TELEPORT_MAPPING_NAME);
// for (var i = 0; i < FAR_GRAB_INPUTS.length; ++i) {
// mapping.from([TELEPORT_INPUTS[i]]).to(noop);
// }
//
// mapping.from([Controller.Standard.RT]).to(noop);
// mapping.from([Controller.Standard.RTClick]).to(noop);
//
// mapping.from([Controller.Standard.LT]).to(noop);
// mapping.from([Controller.Standard.LTClick]).to(noop);
//
// mapping.from([Controller.Standard.RB]).to(noop);
// mapping.from([Controller.Standard.LB]).to(noop);
// mapping.from([Controller.Standard.LeftGrip]).to(noop);
// mapping.from([Controller.Standard.RightGrip]).to(noop);
//
// mapping.from([Controller.Standard.LeftPrimaryThumb]).to(noop);
// mapping.from([Controller.Standard.RightPrimaryThumb]).to(noop);
//
// Script.scriptEnding.connect(function() {
// Controller.disableMapping(MAPPING_NAME);
// });
//
// Controller.enableMapping(MAPPING_NAME);
var BASKET_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trach-Can-3.fbx";
var BASKET_COLLIDER_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trash-Can-4.obj";
var successSound = SoundCache.getSound(Script.resolvePath("success48.wav"));
function beginsWithFilter(value, key) {
return value.indexOf(properties[key]) == 0;
}
findEntity = function(properties, searchRadius, filterFn) {
var entities = findEntities(properties, searchRadius, filterFn);
return entities.length > 0 ? entities[0] : null;
}
// Return all entities with properties `properties` within radius `searchRadius`
findEntities = function(properties, searchRadius, filterFn) {
if (!filterFn) {
filterFn = function(properties, key, value) {
return value == properties[key];
}
}
searchRadius = searchRadius ? searchRadius : 100000;
var entities = Entities.findEntities({ x: 0, y: 0, z: 0 }, searchRadius);
var matchedEntities = [];
var keys = Object.keys(properties);
for (var i = 0; i < entities.length; ++i) {
var match = true;
var candidateProperties = Entities.getEntityProperties(entities[i], keys);
for (var key in properties) {
if (!filterFn(properties, key, candidateProperties[key])) {
// This isn't a match, move to next entity
match = false;
break;
}
}
if (match) {
matchedEntities.push(entities[i]);
}
}
return matchedEntities;
}
// On start tutorial...
// Load assets
var BOX_SPAWN_NAME = "tutorial/box_spawn";
var BASKET_COLLIDER_NAME = "tutorial/basket_collider";
var GUN_SPAWN_NAME = "tutorial/gun_spawn";
var GUN_AMMO_NAME = "Tutorial Ping Pong Ball"
function spawn(entityData, transform, modifyFn) {
print("Creating: ", entityData);
if (!transform) {
transform = {
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0, w: 1 }
}
}
var ids = [];
for (var i = 0; i < entityData.length; ++i) {
var data = entityData[i];
print("Creating: ", data.name);
data.position = Vec3.sum(transform.position, data.position);
data.rotation = Quat.multiply(data.rotation, transform.rotation);
if (modifyFn) {
data = modifyFn(data);
}
var id = Entities.addEntity(data);
ids.push(id);
}
return ids;
}
function parseJSON(jsonString) {
var data;
try {
data = JSON.parse(jsonString);
} catch(e) {
data = {};
}
return data;
}
function spawnWithTag(entityData, transform, tag) {
function modifyFn(data) {
var userData = parseJSON(data.userData);
userData.tag = tag;
data.userData = JSON.stringify(userData);
return data;
}
return spawn(entityData, transform, modifyFn);
}
function findEntitiesWithTag(tag) {
return findEntities({ userData: "" }, 10000, function(properties, key, value) {
data = parseJSON(value);
return data.tag == tag;
});
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: DISABLE CONTROLLERS //
// //
///////////////////////////////////////////////////////////////////////////////
var stepDisableControllers = function(name) {
this.tag = name;
}
stepDisableControllers.prototype = {
start: function(onFinish) {
Menu.setIsOptionChecked("Overlays", false);
Messages.sendLocalMessage('Hifi-Teleport-Disabler', 'both');
Messages.sendLocalMessage('Hifi-Grab-Disable', JSON.stringify({
nearGrabEnabled: true,
holdEnabled: false,
farGrabEnabled: false,
}));
onFinish();
},
cleanup: function() {
}
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: Raise hands above head //
// //
///////////////////////////////////////////////////////////////////////////////
var stepRaiseAboveHead = function(name) {
this.tag = name;
}
stepRaiseAboveHead.prototype = {
start: function(onFinish) {
var tag = this.tag;
var defaultTransform = {
position: {
x: 0.2459,
y: 0.9011,
z: 0.7266
},
rotation: {
x: 0,
y: 0,
z: 0,
w: 1
}
};
// Spawn content set
spawnWithTag(HandsAboveHeadData, defaultTransform, tag);
var checkIntervalID = null;
function checkForHandsAboveHead() {
print("Checking...");
if (MyAvatar.getLeftPalmPosition().y > (MyAvatar.getHeadPosition().y + 0.1)) {
Script.clearInterval(checkIntervalID);
this.soundInjector = Audio.playSound(successSound, {
position: defaultTransform.position,
volume: 0.7,
loop: false
});
onFinish();
}
}
checkIntervalID = Script.setInterval(checkForHandsAboveHead, 500);
},
cleanup: function() {
var entityIDs = findEntitiesWithTag(this.tag);
print("entities: ", entityIDs.length);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleting: ", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: Near Grab //
// //
///////////////////////////////////////////////////////////////////////////////
var stepNearGrab = function(name) {
this.tag = name;
}
stepNearGrab.prototype = {
start: function(onFinish) {
var tag = this.tag;
// Spawn content set
spawnWithTag(Step1EntityData, null, tag);
var basketColliderID = findEntity({ name: BASKET_COLLIDER_NAME }, 10000);
var basketPosition = Entities.getEntityProperties(basketColliderID, 'position').position;
function createBlock() {
var boxSpawnID = findEntity({ name: BOX_SPAWN_NAME }, 10000);
if (!boxSpawnID) {
print("Error creating block, cannot find spawn");
return null;
}
Step1BlockData.position = Entities.getEntityProperties(boxSpawnID, 'position').position;
return spawnWithTag([Step1BlockData], null, tag)[0];
}
// Enabled grab
// Create table ?
// Create blocks and basket
var boxID = createBlock();
print("Created", boxID);
function onHit() {
onFinish();
}
// When block collides with basket start step 2
var checkCollidesTimer = null;
function checkCollides() {
print("CHECKING...");
if (Vec3.distance(basketPosition, Entities.getEntityProperties(boxID, 'position').position) < 0.1) {
Script.clearInterval(checkCollidesTimer);
this.soundInjector = Audio.playSound(successSound, {
position: basketPosition,
volume: 0.7,
loop: false
});
Script.setTimeout(onHit, 1000);
}
}
checkCollidesTimer = Script.setInterval(checkCollides, 500);
// If block gets too far away or hasn't been touched for X seconds, create a new block and destroy the old block
},
cleanup: function() {
var entityIDs = findEntitiesWithTag(this.tag);
print("entities: ", entityIDs.length);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleting: ", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: Far Grab //
// //
///////////////////////////////////////////////////////////////////////////////
var stepFarGrab = function(name) {
this.tag = name;
}
stepFarGrab.prototype = {
start: function(onFinish) {
Messages.sendLocalMessage('Hifi-Grab-Disable', JSON.stringify({
farGrabEnabled: true,
}));
var tag = this.tag;
var transform = {
position: { x: 3, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0, w: 1 }
}
// Spawn content set
spawnWithTag(Step1EntityData, transform, tag);
var basketColliderID = findEntity({ name: BASKET_COLLIDER_NAME }, 10000);
var basketPosition = Entities.getEntityProperties(basketColliderID, 'position').position;
function createBlock() {
var boxSpawnID = findEntity({ name: BOX_SPAWN_NAME }, 10000);
if (!boxSpawnID) {
print("Error creating block, cannot find spawn");
return null;
}
Step1BlockData.position = Entities.getEntityProperties(boxSpawnID, 'position').position;
return spawnWithTag([Step1BlockData], null, tag)[0];
}
// Enabled grab
// Create table ?
// Create blocks and basket
var boxID = createBlock();
print("Created", boxID);
function onHit() {
onFinish();
}
// When block collides with basket start step 2
var checkCollidesTimer = null;
function checkCollides() {
print("CHECKING...");
if (Vec3.distance(basketPosition, Entities.getEntityProperties(boxID, 'position').position) < 0.1) {
Script.clearInterval(checkCollidesTimer);
this.soundInjector = Audio.playSound(successSound, {
position: basketPosition,
volume: 0.7,
loop: false
});
Script.setTimeout(onHit, 1000);
}
}
checkCollidesTimer = Script.setInterval(checkCollides, 500);
// If block gets too far away or hasn't been touched for X seconds, create a new block and destroy the old block
},
cleanup: function() {
var entityIDs = findEntitiesWithTag(this.tag);
print("entities: ", entityIDs.length);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleting: ", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: Equip //
// //
///////////////////////////////////////////////////////////////////////////////
var stepEquip = function(name) {
this.tag = name;
}
stepEquip.prototype = {
start: function(onFinish) {
Messages.sendLocalMessage('Hifi-Grab-Disable', JSON.stringify({
holdEnabled: true,
}));
var tag = this.tag;
var defaultTransform = {
position: {
x: 0.0,
y: 0.0,
z: 0.75
},
rotation: {
x: 0,
y: 0,
z: 0,
w: 1
}
};
// Spawn content set
spawnWithTag(StepGunData, defaultTransform, tag);
var basketColliderID = findEntity({ name: BASKET_COLLIDER_NAME }, 10000);
var basketPosition = Entities.getEntityProperties(basketColliderID, 'position').position;
function createGun() {
var boxSpawnID = findEntity({ name: GUN_SPAWN_NAME }, 10000);
if (!boxSpawnID) {
print("Error creating block, cannot find spawn");
return null;
}
GunData.position = Entities.getEntityProperties(boxSpawnID, 'position').position;
Vec3.print("spawn", GunData.position);
print("Adding: ", JSON.stringify(GunData));
return spawnWithTag([GunData], null, tag)[0];
}
// Enabled grab
// Create table ?
// Create blocks and basket
var gunID = createGun();
print("Created", gunID);
function onHit() {
onFinish();
}
// When block collides with basket start step 2
var checkCollidesTimer = null;
function checkCollides() {
print("CHECKING...");
var ammoIDs = findEntities({ name: GUN_AMMO_NAME }, 15);
for (var i = 0; i < ammoIDs.length; ++i) {
if (Vec3.distance(basketPosition, Entities.getEntityProperties(ammoIDs[i], 'position').position) < 0.2) {
Script.clearInterval(checkCollidesTimer);
this.soundInjector = Audio.playSound(successSound, {
position: basketPosition,
volume: 0.7,
loop: false
});
Script.setTimeout(onHit, 1000);
}
}
}
checkCollidesTimer = Script.setInterval(checkCollides, 500);
// If block gets too far away or hasn't been touched for X seconds, create a new block and destroy the old block
},
cleanup: function() {
var entityIDs = findEntitiesWithTag(this.tag);
print("entities: ", entityIDs.length);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleting: ", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// STEP: Teleport //
// //
///////////////////////////////////////////////////////////////////////////////
var stepTeleport = function(name) {
this.tag = name;
}
stepTeleport.prototype = {
start: function(onFinish) {
Messages.sendLocalMessage('Hifi-Teleport-Disabler', 'none');
Menu.setIsOptionChecked("Overlays", false);
},
cleanup: function() {
var entityIDs = findEntitiesWithTag(this.tag);
print("entities: ", entityIDs.length);
for (var i = 0; i < entityIDs.length; ++i) {
print("Deleting: ", entityIDs[i]);
Entities.deleteEntity(entityIDs[i]);
}
}
};
var STEPS;
var currentStepNum = -1;
var currentStep = null;
function startTutorial() {
currentStepNum = -1;
currentStep = null;
STEPS = [
new stepDisableControllers("step0"),
//new stepRaiseAboveHead("step1"),
new stepNearGrab("step2"),
new stepFarGrab("step3"),
new stepEquip("step4"),
new stepTeleport("teleport"),
]
startNextStep();
}
function startNextStep() {
if (currentStep) {
//currentStep.cleanup();
}
++currentStepNum;
if (currentStepNum >= STEPS.length) {
// Done
print("DONE WITH TUTORIAL");
} else {
print("Starting step", currentStepNum);
currentStep = STEPS[currentStepNum];
currentStep.start(startNextStep);
startNextStep();
}
}
function skipTutorial() {
}
function stopTutorial() {
if (currentStep) {
currentStep.cleanup();
}
}
location = "/tutorial";
startTutorial();
Script.scriptEnding.connect(stopTutorial);