From 8bc5f866668ec797ec1e0a682eecec019fcdebb4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 19 Aug 2014 19:21:53 -0700 Subject: [PATCH 1/9] Add Audio Sphere menu option --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/Avatar.cpp | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c21b533695..a9fac1e32c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -390,6 +390,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderBoundingCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollideAsRagdoll); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::BlueAudioMeter, 0, true); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false); #ifdef HAVE_FACESHIFT diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7ef744e62e..a923babf57 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -342,6 +342,7 @@ namespace MenuOption { const QString AvatarsReceiveShadows = "Avatars Receive Shadows"; const QString Bandwidth = "Bandwidth Display"; const QString BandwidthDetails = "Bandwidth Details"; + const QString BlueAudioMeter = "Blue Sphere While Speaking"; const QString BuckyBalls = "Bucky Balls"; const QString CascadedShadows = "Cascaded"; const QString Chat = "Chat..."; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 41912afd09..b929d5b75e 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -368,7 +368,9 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { // quick check before falling into the code below: // (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m) const float MIN_VOICE_SPHERE_DISTANCE = 12.0f; - if (distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) { + if (Menu::getInstance()->isOptionChecked(MenuOption::BlueAudioMeter) + && distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) { + // render voice intensity sphere for avatars that are farther away const float MAX_SPHERE_ANGLE = 10.0f * RADIANS_PER_DEGREE; const float MIN_SPHERE_ANGLE = 1.0f * RADIANS_PER_DEGREE; From 3b7260c434178de44945ef95a8745a8c8da67cee Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 19 Aug 2014 19:22:11 -0700 Subject: [PATCH 2/9] Fix blue audio sphere not showing correctly --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b929d5b75e..165b218873 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -302,7 +302,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { return; } - glm::vec3 toTarget = cameraPosition - Application::getInstance()->getAvatar()->getPosition(); + glm::vec3 toTarget = cameraPosition - getPosition(); float distanceToTarget = glm::length(toTarget); { From 42de56381a76c376913733d056b0d72dbc829e70 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 19 Aug 2014 19:40:27 -0700 Subject: [PATCH 3/9] Update blue audio sphere name and angle to draw at --- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 2 +- interface/src/avatar/Avatar.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a9fac1e32c..d535bb9930 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -390,7 +390,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderHeadCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::RenderBoundingCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::CollideAsRagdoll); - addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::BlueAudioMeter, 0, true); + addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::BlueSpeechSphere, 0, true); addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::LookAtVectors, 0, false); #ifdef HAVE_FACESHIFT diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a923babf57..ca062e0a75 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -342,7 +342,7 @@ namespace MenuOption { const QString AvatarsReceiveShadows = "Avatars Receive Shadows"; const QString Bandwidth = "Bandwidth Display"; const QString BandwidthDetails = "Bandwidth Details"; - const QString BlueAudioMeter = "Blue Sphere While Speaking"; + const QString BlueSpeechSphere = "Blue Sphere While Speaking"; const QString BuckyBalls = "Bucky Balls"; const QString CascadedShadows = "Cascaded"; const QString Chat = "Chat..."; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 165b218873..f93813d56c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -368,12 +368,12 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { // quick check before falling into the code below: // (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m) const float MIN_VOICE_SPHERE_DISTANCE = 12.0f; - if (Menu::getInstance()->isOptionChecked(MenuOption::BlueAudioMeter) + if (Menu::getInstance()->isOptionChecked(MenuOption::BlueSpeechSphere) && distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) { // render voice intensity sphere for avatars that are farther away const float MAX_SPHERE_ANGLE = 10.0f * RADIANS_PER_DEGREE; - const float MIN_SPHERE_ANGLE = 1.0f * RADIANS_PER_DEGREE; + const float MIN_SPHERE_ANGLE = 0.5f * RADIANS_PER_DEGREE; const float MIN_SPHERE_SIZE = 0.01f; const float SPHERE_LOUDNESS_SCALING = 0.0005f; const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f }; From 3d940469de953a075d29e0630e2fca473bc07c10 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 19 Aug 2014 19:41:31 -0700 Subject: [PATCH 4/9] Increase display name drawing distance --- interface/src/avatar/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f93813d56c..615fda0710 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -394,7 +394,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { } } - const float DISPLAYNAME_DISTANCE = 10.0f; + const float DISPLAYNAME_DISTANCE = 20.0f; setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE); if (renderMode != NORMAL_RENDER_MODE || (isMyAvatar() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) { From e3ab6476cac848a554ca4fdf580e2a90b6191cb8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Aug 2014 15:21:18 -0700 Subject: [PATCH 5/9] Recorder.js first draft --- examples/Recorder.js | 148 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 examples/Recorder.js diff --git a/examples/Recorder.js b/examples/Recorder.js new file mode 100644 index 0000000000..51cdf06211 --- /dev/null +++ b/examples/Recorder.js @@ -0,0 +1,148 @@ +// +// Recorder.js +// examples +// +// Created by Clément Brisset on 8/20/14. +// Copyright 2014 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 +// + +Script.include("toolBars.js"); + +var recordingFile = "recording.rec"; + +var windowDimensions = Controller.getViewportDimensions(); +var TOOL_ICON_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/"; +var TOOL_WIDTH = 50; +var TOOL_HEIGHT = 50; +var ALPHA_ON = 1.0; +var ALPHA_OFF = 0.5; + +var toolBar = null; +var recordIcon; +var playIcon; +var saveIcon; +var loadIcon; +var loadLastIcon; +setupToolBar(); + +function setupToolBar() { + if (toolBar != null) { + print("Multiple calls to Recorder.js:setupToolBar()"); + return; + } + + toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); + + recordIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: TOOL_WIDTH, + height: TOOL_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, true, MyAvatar.isRecording()); + + playIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: TOOL_WIDTH, + height: TOOL_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false, false); + + saveIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: TOOL_WIDTH, + height: TOOL_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false, false); + + loadIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: TOOL_WIDTH, + height: TOOL_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false, false); + + loadLastIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "add-model-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: TOOL_WIDTH, + height: TOOL_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false, false); + + moveUI(); +} + +function moveUI() { + var relative = { x: 30, y: 90 }; + toolBar.move(relative.x, + windowDimensions.y - relative.y); +} + +function mousePressEvent(event) { + clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + + if (recordIcon === toolBar.clicked(clickedOverlay)) { + if (!MyAvatar.isRecording()) { + MyAvatar.startRecording(); + } else { + MyAvatar.stopRecording(); + } + } else if (playIcon === toolBar.clicked(clickedOverlay)) { + if (!MyAvatar.isRecording()) { + if (MyAvatar.isPlaying()) { + MyAvatar.stopPlaying(); + } else { + MyAvatar.startPlaying(); + } + } + } else if (saveIcon === toolBar.clicked(clickedOverlay)) { + recordingFile = Window.save("Save recording to file", ".", "*.rec"); + MyAvatar.saveRecording(recordingFile); + } else if (loadIcon === toolBar.clicked(clickedOverlay)) { + recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); + MyAvatar.loadRecording(recordingFile); + } else if (loadLastIcon === toolBar.clicked(clickedOverlay)) { + MyAvatar.loadLastRecording(); + } else { + + } +} + +function update() { + var newDimensions = Controller.getViewportDimensions(); + if (windowDimensions.x != newDimensions.x || + windowDimensions.y != newDimensions.y) { + windowDimensions = newDimensions; + moveUI(); + } +} + +function scriptEnding() { + if (MyAvatar.isRecording()) { + MyAvatar.stopRecording(); + } + if (MyAvatar.isPlaying()) { + MyAvatar.stopPlaying(); + } + toolBar.cleanup(); +} + +Controller.mousePressEvent.connect(mousePressEvent); +Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); + + + + From 4922592cfa86e197b8fbda0aca09fe2c19b0cc1b Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Aug 2014 15:21:33 -0700 Subject: [PATCH 6/9] Debug tweaks --- interface/src/Recorder.cpp | 15 ++++++++------- interface/src/avatar/MyAvatar.cpp | 1 + .../src/scripting/WindowScriptingInterface.cpp | 2 -- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index 52d183332d..1d2ad3f059 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -223,7 +223,7 @@ void Player::startPlaying() { _audioThread = new QThread(); _options.setPosition(_avatar->getPosition()); _options.setOrientation(_avatar->getOrientation()); - _injector.reset(new AudioInjector(_recording->getAudio(), _options)); + _injector.reset(new AudioInjector(_recording->getAudio(), _options), &QObject::deleteLater); _injector->moveToThread(_audioThread); _audioThread->start(); QMetaObject::invokeMethod(_injector.data(), "injectAudio", Qt::QueuedConnection); @@ -317,13 +317,13 @@ bool Player::computeCurrentFrame() { } void writeRecordingToFile(RecordingPointer recording, QString filename) { - qDebug() << "Writing recording to " << filename; + qDebug() << "Writing recording to " << filename << "."; QElapsedTimer timer; QFile file(filename); if (!file.open(QIODevice::WriteOnly)){ return; } - qDebug() << file.fileName(); + timer.start(); QDataStream fileStream(&file); @@ -443,20 +443,21 @@ void writeRecordingToFile(RecordingPointer recording, QString filename) { fileStream << recording->_audio->getByteArray(); - qDebug() << "Wrote " << file.size() << " bytes in " << timer.elapsed(); + qDebug() << "Wrote " << file.size() << " bytes in " << timer.elapsed() << " ms."; } RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filename) { - qDebug() << "Reading recording from " << filename; + qDebug() << "Reading recording from " << filename << "."; if (!recording) { recording.reset(new Recording()); } + QElapsedTimer timer; QFile file(filename); if (!file.open(QIODevice::ReadOnly)){ return recording; } - + timer.start(); QDataStream fileStream(&file); fileStream >> recording->_timestamps; @@ -557,7 +558,7 @@ RecordingPointer readRecordingFromFile(RecordingPointer recording, QString filen recording->addAudioPacket(audioArray); - qDebug() << "Read " << file.size() << " bytes"; + qDebug() << "Read " << file.size() << " bytes in " << timer.elapsed() << " ms."; return recording; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b3805d15c7..41c0f3032b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -528,6 +528,7 @@ void MyAvatar::startRecording() { } Application::getInstance()->getAudio()->setRecorder(_recorder); _recorder->startRecording(); + } void MyAvatar::stopRecording() { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 7cf37b4424..7a85fc7117 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -295,7 +295,6 @@ QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QS // filename if the directory is valid. QString path = ""; QFileInfo fileInfo = QFileInfo(directory); - qDebug() << "File: " << directory << fileInfo.isFile(); if (fileInfo.isDir()) { fileInfo.setFile(directory, "__HIFI_INVALID_FILE__"); path = fileInfo.filePath(); @@ -303,7 +302,6 @@ QScriptValue WindowScriptingInterface::showBrowse(const QString& title, const QS QFileDialog fileDialog(Application::getInstance()->getWindow(), title, path, nameFilter); fileDialog.setAcceptMode(acceptMode); - qDebug() << "Opening!"; QUrl fileUrl(directory); if (acceptMode == QFileDialog::AcceptSave) { fileDialog.setFileMode(QFileDialog::Directory); From 8f9a32231838a47e88feb820fe7b24854429ea3e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Aug 2014 18:04:17 -0700 Subject: [PATCH 7/9] Recording UI --- examples/Recorder.js | 56 ++++++++++++++++++------------------------- examples/toolBars.js | 57 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/examples/Recorder.js b/examples/Recorder.js index 51cdf06211..d691b64481 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -15,17 +15,16 @@ var recordingFile = "recording.rec"; var windowDimensions = Controller.getViewportDimensions(); var TOOL_ICON_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/"; -var TOOL_WIDTH = 50; -var TOOL_HEIGHT = 50; var ALPHA_ON = 1.0; -var ALPHA_OFF = 0.5; +var ALPHA_OFF = 0.7; +Tool.IMAGE_WIDTH *= 0.7; +Tool.IMAGE_HEIGHT *= 0.7; var toolBar = null; var recordIcon; var playIcon; var saveIcon; var loadIcon; -var loadLastIcon; setupToolBar(); function setupToolBar() { @@ -35,48 +34,36 @@ function setupToolBar() { } toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); + toolBar.setBack({ red: 128, green: 128, blue: 128 }, 0.8); recordIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: TOOL_WIDTH, - height: TOOL_HEIGHT, - alpha: ALPHA_ON, + imageURL: "file:/Users/clement/Downloads/svg/camera8.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (MyAvatar.isRecording()) ? ALPHA_ON : ALPHA_OFF, visible: true - }, true, MyAvatar.isRecording()); + }, false); playIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: TOOL_WIDTH, - height: TOOL_HEIGHT, + imageURL: "file:/Users/clement/Downloads/svg/media23.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, visible: true }, false, false); saveIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: TOOL_WIDTH, - height: TOOL_HEIGHT, + imageURL: "file:/Users/clement/Downloads/svg/save15.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, visible: true }, false, false); loadIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: TOOL_WIDTH, - height: TOOL_HEIGHT, - alpha: ALPHA_ON, - visible: true - }, false, false); - - loadLastIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "add-model-tool.svg", - subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: TOOL_WIDTH, - height: TOOL_HEIGHT, + imageURL: "file:/Users/clement/Downloads/svg/upload2.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, visible: true }, false, false); @@ -96,8 +83,13 @@ function mousePressEvent(event) { if (recordIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { MyAvatar.startRecording(); + toolBar.setAlpha(ALPHA_ON, recordIcon); + toolBar.setBack({ red: 128, green: 0, blue: 0 }, 0.9); } else { MyAvatar.stopRecording(); + MyAvatar.loadLastRecording(); + toolBar.setAlpha(ALPHA_OFF, recordIcon); + toolBar.setBack({ red: 128, green: 128, blue: 128 }, 0.8); } } else if (playIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { @@ -113,8 +105,6 @@ function mousePressEvent(event) { } else if (loadIcon === toolBar.clicked(clickedOverlay)) { recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); MyAvatar.loadRecording(recordingFile); - } else if (loadLastIcon === toolBar.clicked(clickedOverlay)) { - MyAvatar.loadLastRecording(); } else { } diff --git a/examples/toolBars.js b/examples/toolBars.js index ede3b80062..064ae372fd 100644 --- a/examples/toolBars.js +++ b/examples/toolBars.js @@ -132,20 +132,34 @@ ToolBar = function(x, y, direction) { this.y = y; this.width = 0; this.height = 0; - + this.back = this.back = Overlays.addOverlay("text", { + backgroundColor: { red: 255, green: 255, blue: 255 }, + x: this.x, + y: this.y, + width: this.width, + height: this.height, + alpha: 1.0, + visible: false + }); this.addTool = function(properties, selectable, selected) { if (direction == ToolBar.HORIZONTAL) { properties.x = this.x + this.width; properties.y = this.y; this.width += properties.width + ToolBar.SPACING; - this.height += Math.max(properties.height, this.height); + this.height = Math.max(properties.height, this.height); } else { properties.x = this.x; properties.y = this.y + this.height; this.width = Math.max(properties.width, this.width); this.height += properties.height + ToolBar.SPACING; } + if (this.back != null) { + Overlays.editOverlay(this.back, { + width: this.width + 2 * ToolBar.SPACING, + height: this.height + 2 * ToolBar.SPACING + }); + } this.tools[this.tools.length] = new Tool(properties, selectable, selected); return ((this.tools.length) - 1); @@ -159,18 +173,48 @@ ToolBar = function(x, y, direction) { for(var tool in this.tools) { this.tools[tool].move(this.tools[tool].x() + dx, this.tools[tool].y() + dy); } + if (this.back != null) { + Overlays.editOverlay(this.back, { + x: x - ToolBar.SPACING, + y: y - ToolBar.SPACING + }); + } } - this.setAlpha = function(alpha) { - for(var tool in this.tools) { + this.setAlpha = function(alpha, tool) { + if(typeof(tool) === 'undefined') { + for(var tool in this.tools) { + this.tools[tool].setAlpha(alpha); + } + if (this.back != null) { + Overlays.editOverlay(this.back, { alpha: alpha}); + } + } else { this.tools[tool].setAlpha(alpha); } } + + this.setBack = function(color, alpha) { + if (color == null) { + Overlays.editOverlay(this.back, { + visible: false + }); + } else { + Overlays.editOverlay(this.back, { + visible: true, + backgroundColor: color, + alpha: alpha + }) + } + } this.show = function(doShow) { for(var tool in this.tools) { this.tools[tool].show(doShow); } + if (this.back != null) { + Overlays.editOverlay(this.back, { visible: doShow}); + } } this.clicked = function(clickedOverlay) { @@ -200,6 +244,11 @@ ToolBar = function(x, y, direction) { delete this.tools[tool]; } + if (this.back != null) { + Overlays.deleteOverlay(this.back); + this.back = null; + } + this.tools = []; this.x = x; this.y = y; From 56f7f88d75ebbddec2ab4ffcbf00c56af8b37030 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Aug 2014 18:17:38 -0700 Subject: [PATCH 8/9] Changed icon URLs to the right ones --- examples/Recorder.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/Recorder.js b/examples/Recorder.js index d691b64481..e37b19b268 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -14,9 +14,11 @@ Script.include("toolBars.js"); var recordingFile = "recording.rec"; var windowDimensions = Controller.getViewportDimensions(); -var TOOL_ICON_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/"; +var TOOL_ICON_URL = "http://s3-us-west-1.amazonaws.com/highfidelity-public/images/tools/"; var ALPHA_ON = 1.0; var ALPHA_OFF = 0.7; +var COLOR_ON = { red: 128, green: 0, blue: 0 }; +var COLOR_OFF = { red: 128, green: 128, blue: 128 }; Tool.IMAGE_WIDTH *= 0.7; Tool.IMAGE_HEIGHT *= 0.7; @@ -34,18 +36,18 @@ function setupToolBar() { } toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); - toolBar.setBack({ red: 128, green: 128, blue: 128 }, 0.8); + toolBar.setBack(COLOR_OFF, ALPHA_OFF); recordIcon = toolBar.addTool({ - imageURL: "file:/Users/clement/Downloads/svg/camera8.svg", + imageURL: TOOL_ICON_URL + "record.svg", width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT, - alpha: (MyAvatar.isRecording()) ? ALPHA_ON : ALPHA_OFF, + alpha: ALPHA_ON, visible: true }, false); playIcon = toolBar.addTool({ - imageURL: "file:/Users/clement/Downloads/svg/media23.svg", + imageURL: TOOL_ICON_URL + "play.svg", width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, @@ -53,7 +55,7 @@ function setupToolBar() { }, false, false); saveIcon = toolBar.addTool({ - imageURL: "file:/Users/clement/Downloads/svg/save15.svg", + imageURL: TOOL_ICON_URL + "save.svg", width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, @@ -61,7 +63,7 @@ function setupToolBar() { }, false, false); loadIcon = toolBar.addTool({ - imageURL: "file:/Users/clement/Downloads/svg/upload2.svg", + imageURL: TOOL_ICON_URL + "load.svg", width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT, alpha: ALPHA_ON, @@ -83,13 +85,11 @@ function mousePressEvent(event) { if (recordIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { MyAvatar.startRecording(); - toolBar.setAlpha(ALPHA_ON, recordIcon); - toolBar.setBack({ red: 128, green: 0, blue: 0 }, 0.9); + toolBar.setBack(COLOR_ON, ALPHA_ON); } else { MyAvatar.stopRecording(); MyAvatar.loadLastRecording(); - toolBar.setAlpha(ALPHA_OFF, recordIcon); - toolBar.setBack({ red: 128, green: 128, blue: 128 }, 0.8); + toolBar.setBack(COLOR_OFF, ALPHA_OFF); } } else if (playIcon === toolBar.clicked(clickedOverlay)) { if (!MyAvatar.isRecording()) { From 022109a249d5458cb8fefbf9c708eddb9438bcdb Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 20 Aug 2014 19:36:56 -0700 Subject: [PATCH 9/9] Added timestamps to the scripted UI --- examples/Recorder.js | 81 ++++++++++++++++++++++++++++--- interface/src/Recorder.cpp | 5 ++ interface/src/Recorder.h | 2 + interface/src/avatar/MyAvatar.cpp | 56 +++++++++++++++++++++ interface/src/avatar/MyAvatar.h | 3 ++ 5 files changed, 139 insertions(+), 8 deletions(-) diff --git a/examples/Recorder.js b/examples/Recorder.js index e37b19b268..9a4375ab4f 100644 --- a/examples/Recorder.js +++ b/examples/Recorder.js @@ -29,6 +29,9 @@ var saveIcon; var loadIcon; setupToolBar(); +var timer = null; +setupTimer(); + function setupToolBar() { if (toolBar != null) { print("Multiple calls to Recorder.js:setupToolBar()"); @@ -69,14 +72,68 @@ function setupToolBar() { alpha: ALPHA_ON, visible: true }, false, false); - - moveUI(); } - + +function setupTimer() { + timer = Overlays.addOverlay("text", { + font: { size: 20 }, + text: (0.00).toFixed(3), + backgroundColor: COLOR_OFF, + x: 0, y: 0, + width: 100, + height: 100, + alpha: 1.0, + visible: true + }); +} + +function updateTimer() { + var text = ""; + if (MyAvatar.isRecording()) { + text = formatTime(MyAvatar.recorderElapsed()) + } else { + text = formatTime(MyAvatar.playerElapsed()) + " / " + + formatTime(MyAvatar.playerLength()); + } + + Overlays.editOverlay(timer, { + text: text + }) +} + +function formatTime(time) { + var MIN_PER_HOUR = 60; + var SEC_PER_MIN = 60; + var MSEC_PER_SEC = 1000; + + var hours = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR)); + time -= hours * (MSEC_PER_SEC * SEC_PER_MIN * MIN_PER_HOUR); + + var minutes = Math.floor(time / (MSEC_PER_SEC * SEC_PER_MIN)); + time -= minutes * (MSEC_PER_SEC * SEC_PER_MIN); + + var seconds = Math.floor(time / MSEC_PER_SEC); + seconds = time / MSEC_PER_SEC; + + var text = ""; + text += (hours > 0) ? hours + ":" : + ""; + text += (minutes > 0) ? ((minutes < 10 && text != "") ? "0" : "") + minutes + ":" : + ""; + text += ((seconds < 10 && text != "") ? "0" : "") + seconds.toFixed(3); + return text; +} + function moveUI() { var relative = { x: 30, y: 90 }; toolBar.move(relative.x, windowDimensions.y - relative.y); + Overlays.editOverlay(timer, { + x: relative.x - 10, + y: windowDimensions.y - relative.y - 35, + width: 0, + height: 0 + }); } function mousePressEvent(event) { @@ -100,11 +157,15 @@ function mousePressEvent(event) { } } } else if (saveIcon === toolBar.clicked(clickedOverlay)) { - recordingFile = Window.save("Save recording to file", ".", "*.rec"); - MyAvatar.saveRecording(recordingFile); + if (!MyAvatar.isRecording()) { + recordingFile = Window.save("Save recording to file", ".", "*.rec"); + MyAvatar.saveRecording(recordingFile); + } } else if (loadIcon === toolBar.clicked(clickedOverlay)) { - recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); - MyAvatar.loadRecording(recordingFile); + if (!MyAvatar.isRecording()) { + recordingFile = Window.browse("Load recorcding from file", ".", "*.rec"); + MyAvatar.loadRecording(recordingFile); + } } else { } @@ -117,6 +178,8 @@ function update() { windowDimensions = newDimensions; moveUI(); } + + updateTimer(); } function scriptEnding() { @@ -127,12 +190,14 @@ function scriptEnding() { MyAvatar.stopPlaying(); } toolBar.cleanup(); + Overlays.deleteOverlay(timer); } Controller.mousePressEvent.connect(mousePressEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); - +// Should be called last to put everything into position +moveUI(); diff --git a/interface/src/Recorder.cpp b/interface/src/Recorder.cpp index 1d2ad3f059..fb5c92c849 100644 --- a/interface/src/Recorder.cpp +++ b/interface/src/Recorder.cpp @@ -317,6 +317,11 @@ bool Player::computeCurrentFrame() { } void writeRecordingToFile(RecordingPointer recording, QString filename) { + if (!recording || recording->getFrameNumber() < 1) { + qDebug() << "Can't save empty recording"; + return; + } + qDebug() << "Writing recording to " << filename << "."; QElapsedTimer timer; QFile file(filename); diff --git a/interface/src/Recorder.h b/interface/src/Recorder.h index 9f7eb66ec6..2670d78365 100644 --- a/interface/src/Recorder.h +++ b/interface/src/Recorder.h @@ -137,6 +137,8 @@ public: bool isPlaying() const; qint64 elapsed() const; + RecordingPointer getRecording() const { return _recording; } + // Those should only be called if isPlaying() returns true glm::quat getHeadRotation(); float getLeanSideways(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 41c0f3032b..1d271d5f40 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -509,6 +509,9 @@ bool MyAvatar::setJointReferential(int id, int jointIndex) { } bool MyAvatar::isRecording() { + if (!_recorder) { + return false; + } if (QThread::currentThread() != thread()) { bool result; QMetaObject::invokeMethod(this, "isRecording", Qt::BlockingQueuedConnection, @@ -518,6 +521,19 @@ bool MyAvatar::isRecording() { return _recorder && _recorder->isRecording(); } +qint64 MyAvatar::recorderElapsed() { + if (!_recorder) { + return 0; + } + if (QThread::currentThread() != thread()) { + qint64 result; + QMetaObject::invokeMethod(this, "recorderElapsed", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(qint64, result)); + return result; + } + return _recorder->elapsed(); +} + void MyAvatar::startRecording() { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "startRecording", Qt::BlockingQueuedConnection); @@ -532,6 +548,9 @@ void MyAvatar::startRecording() { } void MyAvatar::stopRecording() { + if (!_recorder) { + return; + } if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "stopRecording", Qt::BlockingQueuedConnection); return; @@ -542,6 +561,10 @@ void MyAvatar::stopRecording() { } void MyAvatar::saveRecording(QString filename) { + if (!_recorder) { + qDebug() << "There is no recording to save"; + return; + } if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "saveRecording", Qt::BlockingQueuedConnection, Q_ARG(QString, filename)); @@ -553,6 +576,9 @@ void MyAvatar::saveRecording(QString filename) { } bool MyAvatar::isPlaying() { + if (!_player) { + return false; + } if (QThread::currentThread() != thread()) { bool result; QMetaObject::invokeMethod(this, "isPlaying", Qt::BlockingQueuedConnection, @@ -562,6 +588,32 @@ bool MyAvatar::isPlaying() { return _player && _player->isPlaying(); } +qint64 MyAvatar::playerElapsed() { + if (!_player) { + return 0; + } + if (QThread::currentThread() != thread()) { + qint64 result; + QMetaObject::invokeMethod(this, "playerElapsed", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(qint64, result)); + return result; + } + return _player->elapsed(); +} + +qint64 MyAvatar::playerLength() { + if (!_player) { + return 0; + } + if (QThread::currentThread() != thread()) { + qint64 result; + QMetaObject::invokeMethod(this, "playerLength", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(qint64, result)); + return result; + } + return _player->getRecording()->getLength(); +} + void MyAvatar::loadRecording(QString filename) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "loadRecording", Qt::BlockingQueuedConnection, @@ -581,6 +633,7 @@ void MyAvatar::loadLastRecording() { return; } if (!_recorder) { + qDebug() << "There is no recording to load"; return; } if (!_player) { @@ -604,6 +657,9 @@ void MyAvatar::startPlaying() { } void MyAvatar::stopPlaying() { + if (!_player) { + return; + } if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "stopPlaying", Qt::BlockingQueuedConnection); return; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0af105725b..b7abe96afa 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -162,11 +162,14 @@ public slots: bool setJointReferential(int id, int jointIndex); bool isRecording(); + qint64 recorderElapsed(); void startRecording(); void stopRecording(); void saveRecording(QString filename); bool isPlaying(); + qint64 playerElapsed(); + qint64 playerLength(); void loadRecording(QString filename); void loadLastRecording(); void startPlaying();