Merge pull request #69 from AleziaKurdis/FixRecordApp

Fix the "Record" app
This commit is contained in:
ksuprynowicz 2024-05-24 02:26:10 +02:00 committed by GitHub
commit 1d9292d83a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 206 additions and 211 deletions

View file

@ -1,4 +0,0 @@
# Record App
The master source for this app is in the Vircadia repo at:
https://github.com/kasenvr/project-athena/tree/master/unpublishedScripts/marketplace/record

View file

@ -1,10 +1,10 @@
"use strict";
//
// record.js
//
// Created by David Rowe on 5 Apr 2017.
// Created by David Rowe on April 5th, 2017.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2024, Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -289,5 +289,9 @@ function onBodyLoaded() {
elFinishOnOpenLabel = document.getElementById("finish-on-open-label");
var currentPath = window.location.protocol + "//" + window.location.host + window.location.pathname;
var ROOT = currentPath.replace("html/record.html", ""); //<=== Could be useful
document.getElementById("aCscriptUrl").value = ROOT + "playRecordingAC.js";
signalBodyLoaded();
}

View file

@ -1,9 +1,10 @@
<!--
// record.html
//
// Created by David Rowe on 5 Apr 2017.
// Created by David Rowe on April 5th, 2017.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
// Copyright 2024, Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -38,13 +39,13 @@
<tbody id="instructions" class="hidden">
<tr>
<td colspan="2">
<p>This app lets you record and play back multiple instances of your avatar in your Sandbox.</p>
<p>This app lets you record and play back multiple instances of your avatar in your domain.</p>
<h1>Setup Instructions</h1>
<p>In your sandbox domain:</p>
<p>In your domain server:</p>
<ul>
<li>Right-click the Vircadia Sandbox icon in your system tray and click &ldquo;Settings&rdquo;.</li>
<li>Right-click the domain server icon in your system tray and click &ldquo;Settings&rdquo;.</li>
<li>In the &ldquo;Scripts&rdquo; section add a new row and paste in this script URL:<br />
<input type="text" value="https://cdn.vircadia.com/community-apps/applications/record/playRecordingAC.js" readonly />
<input type="text" id= "aCscriptUrl" value="" readonly />
</li>
<li>Set the number of recordings you&rsquo;d like to run at a given time in the &ldquo;Instances&rdquo; slot.</li>
<li>Click &ldquo;Save and restart&rdquo;.</li>

View file

