mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:00:13 +02:00
Add ownership token tot tutorial
This commit is contained in:
parent
2bf13b9cf6
commit
a05f681704
2 changed files with 292 additions and 93 deletions
188
tutorial/ownershipToken.js
Normal file
188
tutorial/ownershipToken.js
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
if (!Function.prototype.bind) {
|
||||||
|
Function.prototype.bind = function(oThis) {
|
||||||
|
if (typeof this !== 'function') {
|
||||||
|
// closest thing possible to the ECMAScript 5
|
||||||
|
// internal IsCallable function
|
||||||
|
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
|
||||||
|
}
|
||||||
|
|
||||||
|
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||||
|
fToBind = this,
|
||||||
|
fNOP = function() {},
|
||||||
|
fBound = function() {
|
||||||
|
return fToBind.apply(this instanceof fNOP
|
||||||
|
? this
|
||||||
|
: oThis,
|
||||||
|
aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.prototype) {
|
||||||
|
// Function.prototype doesn't have a prototype property
|
||||||
|
fNOP.prototype = this.prototype;
|
||||||
|
}
|
||||||
|
fBound.prototype = new fNOP();
|
||||||
|
|
||||||
|
return fBound;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOption(options, key, defaultValue) {
|
||||||
|
if (options.hasOwnProperty(key)) {
|
||||||
|
return options[key];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var TOKEN_NAME_PREFIX = "ownership_token-";
|
||||||
|
|
||||||
|
function getOwnershipTokenID(parentEntityID) {
|
||||||
|
var childEntityIDs = Entities.getChildrenIDs(parentEntityID);
|
||||||
|
var ownerID = null;
|
||||||
|
var ownerName = '';
|
||||||
|
for (var i = 0; i < childEntityIDs.length; ++i) {
|
||||||
|
var childID = childEntityIDs[i];
|
||||||
|
var properties = Entities.getEntityProperties(childID, ['name', 'userData', 'lifetime', 'age']);
|
||||||
|
var childName = properties.name;
|
||||||
|
//debug("Owner lifetime: ", properties.lifetime, properties.age);
|
||||||
|
if (properties.age > 0.5 && childName.indexOf(TOKEN_NAME_PREFIX) == 0) {
|
||||||
|
if (ownerID === null || childName < ownerName) {
|
||||||
|
ownerID = childID;
|
||||||
|
ownerName = childName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ownerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createOwnershipToken(name, parentEntityID) {
|
||||||
|
return Entities.addEntity({
|
||||||
|
type: "Box",
|
||||||
|
name: TOKEN_NAME_PREFIX + name,
|
||||||
|
visible: false,
|
||||||
|
parentID: parentEntityID,
|
||||||
|
locationPosition: { x: 0, y: 0, z: 0 },
|
||||||
|
dimensions: { x: 100, y: 100, z: 100 },
|
||||||
|
collisionless: true,
|
||||||
|
lifetime: 5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var DEBUG = true;
|
||||||
|
function debug() {
|
||||||
|
if (DEBUG) {
|
||||||
|
var args = Array.prototype.slice.call(arguments);
|
||||||
|
print.apply(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var TOKEN_STATE_DESTROYED = -1;
|
||||||
|
var TOKEN_STATE_UNOWNED = 0;
|
||||||
|
var TOKEN_STATE_REQUESTING_OWNERSHIP = 1;
|
||||||
|
var TOKEN_STATE_OWNED = 2;
|
||||||
|
|
||||||
|
OwnershipToken = function(name, parentEntityID, options) {
|
||||||
|
this.name = MyAvatar.sessionUUID + "-" + Math.floor(Math.random() * 10000000);
|
||||||
|
this.name = Math.floor(Math.random() * 10000000);
|
||||||
|
this.parentEntityID = parentEntityID;
|
||||||
|
|
||||||
|
// How often to check whether the token is available if we don't currently own it
|
||||||
|
this.checkEverySeconds = getOption(options, 'checkEverySeconds', 1000);
|
||||||
|
this.updateTokenLifetimeEvery = getOption(options, 'updateTokenLifetimeEvery', 2000);
|
||||||
|
|
||||||
|
//this.onRequestingOwnership = getOption(options, 'onRequestingOwnership', function() { });
|
||||||
|
this.onGainedOwnership = getOption(options, 'onGainedOwnership', function() { });
|
||||||
|
this.onLostOwnership = getOption(options, 'onLostOwnership', function() { });
|
||||||
|
|
||||||
|
this.ownershipTokenID = null;
|
||||||
|
this.setState(TOKEN_STATE_UNOWNED);
|
||||||
|
};
|
||||||
|
|
||||||
|
OwnershipToken.prototype = {
|
||||||
|
destroy: function() {
|
||||||
|
debug(this.name, "Destroying token");
|
||||||
|
this.setState(TOKEN_STATE_DESTROYED);
|
||||||
|
},
|
||||||
|
|
||||||
|
setState: function(newState) {
|
||||||
|
if (this.state == newState) {
|
||||||
|
debug(this.name, "Warning: Trying to set state to the current state");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.updateLifetimeID) {
|
||||||
|
Script.clearInterval(this.updateLifetimeID);
|
||||||
|
this.updateLifetimeID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.checkOwnershipAvailableID) {
|
||||||
|
Script.clearInterval(this.checkOwnershipAvailableID);
|
||||||
|
this.checkOwnershipAvailableID = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state == TOKEN_STATE_OWNED) {
|
||||||
|
this.onLostOwnership(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newState == TOKEN_STATE_UNOWNED) {
|
||||||
|
this.checkOwnershipAvailableID = Script.setInterval(
|
||||||
|
this.tryRequestingOwnership.bind(this), this.checkEverySeconds);
|
||||||
|
|
||||||
|
} else if (newState == TOKEN_STATE_REQUESTING_OWNERSHIP) {
|
||||||
|
|
||||||
|
} else if (newState == TOKEN_STATE_OWNED) {
|
||||||
|
this.onGainedOwnership(this);
|
||||||
|
this.updateLifetimeID = Script.setInterval(
|
||||||
|
this.updateTokenLifetime.bind(this), this.updateTokenLifetimeEvery);
|
||||||
|
} else if (newState == TOKEN_STATE_DESTROYED) {
|
||||||
|
Entities.deleteEntity(this.ownershipTokenID);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(this.name, "Info: Switching to state:", newState);
|
||||||
|
this.state = newState;
|
||||||
|
},
|
||||||
|
updateTokenLifetime: function() {
|
||||||
|
if (this.state != TOKEN_STATE_OWNED) {
|
||||||
|
debug(this.name, "Error: Trying to update token while it is unowned");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(this.name, "Updating entity lifetime");
|
||||||
|
var age = Entities.getEntityProperties(this.ownershipTokenID, 'age').age;
|
||||||
|
Entities.editEntity(this.ownershipTokenID, {
|
||||||
|
lifetime: age + 5
|
||||||
|
});
|
||||||
|
},
|
||||||
|
tryRequestingOwnership: function() {
|
||||||
|
if (this.state == TOKEN_STATE_REQUESTING_OWNERSHIP || this.state == TOKEN_STATE_OWNED) {
|
||||||
|
debug(this.name, "We already have or are requesting ownership");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ownerID = getOwnershipTokenID(this.parentEntityID);
|
||||||
|
if (ownerID !== null) {
|
||||||
|
// Already owned, return
|
||||||
|
debug(this.name, "Token already owned by another client, return");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ownershipTokenID = createOwnershipToken(this.name, this.parentEntityID);
|
||||||
|
this.setState(TOKEN_STATE_REQUESTING_OWNERSHIP);
|
||||||
|
|
||||||
|
function checkOwnershipRequest() {
|
||||||
|
var ownerID = getOwnershipTokenID(this.parentEntityID);
|
||||||
|
if (ownerID == this.ownershipTokenID) {
|
||||||
|
debug(this.name, "Info: Obtained ownership");
|
||||||
|
this.setState(TOKEN_STATE_OWNED);
|
||||||
|
} else {
|
||||||
|
if (ownerID === null) {
|
||||||
|
debug(this.name, "Warning: Checked ownership request and no tokens existed");
|
||||||
|
}
|
||||||
|
debug(this.name, "Info: Lost ownership request")
|
||||||
|
this.ownershipTokenID = null;
|
||||||
|
this.setState(TOKEN_STATE_UNOWNED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.setTimeout(checkOwnershipRequest.bind(this), 2000);
|
||||||
|
},
|
||||||
|
};
|
|
@ -30,6 +30,7 @@ Script.include("entityData.js");
|
||||||
|
|
||||||
Script.include("viveHandsv2.js");
|
Script.include("viveHandsv2.js");
|
||||||
Script.include("lighter/createButaneLighter.js");
|
Script.include("lighter/createButaneLighter.js");
|
||||||
|
Script.include('ownershipToken.js');
|
||||||
|
|
||||||
var BASKET_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trach-Can-3.fbx";
|
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 BASKET_COLLIDER_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/Trash-Can-4.obj";
|
||||||
|
@ -146,19 +147,19 @@ function spawnWithTag(entityData, transform, tag) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteEntitiesWithTag(tag) {
|
function deleteEntitiesWithTag(tag) {
|
||||||
print("searching for...:", tag);
|
print("searching for...:", tag);
|
||||||
var entityIDs = findEntitiesWithTag(tag);
|
var entityIDs = findEntitiesWithTag(tag);
|
||||||
for (var i = 0; i < entityIDs.length; ++i) {
|
for (var i = 0; i < entityIDs.length; ++i) {
|
||||||
print("Deleteing:", entityIDs[i]);
|
//print("Deleteing:", entityIDs[i]);
|
||||||
Entities.deleteEntity(entityIDs[i]);
|
Entities.deleteEntity(entityIDs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function editEntitiesWithTag(tag, propertiesOrFn) {
|
function editEntitiesWithTag(tag, propertiesOrFn) {
|
||||||
print("Editing:", tag);
|
//print("Editing:", tag);
|
||||||
var entityIDs = findEntitiesWithTag(tag);
|
var entityIDs = findEntitiesWithTag(tag);
|
||||||
print("Editing...", entityIDs);
|
//print("Editing...", entityIDs);
|
||||||
for (var i = 0; i < entityIDs.length; ++i) {
|
for (var i = 0; i < entityIDs.length; ++i) {
|
||||||
print("Editing...", entityIDs[i]);
|
//print("Editing...", entityIDs[i]);
|
||||||
if (isFunction(propertiesOrFn)) {
|
if (isFunction(propertiesOrFn)) {
|
||||||
Entities.editEntity(entityIDs[i], propertiesOrFn(entityIDs[i]));
|
Entities.editEntity(entityIDs[i], propertiesOrFn(entityIDs[i]));
|
||||||
} else {
|
} else {
|
||||||
|
@ -318,11 +319,11 @@ stepOrient.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.overlay = new StayInFrontOverlay("model", {
|
// this.overlay = new StayInFrontOverlay("model", {
|
||||||
url: "http://hifi-content.s3.amazonaws.com/alan/dev/Prompt-Cards/welcome.fbx?11",
|
// url: "http://hifi-content.s3.amazonaws.com/alan/dev/Prompt-Cards/welcome.fbx?11",
|
||||||
ignoreRayIntersection: true,
|
// ignoreRayIntersection: true,
|
||||||
visible: false
|
// visible: false
|
||||||
}, 1.5, { x: 0, y: 0.3, z: 0 });
|
// }, 1.5, { x: 0, y: 0.3, z: 0 });
|
||||||
|
|
||||||
// Spawn content set
|
// Spawn content set
|
||||||
//spawnWithTag(HandsAboveHeadData, defaultTransform, tag);
|
//spawnWithTag(HandsAboveHeadData, defaultTransform, tag);
|
||||||
|
@ -952,105 +953,115 @@ function hideEntitiesWithTag(tag) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var STEPS;
|
|
||||||
|
|
||||||
var currentStepNum = -1;
|
TutorialManager = function() {
|
||||||
var currentStep = null;
|
var STEPS;
|
||||||
function startTutorial() {
|
|
||||||
currentStepNum = -1;
|
|
||||||
currentStep = null;
|
|
||||||
STEPS = [
|
|
||||||
new stepDisableControllers("step0"),
|
|
||||||
new stepOrient("orient"),
|
|
||||||
//new stepWelcome("welcome"),
|
|
||||||
new stepRaiseAboveHead("raiseHands"),
|
|
||||||
new stepNearGrab("nearGrab"),
|
|
||||||
new stepFarGrab("farGrab"),
|
|
||||||
new stepEquip("equip"),
|
|
||||||
new stepTurnAround("turnAround"),
|
|
||||||
new stepTeleport("teleport"),
|
|
||||||
new stepFinish("finish"),
|
|
||||||
];
|
|
||||||
for (var i = 0; i < STEPS.length; ++i) {
|
|
||||||
STEPS[i].cleanup();
|
|
||||||
}
|
|
||||||
location = "/tutorial_begin";
|
|
||||||
//location = "/tutorial";
|
|
||||||
MyAvatar.shouldRenderLocally = false;
|
|
||||||
startNextStep();
|
|
||||||
}
|
|
||||||
|
|
||||||
function startNextStep() {
|
var currentStepNum = -1;
|
||||||
if (currentStep) {
|
var currentStep = null;
|
||||||
currentStep.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
++currentStepNum;
|
this.startTutorial = function() {
|
||||||
|
currentStepNum = -1;
|
||||||
if (currentStepNum >= STEPS.length) {
|
currentStep = null;
|
||||||
// Done
|
STEPS = [
|
||||||
print("DONE WITH TUTORIAL");
|
new stepDisableControllers("step0"),
|
||||||
|
new stepOrient("orient"),
|
||||||
|
//new stepWelcome("welcome"),
|
||||||
|
new stepRaiseAboveHead("raiseHands"),
|
||||||
|
new stepNearGrab("nearGrab"),
|
||||||
|
new stepFarGrab("farGrab"),
|
||||||
|
new stepEquip("equip"),
|
||||||
|
new stepTurnAround("turnAround"),
|
||||||
|
new stepTeleport("teleport"),
|
||||||
|
new stepFinish("finish"),
|
||||||
|
];
|
||||||
|
for (var i = 0; i < STEPS.length; ++i) {
|
||||||
|
STEPS[i].cleanup();
|
||||||
|
}
|
||||||
|
location = "/tutorial_begin";
|
||||||
|
//location = "/tutorial";
|
||||||
|
MyAvatar.shouldRenderLocally = false;
|
||||||
|
this.startNextStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startNextStep = function() {
|
||||||
|
if (currentStep) {
|
||||||
|
currentStep.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
++currentStepNum;
|
||||||
|
|
||||||
|
if (currentStepNum >= STEPS.length) {
|
||||||
|
// Done
|
||||||
|
print("DONE WITH TUTORIAL");
|
||||||
|
currentStepNum = -1;
|
||||||
|
currentStep = null;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
print("Starting step", currentStepNum);
|
||||||
|
currentStep = STEPS[currentStepNum];
|
||||||
|
currentStep.start(this.startNextStep);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
this.restartStep = function() {
|
||||||
|
if (currentStep) {
|
||||||
|
currentStep.cleanup();
|
||||||
|
currentStep.start(this.startNextStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stopTutorial = function() {
|
||||||
|
if (currentStep) {
|
||||||
|
currentStep.cleanup();
|
||||||
|
}
|
||||||
currentStepNum = -1;
|
currentStepNum = -1;
|
||||||
currentStep = null;
|
currentStep = null;
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
print("Starting step", currentStepNum);
|
|
||||||
currentStep = STEPS[currentStepNum];
|
|
||||||
currentStep.start(startNextStep);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function restartStep() {
|
|
||||||
if (currentStep) {
|
|
||||||
currentStep.cleanup();
|
|
||||||
currentStep.start(startNextStep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function skipTutorial() {
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopTutorial() {
|
|
||||||
if (currentStep) {
|
|
||||||
currentStep.cleanup();
|
|
||||||
}
|
|
||||||
currentStepNum = -1;
|
|
||||||
currentStep = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
startTutorial();
|
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
Script.scriptEnding.connect(function() {
|
||||||
Controller.enableMapping('handControllerPointer-click');
|
Controller.enableMapping('handControllerPointer-click');
|
||||||
});
|
});
|
||||||
Controller.disableMapping('handControllerPointer-click');
|
Controller.disableMapping('handControllerPointer-click');
|
||||||
|
|
||||||
//mapping.from([Controller.Standard.RY]).to(noop);
|
// var entityID = '{be3d10a3-262a-4827-b30c-ec025c4325dc}';
|
||||||
//{ "from": "Vive.LeftApplicationMenu", "to": "Standard.LeftSecondaryThumb" },
|
// var token = new OwnershipToken(Math.random() * 100000, entityID, {
|
||||||
//mapping.from([Controller.Standard.RY]).when("Controller.Application.Grounded").to(noop);
|
// onGainedOwnership: function(token) {
|
||||||
//mapping.from([Controller.Standard.RY]).when(Controller.Application.Grounded).to(noop);
|
// //Script.setTimeout(function() { token.destroy() }, 15000);
|
||||||
|
// Controller.keyReleaseEvent.connect(keyReleaseHandler);
|
||||||
|
// startTutorial();
|
||||||
|
// },
|
||||||
|
// onLostOwnership: function(token) {
|
||||||
|
// Controller.keyReleaseEvent.disconnect(keyReleaseHandler);
|
||||||
|
// stopTutorial();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
//tutorialManager = new TutorialManager();
|
||||||
Script.scriptEnding.connect(stopTutorial);
|
//tutorialManager.startTutorial();
|
||||||
|
//Controller.keyReleaseEvent.connect(keyReleaseHandler);
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
//token.destroy();
|
||||||
Controller.keyReleaseEvent.connect(function (event) {
|
//stopTutorial();
|
||||||
print(event.text);
|
|
||||||
if (event.text == ",") {
|
|
||||||
if (!startNextStep()) {
|
|
||||||
startTutorial();
|
|
||||||
}
|
|
||||||
} else if (event.text == "F11") {
|
|
||||||
restartStep();
|
|
||||||
} else if (event.text == "F10") {
|
|
||||||
MyAvatar.shouldRenderLocally = !MyAvatar.shouldRenderLocally;
|
|
||||||
} else if (event.text == "r") {
|
|
||||||
stopTutorial();
|
|
||||||
startTutorial();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// function keyReleaseHandler(event) {
|
||||||
|
// print(event.text);
|
||||||
|
// if (event.text == ",") {
|
||||||
|
// if (!tutorialManager.startNextStep()) {
|
||||||
|
// tutorialManager.startTutorial();
|
||||||
|
// }
|
||||||
|
// } else if (event.text == "F11") {
|
||||||
|
// tutorialManager.restartStep();
|
||||||
|
// } else if (event.text == "F10") {
|
||||||
|
// MyAvatar.shouldRenderLocally = !MyAvatar.shouldRenderLocally;
|
||||||
|
// } else if (event.text == "r") {
|
||||||
|
// tutorialManager.stopTutorial();
|
||||||
|
// tutorialManager.startTutorial();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
// Messages.sendLocalMessage('Controller-Display', JSON.stringify({
|
// Messages.sendLocalMessage('Controller-Display', JSON.stringify({
|
||||||
// name: "menu",
|
// name: "menu",
|
||||||
// visible: false,
|
// visible: false,
|
||||||
|
|
Loading…
Reference in a new issue