236 lines
8.9 KiB
JavaScript
236 lines
8.9 KiB
JavaScript
'use strict';
|
|
// smartBoardZoneServer.js
|
|
//
|
|
// Milad Nazeri and Zach Fox 10/30/2019
|
|
// Copyright 2019 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
|
|
(function() {
|
|
var DEBUG = false;
|
|
|
|
// BOARD UI
|
|
// send a message to all registered clients on the state of the board
|
|
var WHITEBOARD_STATUS_ICON = Script.resolvePath("../resources/models/button-state-whiteboard.fbx");
|
|
var SCREENSHARE_STATUS_ICON = Script.resolvePath("../resources/models/button-state-screen-share.fbx");
|
|
function updateCurrentBoardState(id, args) {
|
|
// If there's an active presenter, only the active presenter can update the current board state.
|
|
if (_this.activePresenterUUID !== "" && _this.activePresenterUUID !== args[1]) {
|
|
return;
|
|
}
|
|
|
|
_this.currentBoardState = args[0];
|
|
_this.activePresenterUUID = args[1];
|
|
|
|
// Reset the active presenter UUID if the new current board state is "whiteboard".
|
|
if (_this.currentBoardState === "whiteboard") {
|
|
_this.activePresenterUUID = "";
|
|
}
|
|
|
|
var smartboardStatusIcon = _this.currentBoardState === "screenshare" ? SCREENSHARE_STATUS_ICON : WHITEBOARD_STATUS_ICON;
|
|
Entities.editEntity(_this.smartboardStatusIconID, {modelURL: smartboardStatusIcon});
|
|
|
|
if (DEBUG) {
|
|
console.log("args:", args, "smartBoardZoneServer.js: " + _this.entityID + ": `updateCurrentBoardState()`." +
|
|
"\n`_this.currentBoardState`: " + _this.currentBoardState +
|
|
"\n`_this.activePresenterUUID`: " + _this.activePresenterUUID +
|
|
"\nparticipants:" + JSON.stringify(_this.participants, null, 4));
|
|
}
|
|
|
|
var participants = Object.keys(_this.participants);
|
|
for (var i = 0; i < participants.length; i++) {
|
|
Entities.callEntityClientMethod(participants[i], _this.entityID,
|
|
"receiveBoardState", [_this.currentBoardState, _this.activePresenterUUID]);
|
|
}
|
|
setVisibilityOfSmartboardWhiteboardComponents();
|
|
}
|
|
|
|
// The following Smartboard Whiteboard components should be visible/invisible:
|
|
// 1. Whiteboard palette circle background
|
|
// 2. Whiteboard palette circles
|
|
// 3. Whiteboard "reset" button
|
|
// 4. Whiteboard polylines
|
|
var HIDE_POLYLINES_IN_SCREENSHARE_MODE = false;
|
|
function setVisibilityOfSmartboardWhiteboardComponents() {
|
|
var smartboardChildrenIDs = Entities.getChildrenIDs(_this.smartboard);
|
|
var entityNamesToShowOrHide = ["reset", "palette", "erase"];
|
|
if (HIDE_POLYLINES_IN_SCREENSHARE_MODE) {
|
|
entityNamesToShowOrHide.push("polyline");
|
|
}
|
|
smartboardChildrenIDs.forEach(function(smartboardPiece) {
|
|
var entityName = Entities.getEntityProperties(smartboardPiece, 'name').name;
|
|
if (!entityName) {
|
|
return;
|
|
}
|
|
|
|
var lowerCaseName = entityName.toLowerCase();
|
|
var foundWhiteBoardComponent = false;
|
|
for (var i = 0; i < entityNamesToShowOrHide.length; i++) {
|
|
if (lowerCaseName.indexOf(entityNamesToShowOrHide[i]) === -1) {
|
|
continue;
|
|
} else {
|
|
foundWhiteBoardComponent = true;
|
|
break;
|
|
}
|
|
}
|
|
if (foundWhiteBoardComponent) {
|
|
Entities.editEntity(smartboardPiece, {visible: _this.currentBoardState === "whiteboard"});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
// PARTICIPANTS
|
|
// When a client first enters the zone, register them and send them the state of the board
|
|
function registerParticipant(id, args) {
|
|
var UUID = args[0];
|
|
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `registerParticipant()`." +
|
|
"\n`UUID`: " + UUID + "\n`_this.currentBoardState`: " +
|
|
_this.currentBoardState + "\n`_this.activePresenterUUID`: " + _this.activePresenterUUID);
|
|
}
|
|
|
|
_this.participants[UUID] = {
|
|
displayName: AvatarList.getAvatar(UUID).displayName
|
|
};
|
|
|
|
// Eventually, we'll want to hook up the `Avatar.displayNameChanged()` signal to a handler that
|
|
// changes the Display Name of the broadcaster that is shown to viewers on the Smartboard.
|
|
// That's too advanced for now, so we'll not worry about it yet.
|
|
|
|
Entities.callEntityClientMethod(UUID, _this.entityID, "receiveBoardState",
|
|
[_this.currentBoardState, _this.activePresenterUUID]);
|
|
}
|
|
|
|
|
|
// Remove a particpant from the screenshare. If they are the presenter, then end screenshare for everyone
|
|
function removeParticipant(id, args) {
|
|
var UUID = args[0];
|
|
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `removeParticipant()`." +
|
|
"\n`UUID`: " + UUID +
|
|
"\n`_this.currentBoardState`: " + _this.currentBoardState +
|
|
"\n`_this.activePresenterUUID`: " + _this.activePresenterUUID);
|
|
}
|
|
|
|
if (_this.participants[UUID]) {
|
|
delete _this.participants[UUID];
|
|
|
|
if (_this.activePresenterUUID === UUID) {
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `removeParticipant()`." +
|
|
"The removed participant was the active presenter. Updating current board state to 'smartboard'...");
|
|
}
|
|
|
|
// `updateCurrentBoardState()` will reset `_this.activePresenterUUID` to "".
|
|
updateCurrentBoardState(_this.entityID, ["whiteboard", _this.activePresenterUUID]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// When the ESS detects that an avatar has been removed from the participants group, call removeParticipant().
|
|
function onAvatarRemovedEvent(UUID) {
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `onAvatarRemovedEvent()`." +
|
|
"\n`UUID`: " + UUID);
|
|
}
|
|
|
|
if (UUID in _this.participants) {
|
|
removeParticipant(_this.entityID, [UUID]);
|
|
}
|
|
}
|
|
|
|
|
|
// ENTITY SIGNALS
|
|
// check to see if this is a whiteboardOnly zone
|
|
// connect the avatar removed event
|
|
var signalsConnected = false;
|
|
function preload(entityID) {
|
|
_this.entityID = entityID;
|
|
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `preload()`.");
|
|
}
|
|
|
|
var props = Entities.getEntityProperties(entityID, ["userData", "parentID"]);
|
|
var userData = props.userData;
|
|
_this.smartboard = props.parentID;
|
|
var parsedData = {};
|
|
try {
|
|
parsedData = JSON.parse(userData);
|
|
_this.whiteboardOnlyZone = parsedData.whiteboardOnlyZone;
|
|
} catch (e) {
|
|
console.log("Error reading userData in smartBoardZoneServer.js: " + e);
|
|
}
|
|
|
|
if (_this.whiteboardOnlyZone) {
|
|
updateCurrentBoardState(_this.entityID, ["whiteboard", ""]);
|
|
}
|
|
|
|
if (!signalsConnected) {
|
|
AvatarList.avatarRemovedEvent.connect(onAvatarRemovedEvent);
|
|
signalsConnected = true;
|
|
}
|
|
|
|
var smartboardChildrenIDS = Entities.getChildrenIDs(_this.smartboard);
|
|
for (var i = 0; i < smartboardChildrenIDS.length; i++) {
|
|
var childID = smartboardChildrenIDS[i];
|
|
var name = Entities.getEntityProperties(childID, "name").name;
|
|
if (name === "Smartboard Status Icon") {
|
|
_this.smartboardStatusIconID = childID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// update the board back to whiteboard only
|
|
// might be unnessary, but maybe help clear left over local entities
|
|
function unload() {
|
|
if (DEBUG) {
|
|
console.log("smartBoardZoneServer.js: " + _this.entityID + ": `unload()`.");
|
|
}
|
|
|
|
updateCurrentBoardState(_this.entityID, ["whiteboard", ""]);
|
|
|
|
if (signalsConnected) {
|
|
AvatarList.avatarRemovedEvent.disconnect(onAvatarRemovedEvent);
|
|
}
|
|
signalsConnected = false;
|
|
}
|
|
|
|
|
|
// SMARTBOARD OBJECT
|
|
var _this;
|
|
function SmartboardZoneServer() {
|
|
_this = this;
|
|
this.entityID;
|
|
this.smartboard;
|
|
this.activePresenterUUID = "";
|
|
this.currentBoardState = "whiteboard";
|
|
this.participants = {};
|
|
this.whiteboardOnlyZone = false;
|
|
this.smartboardStatusIconID;
|
|
this.remotelyCallable = [
|
|
"updateCurrentBoardState",
|
|
"registerParticipant",
|
|
"removeParticipant"
|
|
];
|
|
}
|
|
|
|
|
|
SmartboardZoneServer.prototype = {
|
|
preload: preload,
|
|
unload: unload,
|
|
updateCurrentBoardState: updateCurrentBoardState,
|
|
registerParticipant: registerParticipant,
|
|
removeParticipant: removeParticipant
|
|
};
|
|
|
|
|
|
return new SmartboardZoneServer();
|
|
});
|