200 lines
6.9 KiB
JavaScript
200 lines
6.9 KiB
JavaScript
/* eslint-disable no-magic-numbers */
|
|
//
|
|
// spinabbleWheelServer.js
|
|
//
|
|
// Created by Zach Fox on 2019-04-19
|
|
// Copyright High Fidelity 2019
|
|
//
|
|
// Licensed under the Apache 2.0 License
|
|
// See accompanying license file or http://apache.org/
|
|
//
|
|
/* global console */
|
|
|
|
(function() {
|
|
var that;
|
|
var CHECK_SPINNING_TIMEOUT_MS = 100;
|
|
var RAD_PER_DEG = Math.PI / 180;
|
|
var SMALL_Z_ANGULAR_VELOCITY_RAD_PER_SEC = 15 * RAD_PER_DEG;
|
|
var MIN_ANGULAR_VELOCITY_RAD_PER_SEC = 40;
|
|
var MAX_ANGULAR_VELOCITY_RAD_PER_SEC = 100;
|
|
|
|
// Called upon a timer callback. Checks if the wheel is spinning slowly enough to set
|
|
// the `wheelIsSpinning` flag back to `false`. If it's not spinning slowly enough,
|
|
// restarts the timeout that'll call this function upon expiry.
|
|
function checkSpinning() {
|
|
var props = Entities.getEntityProperties(that.entityID, ["angularVelocity"]);
|
|
if (Math.abs(props.angularVelocity.z) < SMALL_Z_ANGULAR_VELOCITY_RAD_PER_SEC) {
|
|
Entities.editEntity(that.entityID, {
|
|
"angularVelocity": [0, 0, 0]
|
|
});
|
|
|
|
that.wheelIsSpinning = false;
|
|
return;
|
|
}
|
|
|
|
that.checkSpinningTimeout = Script.setTimeout(checkSpinning, CHECK_SPINNING_TIMEOUT_MS);
|
|
}
|
|
|
|
|
|
// Populates the spinnable wheel with some text entities and separators according to the attached
|
|
// entity's User Data.
|
|
var TEXT_ENTITY_STATIC_PROPS = {
|
|
"type": "Text",
|
|
"dimensions": {
|
|
"x": 0.6000000238418579,
|
|
"y": 0.20000000298023224,
|
|
"z": 0.009999999776482582
|
|
},
|
|
"canCastShadow": false,
|
|
"grab": {
|
|
"grabbable": false
|
|
},
|
|
"damping": 0,
|
|
"angularDamping": 0,
|
|
"collisionless": true,
|
|
"ignoreForCollisions": true,
|
|
"lineHeight": 0.06,
|
|
"registrationPoint": [1, 0.5, 0.5],
|
|
"triggerable": false
|
|
};
|
|
var SPINNER_RADIUS_M = 1.25;
|
|
var TEXT_ENTITY_PADDING_M = 0.2;
|
|
var BORDER_ENTITY_STATIC_PROPS = {
|
|
"type": "Box",
|
|
"dimensions": {
|
|
"x": SPINNER_RADIUS_M,
|
|
"y": 0.05,
|
|
"z": 0.05
|
|
},
|
|
"color": [0, 0, 0],
|
|
"canCastShadow": false,
|
|
"grab": {
|
|
"grabbable": false
|
|
},
|
|
"damping": 0,
|
|
"angularDamping": 0,
|
|
"collisionless": true,
|
|
"ignoreForCollisions": true,
|
|
"lineHeight": 0.06,
|
|
"registrationPoint": [1, 0.5, 0.5],
|
|
"triggerable": false
|
|
};
|
|
function populateWheel(data) {
|
|
var numTextEntities = data.length;
|
|
var angleBetweenTextEntities = 360 / numTextEntities;
|
|
var currentAngle = 0;
|
|
|
|
for (var i = 0; i < numTextEntities; i++) {
|
|
var props = TEXT_ENTITY_STATIC_PROPS;
|
|
props.text = data[i];
|
|
props.parentID = that.entityID;
|
|
props.localRotation = Quat.fromVec3Degrees([-90, -currentAngle, 0]);
|
|
var x = Math.cos(currentAngle * RAD_PER_DEG) * (SPINNER_RADIUS_M - TEXT_ENTITY_PADDING_M);
|
|
var z = Math.sin(currentAngle * RAD_PER_DEG) * (SPINNER_RADIUS_M - TEXT_ENTITY_PADDING_M);
|
|
props.localPosition = [x, 0.0375, z];
|
|
|
|
that.rezzedEntities.push(Entities.addEntity(props));
|
|
|
|
currentAngle -= angleBetweenTextEntities / 2;
|
|
|
|
props = BORDER_ENTITY_STATIC_PROPS;
|
|
props.parentID = that.entityID;
|
|
props.localRotation = Quat.fromVec3Degrees([-90, -currentAngle, 0]);
|
|
x = Math.cos(currentAngle * RAD_PER_DEG) * (SPINNER_RADIUS_M);
|
|
z = Math.sin(currentAngle * RAD_PER_DEG) * (SPINNER_RADIUS_M);
|
|
props.localPosition = [x, 0.0375, z];
|
|
|
|
that.rezzedEntities.push(Entities.addEntity(props));
|
|
|
|
currentAngle -= angleBetweenTextEntities / 2;
|
|
}
|
|
}
|
|
|
|
|
|
// It's a constructor for Spinnable Wheel Server.
|
|
var SpinnableWheelServer = function() {
|
|
that = this;
|
|
that.entityID = false;
|
|
that.wheelIsSpinning = false;
|
|
that.checkSpinningTimeout = false;
|
|
that.rezzedEntities = [];
|
|
};
|
|
|
|
|
|
SpinnableWheelServer.prototype = {
|
|
remotelyCallable: ['spinWheel'],
|
|
|
|
|
|
// On script preload, save a reference to this entity ID and initialize some variables.
|
|
// Also, populate the spinnable wheel with some text entities and separators if the
|
|
// user data is valid.
|
|
preload: function(entityID) {
|
|
that.entityID = entityID;
|
|
that.wheelIsSpinning = false;
|
|
that.checkSpinningTimeout = false;
|
|
|
|
var properties = Entities.getEntityProperties(that.entityID, ["userData"]);
|
|
|
|
var userData;
|
|
|
|
try {
|
|
userData = JSON.parse(properties.userData);
|
|
} catch (e) {
|
|
console.error("Error parsing userData: ", e);
|
|
}
|
|
|
|
if (userData) {
|
|
if (userData.wheelText && userData.wheelText.length > 0) {
|
|
populateWheel(userData.wheelText);
|
|
} else {
|
|
console.log("Please specify the `wheelText` array inside this entity's `userData`!");
|
|
return;
|
|
}
|
|
} else {
|
|
console.log("Please specify this entity's `userData`! See README.md for instructions.");
|
|
return;
|
|
}
|
|
},
|
|
|
|
|
|
// On script unload, clear the timeout (if one exists), and delete all entities that we've rezzed.
|
|
// Also make the wheel stop.
|
|
unload: function() {
|
|
if (that.checkSpinningTimeout) {
|
|
Script.clearTimeout(that.checkSpinningTimeout);
|
|
that.checkSpinningTimeout = false;
|
|
}
|
|
|
|
for (var i = 0; i < that.rezzedEntities.length; i++) {
|
|
Entities.deleteEntity(that.rezzedEntities[i]);
|
|
}
|
|
|
|
Entities.editEntity(that.entityID, {
|
|
"angularVelocity": [0, 0, 0]
|
|
});
|
|
},
|
|
|
|
|
|
// Spin the wheel if it isn't already spinning! Wheeee!
|
|
// Also start the timer used to determine when the wheel has stopped spinning.
|
|
spinWheel: function(thisID, params) {
|
|
if (!that.wheelIsSpinning) {
|
|
that.wheelIsSpinning = true;
|
|
|
|
var rotation = Entities.getEntityProperties(that.entityID, ["rotation"]).rotation;
|
|
var front = Quat.getUp(rotation);
|
|
var angularVelocityAmplitude = Math.random() * MAX_ANGULAR_VELOCITY_RAD_PER_SEC + MIN_ANGULAR_VELOCITY_RAD_PER_SEC;
|
|
|
|
// -1 so that the wheel spins the "right" way
|
|
Entities.editEntity(that.entityID, {
|
|
"angularVelocity": Vec3.multiply(front, -1 * angularVelocityAmplitude)
|
|
});
|
|
|
|
that.checkSpinningTimeout = Script.setTimeout(checkSpinning, CHECK_SPINNING_TIMEOUT_MS);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
return new SpinnableWheelServer();
|
|
});
|