From d60d4d0755d77dd3045467dc3c380343b6952dba Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 9 Apr 2017 15:52:56 +1200 Subject: [PATCH] Auto-play recording at start-up --- scripts/system/playRecordingAC.js | 121 ++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/scripts/system/playRecordingAC.js b/scripts/system/playRecordingAC.js index a6c8c3b873..958a6d858c 100644 --- a/scripts/system/playRecordingAC.js +++ b/scripts/system/playRecordingAC.js @@ -36,14 +36,16 @@ TIMESTAMP_UPDATE_INTERVAL = 2000, // TODO: Final value. ENTITY_NAME = "Recording", ENTITY_DESCRIPTION = "Avatar recording to play back", - ENTITIY_POSITION = { x: -16382, y: -16382, z: -16382 }; // Near but not right on corner boundary. + 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. function onUpdateTimestamp() { userData.timestamp = Date.now(); Entities.editEntity(entityID, { userData: JSON.stringify(userData) }); + EntityViewer.queryOctree(); // Keep up to date ready for find(). } - function create(filename, scriptUUID) { + function create(filename, position, orientation, scriptUUID) { // Create a new persistence entity (even if already have one but that should never occur). var properties; @@ -53,6 +55,8 @@ userData = { recording: filename, + position: position, + orientation: orientation, scriptUUID: scriptUUID, timestamp: Date.now() }; @@ -67,12 +71,48 @@ }; entityID = Entities.addEntity(properties); + // TODO: Handle failure adding entity? updateTimestampTimer = Script.setInterval(onUpdateTimestamp, TIMESTAMP_UPDATE_INTERVAL); } - function find() { - // TODO + function find(scriptUUID) { + // Find a recording that isn't being played. + var isFound = false, + entityIDs, + index = 0, + properties; + + entityIDs = Entities.findEntities(ENTITIY_POSITION, ENTITY_SEARCH_DELTA.x); + if (entityIDs.length > 0) { + while (!isFound && index < entityIDs.length - 1) { + // Find recording that isn't being played. + index += 1; + properties = Entities.getEntityProperties(entityIDs[index], ["name", "userData"]); + if (properties.name === ENTITY_NAME) { + // TODO: Guard against userData being non-existent or corrupt. + userData = JSON.parse(properties.userData); + // TODO: Verify that 2 * TIMESTAMP_UPDATE_INTERVAL is sufficient w.r.t. EntityViewer.queryOctree(). + isFound = (Date.now() - userData.timestamp) > (2 * TIMESTAMP_UPDATE_INTERVAL); + } + } + } + + if (isFound) { + // Claim recording. + // TODO: Guard against another AC script claiming the same recording at the same time. + entityID = entityIDs[index]; + userData.scriptUUID = scriptUUID; + userData.timestamp = Date.now(); + Entities.editEntity(entityID, { userData: JSON.stringify(userData) }); + updateTimestampTimer = Script.setInterval(onUpdateTimestamp, TIMESTAMP_UPDATE_INTERVAL); + + // Return recording info to play. + return { recording: userData.recording, position: userData.position, orientation: userData.orientation }; + } + + EntityViewer.queryOctree(); // Update octree ready for next find() call. + return null; } function destroy() { @@ -86,32 +126,41 @@ } } + function setUp() { + // Set up EntityViewer so that can do Entities.findEntities(). + // Position and orientation set so that viewing entities only in corner of domain. + var entityViewerPosition = Vec3.sum(ENTITIY_POSITION, ENTITY_SEARCH_DELTA); + EntityViewer.setPosition(entityViewerPosition); + EntityViewer.setOrientation(Quat.lookAtSimple(entityViewerPosition, ENTITIY_POSITION)); + EntityViewer.queryOctree(); + } + + function tearDown() { + // Nothing to do. + } + return { create: create, find: find, - destroy: destroy + destroy: destroy, + setUp: setUp, + tearDown: tearDown }; - }()); Player = (function () { // Recording playback functions. var isPlayingRecording = false, - recordingFilename = ""; - - function play(recording, position, orientation) { - isPlayingRecording = true; - recordingFilename = recording; - - log("Play new recording " + recordingFilename); - - Entity.create(recordingFilename, scriptUUID); + recordingFilename = "", + autoPlayTimer = null, + AUTOPLAY_SEARCH_INTERVAL = 2000; // TODO: Final value. + function playRecording(recording, position, orientation) { Agent.isAvatar = true; Avatar.position = position; Avatar.orientation = orientation; - Recording.loadRecording(recordingFilename); + Recording.loadRecording(recording); Recording.setPlayFromCurrentLocation(true); Recording.setPlayerUseDisplayName(true); Recording.setPlayerUseHeadModel(false); @@ -123,8 +172,30 @@ Recording.startPlaying(); } + function play(recording, position, orientation) { + isPlayingRecording = true; + recordingFilename = recording; + + log("Play new recording " + recordingFilename); + + Entity.create(recordingFilename, position, orientation, scriptUUID); + playRecording(recordingFilename, position, orientation); + } + function autoPlay() { - // TODO: Automatically play a persisted recording, if any. + var recording; + + recording = Entity.find(scriptUUID); + if (recording) { + isPlayingRecording = true; + recordingFilename = recording.recording; + + log("Play persisted recording " + recordingFilename); + + playRecording(recording.recording, recording.position, recording.orientation); + } else { + autoPlayTimer = Script.setTimeout(autoPlay, AUTOPLAY_SEARCH_INTERVAL); // Try again soon. + } } function stop() { @@ -148,11 +219,15 @@ } function setUp() { - // Nothing to do. + Entity.setUp(); } function tearDown() { - // Nothing to do. + if (autoPlayTimer) { + Script.clearTimeout(autoPlayTimer); + autoPlayTimer = null; + } + Entity.tearDown(); } return { @@ -174,7 +249,7 @@ heartbeatTimer = Script.setTimeout(sendHeartbeat, HEARTBEAT_INTERVAL); } - function cancelHeartbeat() { + function stopHeartbeat() { if (heartbeatTimer) { Script.clearTimeout(heartbeatTimer); heartbeatTimer = null; @@ -195,7 +270,7 @@ break; case PLAYER_COMMAND_STOP: Player.stop(); - Player.autoPlay(); + Player.autoPlay(); // There may be another recording to play. sendHeartbeat(); break; } @@ -215,12 +290,12 @@ } function tearDown() { - cancelHeartbeat(); + stopHeartbeat(); + Player.stop(); Messages.messageReceived.disconnect(onMessageReceived); Messages.unsubscribe(HIFI_PLAYER_CHANNEL); - Player.stop(); Player.tearDown(); }