@ -1,10 +1,10 @@
"use strict";
//
// playRecordingAC.js
//
// Created by David Rowe on 7 Apr 2017.
// Created by David Rowe on April 7th, 2017.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2024, Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -24,7 +24,6 @@
AUTOPLAY_SEARCH_INTERVAL = 5000,
AUTOPLAY_ERROR_INTERVAL = 30000, // 30s
scriptUUID,
Entity,
Player;
@ -39,8 +38,8 @@
updateTimestampTimer = null,
ENTITY_NAME = "Recording",
ENTITY_DESCRIPTION = "Avatar recording to play back",
ENTITIY_POSITION = { x: -16382, y: -16382, z: -16382 }, // Near but not right on domain corner.
ENTITY_SEARCH_DELTA = { x: 1, y: 1, z: 1 }, // Allow for position imprecision.
ENTITIY_POSITION = { "x": -16382, "y": -16382, "z": -16382 }, // Near but not right on domain corner.
ENTITY_SEARCH_DELTA = { "x": 1, "y": 1, "z": 1 }, // Allow for position imprecision.
SEARCH_IDLE = 0,
SEARCH_SEARCHING = 1,
SEARCH_CLAIMING = 2,
@ -50,7 +49,6 @@
otherPlayersPlayingCounts,
pauseCount,
isDestroyLater = false,
destroy;
function onUpdateTimestamp() {
@ -60,7 +58,7 @@
}
userData.timestamp = Date.now();
Entities.editEntity(entityID, { userData: JSON.stringify(userData) });
Entities.editEntity(entityID, { "userData": JSON.stringify(userData) });
EntityViewer.queryOctree(); // Keep up to date ready for find().
}
@ -104,20 +102,20 @@
searchState = SEARCH_IDLE;
userData = {
recording: filename,
position: position,
orientation: orientation,
scriptUUID: scriptUUID,
timestamp: Date.now()
"recording": filename,
"position": position,
"orientation": orientation,
"scriptUUID": scriptUUID,
"timestamp": Date.now()
};
properties = {
type: "Box",
name: ENTITY_NAME,
description: ENTITY_DESCRIPTION,
position: ENTITIY_POSITION,
visible: false,
userData: JSON.stringify(userData)
"type": "Box",
"name": ENTITY_NAME,
"description": ENTITY_DESCRIPTION,
"position": ENTITIY_POSITION,
"visible": false,
"userData": JSON.stringify(userData)
};
entityID = Entities.addEntity(properties);
@ -162,75 +160,74 @@
result = null;
switch (searchState) {
case SEARCH_IDLE:
log("Start searching");
otherPlayersPlaying = [];
otherPlayersPlayingCounts = [];
Messages.subscribe(HIFI_RECORDER_CHANNEL);
Messages.messageReceived.connect(onMessageReceived);
searchState = SEARCH_SEARCHING;
break;
case SEARCH_SEARCHING:
// Find an entity that isn't being played or claimed.
entityIDs = Entities.findEntities(ENTITIY_POSITION, ENTITY_SEARCH_DELTA.x);
if (entityIDs.length > 0) {
index = -1;
while (!found && index < entityIDs.length - 1) {
index += 1;
if (otherPlayersPlaying.indexOf(entityIDs[index]) === -1) {
properties = Entities.getEntityProperties(entityIDs[index], ["name", "userData"]);
userData = JSON.parse(properties.userData);
found = properties.name === ENTITY_NAME && userData.recording !== undefined;
}
}
}
// Claim entity if found.
if (found) {
log("Claim entity " + entityIDs[index]);
entityID = entityIDs[index];
searchState = SEARCH_CLAIMING;
}
break;
case SEARCH_CLAIMING:
// How many other players are claiming (or playing) this entity?
index = otherPlayersPlaying.indexOf(entityID);
numberOfClaims = index !== -1 ? otherPlayersPlayingCounts[index] : 0;
// Have found an entity to play if no other players are also claiming it.
if (numberOfClaims === 0) {
log("Complete claim " + entityID);
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(HIFI_RECORDER_CHANNEL);
searchState = SEARCH_IDLE;
userData.scriptUUID = scriptUUID;
userData.timestamp = Date.now();
Entities.editEntity(entityID, { userData: JSON.stringify(userData) });
updateTimestampTimer = Script.setInterval(onUpdateTimestamp, TIMESTAMP_UPDATE_INTERVAL);
result = { recording: userData.recording, position: userData.position, orientation: userData.orientation };
break;
}
// Otherwise back off for a bit before resuming search.
log("Release claim " + entityID + " and pause searching");
entityID = null;
pauseCount = randomInt(0, otherPlayersPlaying.length);
searchState = SEARCH_PAUSING;
break;
case SEARCH_PAUSING:
// Resume searching if have paused long enough.
pauseCount -= 1;
if (pauseCount < 0) {
log("Resume searching");
case SEARCH_IDLE:
log("Start searching");
otherPlayersPlaying = [];
otherPlayersPlayingCounts = [];
Messages.subscribe(HIFI_RECORDER_CHANNEL);
Messages.messageReceived.connect(onMessageReceived);
searchState = SEARCH_SEARCHING;
}
break;
break;
case SEARCH_SEARCHING:
// Find an entity that isn't being played or claimed.
entityIDs = Entities.findEntities(ENTITIY_POSITION, ENTITY_SEARCH_DELTA.x);
if (entityIDs.length > 0) {
index = -1;
while (!found && index < entityIDs.length - 1) {
index += 1;
if (otherPlayersPlaying.indexOf(entityIDs[index]) === -1) {
properties = Entities.getEntityProperties(entityIDs[index], ["name", "userData"]);
userData = JSON.parse(properties.userData);
found = properties.name === ENTITY_NAME && userData.recording !== undefined;
}
}
}
// Claim entity if found.
if (found) {
log("Claim entity " + entityIDs[index]);
entityID = entityIDs[index];
searchState = SEARCH_CLAIMING;
}
break;
case SEARCH_CLAIMING:
// How many other players are claiming (or playing) this entity?
index = otherPlayersPlaying.indexOf(entityID);
numberOfClaims = index !== -1 ? otherPlayersPlayingCounts[index] : 0;
// Have found an entity to play if no other players are also claiming it.
if (numberOfClaims === 0) {
log("Complete claim " + entityID);
Messages.messageReceived.disconnect(onMessageReceived);
Messages.unsubscribe(HIFI_RECORDER_CHANNEL);
searchState = SEARCH_IDLE;
userData.scriptUUID = scriptUUID;
userData.timestamp = Date.now();
Entities.editEntity(entityID, { userData: JSON.stringify(userData) });
updateTimestampTimer = Script.setInterval(onUpdateTimestamp, TIMESTAMP_UPDATE_INTERVAL);
result = { recording: userData.recording, position: userData.position, orientation: userData.orientation };
break;
}
// Otherwise back off for a bit before resuming search.
log("Release claim " + entityID + " and pause searching");
entityID = null;
pauseCount = randomInt(0, otherPlayersPlaying.length);
searchState = SEARCH_PAUSING;
break;
case SEARCH_PAUSING:
// Resume searching if have paused long enough.
pauseCount -= 1;
if (pauseCount < 0) {
log("Resume searching");
otherPlayersPlaying = [];
otherPlayersPlayingCounts = [];
searchState = SEARCH_SEARCHING;
}
break;
}
EntityViewer.queryOctree();
@ -269,13 +266,13 @@
}
return {
id: id,
create: create,
find: find,
destroy: destroy,
destroyLater: destroyLater,
setUp: setUp,
tearDown: tearDown
"id": id,
"create": create,
"find": find,
"destroy": destroy,
"destroyLater": destroyLater,
"setUp": setUp,
"tearDown": tearDown
};
}());
@ -285,16 +282,15 @@
isPlayingRecording = false,
recordingFilename = "",
autoPlayTimer = null,
autoPlay,
playRecording;
function error(message) {
// Send error message to user.
Messages.sendMessage(HIFI_RECORDER_CHANNEL, JSON.stringify({
command: RECORDER_COMMAND_ERROR,
user: userID,
message: message
"command": RECORDER_COMMAND_ERROR,
"user": userID,
"message": message
}));
}
@ -422,21 +418,21 @@
}
return {
autoPlay: autoPlay,
play: play,
stop: stop,
isPlaying: isPlaying,
recording: recording,
setUp: setUp,
tearDown: tearDown
"autoPlay": autoPlay,
"play": play,
"stop": stop,
"isPlaying": isPlaying,
"recording": recording,
"setUp": setUp,
"tearDown": tearDown
};
}());
function sendHeartbeat() {
Messages.sendMessage(HIFI_RECORDER_CHANNEL, JSON.stringify({
playing: Player.isPlaying(),
recording: Player.recording(),
entity: Entity.id()
"playing": Player.isPlaying(),
"recording": Player.recording(),
"entity": Entity.id()
}));
}

