From 24178b72fb8c854305f524ef694810e9625a8073 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 21 Apr 2015 21:55:52 -0700 Subject: [PATCH 01/36] Use lobby.js as starting point for avatarSelector.js --- examples/avatarSelector.js | 400 +++++++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 examples/avatarSelector.js diff --git a/examples/avatarSelector.js b/examples/avatarSelector.js new file mode 100644 index 0000000000..41d6abbe2b --- /dev/null +++ b/examples/avatarSelector.js @@ -0,0 +1,400 @@ +// +// avatarSelector.js +// examples +// +// Created by David Rowe on 21 Apr 2015. +// Copyright 2015 High Fidelity, Inc. +// +// Based on lobby.js created by Stephen Birarda on 17 Oct 2014. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + +var panelWall = false; +var orbShell = false; +var descriptionText = false; +var showText = false; + +// used for formating the description text, in meters +var textWidth = 4; +var textHeight = .5; +var numberOfLines = 2; +var textMargin = 0.0625; +var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines; + +var avatarStickPosition = {}; + +var orbNaturalExtentsMin = { x: -1.230354, y: -1.22077, z: -1.210487 }; +var orbNaturalExtentsMax = { x: 1.230353, y: 1.229819, z: 1.210487 }; +var panelsNaturalExtentsMin = { x: -1.223182, y: -0.348487, z: 0.0451369 }; +var panelsNaturalExtentsMax = { x: 1.223039, y: 0.602978, z: 1.224298 }; + +var orbNaturalDimensions = Vec3.subtract(orbNaturalExtentsMax, orbNaturalExtentsMin); +var panelsNaturalDimensions = Vec3.subtract(panelsNaturalExtentsMax, panelsNaturalExtentsMin); + +var SCALING_FACTOR = 10; +var orbDimensions = Vec3.multiply(orbNaturalDimensions, SCALING_FACTOR); +var panelsDimensions = Vec3.multiply(panelsNaturalDimensions, SCALING_FACTOR); + +var orbNaturalCenter = Vec3.sum(orbNaturalExtentsMin, Vec3.multiply(orbNaturalDimensions, 0.5)); +var panelsNaturalCenter = Vec3.sum(panelsNaturalExtentsMin, Vec3.multiply(panelsNaturalDimensions, 0.5)); +var orbCenter = Vec3.multiply(orbNaturalCenter, SCALING_FACTOR); +var panelsCenter = Vec3.multiply(panelsNaturalCenter, SCALING_FACTOR); +var panelsCenterShift = Vec3.subtract(panelsCenter, orbCenter); + +var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8 }; + +var LOBBY_PANEL_WALL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/PanelWallForInterface.fbx"; +var LOBBY_BLANK_PANEL_TEXTURE_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Texture.jpg"; +var LOBBY_SHELL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyShellForInterface.fbx"; + +var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.stereo.raw") +var currentDrone = null; + +var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.stereo.raw") +var latinInjector = null; +var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.stereo.raw") +var elevatorInjector = null; +var currentMuzakInjector = null; +var currentSound = null; + +function textOverlayPosition() { + var TEXT_DISTANCE_OUT = 6; + var TEXT_DISTANCE_DOWN = -2; + return Vec3.sum(Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), TEXT_DISTANCE_OUT)), + Vec3.multiply(Quat.getUp(Camera.orientation), TEXT_DISTANCE_DOWN)); +} + +var panelPlaceOrder = [ + 7, 8, 9, 10, 11, 12, 13, + 0, 1, 2, 3, 4, 5, 6, + 14, 15, 16, 17, 18, 19, 20 +]; + +// place index is 0-based +function placeIndexToPanelIndex(placeIndex) { + return panelPlaceOrder.indexOf(placeIndex) + 1; +} + +// Panel index is 1-based +function panelIndexToPlaceIndex(panelIndex) { + return panelPlaceOrder[panelIndex - 1]; +} + +var MAX_NUM_PANELS = 21; +var DRONE_VOLUME = 0.3; + +function drawLobby() { + if (!panelWall) { + print("Adding overlays for the lobby panel wall and orb shell."); + + var cameraEuler = Quat.safeEulerAngles(Camera.orientation); + var towardsMe = Quat.angleAxis(cameraEuler.y + 180, { x: 0, y: 1, z: 0 }); + + var orbPosition = Vec3.sum(Camera.position, Vec3.multiplyQbyV(towardsMe, ORB_SHIFT)); + + var panelWallProps = { + url: LOBBY_PANEL_WALL_URL, + position: Vec3.sum(orbPosition, Vec3.multiplyQbyV(towardsMe, panelsCenterShift)), + rotation: towardsMe, + dimensions: panelsDimensions + }; + + var orbShellProps = { + url: LOBBY_SHELL_URL, + position: orbPosition, + rotation: towardsMe, + dimensions: orbDimensions, + ignoreRayIntersection: true + }; + + var windowDimensions = Controller.getViewportDimensions(); + + var descriptionTextProps = { + position: textOverlayPosition(), + dimensions: { x: textWidth, y: textHeight }, + backgroundColor: { red: 0, green: 0, blue: 0 }, + color: { red: 255, green: 255, blue: 255 }, + topMargin: textMargin, + leftMargin: textMargin, + bottomMargin: textMargin, + rightMargin: textMargin, + text: "", + lineHeight: lineHeight, + alpha: 0.9, + backgroundAlpha: 0.9, + ignoreRayIntersection: true, + visible: false, + isFacingAvatar: true + }; + + avatarStickPosition = MyAvatar.position; + + panelWall = Overlays.addOverlay("model", panelWallProps); + orbShell = Overlays.addOverlay("model", orbShellProps); + descriptionText = Overlays.addOverlay("text3d", descriptionTextProps); + + if (droneSound.downloaded) { + // start the drone sound + if (!currentDrone) { + currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME }); + } else { + currentDrone.restart(); + } + } + + // start one of our muzak sounds + playRandomMuzak(); + } +} + +var places = {}; + +function changeLobbyTextures() { + var req = new XMLHttpRequest(); + req.open("GET", "https://metaverse.highfidelity.com/api/v1/places?limit=21", false); + req.send(); + + places = JSON.parse(req.responseText).data.places; + + var NUM_PANELS = places.length; + + var textureProp = { + textures: {} + }; + + for (var j = 0; j < NUM_PANELS; j++) { + var panelIndex = placeIndexToPanelIndex(j); + textureProp["textures"]["file" + panelIndex] = places[j].previews.lobby; + }; + + Overlays.editOverlay(panelWall, textureProp); +} + +var MUZAK_VOLUME = 0.1; + +function playCurrentSound(secondOffset) { + if (currentSound == latinSound) { + if (!latinInjector) { + latinInjector = Audio.playSound(latinSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME }); + } else { + latinInjector.restart(); + } + + currentMuzakInjector = latinInjector; + } else if (currentSound == elevatorSound) { + if (!elevatorInjector) { + elevatorInjector = Audio.playSound(elevatorSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME }); + } else { + elevatorInjector.restart(); + } + + currentMuzakInjector = elevatorInjector; + } +} + +function playNextMuzak() { + if (panelWall) { + if (currentSound == latinSound) { + if (elevatorSound.downloaded) { + currentSound = elevatorSound; + } + } else if (currentSound == elevatorSound) { + if (latinSound.downloaded) { + currentSound = latinSound; + } + } + + playCurrentSound(0); + } +} + +function playRandomMuzak() { + currentSound = null; + + if (latinSound.downloaded && elevatorSound.downloaded) { + currentSound = Math.random() < 0.5 ? latinSound : elevatorSound; + } else if (latinSound.downloaded) { + currentSound = latinSound; + } else if (elevatorSound.downloaded) { + currentSound = elevatorSound; + } + + if (currentSound) { + // pick a random number of seconds from 0-10 to offset the muzak + var secondOffset = Math.random() * 10; + + playCurrentSound(secondOffset); + } else { + currentMuzakInjector = null; + } +} + +function cleanupLobby() { + toggleEnvironmentRendering(true); + + // for each of the 21 placeholder textures, set them back to default so the cached model doesn't have changed textures + var panelTexturesReset = {}; + panelTexturesReset["textures"] = {}; + + for (var j = 0; j < MAX_NUM_PANELS; j++) { + panelTexturesReset["textures"]["file" + (j + 1)] = LOBBY_BLANK_PANEL_TEXTURE_URL; + }; + + Overlays.editOverlay(panelWall, panelTexturesReset); + + Overlays.deleteOverlay(panelWall); + Overlays.deleteOverlay(orbShell); + Overlays.deleteOverlay(descriptionText); + + panelWall = false; + orbShell = false; + + if (currentDrone) { + currentDrone.stop(); + currentDrone = null + } + + if (currentMuzakInjector) { + currentMuzakInjector.stop(); + currentMuzakInjector = null; + } + + places = {}; + +} + +function actionStartEvent(event) { + if (panelWall) { + // we've got an action event and our panel wall is up + // check if we hit a panel and if we should jump there + var result = Overlays.findRayIntersection(event.actionRay); + if (result.intersects && result.overlayID == panelWall) { + + var panelName = result.extraInfo; + + var panelStringIndex = panelName.indexOf("Panel"); + if (panelStringIndex != -1) { + var panelIndex = parseInt(panelName.slice(5)); + var placeIndex = panelIndexToPlaceIndex(panelIndex); + if (placeIndex < places.length) { + var actionPlace = places[placeIndex]; + + print("Jumping to " + actionPlace.name + " at " + actionPlace.address + + " after click on panel " + panelIndex + " with place index " + placeIndex); + + Window.location = actionPlace.address; + maybeCleanupLobby(); + } + } + } + } +} + +function backStartEvent() { + if (!panelWall) { + toggleEnvironmentRendering(false); + drawLobby(); + changeLobbyTextures(); + } else { + cleanupLobby(); + } +} + +var CLEANUP_EPSILON_DISTANCE = 0.05; + +function maybeCleanupLobby() { + if (panelWall && Vec3.length(Vec3.subtract(avatarStickPosition, MyAvatar.position)) > CLEANUP_EPSILON_DISTANCE) { + cleanupLobby(); + } +} + +function toggleEnvironmentRendering(shouldRender) { + Scene.shouldRenderAvatars = shouldRender; + Scene.shouldRenderEntities = shouldRender; +} + +function handleLookAt(pickRay) { + if (panelWall && descriptionText) { + // we've got an action event and our panel wall is up + // check if we hit a panel and if we should jump there + var result = Overlays.findRayIntersection(pickRay); + if (result.intersects && result.overlayID == panelWall) { + var panelName = result.extraInfo; + var panelStringIndex = panelName.indexOf("Panel"); + if (panelStringIndex != -1) { + var panelIndex = parseInt(panelName.slice(5)); + var placeIndex = panelIndexToPlaceIndex(panelIndex); + if (placeIndex < places.length) { + var actionPlace = places[placeIndex]; + + if (actionPlace.description == "") { + Overlays.editOverlay(descriptionText, { text: actionPlace.name, visible: showText }); + } else { + // handle line wrapping + var allWords = actionPlace.description.split(" "); + var currentGoodLine = ""; + var currentTestLine = ""; + var formatedDescription = ""; + var wordsFormated = 0; + var currentTestWord = 0; + var wordsOnLine = 0; + while (wordsFormated < allWords.length) { + // first add the "next word" to the line and test it. + currentTestLine = currentGoodLine; + if (wordsOnLine > 0) { + currentTestLine += " " + allWords[currentTestWord]; + } else { + currentTestLine = allWords[currentTestWord]; + } + var lineLength = Overlays.textSize(descriptionText, currentTestLine).width; + if (lineLength < textWidth || wordsOnLine == 0) { + wordsFormated++; + currentTestWord++; + wordsOnLine++; + currentGoodLine = currentTestLine; + } else { + formatedDescription += currentGoodLine + "\n"; + wordsOnLine = 0; + currentGoodLine = ""; + currentTestLine = ""; + } + } + formatedDescription += currentGoodLine; + Overlays.editOverlay(descriptionText, { text: formatedDescription, visible: showText }); + } + } else { + Overlays.editOverlay(descriptionText, { text: "", visible: false }); + } + } + } + } +} + +function update(deltaTime) { + maybeCleanupLobby(); + if (panelWall) { + Overlays.editOverlay(descriptionText, { position: textOverlayPosition() }); + + // if the reticle is up then we may need to play the next muzak + if (currentMuzakInjector && !currentMuzakInjector.isPlaying) { + playNextMuzak(); + } + } +} + +function mouseMoveEvent(event) { + if (panelWall) { + var pickRay = Camera.computePickRay(event.x, event.y); + handleLookAt(pickRay); + } +} + +Controller.actionStartEvent.connect(actionStartEvent); +Controller.backStartEvent.connect(backStartEvent); +Script.update.connect(update); +Script.scriptEnding.connect(maybeCleanupLobby); +Controller.mouseMoveEvent.connect(mouseMoveEvent); From 63d0efcdecf7da71746163c304fd7a1b58d05316 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Apr 2015 09:16:15 -0700 Subject: [PATCH 02/36] Open and close avatar selector with Ctrl-A --- examples/avatarSelector.js | 33 ++++++++++++++++++++++++--------- interface/src/Application.cpp | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/examples/avatarSelector.js b/examples/avatarSelector.js index 41d6abbe2b..dfc3f21cb5 100644 --- a/examples/avatarSelector.js +++ b/examples/avatarSelector.js @@ -89,7 +89,7 @@ var DRONE_VOLUME = 0.3; function drawLobby() { if (!panelWall) { - print("Adding overlays for the lobby panel wall and orb shell."); + print("Adding overlays for the avatar selector panel wall and orb shell."); var cameraEuler = Quat.safeEulerAngles(Camera.orientation); var towardsMe = Quat.angleAxis(cameraEuler.y + 180, { x: 0, y: 1, z: 0 }); @@ -294,13 +294,27 @@ function actionStartEvent(event) { } } -function backStartEvent() { - if (!panelWall) { - toggleEnvironmentRendering(false); - drawLobby(); - changeLobbyTextures(); - } else { - cleanupLobby(); +var control = false; + +function keyPressEvent(event) { + if (event.text === "CONTROL") { + control = true; + } + + if (control && event.text === "a") { + if (!panelWall) { + toggleEnvironmentRendering(false); + drawLobby(); + changeLobbyTextures(); + } else { + cleanupLobby(); + } + } +} + +function keyReleaseEvent(event) { + if (event.text === "CONTROL") { + control = false; } } @@ -394,7 +408,8 @@ function mouseMoveEvent(event) { } Controller.actionStartEvent.connect(actionStartEvent); -Controller.backStartEvent.connect(backStartEvent); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.update.connect(update); Script.scriptEnding.connect(maybeCleanupLobby); Controller.mouseMoveEvent.connect(mouseMoveEvent); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 34825ee725..734738a290 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1020,7 +1020,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_A: if (isShifted) { Menu::getInstance()->triggerOption(MenuOption::Atmosphere); - } else { + } else if (!isMeta) { _myAvatar->setDriveKeys(ROT_LEFT, 1.0f); } break; From 2eb50596683fffa58842a2d5b80ae4718b1fe1f8 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 22 Apr 2015 10:59:53 -0700 Subject: [PATCH 03/36] Display avatar images and change avatar upon selection --- examples/avatarSelector.js | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/examples/avatarSelector.js b/examples/avatarSelector.js index dfc3f21cb5..dc2916a1a8 100644 --- a/examples/avatarSelector.js +++ b/examples/avatarSelector.js @@ -74,9 +74,9 @@ var panelPlaceOrder = [ 14, 15, 16, 17, 18, 19, 20 ]; -// place index is 0-based -function placeIndexToPanelIndex(placeIndex) { - return panelPlaceOrder.indexOf(placeIndex) + 1; +// Avatar index is 0-based +function avatarIndexToPanelIndex(avatarIndex) { + return panelPlaceOrder.indexOf(avatarIndex) + 1; } // Panel index is 1-based @@ -151,24 +151,24 @@ function drawLobby() { } } -var places = {}; +var avatars = {}; function changeLobbyTextures() { var req = new XMLHttpRequest(); - req.open("GET", "https://metaverse.highfidelity.com/api/v1/places?limit=21", false); - req.send(); + req.open("GET", "https://metaverse.highfidelity.com/api/v1/marketplace?category=head+%26+body&limit=21", false); + req.send(); // Data returned is randomized. - places = JSON.parse(req.responseText).data.places; + avatars = JSON.parse(req.responseText).data.items; - var NUM_PANELS = places.length; + var NUM_PANELS = avatars.length; var textureProp = { textures: {} }; for (var j = 0; j < NUM_PANELS; j++) { - var panelIndex = placeIndexToPanelIndex(j); - textureProp["textures"]["file" + panelIndex] = places[j].previews.lobby; + var panelIndex = avatarIndexToPanelIndex(j); + textureProp["textures"]["file" + panelIndex] = avatars[j].preview_url; }; Overlays.editOverlay(panelWall, textureProp); @@ -263,7 +263,7 @@ function cleanupLobby() { currentMuzakInjector = null; } - places = {}; + avatars = {}; } @@ -279,14 +279,15 @@ function actionStartEvent(event) { var panelStringIndex = panelName.indexOf("Panel"); if (panelStringIndex != -1) { var panelIndex = parseInt(panelName.slice(5)); - var placeIndex = panelIndexToPlaceIndex(panelIndex); - if (placeIndex < places.length) { - var actionPlace = places[placeIndex]; + var avatarIndex = panelIndexToPlaceIndex(panelIndex); + if (avatarIndex < avatars.length) { + var actionPlace = avatars[avatarIndex]; - print("Jumping to " + actionPlace.name + " at " + actionPlace.address - + " after click on panel " + panelIndex + " with place index " + placeIndex); + print("Changing avatar to " + actionPlace.name + + " after click on panel " + panelIndex + " with avatar index " + avatarIndex); + + MyAvatar.useFullAvatarURL(actionPlace.content_url); - Window.location = actionPlace.address; maybeCleanupLobby(); } } @@ -341,9 +342,9 @@ function handleLookAt(pickRay) { var panelStringIndex = panelName.indexOf("Panel"); if (panelStringIndex != -1) { var panelIndex = parseInt(panelName.slice(5)); - var placeIndex = panelIndexToPlaceIndex(panelIndex); - if (placeIndex < places.length) { - var actionPlace = places[placeIndex]; + var avatarIndex = panelIndexToPlaceIndex(panelIndex); + if (avatarIndex < avatars.length) { + var actionPlace = avatars[avatarIndex]; if (actionPlace.description == "") { Overlays.editOverlay(descriptionText, { text: actionPlace.name, visible: showText }); From 1d7420d0dc908cabca046ceba5b4b8c6836710bf Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 28 Apr 2015 12:53:11 -0700 Subject: [PATCH 04/36] Adapt DDE control of eyes to be predominantly open or closed --- interface/src/devices/DdeFaceTracker.cpp | 155 ++++++++++++++++------- interface/src/devices/DdeFaceTracker.h | 21 ++- 2 files changed, 127 insertions(+), 49 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index be25c0794d..ece9667816 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -65,16 +65,16 @@ static const int DDE_TO_FACESHIFT_MAPPING[] = { // The DDE coefficients, overall, range from -0.2 to 1.5 or so. However, individual coefficients typically vary much // less than this. static const float DDE_COEFFICIENT_SCALES[] = { - 4.0f, // EyeBlink_L - 4.0f, // EyeBlink_R + 1.0f, // EyeBlink_L + 1.0f, // EyeBlink_R 1.0f, // EyeSquint_L 1.0f, // EyeSquint_R 1.0f, // EyeDown_L 1.0f, // EyeDown_R 1.0f, // EyeIn_L 1.0f, // EyeIn_R - 4.0f, // EyeOpen_L - 4.0f, // EyeOpen_R + 1.0f, // EyeOpen_L + 1.0f, // EyeOpen_R 1.0f, // EyeOut_L 1.0f, // EyeOut_R 1.0f, // EyeUp_L @@ -136,6 +136,16 @@ struct Packet { const float STARTING_DDE_MESSAGE_TIME = 0.033f; +const int FPS_TIMER_DELAY = 2000; // ms +const int FPS_TIMER_DURATION = 2000; // ms + +#ifdef WIN32 +// warning C4351: new behavior: elements of array 'DdeFaceTracker::_lastEyeBlinks' will be default initialized +// warning C4351: new behavior: elements of array 'DdeFaceTracker::_filteredEyeBlinks' will be default initialized +// warning C4351: new behavior: elements of array 'DdeFaceTracker::_lastEyeCoefficients' will be default initialized +#pragma warning(disable:4351) +#endif + DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT) { @@ -166,24 +176,33 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _averageMessageTime(STARTING_DDE_MESSAGE_TIME), _lastHeadTranslation(glm::vec3(0.0f)), _filteredHeadTranslation(glm::vec3(0.0f)), - _lastLeftEyeBlink(0.0f), - _filteredLeftEyeBlink(0.0f), - _lastRightEyeBlink(0.0f), - _filteredRightEyeBlink(0.0f) + _lastEyeBlinks(), + _filteredEyeBlinks(), + _lastEyeCoefficients(), + _isCalculatingFPS(false), + _frameCount(0) { _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _blendshapeCoefficients.resize(NUM_FACESHIFT_BLENDSHAPES); - + + _eyeStates[0] = EYE_OPEN; + _eyeStates[1] = EYE_OPEN; + connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); - connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); + connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + SLOT(socketStateChanged(QAbstractSocket::SocketState))); } DdeFaceTracker::~DdeFaceTracker() { setEnabled(false); } +#ifdef WIN32 +#pragma warning(default:4351) +#endif + void DdeFaceTracker::setEnabled(bool enabled) { #ifdef HAVE_DDE // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket. @@ -354,40 +373,6 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _coefficients[DDE_TO_FACESHIFT_MAPPING[i]] = packet.expressions[i]; } - // Use EyeBlink values to control both EyeBlink and EyeOpen - static const float RELAXED_EYE_VALUE = 0.1f; - float leftEye = _coefficients[_leftBlinkIndex]; - float rightEye = _coefficients[_rightBlinkIndex]; - if (isFiltering) { - const float BLINK_VELOCITY_FILTER_STRENGTH = 0.3f; - - float velocity = fabs(leftEye - _lastLeftEyeBlink) / _averageMessageTime; - float velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); - _filteredLeftEyeBlink = velocityFilter * leftEye + (1.0f - velocityFilter) * _filteredLeftEyeBlink; - _lastLeftEyeBlink = leftEye; - leftEye = _filteredLeftEyeBlink; - - velocity = fabs(rightEye - _lastRightEyeBlink) / _averageMessageTime; - velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); - _filteredRightEyeBlink = velocityFilter * rightEye + (1.0f - velocityFilter) * _filteredRightEyeBlink; - _lastRightEyeBlink = rightEye; - rightEye = _filteredRightEyeBlink; - } - if (leftEye > RELAXED_EYE_VALUE) { - _coefficients[_leftBlinkIndex] = leftEye - RELAXED_EYE_VALUE; - _coefficients[_leftEyeOpenIndex] = 0.0f; - } else { - _coefficients[_leftBlinkIndex] = 0.0f; - _coefficients[_leftEyeOpenIndex] = RELAXED_EYE_VALUE - leftEye; - } - if (rightEye > RELAXED_EYE_VALUE) { - _coefficients[_rightBlinkIndex] = rightEye - RELAXED_EYE_VALUE; - _coefficients[_rightEyeOpenIndex] = 0.0f; - } else { - _coefficients[_rightBlinkIndex] = 0.0f; - _coefficients[_rightEyeOpenIndex] = RELAXED_EYE_VALUE - rightEye; - } - // Use BrowsU_C to control both brows' up and down _coefficients[_browDownLeftIndex] = -_coefficients[_browUpCenterIndex]; _coefficients[_browDownRightIndex] = -_coefficients[_browUpCenterIndex]; @@ -403,6 +388,88 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { _coefficients[_mouthSmileLeftIndex] = _coefficients[_mouthSmileLeftIndex] - SMILE_THRESHOLD; _coefficients[_mouthSmileRightIndex] = _coefficients[_mouthSmileRightIndex] - SMILE_THRESHOLD; + // Velocity filter EyeBlink values + const float DDE_EYEBLINK_SCALE = 3.0f; + float eyeBlinks[] = { DDE_EYEBLINK_SCALE * _coefficients[_leftBlinkIndex], DDE_EYEBLINK_SCALE * _coefficients[_rightBlinkIndex] }; + if (isFiltering) { + const float BLINK_VELOCITY_FILTER_STRENGTH = 0.3f; + for (int i = 0; i < 2; i += 1) { + float velocity = fabs(eyeBlinks[i] - _lastEyeBlinks[i]) / _averageMessageTime; + float velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); + _filteredEyeBlinks[i] = velocityFilter * eyeBlinks[i] + (1.0f - velocityFilter) * _filteredEyeBlinks[i]; + _lastEyeBlinks[i] = eyeBlinks[i]; + } + } + + // Finesse EyeBlink values + float eyeCoefficients[2]; + for (int i = 0; i < 2; i += 1) { + // Scale EyeBlink values so that they can be used to control both EyeBlink and EyeOpen + // -ve values control EyeOpen; +ve values control EyeBlink + static const float EYE_CONTROL_THRESHOLD = 0.5f; // Resting eye value + eyeCoefficients[i] = (_filteredEyeBlinks[i] - EYE_CONTROL_THRESHOLD) / (1.0f - EYE_CONTROL_THRESHOLD); + + // Change to closing or opening states + const float EYE_CONTROL_HYSTERISIS = 0.25f; + const float EYE_CLOSING_THRESHOLD = 0.95f; + const float EYE_OPENING_THRESHOLD = EYE_CONTROL_THRESHOLD - EYE_CONTROL_HYSTERISIS; + if ((_eyeStates[i] == EYE_OPEN || _eyeStates[i] == EYE_OPENING) && eyeCoefficients[i] > EYE_CLOSING_THRESHOLD) { + _eyeStates[i] = EYE_CLOSING; + } else if ((_eyeStates[i] == EYE_CLOSED || _eyeStates[i] == EYE_CLOSING) + && eyeCoefficients[i] < EYE_OPENING_THRESHOLD) { + _eyeStates[i] = EYE_OPENING; + } + + const float EYELID_MOVEMENT_RATE = 10.0f; // units/second + const float EYE_OPEN_SCALE = 0.2f; + if (_eyeStates[i] == EYE_CLOSING) { + // Close eyelid until it's fully closed + float closingValue = _lastEyeCoefficients[i] + EYELID_MOVEMENT_RATE * _averageMessageTime; + if (closingValue >= 1.0) { + _eyeStates[i] = EYE_CLOSED; + eyeCoefficients[i] = 1.0; + } else { + eyeCoefficients[i] = closingValue; + } + } else if (_eyeStates[i] == EYE_OPENING) { + // Open eyelid until it meets the current adjusted value + float openingValue = _lastEyeCoefficients[i] - EYELID_MOVEMENT_RATE * _averageMessageTime; + if (openingValue < eyeCoefficients[i] * EYE_OPEN_SCALE) { + _eyeStates[i] = EYE_OPEN; + eyeCoefficients[i] = eyeCoefficients[i] * EYE_OPEN_SCALE; + } else { + eyeCoefficients[i] = openingValue; + } + } else if (_eyeStates[i] == EYE_OPEN) { + // Reduce eyelid movement + eyeCoefficients[i] = eyeCoefficients[i] * EYE_OPEN_SCALE; + } else if (_eyeStates[i] == EYE_CLOSED) { + // Keep eyelid fully closed + eyeCoefficients[i] = 1.0; + } + } + if (_eyeStates[0] == EYE_OPEN && _eyeStates[1] == EYE_OPEN) { + // Couple eyelids + eyeCoefficients[0] = eyeCoefficients[1] = (eyeCoefficients[0] + eyeCoefficients[0]) / 2.0f; + } + _lastEyeCoefficients[0] = eyeCoefficients[0]; + _lastEyeCoefficients[1] = eyeCoefficients[1]; + + // Use EyeBlink values to control both EyeBlink and EyeOpen + if (eyeCoefficients[0] > 0) { + _coefficients[_leftBlinkIndex] = eyeCoefficients[0]; + _coefficients[_leftEyeOpenIndex] = 0.0f; + } else { + _coefficients[_leftBlinkIndex] = 0.0f; + _coefficients[_leftEyeOpenIndex] = -eyeCoefficients[0]; + } + if (eyeCoefficients[1] > 0) { + _coefficients[_rightBlinkIndex] = eyeCoefficients[1]; + _coefficients[_rightEyeOpenIndex] = 0.0f; + } else { + _coefficients[_rightBlinkIndex] = 0.0f; + _coefficients[_rightEyeOpenIndex] = -eyeCoefficients[1]; + } // Scale all coefficients for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index d9df5723cf..7ae4a07fea 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -103,12 +103,23 @@ private: quint64 _lastMessageReceived; float _averageMessageTime; + glm::vec3 _lastHeadTranslation; glm::vec3 _filteredHeadTranslation; - float _lastLeftEyeBlink; - float _filteredLeftEyeBlink; - float _lastRightEyeBlink; - float _filteredRightEyeBlink; + + enum EyeState { + EYE_OPEN, + EYE_CLOSING, + EYE_CLOSED, + EYE_OPENING + }; + EyeState _eyeStates[2]; + float _lastEyeBlinks[2]; + float _filteredEyeBlinks[2]; + float _lastEyeCoefficients[2]; + + bool _isCalculatingFPS; + int _frameCount; }; -#endif // hifi_DdeFaceTracker_h \ No newline at end of file +#endif // hifi_DdeFaceTracker_h From 02fd9987c7a6d340e0f5b207b3a07499974529df Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 28 Apr 2015 18:38:41 -0700 Subject: [PATCH 05/36] rework audio mixer so it can exit cleanly --- assignment-client/src/AssignmentClient.cpp | 12 +- assignment-client/src/AssignmentClient.h | 3 + assignment-client/src/AssignmentClientApp.cpp | 6 + .../src/AssignmentClientMonitor.cpp | 6 + .../src/AssignmentClientMonitor.h | 3 + assignment-client/src/audio/AudioMixer.cpp | 159 ++++++++++-------- assignment-client/src/audio/AudioMixer.h | 10 ++ libraries/networking/src/LimitedNodeList.h | 4 + .../networking/src/ThreadedAssignment.cpp | 23 ++- libraries/networking/src/ThreadedAssignment.h | 10 ++ 10 files changed, 155 insertions(+), 81 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a0da273462..5a6868e7e4 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -114,7 +114,16 @@ void AssignmentClient::stopAssignmentClient() { qDebug() << "Exiting."; _requestTimer.stop(); _statsTimerACM.stop(); - QCoreApplication::quit(); + if (_currentAssignment) { + _currentAssignment->aboutToQuit(); + // _currentAssignment->aboutToFinish(); + _currentAssignment->thread()->wait(); + } +} + + +void AssignmentClient::aboutToQuit() { + stopAssignmentClient(); } @@ -197,6 +206,7 @@ void AssignmentClient::readPendingDatagrams() { // start the deployed assignment AssignmentThread* workerThread = new AssignmentThread(_currentAssignment, this); + workerThread->setObjectName("worker"); connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run); connect(_currentAssignment.data(), &ThreadedAssignment::finished, workerThread, &QThread::quit); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 08673ab04c..1ffb862dd3 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -34,6 +34,9 @@ private slots: void sendStatsPacketToACM(); void stopAssignmentClient(); +public slots: + void aboutToQuit(); + private: void setUpStatsToMonitor(int ppid); Assignment _requestAssignment; diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 17f2eac70d..2fcbd67be1 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include @@ -180,14 +181,19 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : } } + QThread::currentThread()->setObjectName("main thread"); if (numForks || minForks || maxForks) { AssignmentClientMonitor monitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); + connect(this, &QCoreApplication::aboutToQuit, &monitor, &AssignmentClientMonitor::aboutToQuit); + + exec(); } else { AssignmentClient client(ppid, requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); + connect(this, &QCoreApplication::aboutToQuit, &client, &AssignmentClient::aboutToQuit); exec(); } } diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index d591087acd..14eb93ad6e 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -80,6 +80,12 @@ void AssignmentClientMonitor::stopChildProcesses() { }); } + +void AssignmentClientMonitor::aboutToQuit() { + stopChildProcesses(); +} + + void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 996220b1b4..23f50ef67d 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -38,6 +38,9 @@ private slots: void readPendingDatagrams(); void checkSpares(); +public slots: + void aboutToQuit(); + private: void spawnChildClient(); QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 06e6f77f69..5d7601ba55 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -588,7 +588,6 @@ void AudioMixer::sendStatsPacket() { _sumMixes = 0; _numStatFrames = 0; - // NOTE: These stats can be too large to fit in an MTU, so we break it up into multiple packts... QJsonObject statsObject2; @@ -712,78 +711,90 @@ void AudioMixer::run() { // check the settings object to see if we have anything we can parse out parseSettingsObject(settingsObject); - int nextFrame = 0; - QElapsedTimer timer; - timer.start(); + _nextFrame = 0; + _timer.start(); - char clientMixBuffer[MAX_PACKET_SIZE]; - - int usecToSleep = AudioConstants::NETWORK_FRAME_USECS; - - const int TRAILING_AVERAGE_FRAMES = 100; - int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; + _idleTimer = new QTimer(); + connect(_idleTimer, SIGNAL(timeout()), this, SLOT(insideLoop())); + _idleTimer->start(0); +} - while (!_isFinished) { - const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; - const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; + +void AudioMixer::insideLoop() { + if (_isFinished) { + qDebug() << "AudioMixer::insideLoop stoping _idleTimer"; + _idleTimer->stop(); + delete _idleTimer; + _idleTimer = nullptr; + + QThread *thisThread = QThread::currentThread(); + thisThread->quit(); + + return; + } + + auto nodeList = DependencyManager::get(); + + const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; + const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; - const float RATIO_BACK_OFF = 0.02f; + const float RATIO_BACK_OFF = 0.02f; - const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; - const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; + const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; + const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; - if (usecToSleep < 0) { - usecToSleep = 0; - } + if (_usecToSleep < 0) { + _usecToSleep = 0; + } - _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) - + (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); + _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) + + (_usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); - float lastCutoffRatio = _performanceThrottlingRatio; - bool hasRatioChanged = false; + float lastCutoffRatio = _performanceThrottlingRatio; + bool hasRatioChanged = false; - if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { - if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { - // we're struggling - change our min required loudness to reduce some load - _performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio)); + if (_framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { + if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { + // we're struggling - change our min required loudness to reduce some load + _performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio)); - qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; - hasRatioChanged = true; - } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) { - // we've recovered and can back off the required loudness - _performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF; + qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" + << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; + hasRatioChanged = true; + } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) { + // we've recovered and can back off the required loudness + _performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF; - if (_performanceThrottlingRatio < 0) { - _performanceThrottlingRatio = 0; - } - - qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; - hasRatioChanged = true; + if (_performanceThrottlingRatio < 0) { + _performanceThrottlingRatio = 0; } - - if (hasRatioChanged) { - // set out min audability threshold from the new ratio - _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio)); - qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; - framesSinceCutoffEvent = 0; - } + qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" + << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; + hasRatioChanged = true; } - - if (!hasRatioChanged) { - ++framesSinceCutoffEvent; - } - - quint64 now = usecTimestampNow(); - if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) { - perSecondActions(); - _lastPerSecondCallbackTime = now; - } - - nodeList->eachNode([&](const SharedNodePointer& node) { + if (hasRatioChanged) { + // set out min audability threshold from the new ratio + _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio)); + qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; + + _framesSinceCutoffEvent = 0; + } + } + + if (!hasRatioChanged) { + ++_framesSinceCutoffEvent; + } + + quint64 now = usecTimestampNow(); + if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) { + perSecondActions(); + _lastPerSecondCallbackTime = now; + } + + nodeList->eachNode([&](const SharedNodePointer& node) { + if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); @@ -807,8 +818,8 @@ void AudioMixer::run() { char* mixDataAt; if (streamsMixed > 0) { // pack header - int numBytesMixPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); - mixDataAt = clientMixBuffer + numBytesMixPacketHeader; + int numBytesMixPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeMixedAudio); + mixDataAt = _clientMixBuffer + numBytesMixPacketHeader; // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); @@ -820,8 +831,8 @@ void AudioMixer::run() { mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; } else { // pack header - int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); - mixDataAt = clientMixBuffer + numBytesPacketHeader; + int numBytesPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeSilentAudioFrame); + mixDataAt = _clientMixBuffer + numBytesPacketHeader; // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); @@ -833,12 +844,12 @@ void AudioMixer::run() { memcpy(mixDataAt, &numSilentSamples, sizeof(quint16)); mixDataAt += sizeof(quint16); } - + // Send audio environment sendAudioEnvironmentPacket(node); // send mixed audio packet - nodeList->writeDatagram(clientMixBuffer, mixDataAt - clientMixBuffer, node); + nodeList->writeDatagram(_clientMixBuffer, mixDataAt - _clientMixBuffer, node); nodeData->incrementOutgoingMixedAudioSequenceNumber(); // send an audio stream stats packet if it's time @@ -852,22 +863,22 @@ void AudioMixer::run() { } }); - ++_numStatFrames; + ++_numStatFrames; - QCoreApplication::processEvents(); + QCoreApplication::processEvents(); - if (_isFinished) { - break; - } + if (_isFinished) { + return; + } - usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us + _usecToSleep = (++_nextFrame * AudioConstants::NETWORK_FRAME_USECS) - _timer.nsecsElapsed() / 1000; // ns to us - if (usecToSleep > 0) { - usleep(usecToSleep); - } + if (_usecToSleep > 0) { + usleep(_usecToSleep); } } + void AudioMixer::perSecondActions() { _sendAudioStreamStats = true; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 6cee557ff9..a81225a0f2 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -32,6 +32,7 @@ public: public slots: /// threaded run of assignment void run(); + void insideLoop(); void readPendingDatagrams() { }; // this will not be called since our datagram processing thread will handle void readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr); @@ -110,6 +111,15 @@ private: MovingMinMaxAvg _timeSpentPerHashMatchCallStats; // update with usecs spent inside each packetVersionAndHashMatch call MovingMinMaxAvg _readPendingCallsPerSecondStats; // update with # of readPendingDatagrams calls in the last second + + // loop variables + QTimer* _idleTimer = nullptr; + int _nextFrame = 0; + QElapsedTimer _timer; + char _clientMixBuffer[MAX_PACKET_SIZE]; + int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS; + const int TRAILING_AVERAGE_FRAMES = 100; + int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; }; #endif // hifi_AudioMixer_h diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 80ceccc407..cd45fbdbdf 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -221,6 +221,10 @@ protected: LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton + + ~LimitedNodeList() { + qDebug() << "XXXXXXXXXXXXXXXXXXXX ~LimitedNodeList called"; + } qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, const QUuid& connectionSecret); diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 79b4e7f437..eda3da8479 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -30,6 +30,17 @@ void ThreadedAssignment::setFinished(bool isFinished) { _isFinished = isFinished; if (_isFinished) { + if (_domainServerTimer) { + _domainServerTimer->stop(); + delete _domainServerTimer; + _domainServerTimer = nullptr; + } + if (_statsTimer) { + _statsTimer->stop(); + delete _statsTimer; + _statsTimer = nullptr; + } + aboutToFinish(); auto nodeList = DependencyManager::get(); @@ -63,15 +74,15 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy // this is a temp fix for Qt 5.3 - rebinding the node socket gives us readyRead for the socket on this thread nodeList->rebindNodeSocket(); - QTimer* domainServerTimer = new QTimer(this); - connect(domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); - domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); + _domainServerTimer = new QTimer(this); + connect(_domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); + _domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); if (shouldSendStats) { // send a stats packet every 1 second - QTimer* statsTimer = new QTimer(this); - connect(statsTimer, &QTimer::timeout, this, &ThreadedAssignment::sendStatsPacket); - statsTimer->start(1000); + _statsTimer = new QTimer(this); + connect(_statsTimer, &QTimer::timeout, this, &ThreadedAssignment::sendStatsPacket); + _statsTimer->start(1000); } } diff --git a/libraries/networking/src/ThreadedAssignment.h b/libraries/networking/src/ThreadedAssignment.h index 454baa85f2..04bee08e62 100644 --- a/libraries/networking/src/ThreadedAssignment.h +++ b/libraries/networking/src/ThreadedAssignment.h @@ -28,8 +28,16 @@ public: public slots: /// threaded run of assignment virtual void run() = 0; + Q_INVOKABLE void stop() { setFinished(true); } virtual void readPendingDatagrams() = 0; virtual void sendStatsPacket(); + +public slots: + virtual void aboutToQuit() { + // emit finished(); + QMetaObject::invokeMethod(this, "stop"); + } + signals: void finished(); @@ -38,6 +46,8 @@ protected: void commonInit(const QString& targetName, NodeType_t nodeType, bool shouldSendStats = true); bool _isFinished; QThread* _datagramProcessingThread; + QTimer* _domainServerTimer = nullptr; + QTimer* _statsTimer = nullptr; private slots: void checkInWithDomainServerOrExit(); From 8b9236a18dee96ffdc1c22d67c762231aa5661ff Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Wed, 29 Apr 2015 09:44:22 -0700 Subject: [PATCH 06/36] added grab.js script, which allows users to grab and fling physical objects --- examples/grab.js | 223 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 examples/grab.js diff --git a/examples/grab.js b/examples/grab.js new file mode 100644 index 0000000000..eca457f0b2 --- /dev/null +++ b/examples/grab.js @@ -0,0 +1,223 @@ +var isGrabbing = false; +var grabbedEntity = null; +var prevMouse = {}; +var deltaMouse = { + z: 0 +} +var entityProps; +var box, box2, ground; +var baseMoveFactor = .001; +var finalMoveMultiplier; +var avatarEntityDistance; +var camYaw, dv; +var prevPosition; +var newPosition; +var flingVelocity; +var flingMultiplier = 10; +var moveUpDown = false; +var savedGravity; + +var DROP_DISTANCE = 5.0; +var DROP_COLOR = { + red: 200, + green: 200, + blue: 200 +}; +var DROP_WIDTH = 4; + + +var autoBox = false; +if (autoBox) { + setUpTestObjects(); +} + +var dropLine = Overlays.addOverlay("line3d", { + start: { + x: 0, + y: 0, + z: 0 + }, + end: { + x: 0, + y: 0, + z: 0 + }, + color: DROP_COLOR, + alpha: 1, + visible: false, + lineWidth: DROP_WIDTH +}); + + +function mousePressEvent(event) { + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Entities.findRayIntersection(pickRay); + if (intersection.intersects && intersection.properties.collisionsWillMove) { + grabbedEntity = intersection.entityID; + var props = Entities.getEntityProperties(grabbedEntity) + prevPosition = props.position; + isGrabbing = true; + savedGravity = props.gravity; + Overlays.editOverlay(dropLine, { + visible: true + }); + Entities.editEntity(grabbedEntity, { + gravity: { + x: 0, + y: 0, + z: 0 + } + }); + //We need to store entity's current gravity, and then disable it while we move + + } + +} + + +function mouseReleaseEvent() { + if (isGrabbing) { + flingObject(); + Entities.editEntity(grabbedEntity, { + gravity: savedGravity + }); + } + isGrabbing = false; + Overlays.editOverlay(dropLine, { + visible: false + }); +} + +function flingObject() { + //calculate velocity to give object base on current and previous position + entityProps = Entities.getEntityProperties(grabbedEntity); + + flingVelocity = Vec3.subtract(entityProps.position, prevPosition); + flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); + flingVelocity.y = 0; + Entities.editEntity(grabbedEntity, { + velocity: flingVelocity + }); +} + +function mouseMoveEvent(event) { + if (isGrabbing) { + entityProps = Entities.getEntityProperties(grabbedEntity); + prevPosition = entityProps.position; + avatarEntityDistance = Vec3.distance(MyAvatar.position, entityProps.position); + finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); + deltaMouse.x = event.x - prevMouse.x; + if (!moveUpDown) { + deltaMouse.z = event.y - prevMouse.y; + } else { + deltaMouse.y = (event.y - prevMouse.y) * -1; + } + finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); + deltaMouse = Vec3.multiply(deltaMouse, finalMoveMultiplier); + camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y; + dv = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse); + newPosition = Vec3.sum(entityProps.position, dv); + Entities.editEntity(grabbedEntity, { + position: newPosition + }); + Overlays.editOverlay(dropLine, { + start: newPosition, + end: Vec3.sum(newPosition, { + x: 0, + y: -DROP_DISTANCE, + z: 0 + }) + }); + } + prevMouse.x = event.x; + prevMouse.y = event.y; +} + +function keyReleaseEvent(event) { + if (event.text === "SHIFT") { + moveUpDown = false; + } +} + +function keyPressEvent(event) { + if (event.text === "SHIFT") { + moveUpDown = true; + } +} + +function cleanup() { + Entities.deleteEntity(box); + Entities.deleteEntity(box2); + Entities.deleteEntity(ground); +} + +function setUpTestObjects() { + var distance = 4; + box = Entities.addEntity({ + type: 'Box', + position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance, Quat.getFront(Camera.getOrientation()))), + dimensions: { + x: .5, + y: .5, + z: .5 + }, + color: { + red: 200, + green: 50, + blue: 192 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -1, + z: 0 + } + }); + + box2 = Entities.addEntity({ + type: 'Box', + position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance + 1, Quat.getFront(Camera.getOrientation()))), + dimensions: { + x: .5, + y: .5, + z: .5 + }, + color: { + red: 200, + green: 50, + blue: 192 + }, + collisionsWillMove: true, + gravity: { + x: 0, + y: -1, + z: 0 + } + }); + + ground = Entities.addEntity({ + type: 'Box', + position: { + x: MyAvatar.position.x, + y: MyAvatar.position.y - 5, + z: MyAvatar.position.z + }, + dimensions: { + x: 100, + y: 2, + z: 100 + }, + color: { + red: 20, + green: 200, + blue: 50 + } + }); +} + +Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.scriptEnding.connect(cleanup); \ No newline at end of file From 489fbaac5765e6b68e821a6b40557b361df02dfa Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Wed, 29 Apr 2015 09:45:58 -0700 Subject: [PATCH 07/36] added grab.js to defaultScripts.js --- examples/defaultScripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index 05ffb0bd3f..a5c086fc44 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -18,3 +18,4 @@ Script.load("lobby.js"); Script.load("notifications.js"); Script.load("look.js"); Script.load("users.js"); +Script.load("grab.js"); From d2cd4fc405f21691855099b8043a03f52f52cdb8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 11:56:45 -0700 Subject: [PATCH 08/36] types 0 and 1 exit cleanly, type 6 crashes --- assignment-client/src/AssignmentClient.cpp | 7 +- assignment-client/src/AssignmentClientApp.cpp | 2 + assignment-client/src/audio/AudioMixer.cpp | 153 ++++++++---------- assignment-client/src/audio/AudioMixer.h | 17 +- assignment-client/src/avatars/AvatarMixer.cpp | 32 +++- assignment-client/src/avatars/AvatarMixer.h | 5 + .../src/entities/EntityServer.cpp | 22 ++- assignment-client/src/entities/EntityServer.h | 2 + .../src/octree/OctreeInboundPacketProcessor.h | 3 +- assignment-client/src/octree/OctreeServer.cpp | 39 ++++- assignment-client/src/octree/OctreeServer.h | 1 + .../networking/src/ReceivedPacketProcessor.h | 4 +- .../networking/src/ThreadedAssignment.cpp | 18 +++ libraries/networking/src/ThreadedAssignment.h | 6 +- libraries/octree/src/OctreePersistThread.cpp | 1 + libraries/shared/src/DependencyManager.h | 10 +- 16 files changed, 211 insertions(+), 111 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 5a6868e7e4..dc4d06e52e 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -116,8 +116,11 @@ void AssignmentClient::stopAssignmentClient() { _statsTimerACM.stop(); if (_currentAssignment) { _currentAssignment->aboutToQuit(); - // _currentAssignment->aboutToFinish(); - _currentAssignment->thread()->wait(); + QThread* currentAssignmentThread = _currentAssignment->thread(); + qDebug() << "main thread waiting on _currentAssignment->thread()" << currentAssignmentThread->objectName(); + currentAssignmentThread->quit(); + currentAssignmentThread->wait(); + qDebug() << "done waiting."; } } diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 2fcbd67be1..c234daac68 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -183,6 +183,8 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : QThread::currentThread()->setObjectName("main thread"); + DependencyManager::registerInheritance(); + if (numForks || minForks || maxForks) { AssignmentClientMonitor monitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 5d7601ba55..06e6f77f69 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -588,6 +588,7 @@ void AudioMixer::sendStatsPacket() { _sumMixes = 0; _numStatFrames = 0; + // NOTE: These stats can be too large to fit in an MTU, so we break it up into multiple packts... QJsonObject statsObject2; @@ -711,90 +712,78 @@ void AudioMixer::run() { // check the settings object to see if we have anything we can parse out parseSettingsObject(settingsObject); - _nextFrame = 0; - _timer.start(); + int nextFrame = 0; + QElapsedTimer timer; + timer.start(); - _idleTimer = new QTimer(); - connect(_idleTimer, SIGNAL(timeout()), this, SLOT(insideLoop())); - _idleTimer->start(0); -} + char clientMixBuffer[MAX_PACKET_SIZE]; + + int usecToSleep = AudioConstants::NETWORK_FRAME_USECS; + + const int TRAILING_AVERAGE_FRAMES = 100; + int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; - -void AudioMixer::insideLoop() { - if (_isFinished) { - qDebug() << "AudioMixer::insideLoop stoping _idleTimer"; - _idleTimer->stop(); - delete _idleTimer; - _idleTimer = nullptr; - - QThread *thisThread = QThread::currentThread(); - thisThread->quit(); - - return; - } - - auto nodeList = DependencyManager::get(); - - const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; - const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; + while (!_isFinished) { + const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; + const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; - const float RATIO_BACK_OFF = 0.02f; + const float RATIO_BACK_OFF = 0.02f; - const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; - const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; + const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; + const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; - if (_usecToSleep < 0) { - _usecToSleep = 0; - } + if (usecToSleep < 0) { + usecToSleep = 0; + } - _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) - + (_usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); + _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) + + (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); - float lastCutoffRatio = _performanceThrottlingRatio; - bool hasRatioChanged = false; + float lastCutoffRatio = _performanceThrottlingRatio; + bool hasRatioChanged = false; - if (_framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { - if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { - // we're struggling - change our min required loudness to reduce some load - _performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio)); + if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { + if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { + // we're struggling - change our min required loudness to reduce some load + _performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio)); - qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; - hasRatioChanged = true; - } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) { - // we've recovered and can back off the required loudness - _performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF; + qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" + << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; + hasRatioChanged = true; + } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) { + // we've recovered and can back off the required loudness + _performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF; - if (_performanceThrottlingRatio < 0) { - _performanceThrottlingRatio = 0; + if (_performanceThrottlingRatio < 0) { + _performanceThrottlingRatio = 0; + } + + qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" + << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; + hasRatioChanged = true; } - - qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; - hasRatioChanged = true; - } - if (hasRatioChanged) { - // set out min audability threshold from the new ratio - _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio)); - qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; + if (hasRatioChanged) { + // set out min audability threshold from the new ratio + _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio)); + qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; - _framesSinceCutoffEvent = 0; + framesSinceCutoffEvent = 0; + } } - } - if (!hasRatioChanged) { - ++_framesSinceCutoffEvent; - } + if (!hasRatioChanged) { + ++framesSinceCutoffEvent; + } - quint64 now = usecTimestampNow(); - if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) { - perSecondActions(); - _lastPerSecondCallbackTime = now; - } + quint64 now = usecTimestampNow(); + if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) { + perSecondActions(); + _lastPerSecondCallbackTime = now; + } - nodeList->eachNode([&](const SharedNodePointer& node) { - + nodeList->eachNode([&](const SharedNodePointer& node) { + if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); @@ -818,8 +807,8 @@ void AudioMixer::insideLoop() { char* mixDataAt; if (streamsMixed > 0) { // pack header - int numBytesMixPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeMixedAudio); - mixDataAt = _clientMixBuffer + numBytesMixPacketHeader; + int numBytesMixPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); + mixDataAt = clientMixBuffer + numBytesMixPacketHeader; // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); @@ -831,8 +820,8 @@ void AudioMixer::insideLoop() { mixDataAt += AudioConstants::NETWORK_FRAME_BYTES_STEREO; } else { // pack header - int numBytesPacketHeader = populatePacketHeader(_clientMixBuffer, PacketTypeSilentAudioFrame); - mixDataAt = _clientMixBuffer + numBytesPacketHeader; + int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeSilentAudioFrame); + mixDataAt = clientMixBuffer + numBytesPacketHeader; // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); @@ -844,12 +833,12 @@ void AudioMixer::insideLoop() { memcpy(mixDataAt, &numSilentSamples, sizeof(quint16)); mixDataAt += sizeof(quint16); } - + // Send audio environment sendAudioEnvironmentPacket(node); // send mixed audio packet - nodeList->writeDatagram(_clientMixBuffer, mixDataAt - _clientMixBuffer, node); + nodeList->writeDatagram(clientMixBuffer, mixDataAt - clientMixBuffer, node); nodeData->incrementOutgoingMixedAudioSequenceNumber(); // send an audio stream stats packet if it's time @@ -863,22 +852,22 @@ void AudioMixer::insideLoop() { } }); - ++_numStatFrames; + ++_numStatFrames; - QCoreApplication::processEvents(); + QCoreApplication::processEvents(); - if (_isFinished) { - return; - } + if (_isFinished) { + break; + } - _usecToSleep = (++_nextFrame * AudioConstants::NETWORK_FRAME_USECS) - _timer.nsecsElapsed() / 1000; // ns to us + usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us - if (_usecToSleep > 0) { - usleep(_usecToSleep); + if (usecToSleep > 0) { + usleep(usecToSleep); + } } } - void AudioMixer::perSecondActions() { _sendAudioStreamStats = true; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index a81225a0f2..4894f91e01 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -32,7 +32,6 @@ public: public slots: /// threaded run of assignment void run(); - void insideLoop(); void readPendingDatagrams() { }; // this will not be called since our datagram processing thread will handle void readPendingDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr); @@ -112,14 +111,14 @@ private: MovingMinMaxAvg _readPendingCallsPerSecondStats; // update with # of readPendingDatagrams calls in the last second - // loop variables - QTimer* _idleTimer = nullptr; - int _nextFrame = 0; - QElapsedTimer _timer; - char _clientMixBuffer[MAX_PACKET_SIZE]; - int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS; - const int TRAILING_AVERAGE_FRAMES = 100; - int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; + /* // loop variables */ + /* // QTimer* _idleTimer = nullptr; */ + /* int _nextFrame = 0; */ + /* QElapsedTimer _timer; */ + /* char _clientMixBuffer[MAX_PACKET_SIZE]; */ + /* int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS; */ + /* const int TRAILING_AVERAGE_FRAMES = 100; */ + /* int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; */ }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index dae6af3fc5..8cff7d705d 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -45,6 +45,10 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : } AvatarMixer::~AvatarMixer() { + qDebug() << "AvatarMixer::~AvatarMixer"; + if (_broadcastTimer) { + _broadcastTimer->deleteLater(); + } _broadcastThread.quit(); _broadcastThread.wait(); } @@ -61,9 +65,7 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present // if the avatar is not in view or in the keyhole. void AvatarMixer::broadcastAvatarData() { - int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp; - ++_numStatFrames; const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; @@ -334,6 +336,22 @@ void AvatarMixer::sendStatsPacket() { _numStatFrames = 0; } +// void AvatarMixer::stop() { +// qDebug() << "AvatarMixer::stop"; +// if (_broadcastTimer) { +// // _broadcastTimer->stop(); +// // delete _broadcastTimer; +// _broadcastTimer->deleteLater(); +// // _broadcastTimer = nullptr; +// } + +// _broadcastThread.quit(); +// _broadcastThread.wait(); + +// ThreadedAssignment::stop(); +// } + + void AvatarMixer::run() { ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); @@ -343,13 +361,13 @@ void AvatarMixer::run() { nodeList->linkedDataCreateCallback = attachAvatarDataToNode; // setup the timer that will be fired on the broadcast thread - QTimer* broadcastTimer = new QTimer(); - broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS); - broadcastTimer->moveToThread(&_broadcastThread); + _broadcastTimer = new QTimer(); + _broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS); + _broadcastTimer->moveToThread(&_broadcastThread); // connect appropriate signals and slots - connect(broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection); - connect(&_broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start())); + connect(_broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection); + connect(&_broadcastThread, SIGNAL(started()), _broadcastTimer, SLOT(start())); // start the broadcastThread _broadcastThread.start(); diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index a69019427b..2a659cface 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -25,6 +25,7 @@ public: public slots: /// runs the avatar mixer void run(); + // Q_INVOKABLE virtual void stop(); void nodeAdded(SharedNodePointer nodeAdded); void nodeKilled(SharedNodePointer killedNode); @@ -32,6 +33,8 @@ public slots: void readPendingDatagrams(); void sendStatsPacket(); + + void finished(); private: void broadcastAvatarData(); @@ -47,6 +50,8 @@ private: int _numStatFrames; int _sumBillboardPackets; int _sumIdentityPackets; + + QTimer* _broadcastTimer = nullptr; }; #endif // hifi_AvatarMixer_h diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 85d0a7414c..e38d0e3c65 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -27,6 +27,13 @@ EntityServer::EntityServer(const QByteArray& packet) } EntityServer::~EntityServer() { + qDebug() << "EntityServer::~EntityServer"; + + if (_pruneDeletedEntitiesTimer) { + _pruneDeletedEntitiesTimer->stop(); + _pruneDeletedEntitiesTimer->deleteLater(); + } + EntityTree* tree = (EntityTree*)_tree; tree->removeNewlyCreatedHook(this); } @@ -48,10 +55,10 @@ Octree* EntityServer::createTree() { } void EntityServer::beforeRun() { - QTimer* pruneDeletedEntitiesTimer = new QTimer(this); - connect(pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities())); + _pruneDeletedEntitiesTimer = new QTimer(this); + connect(_pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities())); const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second - pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS); + _pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS); } void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) { @@ -158,3 +165,12 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio } +// void EntityServer::stop() { +// qDebug() << "EntityServer::stop"; +// if (_pruneDeletedEntitiesTimer) { +// _pruneDeletedEntitiesTimer->stop(); +// delete _pruneDeletedEntitiesTimer; +// _pruneDeletedEntitiesTimer = nullptr; +// } +// OctreeServer::stop(); +// } diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index d8c2e39f3b..78c20d039c 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -44,6 +44,7 @@ public: virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); public slots: + // Q_INVOKABLE virtual void stop(); void pruneDeletedEntities(); protected: @@ -51,6 +52,7 @@ protected: private: EntitySimulation* _entitySimulation; + QTimer* _pruneDeletedEntitiesTimer = nullptr; }; #endif // hifi_EntityServer_h diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h index 8f07f9d566..2f9c060183 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.h +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.h @@ -74,7 +74,8 @@ public: NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; } - void shuttingDown() { _shuttingDown = true;} + // void shuttingDown() { _shuttingDown = true;} + virtual void terminating() { _shuttingDown = true; ReceivedPacketProcessor::terminating(); } protected: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 266183745f..725f4eda2c 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -266,16 +266,19 @@ OctreeServer::~OctreeServer() { } if (_jurisdictionSender) { + _jurisdictionSender->terminating(); _jurisdictionSender->terminate(); _jurisdictionSender->deleteLater(); } if (_octreeInboundPacketProcessor) { + _octreeInboundPacketProcessor->terminating(); _octreeInboundPacketProcessor->terminate(); _octreeInboundPacketProcessor->deleteLater(); } if (_persistThread) { + _persistThread->terminating(); _persistThread->terminate(); _persistThread->deleteLater(); } @@ -1219,7 +1222,7 @@ void OctreeServer::forceNodeShutdown(SharedNodePointer node) { void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish..."; qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; - _octreeInboundPacketProcessor->shuttingDown(); + _octreeInboundPacketProcessor->terminating(); DependencyManager::get()->eachNode([this](const SharedNodePointer& node) { qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; @@ -1233,6 +1236,40 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish..."; } + +// void OctreeServer::stop() { +// qDebug() << "OctreeServer::stop"; +// // setFinished(true); +// // QThread *thisThread = QThread::currentThread(); +// // thisThread->quit(); + +// if (_jurisdictionSender) { +// _jurisdictionSender->terminating(); +// _jurisdictionSender->terminate(); +// // delete _jurisdictionSender; +// // _jurisdictionSender = nullptr; +// } + +// _datagramProcessingThread->quit(); +// if (_octreeInboundPacketProcessor) { +// _octreeInboundPacketProcessor->terminating(); +// _octreeInboundPacketProcessor->terminate(); +// // delete _octreeInboundPacketProcessor; +// // _octreeInboundPacketProcessor = nullptr; +// } + +// // _persistThread +// if (_persistThread) { +// _persistThread->terminating(); +// _persistThread->terminate(); +// // delete _persistThread; +// // _persistThread = nullptr; +// } + +// ThreadedAssignment::stop(); +// } + + QString OctreeServer::getUptime() { QString formattedUptime; quint64 now = usecTimestampNow(); diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 41cd3259cf..10c4e81262 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -123,6 +123,7 @@ public: public slots: /// runs the octree server assignment void run(); + // Q_INVOKABLE virtual void stop(); void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); void sendStatsPacket(); diff --git a/libraries/networking/src/ReceivedPacketProcessor.h b/libraries/networking/src/ReceivedPacketProcessor.h index d5fc006882..bcc9f9a1f5 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.h +++ b/libraries/networking/src/ReceivedPacketProcessor.h @@ -47,6 +47,8 @@ public: /// How many received packets waiting are to be processed int packetsToProcessCount() const { return _packets.size(); } + virtual void terminating(); + public slots: void nodeKilled(SharedNodePointer node); @@ -71,8 +73,6 @@ protected: /// Override to do work after the packets processing loop. Default does nothing. virtual void postProcess() { } - virtual void terminating(); - protected: QVector _packets; diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index eda3da8479..c212aab188 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -26,7 +26,14 @@ ThreadedAssignment::ThreadedAssignment(const QByteArray& packet) : } +ThreadedAssignment::~ThreadedAssignment() { + // setFinished(true); +} + void ThreadedAssignment::setFinished(bool isFinished) { + + qDebug() << "------------- ThreadedAssignment::setFinished" << isFinished << " -------------------"; + _isFinished = isFinished; if (_isFinished) { @@ -50,8 +57,10 @@ void ThreadedAssignment::setFinished(bool isFinished) { if (_datagramProcessingThread) { // tell the datagram processing thread to quit and wait until it is done, then return the node socket to the NodeList + qDebug() << "stopping datagramProcessingThread..."; _datagramProcessingThread->quit(); _datagramProcessingThread->wait(); + qDebug() << "done stopping datagramProcessingThread."; // set node socket parent back to NodeList nodeList->getNodeSocket().setParent(nodeList.data()); @@ -64,6 +73,15 @@ void ThreadedAssignment::setFinished(bool isFinished) { } } + +// void ThreadedAssignment::stop() { +// setFinished(true); +// qDebug() << "ThreadedAssignment::stop"; +// QThread *thisThread = QThread::currentThread(); +// thisThread->quit(); +// } + + void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeType, bool shouldSendStats) { // change the logging target name while the assignment is running LogHandler::getInstance().setTargetName(targetName); diff --git a/libraries/networking/src/ThreadedAssignment.h b/libraries/networking/src/ThreadedAssignment.h index 04bee08e62..e2c6e0a1b6 100644 --- a/libraries/networking/src/ThreadedAssignment.h +++ b/libraries/networking/src/ThreadedAssignment.h @@ -20,6 +20,7 @@ class ThreadedAssignment : public Assignment { Q_OBJECT public: ThreadedAssignment(const QByteArray& packet); + virtual ~ThreadedAssignment(); void setFinished(bool isFinished); virtual void aboutToFinish() { }; @@ -28,14 +29,13 @@ public: public slots: /// threaded run of assignment virtual void run() = 0; - Q_INVOKABLE void stop() { setFinished(true); } + Q_INVOKABLE virtual void stop() { setFinished(true); } virtual void readPendingDatagrams() = 0; virtual void sendStatsPacket(); public slots: virtual void aboutToQuit() { - // emit finished(); - QMetaObject::invokeMethod(this, "stop"); + QMetaObject::invokeMethod(this, "stop"); } signals: diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index 210d074001..52dd2aa4ca 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -228,6 +228,7 @@ void OctreePersistThread::aboutToFinish() { qCDebug(octree) << "Persist thread about to finish..."; persist(); qCDebug(octree) << "Persist thread done with about to finish..."; + _stopThread = true; } void OctreePersistThread::persist() { diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 01b755fdd0..1d91872940 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -26,15 +26,21 @@ class Dependency { public: typedef std::function DeleterFunction; + const QString& getDependencyName() { return _name; } protected: - virtual ~Dependency() {} + virtual ~Dependency() { + qDebug() << "DESTRUCTING" << _name; + } virtual void customDeleter() { _customDeleter(this); } void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; + + void setDependencyName(QString name) { _name = name; } + QString _name; friend class DependencyManager; }; @@ -95,6 +101,7 @@ QSharedPointer DependencyManager::set(Args&&... args) { QSharedPointer newInstance(new T(args...), &T::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); instance.swap(storedInstance); + newInstance->setDependencyName(typeid(T).name()); return newInstance; } @@ -102,6 +109,7 @@ QSharedPointer DependencyManager::set(Args&&... args) { template void DependencyManager::destroy() { static size_t hashCode = _manager.getHashCode(); + qDebug() << "DESTROYING" << _manager.safeGet(hashCode)->getDependencyName(); _manager.safeGet(hashCode).clear(); } From e7d8bccd5d299887792b613e44f555cf749d225c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 12:03:54 -0700 Subject: [PATCH 09/36] cleanups --- assignment-client/src/audio/AudioMixer.h | 9 ----- assignment-client/src/avatars/AvatarMixer.cpp | 18 ++-------- assignment-client/src/avatars/AvatarMixer.h | 3 -- .../src/entities/EntityServer.cpp | 11 ------ assignment-client/src/entities/EntityServer.h | 1 - assignment-client/src/octree/OctreeServer.cpp | 34 ------------------- assignment-client/src/octree/OctreeServer.h | 1 - .../networking/src/ThreadedAssignment.cpp | 9 ----- 8 files changed, 2 insertions(+), 84 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 4894f91e01..6cee557ff9 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -110,15 +110,6 @@ private: MovingMinMaxAvg _timeSpentPerHashMatchCallStats; // update with usecs spent inside each packetVersionAndHashMatch call MovingMinMaxAvg _readPendingCallsPerSecondStats; // update with # of readPendingDatagrams calls in the last second - - /* // loop variables */ - /* // QTimer* _idleTimer = nullptr; */ - /* int _nextFrame = 0; */ - /* QElapsedTimer _timer; */ - /* char _clientMixBuffer[MAX_PACKET_SIZE]; */ - /* int _usecToSleep = AudioConstants::NETWORK_FRAME_USECS; */ - /* const int TRAILING_AVERAGE_FRAMES = 100; */ - /* int _framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; */ }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 8cff7d705d..5612450f1f 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -65,7 +65,9 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present // if the avatar is not in view or in the keyhole. void AvatarMixer::broadcastAvatarData() { + int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp; + ++_numStatFrames; const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; @@ -336,22 +338,6 @@ void AvatarMixer::sendStatsPacket() { _numStatFrames = 0; } -// void AvatarMixer::stop() { -// qDebug() << "AvatarMixer::stop"; -// if (_broadcastTimer) { -// // _broadcastTimer->stop(); -// // delete _broadcastTimer; -// _broadcastTimer->deleteLater(); -// // _broadcastTimer = nullptr; -// } - -// _broadcastThread.quit(); -// _broadcastThread.wait(); - -// ThreadedAssignment::stop(); -// } - - void AvatarMixer::run() { ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 2a659cface..4746f02d14 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -25,7 +25,6 @@ public: public slots: /// runs the avatar mixer void run(); - // Q_INVOKABLE virtual void stop(); void nodeAdded(SharedNodePointer nodeAdded); void nodeKilled(SharedNodePointer killedNode); @@ -33,8 +32,6 @@ public slots: void readPendingDatagrams(); void sendStatsPacket(); - - void finished(); private: void broadcastAvatarData(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index e38d0e3c65..b2a1c62ed4 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -163,14 +163,3 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio EntityTree* tree = static_cast(_tree); tree->setWantEditLogging(wantEditLogging); } - - -// void EntityServer::stop() { -// qDebug() << "EntityServer::stop"; -// if (_pruneDeletedEntitiesTimer) { -// _pruneDeletedEntitiesTimer->stop(); -// delete _pruneDeletedEntitiesTimer; -// _pruneDeletedEntitiesTimer = nullptr; -// } -// OctreeServer::stop(); -// } diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 78c20d039c..9edec7b704 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -44,7 +44,6 @@ public: virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject); public slots: - // Q_INVOKABLE virtual void stop(); void pruneDeletedEntities(); protected: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 725f4eda2c..506733e13d 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1236,40 +1236,6 @@ void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish..."; } - -// void OctreeServer::stop() { -// qDebug() << "OctreeServer::stop"; -// // setFinished(true); -// // QThread *thisThread = QThread::currentThread(); -// // thisThread->quit(); - -// if (_jurisdictionSender) { -// _jurisdictionSender->terminating(); -// _jurisdictionSender->terminate(); -// // delete _jurisdictionSender; -// // _jurisdictionSender = nullptr; -// } - -// _datagramProcessingThread->quit(); -// if (_octreeInboundPacketProcessor) { -// _octreeInboundPacketProcessor->terminating(); -// _octreeInboundPacketProcessor->terminate(); -// // delete _octreeInboundPacketProcessor; -// // _octreeInboundPacketProcessor = nullptr; -// } - -// // _persistThread -// if (_persistThread) { -// _persistThread->terminating(); -// _persistThread->terminate(); -// // delete _persistThread; -// // _persistThread = nullptr; -// } - -// ThreadedAssignment::stop(); -// } - - QString OctreeServer::getUptime() { QString formattedUptime; quint64 now = usecTimestampNow(); diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 10c4e81262..41cd3259cf 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -123,7 +123,6 @@ public: public slots: /// runs the octree server assignment void run(); - // Q_INVOKABLE virtual void stop(); void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); void sendStatsPacket(); diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index c212aab188..6ec47d7cdd 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -73,15 +73,6 @@ void ThreadedAssignment::setFinished(bool isFinished) { } } - -// void ThreadedAssignment::stop() { -// setFinished(true); -// qDebug() << "ThreadedAssignment::stop"; -// QThread *thisThread = QThread::currentThread(); -// thisThread->quit(); -// } - - void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeType, bool shouldSendStats) { // change the logging target name while the assignment is running LogHandler::getInstance().setTargetName(targetName); From 009bb9dc710fe34376ff546050899e6320332457 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 15:16:00 -0700 Subject: [PATCH 10/36] all 4 types of assignment-client appear to exit cleanly, now --- assignment-client/src/AssignmentClient.cpp | 8 ++++++++ assignment-client/src/AssignmentClientApp.cpp | 3 --- .../src/AssignmentClientMonitor.cpp | 2 ++ .../src/entities/EntityServer.cpp | 2 ++ assignment-client/src/octree/OctreeServer.cpp | 18 ++++++++++++++---- assignment-client/src/octree/OctreeServer.h | 3 +++ libraries/networking/src/LimitedNodeList.h | 4 +--- libraries/networking/src/NodeList.h | 5 +++++ libraries/shared/src/LogHandler.h | 6 ++++++ 9 files changed, 41 insertions(+), 10 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index dc4d06e52e..4f00b30f42 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -126,7 +126,15 @@ void AssignmentClient::stopAssignmentClient() { void AssignmentClient::aboutToQuit() { + qDebug() << "AssignmentClient::aboutToQuit start"; stopAssignmentClient(); + qDebug() << "AssignmentClient::aboutToQuit end"; + // clear the log handler so that Qt doesn't call the destructor on LogHandler + qInstallMessageHandler(0); + // clear out pointer to the assignment so the destructor gets called. if we don't do this here, + // it will get destroyed along with all the other "static" stuff. various static member variables + // will be destroyed first and things go wrong. + _currentAssignment.clear(); } diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index c234daac68..d8e4306ec5 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -167,7 +167,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : } - if (parser.isSet(numChildsOption)) { if (minForks && minForks > numForks) { qCritical() << "--min can't be more than -n"; @@ -189,8 +188,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : AssignmentClientMonitor monitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool, walletUUID, assignmentServerHostname, assignmentServerPort); connect(this, &QCoreApplication::aboutToQuit, &monitor, &AssignmentClientMonitor::aboutToQuit); - - exec(); } else { AssignmentClient client(ppid, requestAssignmentType, assignmentPool, diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 14eb93ad6e..31743ea630 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -83,6 +83,8 @@ void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::aboutToQuit() { stopChildProcesses(); + // clear the log handler so that Qt doesn't call the destructor on LogHandler + qInstallMessageHandler(0); } diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index b2a1c62ed4..a175eef475 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -163,3 +163,5 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio EntityTree* tree = static_cast(_tree); tree->setWantEditLogging(wantEditLogging); } + + diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 506733e13d..11509192ad 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -239,8 +239,10 @@ OctreeServer::OctreeServer(const QByteArray& packet) : _octreeInboundPacketProcessor(NULL), _persistThread(NULL), _started(time(0)), - _startedUSecs(usecTimestampNow()) + _startedUSecs(usecTimestampNow()), + _nodeList(DependencyManager::get()) { + if (_instance) { qDebug() << "Octree Server starting... while old instance still running _instance=["<<_instance<<"] this=[" << this << "]"; } @@ -1098,7 +1100,7 @@ void OctreeServer::readConfiguration() { } void OctreeServer::run() { - qInstallMessageHandler(LogHandler::verboseMessageHandler); + // qInstallMessageHandler(LogHandler::verboseMessageHandler); _safeServerName = getMyServerName(); @@ -1222,8 +1224,15 @@ void OctreeServer::forceNodeShutdown(SharedNodePointer node) { void OctreeServer::aboutToFinish() { qDebug() << qPrintable(_safeServerName) << "server STARTING about to finish..."; qDebug() << qPrintable(_safeServerName) << "inform Octree Inbound Packet Processor that we are shutting down..."; - _octreeInboundPacketProcessor->terminating(); - + + if (_octreeInboundPacketProcessor) { + _octreeInboundPacketProcessor->terminating(); + } + + if (_jurisdictionSender) { + _jurisdictionSender->terminating(); + } + DependencyManager::get()->eachNode([this](const SharedNodePointer& node) { qDebug() << qPrintable(_safeServerName) << "server about to finish while node still connected node:" << *node; forceNodeShutdown(node); @@ -1231,6 +1240,7 @@ void OctreeServer::aboutToFinish() { if (_persistThread) { _persistThread->aboutToFinish(); + _persistThread->terminating(); } qDebug() << qPrintable(_safeServerName) << "server ENDING about to finish..."; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 41cd3259cf..09368fbe4d 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -238,6 +238,9 @@ protected: static QMutex _threadsDidPacketDistributorMutex; static QMutex _threadsDidHandlePacketSendMutex; static QMutex _threadsDidCallWriteDatagramMutex; + + // keep a pointer to node list so that it doesn't get shut down before this class. + QSharedPointer _nodeList; }; #endif // hifi_OctreeServer_h diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index cd45fbdbdf..f541a29d01 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -222,7 +222,7 @@ protected: LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton - ~LimitedNodeList() { + virtual ~LimitedNodeList() { qDebug() << "XXXXXXXXXXXXXXXXXXXX ~LimitedNodeList called"; } @@ -241,8 +241,6 @@ protected: HifiSockAddr _localSockAddr; HifiSockAddr _publicSockAddr; HifiSockAddr _stunSockAddr; - - QTimer* _silentNodeTimer; // XXX can BandwidthRecorder be used for this? int _numCollectedPackets; diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index ccfaa7a4cf..4cb3fb8ea2 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -45,6 +45,11 @@ class NodeList : public LimitedNodeList { SINGLETON_DEPENDENCY public: + virtual ~NodeList() { + qDebug() << "XXXXXXXXXXXXXXXXXXXX ~NodeList called"; + } + + NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 914cad212d..1e9567b4d7 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -19,6 +19,8 @@ #include #include +#include + const int VERBOSE_LOG_INTERVAL_SECONDS = 5; enum LogMsgType { @@ -34,6 +36,10 @@ class LogHandler : public QObject { Q_OBJECT public: static LogHandler& getInstance(); + + virtual ~LogHandler() { + std::cerr << "XXXXXXXX ~LogHandler()\n"; + } /// sets the target name to output via the verboseMessageHandler, called once before logging begins /// \param targetName the desired target name to output in logs From e985f56b122a883a767348aa0b911c5e915ab878 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 15:30:13 -0700 Subject: [PATCH 11/36] cleanups --- assignment-client/src/AssignmentClient.cpp | 4 ---- assignment-client/src/AssignmentClientApp.cpp | 1 + .../src/octree/OctreeInboundPacketProcessor.h | 1 - assignment-client/src/octree/OctreeServer.cpp | 6 +----- assignment-client/src/octree/OctreeServer.h | 3 --- libraries/networking/src/LimitedNodeList.h | 4 ---- libraries/networking/src/NodeList.h | 5 ----- libraries/networking/src/ThreadedAssignment.cpp | 9 --------- libraries/networking/src/ThreadedAssignment.h | 1 - libraries/shared/src/DependencyManager.h | 10 +--------- libraries/shared/src/LogHandler.h | 6 ------ 11 files changed, 3 insertions(+), 47 deletions(-) diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 4f00b30f42..594805c7c2 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -117,18 +117,14 @@ void AssignmentClient::stopAssignmentClient() { if (_currentAssignment) { _currentAssignment->aboutToQuit(); QThread* currentAssignmentThread = _currentAssignment->thread(); - qDebug() << "main thread waiting on _currentAssignment->thread()" << currentAssignmentThread->objectName(); currentAssignmentThread->quit(); currentAssignmentThread->wait(); - qDebug() << "done waiting."; } } void AssignmentClient::aboutToQuit() { - qDebug() << "AssignmentClient::aboutToQuit start"; stopAssignmentClient(); - qDebug() << "AssignmentClient::aboutToQuit end"; // clear the log handler so that Qt doesn't call the destructor on LogHandler qInstallMessageHandler(0); // clear out pointer to the assignment so the destructor gets called. if we don't do this here, diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index d8e4306ec5..2de349ca4e 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -167,6 +167,7 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : } + if (parser.isSet(numChildsOption)) { if (minForks && minForks > numForks) { qCritical() << "--min can't be more than -n"; diff --git a/assignment-client/src/octree/OctreeInboundPacketProcessor.h b/assignment-client/src/octree/OctreeInboundPacketProcessor.h index 2f9c060183..156e09b493 100644 --- a/assignment-client/src/octree/OctreeInboundPacketProcessor.h +++ b/assignment-client/src/octree/OctreeInboundPacketProcessor.h @@ -74,7 +74,6 @@ public: NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; } - // void shuttingDown() { _shuttingDown = true;} virtual void terminating() { _shuttingDown = true; ReceivedPacketProcessor::terminating(); } protected: diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 11509192ad..f6f1c486b5 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -239,10 +239,8 @@ OctreeServer::OctreeServer(const QByteArray& packet) : _octreeInboundPacketProcessor(NULL), _persistThread(NULL), _started(time(0)), - _startedUSecs(usecTimestampNow()), - _nodeList(DependencyManager::get()) + _startedUSecs(usecTimestampNow()) { - if (_instance) { qDebug() << "Octree Server starting... while old instance still running _instance=["<<_instance<<"] this=[" << this << "]"; } @@ -1100,8 +1098,6 @@ void OctreeServer::readConfiguration() { } void OctreeServer::run() { - // qInstallMessageHandler(LogHandler::verboseMessageHandler); - _safeServerName = getMyServerName(); // Before we do anything else, create our tree... diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 09368fbe4d..41cd3259cf 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -238,9 +238,6 @@ protected: static QMutex _threadsDidPacketDistributorMutex; static QMutex _threadsDidHandlePacketSendMutex; static QMutex _threadsDidCallWriteDatagramMutex; - - // keep a pointer to node list so that it doesn't get shut down before this class. - QSharedPointer _nodeList; }; #endif // hifi_OctreeServer_h diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index f541a29d01..a7057b4ed8 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -221,10 +221,6 @@ protected: LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton - - virtual ~LimitedNodeList() { - qDebug() << "XXXXXXXXXXXXXXXXXXXX ~LimitedNodeList called"; - } qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, const QUuid& connectionSecret); diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 4cb3fb8ea2..ccfaa7a4cf 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -45,11 +45,6 @@ class NodeList : public LimitedNodeList { SINGLETON_DEPENDENCY public: - virtual ~NodeList() { - qDebug() << "XXXXXXXXXXXXXXXXXXXX ~NodeList called"; - } - - NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 6ec47d7cdd..eda3da8479 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -26,14 +26,7 @@ ThreadedAssignment::ThreadedAssignment(const QByteArray& packet) : } -ThreadedAssignment::~ThreadedAssignment() { - // setFinished(true); -} - void ThreadedAssignment::setFinished(bool isFinished) { - - qDebug() << "------------- ThreadedAssignment::setFinished" << isFinished << " -------------------"; - _isFinished = isFinished; if (_isFinished) { @@ -57,10 +50,8 @@ void ThreadedAssignment::setFinished(bool isFinished) { if (_datagramProcessingThread) { // tell the datagram processing thread to quit and wait until it is done, then return the node socket to the NodeList - qDebug() << "stopping datagramProcessingThread..."; _datagramProcessingThread->quit(); _datagramProcessingThread->wait(); - qDebug() << "done stopping datagramProcessingThread."; // set node socket parent back to NodeList nodeList->getNodeSocket().setParent(nodeList.data()); diff --git a/libraries/networking/src/ThreadedAssignment.h b/libraries/networking/src/ThreadedAssignment.h index e2c6e0a1b6..590c2f56ca 100644 --- a/libraries/networking/src/ThreadedAssignment.h +++ b/libraries/networking/src/ThreadedAssignment.h @@ -20,7 +20,6 @@ class ThreadedAssignment : public Assignment { Q_OBJECT public: ThreadedAssignment(const QByteArray& packet); - virtual ~ThreadedAssignment(); void setFinished(bool isFinished); virtual void aboutToFinish() { }; diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 1d91872940..cdda72438a 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -26,12 +26,9 @@ class Dependency { public: typedef std::function DeleterFunction; - const QString& getDependencyName() { return _name; } protected: - virtual ~Dependency() { - qDebug() << "DESTRUCTING" << _name; - } + virtual ~Dependency() {} virtual void customDeleter() { _customDeleter(this); } @@ -39,9 +36,6 @@ protected: void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; - void setDependencyName(QString name) { _name = name; } - QString _name; - friend class DependencyManager; }; @@ -101,7 +95,6 @@ QSharedPointer DependencyManager::set(Args&&... args) { QSharedPointer newInstance(new T(args...), &T::customDeleter); QSharedPointer storedInstance = qSharedPointerCast(newInstance); instance.swap(storedInstance); - newInstance->setDependencyName(typeid(T).name()); return newInstance; } @@ -109,7 +102,6 @@ QSharedPointer DependencyManager::set(Args&&... args) { template void DependencyManager::destroy() { static size_t hashCode = _manager.getHashCode(); - qDebug() << "DESTROYING" << _manager.safeGet(hashCode)->getDependencyName(); _manager.safeGet(hashCode).clear(); } diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 1e9567b4d7..914cad212d 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -19,8 +19,6 @@ #include #include -#include - const int VERBOSE_LOG_INTERVAL_SECONDS = 5; enum LogMsgType { @@ -36,10 +34,6 @@ class LogHandler : public QObject { Q_OBJECT public: static LogHandler& getInstance(); - - virtual ~LogHandler() { - std::cerr << "XXXXXXXX ~LogHandler()\n"; - } /// sets the target name to output via the verboseMessageHandler, called once before logging begins /// \param targetName the desired target name to output in logs From 69766f6e595328052468ea4adf4e6b5879865c0d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 15:34:31 -0700 Subject: [PATCH 12/36] cleanups --- assignment-client/src/avatars/AvatarMixer.cpp | 5 ++--- libraries/shared/src/DependencyManager.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 5612450f1f..6c8ba91f1b 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -45,7 +45,6 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : } AvatarMixer::~AvatarMixer() { - qDebug() << "AvatarMixer::~AvatarMixer"; if (_broadcastTimer) { _broadcastTimer->deleteLater(); } @@ -65,9 +64,9 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 300.0f; // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present // if the avatar is not in view or in the keyhole. void AvatarMixer::broadcastAvatarData() { - + int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp; - + ++_numStatFrames; const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index cdda72438a..01b755fdd0 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -35,7 +35,7 @@ protected: void setCustomDeleter(DeleterFunction customDeleter) { _customDeleter = customDeleter; } DeleterFunction _customDeleter = [](Dependency* pointer) { delete pointer; }; - + friend class DependencyManager; }; From b041fd1b7f53336ef937bbe9f02b3c406ffe8c04 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 15:58:56 -0700 Subject: [PATCH 13/36] AssignmentClientMonitor now waits() on children --- .../src/AssignmentClientMonitor.cpp | 22 +++++++++++++++---- .../src/AssignmentClientMonitor.h | 4 +++- .../src/entities/EntityServer.cpp | 2 -- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 31743ea630..df77e33ef0 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -69,6 +69,17 @@ AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); } +void AssignmentClientMonitor::waitOnChildren(int msecs) { + QMutableListIterator i(_childProcesses); + while (i.hasNext()) { + QProcess* childProcess = i.next(); + bool finished = childProcess->waitForFinished(msecs); + if (finished) { + i.remove(); + } + } +} + void AssignmentClientMonitor::stopChildProcesses() { auto nodeList = DependencyManager::get(); @@ -78,8 +89,10 @@ void AssignmentClientMonitor::stopChildProcesses() { QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket()); }); -} + // try to give all the children time to shutdown + waitOnChildren(15000); +} void AssignmentClientMonitor::aboutToQuit() { stopChildProcesses(); @@ -87,10 +100,11 @@ void AssignmentClientMonitor::aboutToQuit() { qInstallMessageHandler(0); } - void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); + _childProcesses.append(assignmentClient); + // unparse the parts of the command-line that the child cares about QStringList _childArguments; if (_assignmentPool != "") { @@ -127,8 +141,6 @@ void AssignmentClientMonitor::spawnChildClient() { qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); } - - void AssignmentClientMonitor::checkSpares() { auto nodeList = DependencyManager::get(); QUuid aSpareId = ""; @@ -164,6 +176,8 @@ void AssignmentClientMonitor::checkSpares() { nodeList->writeUnverifiedDatagram(diePacket, childNode); } } + + waitOnChildren(0); } diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 23f50ef67d..e0129bd9b9 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -32,7 +32,8 @@ public: QString assignmentPool, QUuid walletUUID, QString assignmentServerHostname, quint16 assignmentServerPort); ~AssignmentClientMonitor(); - + + void waitOnChildren(int msecs); void stopChildProcesses(); private slots: void readPendingDatagrams(); @@ -55,6 +56,7 @@ private: QString _assignmentServerHostname; quint16 _assignmentServerPort; + QList _childProcesses; }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index a175eef475..e202c17a7d 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -27,8 +27,6 @@ EntityServer::EntityServer(const QByteArray& packet) } EntityServer::~EntityServer() { - qDebug() << "EntityServer::~EntityServer"; - if (_pruneDeletedEntitiesTimer) { _pruneDeletedEntitiesTimer->stop(); _pruneDeletedEntitiesTimer->deleteLater(); From 0d2991b9b0e31f84d2ca59c494e8280bd6e93f9d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 29 Apr 2015 16:24:36 -0700 Subject: [PATCH 14/36] Update edit.js to buffer mouseMove events This helps keep events from getting backed up on the event queue by handling move events in the update() loop and dropping extra move events that might come before an update. --- examples/edit.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index 59dcbaad19..e6dd03de96 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -592,7 +592,11 @@ var idleMouseTimerId = null; var IDLE_MOUSE_TIMEOUT = 200; var DEFAULT_ENTITY_DRAG_DROP_DISTANCE = 2.0; -function mouseMoveEvent(event) { +var lastMouseMoveEvent = null; +function mouseMoveEventBuffered(event) { + lastMouseMoveEvent = event; +} +function mouseMove(event) { mouseHasMovedSincePress = true; if (placingEntityID) { @@ -661,6 +665,10 @@ function highlightEntityUnderCursor(position, accurateRay) { function mouseReleaseEvent(event) { + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + lastMouseMoveEvent = null; + } if (propertyMenu.mouseReleaseEvent(event) || toolBar.mouseReleaseEvent(event)) { return true; } @@ -772,7 +780,7 @@ function mouseClickEvent(event) { } Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); @@ -882,6 +890,10 @@ Script.update.connect(function (deltaTime) { lastOrientation = Camera.orientation; lastPosition = Camera.position; } + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + lastMouseMoveEvent = null; + } }); function insideBox(center, dimensions, point) { From 09eea83461ac8b8cfb2718b65c4fa686daa369a6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 29 Apr 2015 19:18:58 -0700 Subject: [PATCH 15/36] don't give timers owners while also keeping track of them in as class instance variables --- assignment-client/src/entities/EntityServer.cpp | 2 +- libraries/networking/src/ThreadedAssignment.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index e202c17a7d..bb5042f4b4 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -53,7 +53,7 @@ Octree* EntityServer::createTree() { } void EntityServer::beforeRun() { - _pruneDeletedEntitiesTimer = new QTimer(this); + _pruneDeletedEntitiesTimer = new QTimer(); connect(_pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities())); const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second _pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS); diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index eda3da8479..43bcce4530 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -74,13 +74,13 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy // this is a temp fix for Qt 5.3 - rebinding the node socket gives us readyRead for the socket on this thread nodeList->rebindNodeSocket(); - _domainServerTimer = new QTimer(this); + _domainServerTimer = new QTimer(); connect(_domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); _domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); if (shouldSendStats) { // send a stats packet every 1 second - _statsTimer = new QTimer(this); + _statsTimer = new QTimer(); connect(_statsTimer, &QTimer::timeout, this, &ThreadedAssignment::sendStatsPacket); _statsTimer->start(1000); } From 2b9ec8b6bf4e369316e3288cdf1f95a9b15cd82a Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Wed, 29 Apr 2015 22:13:26 -0700 Subject: [PATCH 16/36] fixed bug in grab.js where drop line overlay was not showing in correct position on first grab --- examples/grab.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/grab.js b/examples/grab.js index eca457f0b2..4e0c536a1b 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -59,7 +59,13 @@ function mousePressEvent(event) { isGrabbing = true; savedGravity = props.gravity; Overlays.editOverlay(dropLine, { - visible: true + visible: true, + start: props.position, + end: Vec3.sum(props.position, { + x: 0, + y: -DROP_DISTANCE, + z: 0 + }) }); Entities.editEntity(grabbedEntity, { gravity: { From 81e23eab28ae151f6ddd5f16bd222787663f7e29 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 29 Apr 2015 22:15:49 -0700 Subject: [PATCH 17/36] Coding standard --- interface/src/devices/DdeFaceTracker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index ece9667816..e28496335f 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -369,7 +369,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { } // Translate DDE coefficients to Faceshift compatible coefficients - for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { + for (int i = 0; i < NUM_EXPRESSIONS; i++) { _coefficients[DDE_TO_FACESHIFT_MAPPING[i]] = packet.expressions[i]; } @@ -393,7 +393,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { float eyeBlinks[] = { DDE_EYEBLINK_SCALE * _coefficients[_leftBlinkIndex], DDE_EYEBLINK_SCALE * _coefficients[_rightBlinkIndex] }; if (isFiltering) { const float BLINK_VELOCITY_FILTER_STRENGTH = 0.3f; - for (int i = 0; i < 2; i += 1) { + for (int i = 0; i < 2; i++) { float velocity = fabs(eyeBlinks[i] - _lastEyeBlinks[i]) / _averageMessageTime; float velocityFilter = glm::clamp(velocity * BLINK_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); _filteredEyeBlinks[i] = velocityFilter * eyeBlinks[i] + (1.0f - velocityFilter) * _filteredEyeBlinks[i]; @@ -403,7 +403,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Finesse EyeBlink values float eyeCoefficients[2]; - for (int i = 0; i < 2; i += 1) { + for (int i = 0; i < 2; i++) { // Scale EyeBlink values so that they can be used to control both EyeBlink and EyeOpen // -ve values control EyeOpen; +ve values control EyeBlink static const float EYE_CONTROL_THRESHOLD = 0.5f; // Resting eye value @@ -472,7 +472,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { } // Scale all coefficients - for (int i = 0; i < NUM_EXPRESSIONS; i += 1) { + for (int i = 0; i < NUM_EXPRESSIONS; i++) { _blendshapeCoefficients[i] = glm::clamp(DDE_COEFFICIENT_SCALES[i] * _coefficients[i], 0.0f, 1.0f); } From 45ba6786869aad82fb07f6f9f9a279158e299a37 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Wed, 29 Apr 2015 23:40:53 -0700 Subject: [PATCH 18/36] can now fling up and down as well as in xz plane --- examples/grab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/grab.js b/examples/grab.js index 4e0c536a1b..dc250b9d27 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -100,7 +100,6 @@ function flingObject() { flingVelocity = Vec3.subtract(entityProps.position, prevPosition); flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); - flingVelocity.y = 0; Entities.editEntity(grabbedEntity, { velocity: flingVelocity }); From 42a4fd8884604a6af192bffa4517d5877cedc744 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 29 Apr 2015 22:07:10 -0700 Subject: [PATCH 19/36] Add velocity filtering of DDE eyebrows --- interface/src/devices/DdeFaceTracker.cpp | 22 +++++++++++++++++----- interface/src/devices/DdeFaceTracker.h | 2 ++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index be25c0794d..d6cc644db1 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -169,7 +169,9 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui _lastLeftEyeBlink(0.0f), _filteredLeftEyeBlink(0.0f), _lastRightEyeBlink(0.0f), - _filteredRightEyeBlink(0.0f) + _filteredRightEyeBlink(0.0f), + _lastBrowUp(0.0f), + _filteredBrowUp(0.0f) { _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); @@ -389,10 +391,20 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { } // Use BrowsU_C to control both brows' up and down - _coefficients[_browDownLeftIndex] = -_coefficients[_browUpCenterIndex]; - _coefficients[_browDownRightIndex] = -_coefficients[_browUpCenterIndex]; - _coefficients[_browUpLeftIndex] = _coefficients[_browUpCenterIndex]; - _coefficients[_browUpRightIndex] = _coefficients[_browUpCenterIndex]; + float browUp = _coefficients[_browUpCenterIndex]; + if (isFiltering) { + const float BROW_VELOCITY_FILTER_STRENGHT = 0.8f; + float velocity = fabs(browUp - _lastBrowUp) / _averageMessageTime; + float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGHT, 0.0f, 1.0f); + _filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp; + _lastBrowUp = browUp; + browUp = _filteredBrowUp; + _coefficients[_browUpCenterIndex] = browUp; + } + _coefficients[_browUpLeftIndex] = browUp; + _coefficients[_browUpRightIndex] = browUp; + _coefficients[_browDownLeftIndex] = -browUp; + _coefficients[_browDownRightIndex] = -browUp; // Offset jaw open coefficient static const float JAW_OPEN_THRESHOLD = 0.16f; diff --git a/interface/src/devices/DdeFaceTracker.h b/interface/src/devices/DdeFaceTracker.h index d9df5723cf..d4572c8430 100644 --- a/interface/src/devices/DdeFaceTracker.h +++ b/interface/src/devices/DdeFaceTracker.h @@ -109,6 +109,8 @@ private: float _filteredLeftEyeBlink; float _lastRightEyeBlink; float _filteredRightEyeBlink; + float _lastBrowUp; + float _filteredBrowUp; }; #endif // hifi_DdeFaceTracker_h \ No newline at end of file From b6890be73d26709e854d1fab40d77a88dd0f4b6d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 30 Apr 2015 08:06:46 -0700 Subject: [PATCH 20/36] Adjust eyebrow filter strength --- interface/src/devices/DdeFaceTracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index d6cc644db1..652254d718 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -393,7 +393,7 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Use BrowsU_C to control both brows' up and down float browUp = _coefficients[_browUpCenterIndex]; if (isFiltering) { - const float BROW_VELOCITY_FILTER_STRENGHT = 0.8f; + const float BROW_VELOCITY_FILTER_STRENGHT = 0.75f; float velocity = fabs(browUp - _lastBrowUp) / _averageMessageTime; float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGHT, 0.0f, 1.0f); _filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp; From f75b599288b29c1f9073b38c21de5a88e27f0568 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 30 Apr 2015 11:28:27 -0700 Subject: [PATCH 21/36] don't save default values in json file --- interface/resources/qml/controls/Dialog.qml | 2 +- .../entities/src/EntityItemProperties.cpp | 71 +++++++++++-------- libraries/entities/src/EntityItemProperties.h | 3 +- .../entities/src/EntityItemPropertiesMacros.h | 35 ++++++--- libraries/entities/src/EntityTree.cpp | 4 +- libraries/entities/src/EntityTree.h | 2 +- .../src/RecurseOctreeToMapOperator.cpp | 17 ++++- .../entities/src/RecurseOctreeToMapOperator.h | 3 +- libraries/fbx/src/FBXReader.h | 10 +++ libraries/octree/src/Octree.cpp | 6 +- libraries/octree/src/Octree.h | 2 +- libraries/shared/src/SharedUtil.h | 11 +++ 12 files changed, 115 insertions(+), 51 deletions(-) diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/Dialog.qml index 46add1dc07..f32b4e2e66 100644 --- a/interface/resources/qml/controls/Dialog.qml +++ b/interface/resources/qml/controls/Dialog.qml @@ -66,7 +66,7 @@ DialogBase { // our close function performs the same way as the OffscreenUI class: // don't do anything but manipulate the enabled flag and let the other - // mechanisms decide if the window should be destoryed after the close + // mechanisms decide if the window should be destroyed after the close // animation completes function close() { if (destroyOnCloseButton) { diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 734f7897bb..267cf75a11 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -295,20 +295,23 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { return changedProperties; } -QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) const { +QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults) const { QScriptValue properties = engine->newObject(); + EntityItemProperties defaultEntityProperties; if (_idSet) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(id, _id.toString()); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(isKnownID, (_id != UNKNOWN_ENTITY_ID)); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(isKnownID, (_id != UNKNOWN_ENTITY_ID)); } else { - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(isKnownID, false); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(isKnownID, false); } COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(type, EntityTypes::getEntityTypeName(_type)); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(position); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(dimensions); - COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(naturalDimensions); // gettable, but not settable + if (!skipDefaults) { + COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(naturalDimensions); // gettable, but not settable + } COPY_PROPERTY_TO_QSCRIPTVALUE_QUAT(rotation); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(velocity); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(gravity); @@ -316,8 +319,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(damping); COPY_PROPERTY_TO_QSCRIPTVALUE(density); COPY_PROPERTY_TO_QSCRIPTVALUE(lifetime); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(age, getAge()); // gettable, but not settable - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable + if (!skipDefaults) { + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(age, getAge()); // gettable, but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(ageAsText, formatSecondsElapsed(getAge())); // gettable, but not settable + } COPY_PROPERTY_TO_QSCRIPTVALUE(script); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(registrationPoint); COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(angularVelocity); @@ -369,31 +374,37 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(stageHour); // Sitting properties support - QScriptValue sittingPoints = engine->newObject(); - for (int i = 0; i < _sittingPoints.size(); ++i) { - QScriptValue sittingPoint = engine->newObject(); - sittingPoint.setProperty("name", _sittingPoints.at(i).name); - sittingPoint.setProperty("position", vec3toScriptValue(engine, _sittingPoints.at(i).position)); - sittingPoint.setProperty("rotation", quatToScriptValue(engine, _sittingPoints.at(i).rotation)); - sittingPoints.setProperty(i, sittingPoint); + if (!skipDefaults) { + QScriptValue sittingPoints = engine->newObject(); + for (int i = 0; i < _sittingPoints.size(); ++i) { + QScriptValue sittingPoint = engine->newObject(); + sittingPoint.setProperty("name", _sittingPoints.at(i).name); + sittingPoint.setProperty("position", vec3toScriptValue(engine, _sittingPoints.at(i).position)); + sittingPoint.setProperty("rotation", quatToScriptValue(engine, _sittingPoints.at(i).rotation)); + sittingPoints.setProperty(i, sittingPoint); + } + sittingPoints.setProperty("length", _sittingPoints.size()); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable } - sittingPoints.setProperty("length", _sittingPoints.size()); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable - AABox aaBox = getAABox(); - QScriptValue boundingBox = engine->newObject(); - QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); - QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft()); - QScriptValue center = vec3toScriptValue(engine, aaBox.calcCenter()); - QScriptValue boundingBoxDimensions = vec3toScriptValue(engine, aaBox.getDimensions()); - boundingBox.setProperty("brn", bottomRightNear); - boundingBox.setProperty("tfl", topFarLeft); - boundingBox.setProperty("center", center); - boundingBox.setProperty("dimensions", boundingBoxDimensions); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(boundingBox, boundingBox); // gettable, but not settable + if (!skipDefaults) { + AABox aaBox = getAABox(); + QScriptValue boundingBox = engine->newObject(); + QScriptValue bottomRightNear = vec3toScriptValue(engine, aaBox.getCorner()); + QScriptValue topFarLeft = vec3toScriptValue(engine, aaBox.calcTopFarLeft()); + QScriptValue center = vec3toScriptValue(engine, aaBox.calcCenter()); + QScriptValue boundingBoxDimensions = vec3toScriptValue(engine, aaBox.getDimensions()); + boundingBox.setProperty("brn", bottomRightNear); + boundingBox.setProperty("tfl", topFarLeft); + boundingBox.setProperty("center", center); + boundingBox.setProperty("dimensions", boundingBoxDimensions); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(boundingBox, boundingBox); // gettable, but not settable + } QString textureNamesList = _textureNames.join(",\n"); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(originalTextures, textureNamesList); // gettable, but not settable + if (!skipDefaults) { + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable + } return properties; } @@ -467,7 +478,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { } QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties) { - return properties.copyToScriptValue(engine); + return properties.copyToScriptValue(engine, false); +} + +QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties) { + return properties.copyToScriptValue(engine, true); } void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemProperties& properties) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index faec9e1206..9a1c8ad5a6 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -159,7 +159,7 @@ public: EntityTypes::EntityType getType() const { return _type; } void setType(EntityTypes::EntityType type) { _type = type; } - virtual QScriptValue copyToScriptValue(QScriptEngine* engine) const; + virtual QScriptValue copyToScriptValue(QScriptEngine* engine, bool skipDefaults) const; virtual void copyFromScriptValue(const QScriptValue& object); // editing related features supported by all entities @@ -307,6 +307,7 @@ private: }; Q_DECLARE_METATYPE(EntityItemProperties); QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties); +QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties); void EntityItemPropertiesFromScriptValue(const QScriptValue &object, EntityItemProperties& properties); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 33714f4ea2..3fc6cfa85f 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -198,26 +198,41 @@ #define COPY_PROPERTY_TO_QSCRIPTVALUE_VEC3(P) \ - QScriptValue P = vec3toScriptValue(engine, _##P); \ - properties.setProperty(#P, P); + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + QScriptValue P = vec3toScriptValue(engine, _##P); \ + properties.setProperty(#P, P); \ + } #define COPY_PROPERTY_TO_QSCRIPTVALUE_QUAT(P) \ - QScriptValue P = quatToScriptValue(engine, _##P); \ - properties.setProperty(#P, P); + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + QScriptValue P = quatToScriptValue(engine, _##P); \ + properties.setProperty(#P, P); \ + } #define COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(P) \ - QScriptValue P = xColorToScriptValue(engine, _##P); \ - properties.setProperty(#P, P); + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + QScriptValue P = xColorToScriptValue(engine, _##P); \ + properties.setProperty(#P, P); \ + } #define COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(P,G) \ - QScriptValue P = xColorToScriptValue(engine, G); \ - properties.setProperty(#P, P); + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + QScriptValue P = xColorToScriptValue(engine, G); \ + properties.setProperty(#P, P); \ + } -#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(P, G) \ +#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(P, G) \ properties.setProperty(#P, G); +#define COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(P, G) \ + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + properties.setProperty(#P, G); \ + } + #define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \ - properties.setProperty(#P, _##P); + if (!skipDefaults || defaultEntityProperties._##P != _##P) { \ + properties.setProperty(#P, _##P); \ + } #define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \ QScriptValue P = object.property(#P); \ diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 436339b3fe..f8f94f8d17 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1137,10 +1137,10 @@ bool EntityTree::sendEntitiesOperation(OctreeElement* element, void* extraData) return true; } -bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElement* element) { +bool EntityTree::writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) { entityDescription["Entities"] = QVariantList(); QScriptEngine scriptEngine; - RecurseOctreeToMapOperator theOperator(entityDescription, element, &scriptEngine); + RecurseOctreeToMapOperator theOperator(entityDescription, element, &scriptEngine, skipDefaultValues); recurseTreeWithOperator(&theOperator); return true; } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 3f01dec408..3880d67eda 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -163,7 +163,7 @@ public: bool wantEditLogging() const { return _wantEditLogging; } void setWantEditLogging(bool value) { _wantEditLogging = value; } - bool writeToMap(QVariantMap& entityDescription, OctreeElement* element); + bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues); bool readFromMap(QVariantMap& entityDescription); signals: diff --git a/libraries/entities/src/RecurseOctreeToMapOperator.cpp b/libraries/entities/src/RecurseOctreeToMapOperator.cpp index afe28e17e0..daa01c203e 100644 --- a/libraries/entities/src/RecurseOctreeToMapOperator.cpp +++ b/libraries/entities/src/RecurseOctreeToMapOperator.cpp @@ -12,11 +12,15 @@ #include "RecurseOctreeToMapOperator.h" -RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map, OctreeElement *top, QScriptEngine *engine) : +RecurseOctreeToMapOperator::RecurseOctreeToMapOperator(QVariantMap& map, + OctreeElement *top, + QScriptEngine *engine, + bool skipDefaultValues) : RecurseOctreeOperator(), _map(map), _top(top), - _engine(engine) + _engine(engine), + _skipDefaultValues(skipDefaultValues) { // if some element "top" was given, only save information for that element and it's children. if (_top) { @@ -36,6 +40,8 @@ bool RecurseOctreeToMapOperator::preRecursion(OctreeElement* element) { bool RecurseOctreeToMapOperator::postRecursion(OctreeElement* element) { + EntityItemProperties defaultProperties; + EntityTreeElement* entityTreeElement = static_cast(element); const QList& entities = entityTreeElement->getEntities(); @@ -43,7 +49,12 @@ bool RecurseOctreeToMapOperator::postRecursion(OctreeElement* element) { foreach (EntityItem* entityItem, entities) { EntityItemProperties properties = entityItem->getProperties(); - QScriptValue qScriptValues = EntityItemPropertiesToScriptValue(_engine, properties); + QScriptValue qScriptValues; + if (_skipDefaultValues) { + qScriptValues = EntityItemNonDefaultPropertiesToScriptValue(_engine, properties); + } else { + qScriptValues = EntityItemPropertiesToScriptValue(_engine, properties); + } entitiesQList << qScriptValues.toVariant(); } _map["Entities"] = entitiesQList; diff --git a/libraries/entities/src/RecurseOctreeToMapOperator.h b/libraries/entities/src/RecurseOctreeToMapOperator.h index 6bd44f3cbf..bfa5024b09 100644 --- a/libraries/entities/src/RecurseOctreeToMapOperator.h +++ b/libraries/entities/src/RecurseOctreeToMapOperator.h @@ -13,7 +13,7 @@ class RecurseOctreeToMapOperator : public RecurseOctreeOperator { public: - RecurseOctreeToMapOperator(QVariantMap& map, OctreeElement *top, QScriptEngine *engine); + RecurseOctreeToMapOperator(QVariantMap& map, OctreeElement *top, QScriptEngine *engine, bool skipDefaultValues); bool preRecursion(OctreeElement* element); bool postRecursion(OctreeElement* element); private: @@ -21,4 +21,5 @@ public: OctreeElement *_top; QScriptEngine *_engine; bool _withinTop; + bool _skipDefaultValues; }; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 871f3d0581..648c47c975 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -203,6 +203,16 @@ public: glm::quat rotation; // relative orientation }; +inline bool operator==(const SittingPoint& lhs, const SittingPoint& rhs) +{ + return (lhs.name == rhs.name) && (lhs.position == rhs.position) && (lhs.rotation == rhs.rotation); +} + +inline bool operator!=(const SittingPoint& lhs, const SittingPoint& rhs) +{ + return (lhs.name != rhs.name) || (lhs.position != rhs.position) || (lhs.rotation != rhs.rotation); +} + /// A set of meshes extracted from an FBX document. class FBXGeometry { public: diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 059c0e5bbc..d53d29e444 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -2087,7 +2087,7 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) { QFile persistFile(fileName); QVariantMap entityDescription; - qCDebug(octree, "Saving to file %s...", fileName); + qCDebug(octree, "Saving JSON SVO to file %s...", fileName); OctreeElement* top; if (element) { @@ -2096,7 +2096,7 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) { top = _rootElement; } - bool entityDescriptionSuccess = writeToMap(entityDescription, top); + bool entityDescriptionSuccess = writeToMap(entityDescription, top, true); if (entityDescriptionSuccess && persistFile.open(QIODevice::WriteOnly)) { persistFile.write(QJsonDocument::fromVariant(entityDescription).toJson()); } else { @@ -2108,7 +2108,7 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElement* element) { std::ofstream file(fileName, std::ios::out|std::ios::binary); if(file.is_open()) { - qCDebug(octree, "Saving to file %s...", fileName); + qCDebug(octree, "Saving binary SVO to file %s...", fileName); PacketType expectedType = expectedDataPacketType(); PacketVersion expectedVersion = versionForPacketType(expectedType); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 21c3efc01d..d7fc58699f 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -331,7 +331,7 @@ public: void writeToFile(const char* filename, OctreeElement* element = NULL, QString persistAsFileType = "svo"); void writeToJSONFile(const char* filename, OctreeElement* element = NULL); void writeToSVOFile(const char* filename, OctreeElement* element = NULL); - virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element) = 0; + virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) = 0; // Octree importers bool readFromFile(const char* filename); diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 9cf76dd1dc..8d55a0f82b 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -43,6 +43,17 @@ inline QDebug& operator<<(QDebug& dbg, const xColor& c) { return dbg; } +inline bool operator==(const xColor& lhs, const xColor& rhs) +{ + return (lhs.red == rhs.red) && (lhs.green == rhs.green) && (lhs.blue == rhs.blue); +} + +inline bool operator!=(const xColor& lhs, const xColor& rhs) +{ + return (lhs.red != rhs.red) || (lhs.green != rhs.green) || (lhs.blue != rhs.blue); +} + + static const float ZERO = 0.0f; static const float ONE = 1.0f; static const float ONE_HALF = 0.5f; From a9c5f044c88ee82742bad322c6728545a22637af Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 30 Apr 2015 11:39:27 -0700 Subject: [PATCH 22/36] changed grab script so user can only grab with left mouse click and we update velocityof grabbed object every frame instead of flinging it onb release --- examples/grab.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index dc250b9d27..71264da509 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -50,6 +50,9 @@ var dropLine = Overlays.addOverlay("line3d", { function mousePressEvent(event) { + if(!event.isLeftButton){ + return; + } var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects && intersection.properties.collisionsWillMove) { @@ -83,7 +86,7 @@ function mousePressEvent(event) { function mouseReleaseEvent() { if (isGrabbing) { - flingObject(); + // flingObject(); Entities.editEntity(grabbedEntity, { gravity: savedGravity }); @@ -108,7 +111,6 @@ function flingObject() { function mouseMoveEvent(event) { if (isGrabbing) { entityProps = Entities.getEntityProperties(grabbedEntity); - prevPosition = entityProps.position; avatarEntityDistance = Vec3.distance(MyAvatar.position, entityProps.position); finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); deltaMouse.x = event.x - prevMouse.x; @@ -133,9 +135,17 @@ function mouseMoveEvent(event) { z: 0 }) }); + + flingVelocity = Vec3.subtract(entityProps.position, prevPosition); + flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); + Entities.editEntity(grabbedEntity, { + velocity: flingVelocity + }); + prevPosition = entityProps.position; } prevMouse.x = event.x; prevMouse.y = event.y; + } function keyReleaseEvent(event) { From 807eab9fc494535e3ef90f4b03dba49ab0a11db7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 30 Apr 2015 12:59:09 -0700 Subject: [PATCH 23/36] Fix typo --- interface/src/devices/DdeFaceTracker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/devices/DdeFaceTracker.cpp b/interface/src/devices/DdeFaceTracker.cpp index 652254d718..f47d4e35be 100644 --- a/interface/src/devices/DdeFaceTracker.cpp +++ b/interface/src/devices/DdeFaceTracker.cpp @@ -393,9 +393,9 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) { // Use BrowsU_C to control both brows' up and down float browUp = _coefficients[_browUpCenterIndex]; if (isFiltering) { - const float BROW_VELOCITY_FILTER_STRENGHT = 0.75f; + const float BROW_VELOCITY_FILTER_STRENGTH = 0.75f; float velocity = fabs(browUp - _lastBrowUp) / _averageMessageTime; - float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGHT, 0.0f, 1.0f); + float velocityFilter = glm::clamp(velocity * BROW_VELOCITY_FILTER_STRENGTH, 0.0f, 1.0f); _filteredBrowUp = velocityFilter * browUp + (1.0f - velocityFilter) * _filteredBrowUp; _lastBrowUp = browUp; browUp = _filteredBrowUp; From 5d5624053f99f164c9b21625e74848349ab6246b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 30 Apr 2015 13:15:55 -0700 Subject: [PATCH 24/36] drow boxes as aabox when we are the simulator --- .../src/RenderableBoxEntityItem.cpp | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index f7828806ab..d756b37797 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -35,16 +35,31 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { glm::vec4 cubeColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR, getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha()); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); - DependencyManager::get()->renderSolidCube(1.0f, cubeColor); - glPopMatrix(); - glPopMatrix(); + bool highlightSimulationOwnership = false; + if (args->_debugFlags & RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP) { + auto nodeList = DependencyManager::get(); + const QUuid& myNodeID = nodeList->getSessionUUID(); + highlightSimulationOwnership = (getSimulatorID() == myNodeID); + } + + if (highlightSimulationOwnership) { + float size = glm::length(dimensions); + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + DependencyManager::get()->renderWireCube(size, cubeColor); + glPopMatrix(); + } else { + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + DependencyManager::get()->renderSolidCube(1.0f, cubeColor); + glPopMatrix(); + glPopMatrix(); + } }; From 3c24d42d933d8cb97adaca8c971c2bb0008bc979 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 30 Apr 2015 14:17:20 -0700 Subject: [PATCH 25/36] improve display of box and model entities when in simulator-id debug mode --- .../src/RenderableBoxEntityItem.cpp | 26 ++++----- .../src/RenderableModelEntityItem.cpp | 55 ++++++++++++------- .../src/RenderableModelEntityItem.h | 1 + 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp index d756b37797..2f40b6ce6b 100644 --- a/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableBoxEntityItem.cpp @@ -43,23 +43,19 @@ void RenderableBoxEntityItem::render(RenderArgs* args) { highlightSimulationOwnership = (getSimulatorID() == myNodeID); } - if (highlightSimulationOwnership) { - float size = glm::length(dimensions); - glPushMatrix(); + glPushMatrix(); glTranslatef(position.x, position.y, position.z); - DependencyManager::get()->renderWireCube(size, cubeColor); - glPopMatrix(); - } else { + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - glPushMatrix(); - glm::vec3 positionToCenter = center - position; - glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); - glScalef(dimensions.x, dimensions.y, dimensions.z); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + if (highlightSimulationOwnership) { + DependencyManager::get()->renderWireCube(1.0f, cubeColor); + } else { DependencyManager::get()->renderSolidCube(1.0f, cubeColor); - glPopMatrix(); + } glPopMatrix(); - } + glPopMatrix(); }; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b9bf1d39a8..cedb5b9924 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -109,6 +109,33 @@ void RenderableModelEntityItem::remapTextures() { } +void RenderableModelEntityItem::renderBoundingBox(RenderArgs* args) { + glm::vec3 position = getPosition(); + glm::vec3 center = getCenter(); + glm::vec3 dimensions = getDimensions(); + glm::quat rotation = getRotation(); + // float size = glm::length(dimensions) / 2.0f; + + const float MAX_COLOR = 255.0f; + glm::vec4 cubeColor(getColor()[RED_INDEX] / MAX_COLOR, + getColor()[GREEN_INDEX] / MAX_COLOR, + getColor()[BLUE_INDEX] / MAX_COLOR, + getLocalRenderAlpha()); + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + glPushMatrix(); + glm::vec3 positionToCenter = center - position; + glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z); + glScalef(dimensions.x, dimensions.y, dimensions.z); + DependencyManager::get()->renderWireCube(1.0f, cubeColor); + glPopMatrix(); + glPopMatrix(); +} + + void RenderableModelEntityItem::render(RenderArgs* args) { PerformanceTimer perfTimer("RMEIrender"); assert(getType() == EntityTypes::Model); @@ -117,7 +144,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) { glm::vec3 position = getPosition(); glm::vec3 dimensions = getDimensions(); - float size = glm::length(dimensions); bool highlightSimulationOwnership = false; if (args->_debugFlags & RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP) { @@ -126,6 +152,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { highlightSimulationOwnership = (getSimulatorID() == myNodeID); } + bool didDraw = false; if (drawAsModel && !highlightSimulationOwnership) { remapTextures(); glPushMatrix(); @@ -179,34 +206,20 @@ void RenderableModelEntityItem::render(RenderArgs* args) { if (args && (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE)) { if (movingOrAnimating) { _model->renderInScene(alpha, args); + didDraw = true; } } else { _model->renderInScene(alpha, args); + didDraw = true; } - } else { - // if we couldn't get a model, then just draw a cube - glm::vec4 color(getColor()[RED_INDEX]/255, getColor()[GREEN_INDEX]/255, getColor()[BLUE_INDEX]/255, 1.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - DependencyManager::get()->renderWireCube(size, color); - glPopMatrix(); } - } else { - // if we couldn't get a model, then just draw a cube - glm::vec4 color(getColor()[RED_INDEX]/255, getColor()[GREEN_INDEX]/255, getColor()[BLUE_INDEX]/255, 1.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - DependencyManager::get()->renderWireCube(size, color); - glPopMatrix(); } } glPopMatrix(); - } else { - glm::vec4 color(getColor()[RED_INDEX]/255, getColor()[GREEN_INDEX]/255, getColor()[BLUE_INDEX]/255, 1.0f); - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - DependencyManager::get()->renderWireCube(size, color); - glPopMatrix(); + } + + if (!didDraw) { + renderBoundingBox(args); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 43f18af0db..ec0e30985c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -42,6 +42,7 @@ public: virtual void somethingChangedNotification() { _needsInitialSimulation = true; } + void renderBoundingBox(RenderArgs* args); virtual void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, From 4c80633a41f5e72c3cf89cbe6256f9c2f2b6c022 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 30 Apr 2015 16:42:32 -0700 Subject: [PATCH 26/36] fixed bug where non-script related content would be deleted on script ending --- examples/grab.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 71264da509..88e23c9a46 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -160,11 +160,6 @@ function keyPressEvent(event) { } } -function cleanup() { - Entities.deleteEntity(box); - Entities.deleteEntity(box2); - Entities.deleteEntity(ground); -} function setUpTestObjects() { var distance = 4; @@ -235,4 +230,3 @@ Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); -Script.scriptEnding.connect(cleanup); \ No newline at end of file From 6da796f7357134fa54577b7abeb7f07a1c55b662 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 30 Apr 2015 23:31:56 -0700 Subject: [PATCH 27/36] fix the bug with sahdows on Mac due to the fbo needing a colorbuffer even though it's not needed --- libraries/gpu/src/gpu/GLBackendOutput.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index 2529070b18..dd8e9c68b6 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -74,6 +74,19 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe } } } +#if (GPU_FEATURE_PROFILE == GPU_LEGACY) + // for reasons that i don;t understand yet, it seems that on mac gl, a fbo must have a color buffer... + else { + GLuint renderBuffer = 0; + glGenRenderbuffers(1, &renderBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, framebuffer.getWidth(), framebuffer.getHeight()); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer); + CHECK_GL_ERROR(); + } +#endif + if (framebuffer.hasDepthStencil()) { auto surface = framebuffer.getDepthStencilBuffer(); From e560687371f56111b072bf9b7804963e3485b21b Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 May 2015 00:14:23 -0700 Subject: [PATCH 28/36] fixing the shader not compiling --- libraries/render-utils/src/model.slf | 4 +-- libraries/render-utils/src/model.slv | 6 ++--- libraries/render-utils/src/model_lightmap.slf | 4 +-- libraries/render-utils/src/model_lightmap.slv | 6 ++--- .../src/model_lightmap_specular_map.slf | 4 +-- .../render-utils/src/model_specular_map.slf | 4 +-- .../render-utils/src/model_translucent.slf | 4 +-- libraries/render-utils/src/simple.slf | 4 +-- libraries/render-utils/src/simple.slv | 4 +-- libraries/render-utils/src/skin_model.slv | 26 +++++++++---------- .../src/skin_model_normal_map.slv | 26 +++++++++---------- 11 files changed, 46 insertions(+), 46 deletions(-) diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index adf80d01bf..7648cac429 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -19,7 +19,7 @@ uniform sampler2D diffuseMap; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -31,7 +31,7 @@ void main(void) { Material mat = getMaterial(); packDeferredFragment( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), getMaterialDiffuse(mat) * diffuse.rgb * color, getMaterialSpecular(mat), diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index f4511da944..97b5eb640b 100755 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -20,7 +20,7 @@ const int MAX_TEXCOORDS = 2; uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -36,7 +36,7 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, normal.xyz)$> + <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - normal = vec4(normalize(normal.xyz), 0.0); + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); } diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index b7660da16d..00d74ed997 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -24,7 +24,7 @@ uniform sampler2D emissiveMap; uniform vec2 emissiveParams; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -39,7 +39,7 @@ void main(void) { Material mat = getMaterial(); packDeferredFragmentLightmap( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), getMaterialDiffuse(mat) * diffuse.rgb * color, getMaterialSpecular(mat), diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index 56b34a5aa8..54d9bd21e1 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -23,7 +23,7 @@ uniform mat4 texcoordMatrices[MAX_TEXCOORDS]; attribute vec2 texcoord1; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; // the interpolated texcoord1 varying vec2 interpolatedTexcoord1; @@ -44,8 +44,8 @@ void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, normal.xyz)$> + <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - normal = vec4(normalize(normal.xyz), 0.0); + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); } diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index e4bb682601..daabfe2d07 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -27,7 +27,7 @@ uniform vec2 emissiveParams; uniform sampler2D specularMap; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec2 interpolatedTexcoord1; @@ -42,7 +42,7 @@ void main(void) { Material mat = getMaterial(); packDeferredFragmentLightmap( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), getMaterialDiffuse(mat) * diffuse.rgb * color, specular, // no use of getMaterialSpecular(mat) diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index a0203d74af..46f565de6c 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -23,7 +23,7 @@ uniform sampler2D diffuseMap; uniform sampler2D specularMap; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -35,7 +35,7 @@ void main(void) { Material mat = getMaterial(); packDeferredFragment( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), getMaterialDiffuse(mat) * diffuse.rgb * color, specular, //getMaterialSpecular(mat), diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 9b8eb97f70..9b34951f88 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -19,7 +19,7 @@ // the diffuse texture uniform sampler2D diffuseMap; -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -31,7 +31,7 @@ void main(void) { Material mat = getMaterial(); packDeferredFragmentTranslucent( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), getMaterialOpacity(mat) * diffuse.a, getMaterialDiffuse(mat) * diffuse.rgb * color, getMaterialSpecular(mat), diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 3e70674e33..4e1a09fb92 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -15,7 +15,7 @@ <@include DeferredBufferWrite.slh@> // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; // the glow intensity //uniform float glowIntensity; @@ -28,7 +28,7 @@ void main(void) { */ packDeferredFragment( - normalize(normal.xyz), + normalize(interpolatedNormal.xyz), glowIntensity, gl_Color.rgb, gl_FrontMaterial.specular.rgb, diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 61338b440d..9ad47a3e66 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -13,11 +13,11 @@ // // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; void main(void) { // transform and store the normal for interpolation - normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + interpolatedNormal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); // pass along the diffuse color gl_FrontColor = gl_Color; diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index f475cbd1f5..fdde2e8295 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -1,5 +1,5 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // skin_model.vert @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; @@ -26,7 +26,7 @@ attribute vec4 clusterIndices; attribute vec4 clusterWeights; // the interpolated normal -varying vec4 normal; +varying vec4 interpolatedNormal; varying vec3 color; @@ -37,7 +37,7 @@ void main(void) { mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; float clusterWeight = clusterWeights[i]; position += clusterMatrix * gl_Vertex * clusterWeight; - normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; + interpolatedNormal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight; } // pass along the diffuse color @@ -46,11 +46,11 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, position, gl_Position)$> - <$transformModelToEyeDir(cam, obj, normal.xyz, normal.xyz)$> - - normal = vec4(normalize(normal.xyz), 0.0); + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, position, gl_Position)$> + <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); } diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index bbc8f81d12..ed552a7aca 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -1,5 +1,5 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // skin_model_normal_map.vert @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> -<$declareStandardTransform()$> +<@include gpu/Transform.slh@> +<$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; const int MAX_CLUSTERS = 128; @@ -54,16 +54,16 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$> + <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); } From 2b631efb5d25e7231c5b48f04d948b381a5ca0bb Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 1 May 2015 00:21:58 -0700 Subject: [PATCH 29/36] shader not compiling properly have been fixed --- .../render-utils/src/model_normal_map.slv | 28 +++++++++---------- libraries/render-utils/src/skin_model.slv | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index e702b446b8..2f493053dd 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -1,5 +1,5 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> +<@include gpu/Config.slh@> +<$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // model.vert @@ -12,9 +12,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Transform.slh@> - -<$declareStandardTransform()$> +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> const int MAX_TEXCOORDS = 2; @@ -29,7 +29,7 @@ varying vec4 interpolatedNormal; // the interpolated tangent varying vec4 interpolatedTangent; -varying vec3 color; +varying vec3 color; void main(void) { // transform and store the normal and tangent for interpolation @@ -42,13 +42,13 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); - // standard transform - TransformCamera cam = getTransformCamera(); - TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$> - - interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + // standard transform + TransformCamera cam = getTransformCamera(); + TransformObject obj = getTransformObject(); + <$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$> + <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> + <$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$> + + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); } diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index fdde2e8295..c94fc0d151 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -32,7 +32,7 @@ varying vec3 color; void main(void) { vec4 position = vec4(0.0, 0.0, 0.0, 0.0); - normal = vec4(0.0, 0.0, 0.0, 0.0); + interpolatedNormal = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < INDICES_PER_VERTEX; i++) { mat4 clusterMatrix = clusterMatrices[int(clusterIndices[i])]; float clusterWeight = clusterWeights[i]; From b49a04c63882939e03e2d098c0000587d8110555 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 May 2015 08:40:24 -0700 Subject: [PATCH 30/36] Add name property to entities --- libraries/entities/src/EntityItem.cpp | 9 ++++++++- libraries/entities/src/EntityItem.h | 4 ++++ libraries/entities/src/EntityItemProperties.cpp | 7 +++++++ libraries/entities/src/EntityItemProperties.h | 3 +++ libraries/entities/src/EntityItemPropertiesDefaults.h | 2 ++ libraries/networking/src/PacketHeaders.cpp | 2 +- libraries/networking/src/PacketHeaders.h | 1 + 7 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 1d358f175a..7c0598fbfa 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -63,6 +63,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : _simulatorID(ENTITY_ITEM_DEFAULT_SIMULATOR_ID), _simulatorIDChangedTime(0), _marketplaceID(ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), + _name(ENTITY_ITEM_DEFAULT_NAME), _physicsInfo(NULL), _dirtyFlags(0), _element(NULL) @@ -105,6 +106,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_LOCKED; requestedProperties += PROP_USER_DATA; requestedProperties += PROP_MARKETPLACE_ID; + requestedProperties += PROP_NAME; requestedProperties += PROP_SIMULATOR_ID; return requestedProperties; @@ -231,6 +233,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); APPEND_ENTITY_PROPERTY(PROP_SIMULATOR_ID, appendValue, getSimulatorID()); APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, getMarketplaceID()); + APPEND_ENTITY_PROPERTY(PROP_NAME, appendValue, getName()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -528,7 +531,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits); } } - + READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation); READ_ENTITY_PROPERTY_SETTER(PROP_DENSITY, float, updateDensity); if (useMeters) { @@ -566,6 +569,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID); } + READ_ENTITY_PROPERTY_STRING(PROP_NAME, setName); + bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData); //////////////////////////////////// @@ -897,6 +902,7 @@ EntityItemProperties EntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData); COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulatorID, getSimulatorID); COPY_ENTITY_PROPERTY_TO_PROPERTIES(marketplaceID, getMarketplaceID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName); properties._defaultSettings = false; @@ -928,6 +934,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulatorID, setSimulatorID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(marketplaceID, setMarketplaceID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName); if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e71f88d723..648ef7aece 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -229,6 +229,9 @@ public: float getAngularDamping() const { return _angularDamping; } void setAngularDamping(float value) { _angularDamping = value; } + QString getName() const { return _name; } + void setName(const QString& value) { _name = value; } + bool getVisible() const { return _visible; } void setVisible(bool value) { _visible = value; } bool isVisible() const { return _visible; } @@ -340,6 +343,7 @@ protected: glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; float _angularDamping; + QString _name; bool _visible; bool _ignoreForCollisions; bool _collisionsWillMove; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 734f7897bb..4376d89314 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -86,6 +86,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(stageAltitude, ZoneEntityItem::DEFAULT_STAGE_ALTITUDE), CONSTRUCT_PROPERTY(stageDay, ZoneEntityItem::DEFAULT_STAGE_DAY), CONSTRUCT_PROPERTY(stageHour, ZoneEntityItem::DEFAULT_STAGE_HOUR), + CONSTRUCT_PROPERTY(name, ENTITY_ITEM_DEFAULT_NAME), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -291,6 +292,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, stageAltitude); CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, stageDay); CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, stageHour); + CHECK_PROPERTY_CHANGE(PROP_NAME, name); return changedProperties; } @@ -356,6 +358,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); + COPY_PROPERTY_TO_QSCRIPTVALUE(name); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(keyLightColor); COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity); @@ -451,6 +454,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(marketplaceID, setMarketplaceID); + COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(name, setName); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(keyLightColor, setKeyLightColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(keyLightIntensity, setKeyLightIntensity); @@ -666,6 +670,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem } APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID()); + APPEND_ENTITY_PROPERTY(PROP_NAME, appendValue, properties.getName()); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -914,6 +919,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int } READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_NAME, setName); return valid; } @@ -963,6 +969,7 @@ void EntityItemProperties::markAllChanged() { _registrationPointChanged = true; _angularVelocityChanged = true; _angularDampingChanged = true; + _nameChanged = true; _visibleChanged = true; _colorChanged = true; _modelURLChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index faec9e1206..950f12577b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -97,6 +97,7 @@ enum EntityPropertyList { PROP_MARKETPLACE_ID, PROP_ACCELERATION, PROP_SIMULATOR_ID, + PROP_NAME, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties ABOVE this line @@ -188,6 +189,7 @@ public: DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3); DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat); + DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString); DEFINE_PROPERTY(PROP_DENSITY, Density, density, float); DEFINE_PROPERTY_REF(PROP_VELOCITY, Velocity, velocity, glm::vec3); DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3); @@ -330,6 +332,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, Dimensions, dimensions, "in meters"); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Velocity, velocity, "in meters"); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, Name, name, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Visible, visible, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Rotation, rotation, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, Density, density, ""); diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index 001f963ecb..bdc1fb37e6 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -55,4 +55,6 @@ const float ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING = 0.39347f; // approx timescale const bool ENTITY_ITEM_DEFAULT_IGNORE_FOR_COLLISIONS = false; const bool ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE = false; +const QString ENTITY_ITEM_DEFAULT_NAME = QString(""); + #endif // hifi_EntityItemPropertiesDefaults_h diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 8fedc6b979..a9ccec34bb 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE; + return VERSION_ENTITIES_HAVE_NAMES; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 01302f5568..7b12b1a089 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -139,5 +139,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15; const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16; const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17; const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18; +const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19; #endif // hifi_PacketHeaders_h From 73a5b8c4e2b94565c6eb02f8546b9fa8a7fabd5c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 May 2015 08:42:23 -0700 Subject: [PATCH 31/36] Add support for 'name' to edit.js --- examples/edit.js | 3 +++ examples/html/entityList.html | 21 +++++++++++++++------ examples/html/entityProperties.html | 10 ++++++++++ examples/html/style.css | 4 ++++ examples/libraries/entityList.js | 5 +++-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/examples/edit.js b/examples/edit.js index e6dd03de96..93c06c38f2 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1213,6 +1213,9 @@ PropertiesTool = function(opts) { data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z); } Entities.editEntity(selectionManager.selections[0], data.properties); + if (data.properties.name != undefined) { + entityListTool.sendUpdate(); + } } pushCommandForSelections(); selectionManager._update(); diff --git a/examples/html/entityList.html b/examples/html/entityList.html index bcc1c117ea..5795cc2acb 100644 --- a/examples/html/entityList.html +++ b/examples/html/entityList.html @@ -13,7 +13,7 @@ var DESC_STRING = ' ▴'; function loaded() { - entityList = new List('entity-list', { valueNames: ['type', 'url']}); + entityList = new List('entity-list', { valueNames: ['name', 'type', 'url']}); entityList.clear(); elEntityTable = document.getElementById("entity-table"); elEntityTableBody = document.getElementById("entity-table-body"); @@ -22,6 +22,9 @@ elTeleport = document.getElementById("teleport"); elNoEntitiesMessage = document.getElementById("no-entities"); + document.getElementById("entity-name").onclick = function() { + setSortColumn('name'); + }; document.getElementById("entity-type").onclick = function() { setSortColumn('type'); }; @@ -56,31 +59,34 @@ })); } - function addEntity(id, type, url) { + function addEntity(id, name, type, url) { if (entities[id] === undefined) { var urlParts = url.split('/'); var filename = urlParts[urlParts.length - 1]; - entityList.add([{ id: id, type: type, url: filename }], function(items) { + entityList.add([{ id: id, name: name, type: type, url: filename }], function(items) { var el = items[0].elm; var id = items[0]._values.id; entities[id] = { id: id, - name: id, + name: name, el: el, + item: items[0], }; el.setAttribute('id', 'entity_' + id); el.setAttribute('title', url); el.dataset.entityId = id; el.onclick = onRowClicked; el.ondblclick = onRowDoubleClicked; - el.innerHTML }); if (refreshEntityListTimer) { clearTimeout(refreshEntityListTimer); } refreshEntityListTimer = setTimeout(refreshEntityListObject, 50); + } else { + var item = entities[id].item; + item.values({ name: name, url: url }); } } @@ -90,6 +96,7 @@ } var elSortOrder = { + name: document.querySelector('#entity-name .sort-order'), type: document.querySelector('#entity-type .sort-order'), url: document.querySelector('#entity-url .sort-order'), } @@ -164,7 +171,7 @@ elNoEntitiesMessage.style.display = "none"; for (var i = 0; i < newEntities.length; i++) { var id = newEntities[i].id; - addEntity(id, newEntities[i].type, newEntities[i].url); + addEntity(id, newEntities[i].name, newEntities[i].type, newEntities[i].url); } updateSelectedEntities(data.selectedIDs); } @@ -190,6 +197,7 @@ Type  ▾ + Name  ▾ URL @@ -197,6 +205,7 @@ Type Type + Name
URL
diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index c01b2a6d10..b2f5cbb82c 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -98,6 +98,7 @@ var allSections = []; var elID = document.getElementById("property-id"); var elType = document.getElementById("property-type"); + var elName = document.getElementById("property-name"); var elLocked = document.getElementById("property-locked"); var elVisible = document.getElementById("property-visible"); var elPositionX = document.getElementById("property-pos-x"); @@ -262,6 +263,8 @@ enableChildren(document.getElementById("properties-list"), 'input'); } + elName.value = properties.name; + elVisible.checked = properties.visible; elPositionX.value = properties.position.x.toFixed(2); @@ -395,6 +398,7 @@ } elLocked.addEventListener('change', createEmitCheckedPropertyUpdateFunction('locked')); + elName.addEventListener('change', createEmitTextPropertyUpdateFunction('name')); elVisible.addEventListener('change', createEmitCheckedPropertyUpdateFunction('visible')); var positionChangeFunction = createEmitVec3PropertyUpdateFunction( @@ -590,6 +594,12 @@ +
+ Name +
+ +
+
Locked diff --git a/examples/html/style.css b/examples/html/style.css index 6a258d8f02..8be9b92a51 100644 --- a/examples/html/style.css +++ b/examples/html/style.css @@ -301,3 +301,7 @@ input[type="number"]::-webkit-inner-spin-button:hover, input[type="number"]::-webkit-inner-spin-button:active{ opacity: .8; } + +input#property-name { + width: 100%; +} diff --git a/examples/libraries/entityList.js b/examples/libraries/entityList.js index d0b8ddac7f..e10aed4051 100644 --- a/examples/libraries/entityList.js +++ b/examples/libraries/entityList.js @@ -31,7 +31,7 @@ EntityListTool = function(opts) { webView.eventBridge.emitScriptEvent(JSON.stringify(data)); }); - function sendUpdate() { + that.sendUpdate = function() { var entities = []; var ids = Entities.findEntities(MyAvatar.position, 100); for (var i = 0; i < ids.length; i++) { @@ -39,6 +39,7 @@ EntityListTool = function(opts) { var properties = Entities.getEntityProperties(id); entities.push({ id: id.id, + name: properties.name, type: properties.type, url: properties.type == "Model" ? properties.modelURL : "", }); @@ -76,7 +77,7 @@ EntityListTool = function(opts) { Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); } } else if (data.type == "refresh") { - sendUpdate(); + that.sendUpdate(); } else if (data.type == "teleport") { if (selectionManager.hasSelection()) { MyAvatar.position = selectionManager.worldPosition; From cac5fa1371e8a93bdc4bceb016ddcb577085f98e Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 1 May 2015 09:39:39 -0700 Subject: [PATCH 32/36] refactored grab script using velocity and spring force --- examples/grab.js | 214 ++++++++++++++++------------------------------- 1 file changed, 74 insertions(+), 140 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 88e23c9a46..cd7d59701e 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -5,17 +5,13 @@ var deltaMouse = { z: 0 } var entityProps; -var box, box2, ground; -var baseMoveFactor = .001; -var finalMoveMultiplier; -var avatarEntityDistance; -var camYaw, dv; -var prevPosition; -var newPosition; -var flingVelocity; -var flingMultiplier = 10; +var targetPosition; var moveUpDown = false; -var savedGravity; + +var currentPosition, currentVelocity; + +var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav"); +var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav"); var DROP_DISTANCE = 5.0; var DROP_COLOR = { @@ -23,14 +19,9 @@ var DROP_COLOR = { green: 200, blue: 200 }; -var DROP_WIDTH = 4; +var DROP_WIDTH = 2; -var autoBox = false; -if (autoBox) { - setUpTestObjects(); -} - var dropLine = Overlays.addOverlay("line3d", { start: { x: 0, @@ -50,104 +41,80 @@ var dropLine = Overlays.addOverlay("line3d", { function mousePressEvent(event) { - if(!event.isLeftButton){ + if (!event.isLeftButton) { return; - } + } var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay); if (intersection.intersects && intersection.properties.collisionsWillMove) { grabbedEntity = intersection.entityID; var props = Entities.getEntityProperties(grabbedEntity) - prevPosition = props.position; isGrabbing = true; - savedGravity = props.gravity; - Overlays.editOverlay(dropLine, { + targetPosition = props.position; + currentPosition = props.position; + currentVelocity = props.velocity; + updateDropLine(targetPosition); + Audio.playSound(grabSound, { + position: props.position, + volume: 0.4 + }); + } +} + +function updateDropLine(position) { + Overlays.editOverlay(dropLine, { visible: true, - start: props.position, - end: Vec3.sum(props.position, { + start: position, + end: Vec3.sum(position, { x: 0, y: -DROP_DISTANCE, z: 0 }) - }); - Entities.editEntity(grabbedEntity, { - gravity: { - x: 0, - y: 0, - z: 0 - } - }); - //We need to store entity's current gravity, and then disable it while we move - - } - + }) } function mouseReleaseEvent() { if (isGrabbing) { - // flingObject(); - Entities.editEntity(grabbedEntity, { - gravity: savedGravity + isGrabbing = false; + Overlays.editOverlay(dropLine, { + visible: false }); + targetPosition = null; + Audio.playSound(grabSound, { + position: entityProps.position, + volume: 0.25 + }); + } - isGrabbing = false; - Overlays.editOverlay(dropLine, { - visible: false - }); -} - -function flingObject() { - //calculate velocity to give object base on current and previous position - entityProps = Entities.getEntityProperties(grabbedEntity); - - flingVelocity = Vec3.subtract(entityProps.position, prevPosition); - flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); - Entities.editEntity(grabbedEntity, { - velocity: flingVelocity - }); } function mouseMoveEvent(event) { if (isGrabbing) { - entityProps = Entities.getEntityProperties(grabbedEntity); - avatarEntityDistance = Vec3.distance(MyAvatar.position, entityProps.position); - finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); deltaMouse.x = event.x - prevMouse.x; if (!moveUpDown) { deltaMouse.z = event.y - prevMouse.y; + deltaMouse.y = 0; } else { deltaMouse.y = (event.y - prevMouse.y) * -1; + deltaMouse.z = 0; } - finalMoveMultiplier = baseMoveFactor * Math.pow(avatarEntityDistance, 1.5); - deltaMouse = Vec3.multiply(deltaMouse, finalMoveMultiplier); - camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y; - dv = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse); - newPosition = Vec3.sum(entityProps.position, dv); - Entities.editEntity(grabbedEntity, { - position: newPosition - }); - Overlays.editOverlay(dropLine, { - start: newPosition, - end: Vec3.sum(newPosition, { - x: 0, - y: -DROP_DISTANCE, - z: 0 - }) - }); - - flingVelocity = Vec3.subtract(entityProps.position, prevPosition); - flingVelocity = Vec3.multiply(flingMultiplier, flingVelocity); - Entities.editEntity(grabbedEntity, { - velocity: flingVelocity - }); - prevPosition = entityProps.position; + // Update the target position by the amount the mouse moved + var camYaw = Quat.safeEulerAngles(Camera.getOrientation()).y; + var dPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), deltaMouse); + // Adjust target position for the object by the mouse move + var avatarEntityDistance = Vec3.distance(Camera.getPosition(), currentPosition); + // Scale distance we want to move by the distance from the camera to the grabbed object + // TODO: Correct SCREEN_TO_METERS to be correct for the actual FOV, resolution + var SCREEN_TO_METERS = 0.001; + targetPosition = Vec3.sum(targetPosition, Vec3.multiply(dPosition, avatarEntityDistance * SCREEN_TO_METERS)); } prevMouse.x = event.x; prevMouse.y = event.y; } + function keyReleaseEvent(event) { if (event.text === "SHIFT") { moveUpDown = false; @@ -160,69 +127,34 @@ function keyPressEvent(event) { } } +function update(deltaTime) { + if (isGrabbing) { -function setUpTestObjects() { - var distance = 4; - box = Entities.addEntity({ - type: 'Box', - position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance, Quat.getFront(Camera.getOrientation()))), - dimensions: { - x: .5, - y: .5, - z: .5 - }, - color: { - red: 200, - green: 50, - blue: 192 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -1, - z: 0 - } - }); + entityProps = Entities.getEntityProperties(grabbedEntity); + currentPosition = entityProps.position; + currentVelocity = entityProps.velocity; - box2 = Entities.addEntity({ - type: 'Box', - position: Vec3.sum(MyAvatar.position, Vec3.multiply(distance + 1, Quat.getFront(Camera.getOrientation()))), - dimensions: { - x: .5, - y: .5, - z: .5 - }, - color: { - red: 200, - green: 50, - blue: 192 - }, - collisionsWillMove: true, - gravity: { - x: 0, - y: -1, - z: 0 - } - }); - - ground = Entities.addEntity({ - type: 'Box', - position: { - x: MyAvatar.position.x, - y: MyAvatar.position.y - 5, - z: MyAvatar.position.z - }, - dimensions: { - x: 100, - y: 2, - z: 100 - }, - color: { - red: 20, - green: 200, - blue: 50 - } - }); + var dPosition = Vec3.subtract(targetPosition, currentPosition); + var CLOSE_ENOUGH = 0.001; + if (Vec3.length(dPosition) > CLOSE_ENOUGH) { + // compute current velocity in the direction we want to move + var velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition)); + // compute the speed we would like to be going toward the target position + var SPRING_RATE = 0.35; + var DAMPING_RATE = 0.55; + var desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE); + // compute how much we want to add to the existing velocity + var addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget); + var newVelocity = Vec3.sum(currentVelocity, addedVelocity); + // Add Damping + newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE)); + // Update entity + Entities.editEntity(grabbedEntity, { + velocity: newVelocity + }) + } + updateDropLine(currentPosition); + } } Controller.mouseMoveEvent.connect(mouseMoveEvent); @@ -230,3 +162,5 @@ Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); +Script.update.connect(update); + From 3ee111d7572ebaf3786e79bbf58bc8dde25c628b Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 1 May 2015 09:56:21 -0700 Subject: [PATCH 33/36] added script to generate a lot of physical blocks within a specified range --- examples/lotsoBlocks.js | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 examples/lotsoBlocks.js diff --git a/examples/lotsoBlocks.js b/examples/lotsoBlocks.js new file mode 100644 index 0000000000..63ed774d2d --- /dev/null +++ b/examples/lotsoBlocks.js @@ -0,0 +1,63 @@ +var NUM_BLOCKS = 200; +var size; +var SPAWN_RANGE = 10; +var boxes = []; +var basePosition, avatarRot; +var isAssignmentScript = false; +if(isAssignmentScript){ + basePosition = {x: 8000, y: 8000, z: 8000}; +} +else { + avatarRot = Quat.fromPitchYawRollDegrees(0, MyAvatar.bodyYaw, 0.0); + basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(SPAWN_RANGE * 3, Quat.getFront(avatarRot))); +} +basePosition.y -= SPAWN_RANGE; + +var ground = Entities.addEntity({ + type: "Model", + modelURL: "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx", + dimensions: { + x: 100, + y: 2, + z: 100 + }, + position: basePosition, + shapeType: 'box' +}); + + +basePosition.y += SPAWN_RANGE + 2; +for (var i = 0; i < NUM_BLOCKS; i++) { + size = randFloat(-.2, 0.7); + boxes.push(Entities.addEntity({ + type: 'Box', + dimensions: { + x: size, + y: size, + z: size + }, + position: { + x: basePosition.x + randFloat(-SPAWN_RANGE, SPAWN_RANGE), + y: basePosition.y - randFloat(-SPAWN_RANGE, SPAWN_RANGE), + z: basePosition.z + randFloat(-SPAWN_RANGE, SPAWN_RANGE) + }, + color: {red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255}, + collisionsWillMove: true, + gravity: {x: 0, y: 0, z: 0} + })); +} + + + +function cleanup() { + Entities.deleteEntity(ground); + boxes.forEach(function(box){ + Entities.deleteEntity(box); + }); +} + +Script.scriptEnding.connect(cleanup); + +function randFloat(low, high) { + return low + Math.random() * ( high - low ); +} \ No newline at end of file From c506c36d7c38e480506989b7ad6c4158cbdd01df Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 May 2015 11:26:43 -0700 Subject: [PATCH 34/36] Fix initialized-out-of-order warnings for name property --- libraries/entities/src/EntityItem.h | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- libraries/entities/src/EntityItemProperties.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 648ef7aece..ef1612ab06 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -343,7 +343,6 @@ protected: glm::vec3 _registrationPoint; glm::vec3 _angularVelocity; float _angularDamping; - QString _name; bool _visible; bool _ignoreForCollisions; bool _collisionsWillMove; @@ -352,6 +351,7 @@ protected: QUuid _simulatorID; // id of Node which is currently responsible for simulating this Entity quint64 _simulatorIDChangedTime; // when was _simulatorID last updated? QString _marketplaceID; + QString _name; // NOTE: Damping is applied like this: v *= pow(1 - damping, dt) // diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4376d89314..9b9c3327e6 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -282,6 +282,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); + CHECK_PROPERTY_CHANGE(PROP_NAME, name); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_COLOR, keyLightColor); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_INTENSITY, keyLightIntensity); CHECK_PROPERTY_CHANGE(PROP_KEYLIGHT_AMBIENT_INTENSITY, keyLightAmbientIntensity); @@ -292,7 +293,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_STAGE_ALTITUDE, stageAltitude); CHECK_PROPERTY_CHANGE(PROP_STAGE_DAY, stageDay); CHECK_PROPERTY_CHANGE(PROP_STAGE_HOUR, stageHour); - CHECK_PROPERTY_CHANGE(PROP_NAME, name); return changedProperties; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 950f12577b..67711d2168 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -189,7 +189,6 @@ public: DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3); DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3); DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat); - DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString); DEFINE_PROPERTY(PROP_DENSITY, Density, density, float); DEFINE_PROPERTY_REF(PROP_VELOCITY, Velocity, velocity, glm::vec3); DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3); @@ -241,6 +240,7 @@ public: DEFINE_PROPERTY(PROP_STAGE_ALTITUDE, StageAltitude, stageAltitude, float); DEFINE_PROPERTY(PROP_STAGE_DAY, StageDay, stageDay, quint16); DEFINE_PROPERTY(PROP_STAGE_HOUR, StageHour, stageHour, float); + DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString); public: From 0883bde1be8ab8bfd85d00e20b62b1e5b7a5fda6 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 May 2015 11:29:23 -0700 Subject: [PATCH 35/36] Update compiler flags to produce warnings on non-gnu compilers --- CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b271664c35..347341efa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,10 +45,11 @@ if (WIN32) # Caveats: http://stackoverflow.com/questions/2288728/drawbacks-of-using-largeaddressaware-for-32-bit-windows-executables # TODO: Remove when building 64-bit. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") -elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic") - #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-strict-aliasing -Wno-unused-parameter -ggdb") +else () + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -fno-strict-aliasing -Wno-unused-parameter") + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb") + endif () endif(WIN32) if (NOT MSVC12) From 7f84b27880094d08cd3b9bef553eeaaa62844f4e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 1 May 2015 11:59:39 -0700 Subject: [PATCH 36/36] Add support for changing sphere color in edit.js --- examples/html/entityProperties.html | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index c01b2a6d10..5d220788e8 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -146,11 +146,10 @@ var elScriptURL = document.getElementById("property-script-url"); var elUserData = document.getElementById("property-user-data"); - var elBoxSections = document.querySelectorAll(".box-section"); - allSections.push(elBoxSections); - var elBoxColorRed = document.getElementById("property-box-red"); - var elBoxColorGreen = document.getElementById("property-box-green"); - var elBoxColorBlue = document.getElementById("property-box-blue"); + var elColorSection = document.getElementById("color-section"); + var elColorRed = document.getElementById("property-color-red"); + var elColorGreen = document.getElementById("property-color-green"); + var elColorBlue = document.getElementById("property-color-blue"); var elLightSections = document.querySelectorAll(".light-section"); allSections.push(elLightSections); @@ -310,16 +309,17 @@ allSections[i][j].style.display = 'none'; } } - - if (properties.type == "Box") { - for (var i = 0; i < elBoxSections.length; i++) { - elBoxSections[i].style.display = 'block'; - } - elBoxColorRed.value = properties.color.red; - elBoxColorGreen.value = properties.color.green; - elBoxColorBlue.value = properties.color.blue; - } else if (properties.type == "Model") { + if (properties.type == "Box" || properties.type == "Sphere") { + elColorSection.style.display = 'block'; + elColorRed.value = properties.color.red; + elColorGreen.value = properties.color.green; + elColorBlue.value = properties.color.blue; + } else { + elColorSection.style.display = 'none'; + } + + if (properties.type == "Model") { for (var i = 0; i < elModelSections.length; i++) { elModelSections[i].style.display = 'block'; } @@ -454,11 +454,11 @@ elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); - var boxColorChangeFunction = createEmitColorPropertyUpdateFunction( - 'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue); - elBoxColorRed.addEventListener('change', boxColorChangeFunction); - elBoxColorGreen.addEventListener('change', boxColorChangeFunction); - elBoxColorBlue.addEventListener('change', boxColorChangeFunction); + var colorChangeFunction = createEmitColorPropertyUpdateFunction( + 'color', elColorRed, elColorGreen, elColorBlue); + elColorRed.addEventListener('change', colorChangeFunction); + elColorGreen.addEventListener('change', colorChangeFunction); + elColorBlue.addEventListener('change', colorChangeFunction); elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight')); @@ -743,12 +743,12 @@
-
+
Color
-
R
-
G
-
B
+
R
+
G
+
B