From 872ec21822712c615524e26b05d534dfbf150103 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Sep 2014 12:55:15 -0700 Subject: [PATCH 1/4] Added removeLastTool() to toolBar.js --- examples/toolBars.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/toolBars.js b/examples/toolBars.js index 064ae372fd..092ab5992e 100644 --- a/examples/toolBars.js +++ b/examples/toolBars.js @@ -127,7 +127,7 @@ Tool.IMAGE_HEIGHT = 50; Tool.IMAGE_WIDTH = 50; ToolBar = function(x, y, direction) { - this.tools = []; + this.tools = new Array(); this.x = x; this.y = y; this.width = 0; @@ -161,9 +161,25 @@ ToolBar = function(x, y, direction) { }); } - this.tools[this.tools.length] = new Tool(properties, selectable, selected); + this.tools.push(new Tool(properties, selectable, selected)); return ((this.tools.length) - 1); } + + this.removeLastTool = function() { + this.tools.pop().cleanup(); + + if (direction == ToolBar.HORIZONTAL) { + this.width -= Tool.IMAGE_WIDTH + ToolBar.SPACING; + } else { + this.height -= Tool.IMAGE_HEIGHT + ToolBar.SPACING; + } + if (this.back != null) { + Overlays.editOverlay(this.back, { + width: this.width + 2 * ToolBar.SPACING, + height: this.height + 2 * ToolBar.SPACING + }); + } + } this.move = function(x, y) { var dx = x - this.x; From a1e6d9e7a1697c787c7b81a878fc3a587ebb1b88 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Sep 2014 12:56:12 -0700 Subject: [PATCH 2/4] Protections against null pointers --- libraries/avatars/src/AvatarData.cpp | 8 ++++++-- libraries/script-engine/src/ScriptEngine.cpp | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 17c5d6c259..264d8ac580 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -649,11 +649,15 @@ void AvatarData::startPlaying() { } void AvatarData::setPlayFromCurrentLocation(bool playFromCurrentLocation) { - _player->setPlayFromCurrentLocation(playFromCurrentLocation); + if (_player) { + _player->setPlayFromCurrentLocation(playFromCurrentLocation); + } } void AvatarData::setPlayerLoop(bool loop) { - _player->setLoop(loop); + if (_player) { + _player->setLoop(loop); + } } void AvatarData::play() { diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2891055b65..a042cd6953 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -186,6 +186,13 @@ void ScriptEngine::setIsAvatar(bool isAvatar) { _avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS); _avatarBillboardTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS); } + + if (!_isAvatar) { + delete _avatarIdentityTimer; + _avatarIdentityTimer = NULL; + delete _avatarBillboardTimer; + _avatarBillboardTimer = NULL; + } } void ScriptEngine::setAvatarData(AvatarData* avatarData, const QString& objectName) { From 61467f7f3d3adf9a990635572100d821cc8bccf7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Sep 2014 12:56:51 -0700 Subject: [PATCH 3/4] Added ControlledAC script --- examples/ControlledAC.js | 153 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 examples/ControlledAC.js diff --git a/examples/ControlledAC.js b/examples/ControlledAC.js new file mode 100644 index 0000000000..84a6c36082 --- /dev/null +++ b/examples/ControlledAC.js @@ -0,0 +1,153 @@ +// +// ControlledAC.js +// examples +// +// Created by Clément Brisset on 8/28/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 +// + +// Set the following variables to the values needed +var filename = "http://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/bartender.rec"; +var playFromCurrentLocation = true; + +// ID of the agent. Two agents can't have the same ID. +var id = 0; + +// Set head and skeleton models +Avatar.faceModelURL = "http://public.highfidelity.io/models/heads/EvilPhilip_v7.fst"; +Avatar.skeletonModelURL = "http://public.highfidelity.io/models/skeletons/Philip_Carl_Body_A-Pose.fst"; +// Set position/orientation/scale here if playFromCurrentLocation is true +Avatar.position = { x:1, y: 1, z: 1 }; +Avatar.orientation = Quat.fromPitchYawRollDegrees(0, 0, 0); +Avatar.scale = 1.0; + +// Those variables MUST be common to every scripts +var controlVoxelSize = 0.25; +var controlVoxelPosition = { x: 2000 , y: 0, z: 0 }; + +// Script. DO NOT MODIFY BEYOND THIS LINE. +var DO_NOTHING = 0; +var PLAY = 1; +var PLAY_LOOP = 2; +var STOP = 3; +var SHOW = 4; +var HIDE = 5; + +var COLORS = []; +COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; +COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; +COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; +COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; +COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; + +controlVoxelPosition.x += id * controlVoxelSize; + +Avatar.setPlayFromCurrentLocation(playFromCurrentLocation); + +Avatar.loadRecording(filename); + +function setupVoxelViewer() { + var voxelViewerOffset = 10; + var voxelViewerPosition = JSON.parse(JSON.stringify(controlVoxelPosition)); + voxelViewerPosition.x -= voxelViewerOffset; + var voxelViewerOrientation = Quat.fromPitchYawRollDegrees(0, -90, 0); + + VoxelViewer.setPosition(voxelViewerPosition); + VoxelViewer.setOrientation(voxelViewerOrientation); + VoxelViewer.queryOctree(); +} + +function getAction(controlVoxel) { + if (controlVoxel.x != controlVoxelPosition.x || + controlVoxel.y != controlVoxelPosition.y || + controlVoxel.z != controlVoxelPosition.z || + controlVoxel.s != controlVoxelSize) { + return DO_NOTHING; + } + + for (i in COLORS) { + if (controlVoxel.red === COLORS[i].red && + controlVoxel.green === COLORS[i].green && + controlVoxel.blue === COLORS[i].blue) { + Voxels.eraseVoxel(controlVoxelPosition.x, + controlVoxelPosition.y, + controlVoxelPosition.z, + controlVoxelSize); + return parseInt(i); + } + } + + return DO_NOTHING; +} + +count = 300; // This is necessary to wait for the audio mixer to connect +function update(event) { + VoxelViewer.queryOctree(); + if (count > 0) { + count--; + return; + } + + var controlVoxel = Voxels.getVoxelAt(controlVoxelPosition.x, + controlVoxelPosition.y, + controlVoxelPosition.z, + controlVoxelSize); + var action = getAction(controlVoxel); + + switch(action) { + case PLAY: + print("Play"); + if (!Agent.isAvatar) { + Agent.isAvatar = true; + } + if (!Avatar.isPlaying()) { + Avatar.startPlaying(); + } + Avatar.setPlayerLoop(false); + break; + case PLAY_LOOP: + print("Play loop"); + if (!Agent.isAvatar) { + Agent.isAvatar = true; + } + if (!Avatar.isPlaying()) { + Avatar.startPlaying(); + } + Avatar.setPlayerLoop(true); + break; + case STOP: + print("Stop"); + if (Avatar.isPlaying()) { + Avatar.stopPlaying(); + } + break; + case SHOW: + print("Show"); + if (!Agent.isAvatar) { + Agent.isAvatar = true; + } + break; + case HIDE: + print("Hide"); + if (Avatar.isPlaying()) { + Avatar.stopPlaying(); + } + Agent.isAvatar = false; + break; + case DO_NOTHING: + break; + default: + print("Unknown action: " + action); + break; + } + + if (Avatar.isPlaying()) { + Avatar.play(); + } +} + +Script.update.connect(update); +setupVoxelViewer(); \ No newline at end of file From 049e0d763def02d66e48f33032a73b163af57095 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 2 Sep 2014 12:57:19 -0700 Subject: [PATCH 4/4] Added ControlACs script --- examples/ControlACs.js | 216 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 examples/ControlACs.js diff --git a/examples/ControlACs.js b/examples/ControlACs.js new file mode 100644 index 0000000000..43eb3290a4 --- /dev/null +++ b/examples/ControlACs.js @@ -0,0 +1,216 @@ +// +// ControlACs.js +// examples +// +// Created by Clément Brisset on 8/28/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 +// + +// Set the following variables to the right value +var NUM_AC = 3; // This is the number of AC. Their ID need to be unique and between 0 (included) and NUM_AC (excluded) +var NAMES = new Array("Arnold", "Jeff"); // ACs names ordered by IDs (Default name is "ACx", x = ID + 1)) + +// Those variables MUST be common to every scripts +var controlVoxelSize = 0.25; +var controlVoxelPosition = { x: 2000 , y: 0, z: 0 }; + +// Script. DO NOT MODIFY BEYOND THIS LINE. +Script.include("toolBars.js"); + +var DO_NOTHING = 0; +var PLAY = 1; +var PLAY_LOOP = 2; +var STOP = 3; +var SHOW = 4; +var HIDE = 5; + +var COLORS = []; +COLORS[PLAY] = { red: PLAY, green: 0, blue: 0 }; +COLORS[PLAY_LOOP] = { red: PLAY_LOOP, green: 0, blue: 0 }; +COLORS[STOP] = { red: STOP, green: 0, blue: 0 }; +COLORS[SHOW] = { red: SHOW, green: 0, blue: 0 }; +COLORS[HIDE] = { red: HIDE, green: 0, blue: 0 }; + + + +var windowDimensions = Controller.getViewportDimensions(); +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_TOOL_BAR = { red: 128, green: 128, blue: 128 }; +var COLOR_MASTER = { red: 200, green: 200, blue: 200 }; +var TEXT_HEIGHT = 10; + +var toolBars = new Array(); +var nameOverlays = new Array(); +var onOffIcon = new Array(); +var playIcon = new Array(); +var playLoopIcon = new Array(); +var stopIcon = new Array(); +setupToolBars(); + +function setupToolBars() { + if (toolBars.length > 0) { + print("Multiple calls to Recorder.js:setupToolBars()"); + return; + } + + for (i = 0; i <= NUM_AC; i++) { + toolBars.push(new ToolBar(0, 0, ToolBar.HORIZONTAL)); + nameOverlays.push(Overlays.addOverlay("text", { + font: { size: TEXT_HEIGHT }, + text: (i === NUM_AC) ? "Master" : + ((i < NAMES.length) ? NAMES[i] : + "AC" + (i + 1)), + x: 0, y: 0, + width: 0, + height: 0, + alpha: 1.0, + visible: true + })); + + onOffIcon.push(toolBars[i].addTool({ + imageURL: TOOL_ICON_URL + "models-tool.svg", + subImage: { x: 0, y: Tool.IMAGE_WIDTH, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, true, false)); + playIcon.push(null); + playLoopIcon.push(null); + stopIcon.push(null); + } +} + +function sendCommand(id, action) { + if (action === SHOW && toolBars[id].numberOfTools() === 1) { + toolBars[id].selectTool(onOffIcon[id], true); + + playIcon[id] = toolBars[id].addTool({ + imageURL: TOOL_ICON_URL + "play.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false); + + playLoopIcon[id] = toolBars[id].addTool({ + imageURL: TOOL_ICON_URL + "play-loop.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false); + + stopIcon[id] = toolBars[id].addTool({ + imageURL: TOOL_ICON_URL + "stop.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: ALPHA_ON, + visible: true + }, false); + + toolBars[id].setBack((id === NUM_AC) ? COLOR_MASTER : COLOR_TOOL_BAR, ALPHA_OFF); + } else if (action === HIDE && toolBars[id].numberOfTools() != 1) { + toolBars[id].selectTool(onOffIcon[id], false); + toolBars[id].removeLastTool(); + toolBars[id].removeLastTool(); + toolBars[id].removeLastTool(); + toolBars[id].setBack(null); + } + + if (id === toolBars.length - 1) { + for (i = 0; i < NUM_AC; i++) { + sendCommand(i, action); + } + return; + } + + Voxels.setVoxel(controlVoxelPosition.x + id * controlVoxelSize, + controlVoxelPosition.y, + controlVoxelPosition.z, + controlVoxelSize, + COLORS[action].red, + COLORS[action].green, + COLORS[action].blue); +} + +function mousePressEvent(event) { + clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + + // Check master control + var i = toolBars.length - 1; + if (onOffIcon[i] === toolBars[i].clicked(clickedOverlay)) { + if (toolBars[i].toolSelected(onOffIcon[i])) { + sendCommand(i, SHOW); + } else { + sendCommand(i, HIDE); + } + } else if (playIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, PLAY); + } else if (playLoopIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, PLAY_LOOP); + } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, STOP); + } else { + // Check individual controls + for (i = 0; i < NUM_AC; i++) { + if (onOffIcon[i] === toolBars[i].clicked(clickedOverlay)) { + if (toolBars[i].toolSelected(onOffIcon[i])) { + sendCommand(i, SHOW); + } else { + sendCommand(i, HIDE); + } + } else if (playIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, PLAY); + } else if (playLoopIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, PLAY_LOOP); + } else if (stopIcon[i] === toolBars[i].clicked(clickedOverlay)) { + sendCommand(i, STOP); + } else { + + } + } + } +} + +function moveUI() { + var relative = { x: 70, y: 400 }; + for (i = 0; i <= NUM_AC; i++) { + toolBars[i].move(relative.x, + windowDimensions.y - relative.y + + i * (Tool.IMAGE_HEIGHT + 2 * ToolBar.SPACING + TEXT_HEIGHT)); + Overlays.editOverlay(nameOverlays[i], { + x: relative.x, + y: windowDimensions.y - relative.y + + i * (Tool.IMAGE_HEIGHT + 2 * ToolBar.SPACING + TEXT_HEIGHT) - + ToolBar.SPACING - 2 * TEXT_HEIGHT + }); + } +} + +function update() { + var newDimensions = Controller.getViewportDimensions(); + if (windowDimensions.x != newDimensions.x || + windowDimensions.y != newDimensions.y) { + windowDimensions = newDimensions; + moveUI(); + } +} + +function scriptEnding() { + for (i = 0; i <= NUM_AC; i++) { + toolBars[i].cleanup(); + Overlays.deleteOverlay(nameOverlays[i]); + } +} + +Controller.mousePressEvent.connect(mousePressEvent); +Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); + +moveUI();