View file

@ -1,10 +1,10 @@
"use strict";
//
// record.js
//
// Created by David Rowe on 5 Apr 2017.
// Created by David Rowe on April 5th, 2017.
// Copyright 2017 High Fidelity, Inc.
// Copyright 2024, Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -20,12 +20,10 @@
tablet,
button,
isConnected,
RecordingIndicator,
Recorder,
Player,
Dialog,
SCRIPT_STARTUP_DELAY = 3000; // 3s
function log(message) {
@ -58,35 +56,37 @@
CAMERA_JOINT_INDEX = -7;
if (HMD.active) {
// 3D overlay attached to avatar.
hmdOverlay = Overlays.addOverlay("text3d", {
text: recordingText,
dimensions: { x: 3 * HMD_FONT_SIZE, y: HMD_FONT_SIZE },
parentID: MyAvatar.sessionUUID,
parentJointIndex: CAMERA_JOINT_INDEX,
localPosition: { x: 0.95, y: 0.95, z: -2.0 },
color: { red: 255, green: 0, blue: 0 },
alpha: 0.9,
lineHeight: HMD_FONT_SIZE,
backgroundAlpha: 0,
ignoreRayIntersection: true,
isFacingAvatar: true,
drawInFront: true,
visible: true
});
// Local Entity attached to avatar.
hmdOverlay = Entities.addEntity({
"type": "Text",
"text": recordingText,
"dimensions": { "x": 4 * HMD_FONT_SIZE, "y": 2 * HMD_FONT_SIZE },
"parentID": MyAvatar.sessionUUID,
"parentJointIndex": CAMERA_JOINT_INDEX,
"localPosition": { "x": 0.35, "y": 0.25, "z": -0.9 },
"textColor": { "red": 255, "green": 0, "blue": 0 },
"textAlpha": 0.9,
"lineHeight": HMD_FONT_SIZE,
"backgroundAlpha": 0,
"ignorePickIntersection": true,
"billboardMode": "full",
"renderLayer": "front",
"visible": true,
"unlit": true
}, "local");
} else {
// 2D overlay on desktop.
desktopOverlay = Overlays.addOverlay("text", {
text: recordingText,
width: 3 * DESKTOP_FONT_SIZE,
height: DESKTOP_FONT_SIZE,
x: screenSize.x - 4 * DESKTOP_FONT_SIZE,
y: DESKTOP_FONT_SIZE,
font: { size: DESKTOP_FONT_SIZE },
color: { red: 255, green: 8, blue: 8 },
alpha: 1.0,
backgroundAlpha: 0,
visible: true
"text": recordingText,
"width": 3 * DESKTOP_FONT_SIZE,
"height": DESKTOP_FONT_SIZE,
"x": screenSize.x - 4 * DESKTOP_FONT_SIZE,
"y": DESKTOP_FONT_SIZE,
"font": { "size": DESKTOP_FONT_SIZE },
"color": { "red": 255, "green": 8, "blue": 8 },
"alpha": 1.0,
"backgroundAlpha": 0,
"visible": true
});
}
}
@ -96,13 +96,13 @@
Overlays.deleteOverlay(desktopOverlay);
}
if (hmdOverlay) {
Overlays.deleteOverlay(hmdOverlay);
Entities.deleteEntity(hmdOverlay);
}
}
return {
show: show,
hide: hide
"show": show,
"hide": hide
};
}());
@ -116,11 +116,9 @@
startPosition,
startOrientation,
play,
countdownTimer,
countdownSeconds,
COUNTDOWN_SECONDS = 3,
tickSound,
startRecordingSound,
finishRecordingSound,
@ -261,16 +259,16 @@
}
return {
startCountdown: startCountdown,
cancelCountdown: cancelCountdown,
startRecording: startRecording,
cancelRecording: cancelRecording,
finishRecording: finishRecording,
isIdle: isIdle,
isCountingDown: isCountingDown,
isRecording: isRecording,
setUp: setUp,
tearDown: tearDown
"startCountdown": startCountdown,
"cancelCountdown": cancelCountdown,
"startRecording": startRecording,
"cancelRecording": cancelRecording,
"finishRecording": finishRecording,
"isIdle": isIdle,
"isCountingDown": isCountingDown,
"isRecording": isRecording,
"setUp": setUp,
"tearDown": tearDown
};
}());
@ -333,18 +331,18 @@
}
Messages.sendMessage(HIFI_PLAYER_CHANNEL, JSON.stringify({
player: playerIDs[index],
command: PLAYER_COMMAND_PLAY,
recording: recording,
position: position,
orientation: orientation
"player": playerIDs[index],
"command": PLAYER_COMMAND_PLAY,
"recording": recording,
"position": position,
"orientation": orientation
}));
}
function stopPlayingRecording(playerID) {
Messages.sendMessage(HIFI_PLAYER_CHANNEL, JSON.stringify({
player: playerID,
command: PLAYER_COMMAND_STOP
"player": playerID,
"command": PLAYER_COMMAND_STOP
}));
}
@ -399,12 +397,12 @@
}
return {
playRecording: playRecording,
stopPlayingRecording: stopPlayingRecording,
numberOfPlayers: numberOfPlayers,
reset: reset,
setUp: setUp,
tearDown: tearDown
"playRecording": playRecording,
"stopPlayingRecording": stopPlayingRecording,
"numberOfPlayers": numberOfPlayers,
"reset": reset,
"setUp": setUp,
"tearDown": tearDown
};
}());
@ -432,18 +430,18 @@
function updateRecordingStatus(isRecording) {
if (isRecording) {
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: START_RECORDING_ACTION
"type": EVENT_BRIDGE_TYPE,
"action": START_RECORDING_ACTION
}));
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: SET_COUNTDOWN_NUMBER_ACTION,
value: countdownNumber
"type": EVENT_BRIDGE_TYPE,
"action": SET_COUNTDOWN_NUMBER_ACTION,
"value": countdownNumber
}));
} else {
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: STOP_RECORDING_ACTION
"type": EVENT_BRIDGE_TYPE,
"action": STOP_RECORDING_ACTION
}));
}
}
@ -456,30 +454,30 @@
for (i = 0, length = playerIsPlayings.length; i < length; i += 1) {
if (playerIsPlayings[i]) {
recordingsBeingPlayed.push({
filename: playerRecordings[i],
playerID: playerIDs[i]
"filename": playerRecordings[i],
"playerID": playerIDs[i]
});
}
}
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: RECORDINGS_BEING_PLAYED_ACTION,
value: JSON.stringify(recordingsBeingPlayed)
"type": EVENT_BRIDGE_TYPE,
"action": RECORDINGS_BEING_PLAYED_ACTION,
"value": JSON.stringify(recordingsBeingPlayed)
}));
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: NUMBER_OF_PLAYERS_ACTION,
value: playerIsPlayings.length
"type": EVENT_BRIDGE_TYPE,
"action": NUMBER_OF_PLAYERS_ACTION,
"value": playerIsPlayings.length
}));
}
function setCountdownNumber(number) {
countdownNumber = number;
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: SET_COUNTDOWN_NUMBER_ACTION,
value: countdownNumber
"type": EVENT_BRIDGE_TYPE,
"action": SET_COUNTDOWN_NUMBER_ACTION,
"value": countdownNumber
}));
}
@ -506,19 +504,19 @@
case BODY_LOADED_ACTION:
// Dialog's ready; initialize its state.
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: USING_TOOLBAR_ACTION,
value: isUsingToolbar()
"type": EVENT_BRIDGE_TYPE,
"action": USING_TOOLBAR_ACTION,
"value": isUsingToolbar()
}));
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: FINISH_ON_OPEN_ACTION,
value: isFinishOnOpen
"type": EVENT_BRIDGE_TYPE,
"action": FINISH_ON_OPEN_ACTION,
"value": isFinishOnOpen
}));
tablet.emitScriptEvent(JSON.stringify({
type: EVENT_BRIDGE_TYPE,
action: NUMBER_OF_PLAYERS_ACTION,
value: Player.numberOfPlayers()
"type": EVENT_BRIDGE_TYPE,
"action": NUMBER_OF_PLAYERS_ACTION,
"value": Player.numberOfPlayers()
}));
updateRecordingStatus(!Recorder.isIdle());
UserActivityLogger.logAction("record_open_dialog", logDetails());
@ -566,12 +564,12 @@
}
return {
updatePlayerDetails: updatePlayerDetails,
updateRecordingStatus: updateRecordingStatus,
setCountdownNumber: setCountdownNumber,
finishOnOpen: finishOnOpen,
setUp: setUp,
tearDown: tearDown
"updatePlayerDetails": updatePlayerDetails,
"updateRecordingStatus": updateRecordingStatus,
"setCountdownNumber": setCountdownNumber,
"finishOnOpen": finishOnOpen,
"setUp": setUp,
"tearDown": tearDown
};
}());
@ -639,10 +637,10 @@
// Tablet/toolbar button.
button = tablet.addButton({
icon: APP_ICON_INACTIVE,
activeIcon: APP_ICON_ACTIVE,
text: APP_NAME,
isActive: false
"icon": APP_ICON_INACTIVE,
"activeIcon": APP_ICON_ACTIVE,
"text": APP_NAME,
"isActive": false
});
if (button) {
button.clicked.connect(onButtonClicked);