From c8c8bccbf3b7768c88791ce2e6f37fe10b2a319a Mon Sep 17 00:00:00 2001 From: matsukaze Date: Mon, 9 Jun 2014 17:52:50 -0400 Subject: [PATCH 01/16] Job #19766 BUG: Stop or reload all scripts crashes interface fixed. QUrl(name).toString() does not equal name, therefore removing name from ScriptEngineHash was failing, and a dangling pointer was left in the script engine hash map. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 574df09ee2..9fb821bff4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3494,7 +3494,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript // start the script on a new thread... QUrl scriptUrl(scriptName); scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptName, scriptEngine); + _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; From b4e984086505814cbc426226777b74a113da8362 Mon Sep 17 00:00:00 2001 From: matsukaze Date: Mon, 9 Jun 2014 23:15:45 -0400 Subject: [PATCH 02/16] Job #19766 BUG: Stop or reload all scripts crashes interface fix, part 2. Keep the scriptUrl internal to the ScriptEngine class and refer to it externally by the file name string. Change the ScriptEngine constructor to accept a filename QString, instead of a QUrl. Resolve constructor ambiguity in Particle, which creates anonymous ScriptEngine. --- interface/src/Application.cpp | 5 ++--- libraries/particles/src/Particle.cpp | 6 +++--- libraries/script-engine/src/ScriptEngine.cpp | 12 +++++------- libraries/script-engine/src/ScriptEngine.h | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9fb821bff4..3ec5588c61 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3492,9 +3492,8 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); } else { // start the script on a new thread... - QUrl scriptUrl(scriptName); - scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); + scriptEngine = new ScriptEngine(scriptName, &_controllerScriptingInterface); + _scriptEnginesHash.insert(scriptName, scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 59265c00dc..90e59b9422 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -873,7 +873,7 @@ void Particle::endParticleScriptContext(ScriptEngine& engine, ParticleScriptObje void Particle::executeUpdateScripts() { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script); + ScriptEngine engine(_script, QString("")); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); particleScriptable.emitUpdate(); @@ -884,7 +884,7 @@ void Particle::executeUpdateScripts() { void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetration) { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script); + ScriptEngine engine(_script, QString("")); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); ParticleScriptObject otherParticleScriptable(other); @@ -896,7 +896,7 @@ void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetrati void Particle::collisionWithVoxel(VoxelDetail* voxelDetails, const glm::vec3& penetration) { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script); + ScriptEngine engine(_script, QString("")); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); particleScriptable.emitCollisionWithVoxel(*voxelDetails, penetration); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index a4aae61248..025f316d29 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -93,7 +93,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam { } -ScriptEngine::ScriptEngine(const QUrl& scriptURL, +ScriptEngine::ScriptEngine(const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface) : _scriptContents(), _isFinished(false), @@ -110,21 +110,19 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL, _controllerScriptingInterface(controllerScriptingInterface), _avatarData(NULL), _scriptName(), - _fileNameString(), + _fileNameString(fileNameString), _quatLibrary(), _vec3Library(), _uuidLibrary(), _animationCache(this) { - QString scriptURLString = scriptURL.toString(); - _fileNameString = scriptURLString; - - QUrl url(scriptURL); + QUrl url(fileNameString); + QString scriptUrlString = url.toString(); // if the scheme length is one or lower, maybe they typed in a file, let's try const int WINDOWS_DRIVE_LETTER_SIZE = 1; if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptURLString); + url = QUrl::fromLocalFile(scriptUrlString); } // ok, let's see if it's valid... and if so, load it diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bf2ac40568..f88017515e 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -40,7 +40,7 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10 class ScriptEngine : public QObject { Q_OBJECT public: - ScriptEngine(const QUrl& scriptURL, + ScriptEngine(const QString& fileNameString, AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); ScriptEngine(const QString& scriptContents = NO_SCRIPT, From faa5b1d2f253e3964cc8781fe821cb283d7b171a Mon Sep 17 00:00:00 2001 From: Dev5 Date: Tue, 10 Jun 2014 17:18:32 -0700 Subject: [PATCH 03/16] Added simple tree placement script that has a UI similar to edit voxels. It grows big trees, dont grow near something important. --- examples/growTrees.js | 837 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 837 insertions(+) create mode 100644 examples/growTrees.js diff --git a/examples/growTrees.js b/examples/growTrees.js new file mode 100644 index 0000000000..d853804e77 --- /dev/null +++ b/examples/growTrees.js @@ -0,0 +1,837 @@ +// +// growPlants.js +// examples +// +// Created by Benjamin Arnold on May 29, 2014 +// Copyright 2014 High Fidelity, Inc. +// +// This sample script allows the user to grow different types of plants on the voxels +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting +var previewLineWidth = 2.0; + +var voxelSize = 1; +var windowDimensions = Controller.getViewportDimensions(); +var toolIconUrl = "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/tools/"; + +var MAX_VOXEL_SCALE_POWER = 5; +var MIN_VOXEL_SCALE_POWER = -8; +var MAX_VOXEL_SCALE = Math.pow(2.0, MAX_VOXEL_SCALE_POWER); +var MIN_VOXEL_SCALE = Math.pow(2.0, MIN_VOXEL_SCALE_POWER); + + +var linePreviewTop = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + visible: false, + lineWidth: previewLineWidth + }); + +var linePreviewBottom = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + visible: false, + lineWidth: previewLineWidth + }); + +var linePreviewLeft = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + visible: false, + lineWidth: previewLineWidth + }); + +var linePreviewRight = Overlays.addOverlay("line3d", { + position: { x: 0, y: 0, z: 0}, + end: { x: 0, y: 0, z: 0}, + color: { red: 0, green: 255, blue: 0}, + alpha: 1, + visible: false, + lineWidth: previewLineWidth + }); + + +var UIColor = { red: 0, green: 160, blue: 0}; +var activeUIColor = { red: 0, green: 255, blue: 0}; + +var toolHeight = 50; +var toolWidth = 50; + +var editToolsOn = true; + +var voxelToolSelected = false; + +var scaleSelectorWidth = 144; +var scaleSelectorHeight = 37; + +var scaleSelectorX = windowDimensions.x / 5.0; +var scaleSelectorY = windowDimensions.y - scaleSelectorHeight; + +var voxelTool = Overlays.addOverlay("image", { + x: scaleSelectorX + scaleSelectorWidth + 1, y: windowDimensions.y - toolHeight, width: toolWidth, height: toolHeight, + subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, + imageURL: toolIconUrl + "voxel-tool.svg", + visible: editToolsOn, + color: UIColor, + alpha: 0.9 + }); + +var copyScale = true; +function ScaleSelector() { + this.x = scaleSelectorX; + this.y = scaleSelectorY; + this.width = scaleSelectorWidth; + this.height = scaleSelectorHeight; + + this.displayPower = false; + this.scale = 1.0; + this.power = 0; + + this.FIRST_PART = this.width * 40.0 / 100.0; + this.SECOND_PART = this.width * 37.0 / 100.0; + + this.buttonsOverlay = Overlays.addOverlay("image", { + x: this.x, y: this.y, + width: this.width, height: this.height, + //subImage: { x: 0, y: toolHeight, width: toolWidth, height: toolHeight }, + imageURL: toolIconUrl + "voxel-size-selector.svg", + alpha: 0.9, + visible: editToolsOn, + color: activeUIColor + }); + this.textOverlay = Overlays.addOverlay("text", { + x: this.x + this.FIRST_PART, y: this.y, + width: this.SECOND_PART, height: this.height, + topMargin: 13, + text: this.scale.toString(), + alpha: 0.0, + visible: editToolsOn, + color: activeUIColor + }); + this.powerOverlay = Overlays.addOverlay("text", { + x: this.x + this.FIRST_PART, y: this.y, + width: this.SECOND_PART, height: this.height, + leftMargin: 28, + text: this.power.toString(), + alpha: 0.0, + visible: false, + color: activeUIColor + }); + this.setScale = function(scale) { + if (scale > MAX_VOXEL_SCALE) { + scale = MAX_VOXEL_SCALE; + } + if (scale < MIN_VOXEL_SCALE) { + scale = MIN_VOXEL_SCALE; + } + + this.scale = scale; + this.power = Math.floor(Math.log(scale) / Math.log(2)); + this.update(); + } + + this.show = function(doShow) { + Overlays.editOverlay(this.buttonsOverlay, {visible: doShow}); + Overlays.editOverlay(this.textOverlay, {visible: doShow}); + Overlays.editOverlay(this.powerOverlay, {visible: doShow && this.displayPower}); + } + + this.move = function() { + this.x = swatchesX + swatchesWidth; + this.y = swatchesY; + + Overlays.editOverlay(this.buttonsOverlay, { + x: this.x, y: this.y, + }); + Overlays.editOverlay(this.textOverlay, { + x: this.x + this.FIRST_PART, y: this.y, + }); + Overlays.editOverlay(this.powerOverlay, { + x: this.x + this.FIRST_PART, y: this.y, + }); + } + + + this.switchDisplay = function() { + this.displayPower = !this.displayPower; + + if (this.displayPower) { + Overlays.editOverlay(this.textOverlay, { + leftMargin: 18, + text: "2" + }); + Overlays.editOverlay(this.powerOverlay, { + text: this.power.toString(), + visible: editToolsOn + }); + } else { + Overlays.editOverlay(this.textOverlay, { + leftMargin: 13, + text: this.scale.toString() + }); + Overlays.editOverlay(this.powerOverlay, { + visible: false + }); + } + } + + this.update = function() { + if (this.displayPower) { + Overlays.editOverlay(this.powerOverlay, {text: this.power.toString()}); + } else { + Overlays.editOverlay(this.textOverlay, {text: this.scale.toString()}); + } + } + + this.incrementScale = function() { + copyScale = false; + if (this.power < MAX_VOXEL_SCALE_POWER) { + ++this.power; + this.scale *= 2.0; + this.update(); + } + } + + this.decrementScale = function() { + copyScale = false; + if (MIN_VOXEL_SCALE_POWER < this.power) { + --this.power; + this.scale /= 2.0; + this.update(); + } + } + + this.clicked = function(x, y) { + if (this.x < x && x < this.x + this.width && + this.y < y && y < this.y + this.height) { + + if (x < this.x + this.FIRST_PART) { + this.decrementScale(); + } else if (x < this.x + this.FIRST_PART + this.SECOND_PART) { + this.switchDisplay(); + } else { + this.incrementScale(); + } + return true; + } + return false; + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.buttonsOverlay); + Overlays.deleteOverlay(this.textOverlay); + Overlays.deleteOverlay(this.powerOverlay); + } + +} +var scaleSelector = new ScaleSelector(); + + +function calculateVoxelFromIntersection(intersection, operation) { + + var resultVoxel; + + var x; + var y; + var z; + + // if our "target voxel size" is larger than the voxel we intersected with, then we need to find the closest + // ancestor voxel of our target size that contains our intersected voxel. + if (voxelSize > intersection.voxel.s) { + x = Math.floor(intersection.voxel.x / voxelSize) * voxelSize; + y = Math.floor(intersection.voxel.y / voxelSize) * voxelSize; + z = Math.floor(intersection.voxel.z / voxelSize) * voxelSize; + } else { + // otherwise, calculate the enclosed voxel of size voxelSize that the intersection point falls inside of. + // if you have a voxelSize that's smaller than the voxel you're intersecting, this calculation will result + // in the subvoxel that the intersection point falls in, if the target voxelSize matches the intersecting + // voxel this still works and results in returning the intersecting voxel which is what we want + var adjustToCenter = Vec3.multiply(Voxels.getFaceVector(intersection.face), (voxelSize * -0.5)); + + var centerOfIntersectingVoxel = Vec3.sum(intersection.intersection, adjustToCenter); + x = Math.floor(centerOfIntersectingVoxel.x / voxelSize) * voxelSize; + y = Math.floor(centerOfIntersectingVoxel.y / voxelSize) * voxelSize; + z = Math.floor(centerOfIntersectingVoxel.z / voxelSize) * voxelSize; + } + resultVoxel = { x: x, y: y, z: z, s: voxelSize }; + var highlightAt = { x: x, y: y, z: z, s: voxelSize }; + + + + // we only do the "add to the face we're pointing at" adjustment, if the operation is an add + // operation, and the target voxel size is equal to or smaller than the intersecting voxel. + var wantAddAdjust = (operation == "add" && (voxelSize <= intersection.voxel.s)); + + // now we also want to calculate the "edge square" for the face for this voxel + if (intersection.face == "MIN_X_FACE") { + + highlightAt.x = x - zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.x -= voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + + } else if (intersection.face == "MAX_X_FACE") { + + highlightAt.x = x + voxelSize + zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.x += resultVoxel.s; + } + + resultVoxel.bottomRight = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.bottomLeft = {x: highlightAt.x, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + resultVoxel.topRight = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.topLeft = {x: highlightAt.x, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + + } else if (intersection.face == "MIN_Y_FACE") { + + highlightAt.y = y - zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.y -= voxelSize; + } + + resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust , y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust }; + + } else if (intersection.face == "MAX_Y_FACE") { + + highlightAt.y = y + voxelSize + zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.y += voxelSize; + } + + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust }; + resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + zFightingSizeAdjust}; + resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; + resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y, z: highlightAt.z + voxelSize - zFightingSizeAdjust}; + + } else if (intersection.face == "MIN_Z_FACE") { + + highlightAt.z = z - zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.z -= voxelSize; + } + + resultVoxel.bottomRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; + resultVoxel.bottomLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; + resultVoxel.topRight = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; + resultVoxel.topLeft = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; + + } else if (intersection.face == "MAX_Z_FACE") { + + highlightAt.z = z + voxelSize + zFightingSizeAdjust; + if (wantAddAdjust) { + resultVoxel.z += voxelSize; + } + + resultVoxel.bottomLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z }; + resultVoxel.bottomRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + zFightingSizeAdjust, z: highlightAt.z}; + resultVoxel.topLeft = {x: highlightAt.x + zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z }; + resultVoxel.topRight = {x: highlightAt.x + voxelSize - zFightingSizeAdjust, y: highlightAt.y + voxelSize - zFightingSizeAdjust, z: highlightAt.z}; + + } + return resultVoxel; +} + +var trackLastMouseX = 0; +var trackLastMouseY = 0; + +function showPreviewLines() { + + var pickRay = Camera.computePickRay(trackLastMouseX, trackLastMouseY); + + var intersection = Voxels.findRayIntersection(pickRay); + + if (intersection.intersects) { + var resultVoxel = calculateVoxelFromIntersection(intersection, ""); + Overlays.editOverlay(linePreviewTop, { position: resultVoxel.topLeft, end: resultVoxel.topRight, visible: true }); + Overlays.editOverlay(linePreviewBottom, { position: resultVoxel.bottomLeft, end: resultVoxel.bottomRight, visible: true }); + Overlays.editOverlay(linePreviewLeft, { position: resultVoxel.topLeft, end: resultVoxel.bottomLeft, visible: true }); + Overlays.editOverlay(linePreviewRight, { position: resultVoxel.topRight, end: resultVoxel.bottomRight, visible: true }); + } else { + Overlays.editOverlay(linePreviewTop, { visible: false }); + Overlays.editOverlay(linePreviewBottom, { visible: false }); + Overlays.editOverlay(linePreviewLeft, { visible: false }); + Overlays.editOverlay(linePreviewRight, { visible: false }); + } +} + +function mouseMoveEvent(event) { + trackLastMouseX = event.x; + trackLastMouseY = event.y; + if (!voxelToolSelected) { + return; + } + showPreviewLines(); +} + + +// Array of possible trees, right now there is only one +var treeTypes = []; + +treeTypes.push({ + name: "Tall Green", + // Voxel Colors + wood: { r: 133, g: 81, b: 53 }, + leaves: { r: 22, g: 83, b: 31 }, + + // How tall the tree is + height: { min: 20, max: 60 }, + middleHeight: 0.3, + + // Chance of making a branch + branchChance: { min: 0.01, max: 0.1 }, + branchLength: { min: 30, max: 60 }, + branchThickness: { min: 2, max: 7}, + + // The width of the core, affects width and shape + coreWidth: { min: 1, max: 4 }, + + //TODO: Make this quadratic splines instead of linear + bottomThickness: { min: 2, max: 8 }, + middleThickness: { min: 1, max: 4 }, + topThickness: { min: 3, max: 6 }, + + //Modifies leaves at top + leafCapSizeOffset: 0 +}); + +// Applies noise to color +var colorNoiseRange = 0.2; + + +// Useful constants +var LEFT = 0; +var BACK = 1; +var RIGHT = 2; +var FRONT = 3; +var UP = 4; + +// Interpolates between min and max of treevar based on b +function interpolate(treeVar, b) { + return (treeVar.min + (treeVar.max - treeVar.min) * b); +} + +function makeBranch(x, y, z, step, length, dir, thickness, wood, leaves) { + var moveDir; + + var currentThickness; + //thickness attenuates to thickness - 3 + var finalThickness = thickness - 3; + if (finalThickness < 1) { + finalThickness = 1; + } + //Iterative branch generation + while (true) { + + //If we are at the end, place a ball of leaves + if (step == 0) { + makeSphere(x, y, z, 2 + finalThickness, leaves); + return; + } + //thickness attenuation + currentThickness = Math.round((finalThickness + (thickness - finalThickness) * (step/length))) - 1; + + + // If the branch is thick, grow a vertical slice + if (currentThickness > 0) { + for (var i = -currentThickness; i <= currentThickness; i++) { + var len = currentThickness - Math.abs(i); + switch (dir) { + case 0: //left + case 2: //right + growInDirection(x, y + i * voxelSize, z, len, len, BACK, wood, false, true); + growInDirection(x, y + i * voxelSize, z, len, len, FRONT, wood, false, false) + break; + case 1: //back + case 3: //front + growInDirection(x, y + i * voxelSize, z, len, len, LEFT, wood, false, true); + growInDirection(x, y + i * voxelSize, z, len, len, RIGHT, wood, false, false) + break; + } + } + } else { + //Otherwise place a single voxel + var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; + Voxels.setVoxel(x, y, z, voxelSize, wood.r * colorNoise, wood.g * colorNoise, wood.b * colorNoise); + } + + // determines random change in direction for branch + var r = Math.floor(Math.random() * 9); + + + if (r >= 6){ + moveDir = dir; //in same direction + } else if (r >= 4) { + moveDir = UP; //up + } + else if (dir == LEFT){ + if (r >= 2){ + moveDir = FRONT; + } + else{ + moveDir = BACK; + } + } + else if (dir == BACK){ + if (r >= 2){ + moveDir = LEFT; + } + else{ + moveDir = RIGHT; + } + } + else if (dir == RIGHT){ + if (r >= 2){ + moveDir = BACK; + } + else{ + moveDir = FRONT; + } + } + else if (dir == FRONT){ + if (r >= 2){ + moveDir = RIGHT; + } + else{ + moveDir = LEFT; + } + } + + //Move the branch by moveDir + switch (moveDir) { + case 0: //left + x = x - voxelSize; + break; + case 1: //back + z = z - voxelSize; + break; + case 2: //right + x = x + voxelSize; + break; + case 3: //front + z = z + voxelSize; + break; + case 4: //up + y = y + voxelSize; + break; + } + + step--; + } +} + +// Places a sphere of voxels +function makeSphere(x, y, z, radius, color) { + if (radius <= 0) { + return; + } + var width = radius * 2 + 1; + var distance; + + for (var i = -radius; i <= radius; i++){ + for (var j = -radius; j <= radius; j++){ + for (var k = -radius; k <= radius; k++){ + distance = Math.sqrt(i * i + j * j + k * k); + if (distance <= radius){ + var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; + Voxels.setVoxel(x + i * voxelSize, y + j * voxelSize, z + k * voxelSize, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); + } + } + } + } +} + +function growInDirection(x, y, z, step, length, dir, color, isSideBranching, addVoxel) { + + + if (addVoxel == true) { + var colorNoise = (colorNoiseRange * Math.random() - colorNoiseRange * 0.5) + 1.0; + Voxels.setVoxel(x, y, z, voxelSize, color.r * colorNoise, color.g * colorNoise, color.b * colorNoise); + } + + // If this is a main vein, it will branch outward perpendicular to its motion + if (isSideBranching == true){ + var step2; + if (step >= length - 1){ + step2 = length; + } + else{ + step2 = step + 1; + } + growInDirection(x, y, z, step, length, BACK, color, false, false); + growInDirection(x, y, z, step, length, FRONT, color, false, false); + } + + if (step < 1) return; + + // Recursively move in the direction + if (dir == LEFT) { //left + growInDirection(x - voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); + } + else if (dir == BACK) { //back + growInDirection(x, y, z - voxelSize, step - 1, length, dir, color, isSideBranching, true); + } + else if (dir == RIGHT) { //right + growInDirection(x + voxelSize, y, z, step - 1, length, dir, color, isSideBranching, true); + } + else if (dir == FRONT) {//front + growInDirection(x, y, z + voxelSize, step - 1, length, dir, color, isSideBranching, true); + } + +} + +// Grows the thickness of the tree +function growHorizontalSlice(x, y, z, thickness, color, side) { + // The side variable determines which directions we should grow in + // it is an optimization that prevents us from visiting voxels multiple + // times for trees with a coreWidth > 1 + + // side: + // 8 == all directions + // 0 1 2 + // 3 -1 4 + // 5 6 7 + + Voxels.setVoxel(x, y, z, voxelSize, color.r, color.g, color.b); + + //We are done if there is no thickness + if (thickness == 0) { + return; + } + + + switch (side) { + case 0: + growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); + break; + case 1: + growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); + break; + case 2: + growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); + break; + case 3: + growInDirection(x, y, z, thickness, thickness, LEFT, color, false, false); + break; + case 4: + growInDirection(x, y, z, thickness, thickness, BACK, color, false, false); + break; + case 5: + growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); + break; + case 6: + growInDirection(x, y, z, thickness, thickness, FRONT, color, false, false); + break; + case 7: + growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false); + break; + case 8: + if (thickness > 1){ + growInDirection(x, y, z, thickness, thickness, LEFT, color, true, false); + growInDirection(x, y, z, thickness, thickness, RIGHT, color, true, false) + } else if (thickness == 1){ + Voxels.setVoxel(x - voxelSize, y, z, voxelSize, color.r, color.g, color.b); + Voxels.setVoxel(x + voxelSize, y, z, voxelSize, color.r, color.g, color.b); + Voxels.setVoxel(x, y, z - voxelSize, voxelSize, color.r, color.g, color.b); + Voxels.setVoxel(x, y, z + voxelSize, voxelSize, color.r, color.g, color.b); + } + break; + } +} + +function computeSide(x, z, coreWidth) { + // side: + // 8 == all directions + // 0 1 2 + // 3 -1 4 + // 5 6 7 + + // if the core is only a single block, we can grow out in all directions + if (coreWidth == 1){ + return 8; + } + + // Back face + if (z == 0) { + if (x == 0) { + return 0; + } else if (x == coreWidth - 1) { + return 2; + } else { + return 1; + } + } + + // Front face + if (z == (coreWidth - 1)) { + if (x == 0) { + return 5; + } else if (x == (coreWidth - 1)) { + return 7; + } else { + return 6; + } + } + + // Left face + if (x == 0) { + return 3; + } + + // Right face + if (x == (coreWidth - 1)) { + return 4; + } + + //Interior + return -1; +} + + +function growTree(x, y, z, tree) { + + // The size of the tree, from 0-1 + var treeSize = Math.random(); + + // Get tree properties by interpolating with the treeSize + var height = interpolate(tree.height, treeSize); + var baseHeight = Math.ceil(tree.middleHeight * height); + var bottomThickness = interpolate(tree.bottomThickness, treeSize); + var middleThickness = interpolate(tree.middleThickness, treeSize); + var topThickness = interpolate(tree.topThickness, treeSize); + var coreWidth = Math.ceil(interpolate(tree.coreWidth, treeSize)); + + var thickness; + var side; + + //Loop upwards through each slice of the tree + for (var i = 0; i < height; i++){ + + //Branch properties are based on current height as well as the overall tree size + var branchChance = interpolate(tree.branchChance, i / height); + var branchLength = Math.ceil(interpolate(tree.branchLength, (i / height) * treeSize)); + var branchThickness = Math.round(interpolate(tree.branchThickness, (i / height) * treeSize)); + + // Get the "thickness" of the tree by doing linear interpolation between the middle thickness + // and the top and bottom thickness. + if (i <= baseHeight && baseHeight != 0){ + thickness = (i / (baseHeight) * (middleThickness - bottomThickness) + bottomThickness); + } else { + var denom = ((height - baseHeight)) * (topThickness - middleThickness) + middleThickness; + if (denom != 0) { + thickness = (i - baseHeight) / denom; + } else { + thickness = 0; + } + } + // The core of the tree is a vertical rectangular prism through the middle of the tree + + //Loop through the "core", which helps shape the trunk + var startX = x - Math.floor(coreWidth / 2) * voxelSize; + var startZ = z - Math.floor(coreWidth / 2) * voxelSize; + for (var j = 0; j < coreWidth; j++) { + for (var k = 0; k < coreWidth; k++) { + //determine which side of the tree we are on + side = computeSide(j, k, coreWidth); + //grow a horizontal slice of the tree + growHorizontalSlice(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, Math.floor(thickness), tree.wood, side); + + // Branches + if (side != -1) { + var r = Math.random(); + if (r <= branchChance){ + var dir = Math.floor((Math.random() * 4)); + makeBranch(startX + j * voxelSize, y + i * voxelSize, startZ + k * voxelSize, branchLength, branchLength, dir, branchThickness, tree.wood, tree.leaves); + + } + } + } + } + } + + makeSphere(x, y + height * voxelSize, z, topThickness + coreWidth + tree.leafCapSizeOffset, tree.leaves); +} + +function mousePressEvent(event) { + var mouseX = event.x; + var mouseY = event.y; + + var clickedOnSomething = false; + // Check if we clicked an overlay + var clickedOverlay = Overlays.getOverlayAtPoint({x: mouseX, y: mouseY}); + + if (clickedOverlay == voxelTool) { + voxelToolSelected = !voxelToolSelected; + + if (voxelToolSelected == true) { + Overlays.editOverlay(voxelTool, { + color: activeUIColor + }); + } else { + Overlays.editOverlay(voxelTool, { + color: UIColor + }); + } + + clickedOnSomething = true; + } else if (scaleSelector.clicked(event.x, event.y)) { + clickedOnSomething = true; + voxelSize = scaleSelector.scale; + } + + // Return if we clicked on the UI or the voxel tool is disabled + if (clickedOnSomething || !voxelToolSelected) { + return; + } + + // Compute the picking ray for the click + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Voxels.findRayIntersection(pickRay); + var resultVoxel = calculateVoxelFromIntersection(intersection, "add"); + + // Currently not in use, could randomly select a tree + var treeIndex = Math.floor(Math.random() * treeTypes.length); + + // Grow the first tree type + growTree(resultVoxel.x, resultVoxel.y, resultVoxel.z, treeTypes[0]); + +} + +function update() { + +} + +function scriptEnding() { + Overlays.deleteOverlay(linePreviewTop); + Overlays.deleteOverlay(linePreviewBottom); + Overlays.deleteOverlay(linePreviewLeft); + Overlays.deleteOverlay(linePreviewRight); + scaleSelector.cleanup(); + Overlays.deleteOverlay(voxelTool); +} + +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseMoveEvent.connect(mouseMoveEvent); + +Script.scriptEnding.connect(scriptEnding); + +Script.update.connect(update); + +Voxels.setPacketsPerSecond(10000); From a48f38b1d263a04f0fba5fce7a3502175e2078b9 Mon Sep 17 00:00:00 2001 From: matsukaze Date: Tue, 10 Jun 2014 21:32:23 -0400 Subject: [PATCH 04/16] Revert "Job #19766 BUG: Stop or reload all scripts crashes interface fix, part 2." This reverts commit b4e984086505814cbc426226777b74a113da8362. --- interface/src/Application.cpp | 5 +++-- libraries/particles/src/Particle.cpp | 6 +++--- libraries/script-engine/src/ScriptEngine.cpp | 12 +++++++----- libraries/script-engine/src/ScriptEngine.h | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3ec5588c61..9fb821bff4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3492,8 +3492,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); } else { // start the script on a new thread... - scriptEngine = new ScriptEngine(scriptName, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptName, scriptEngine); + QUrl scriptUrl(scriptName); + scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); + _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 90e59b9422..59265c00dc 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -873,7 +873,7 @@ void Particle::endParticleScriptContext(ScriptEngine& engine, ParticleScriptObje void Particle::executeUpdateScripts() { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script, QString("")); + ScriptEngine engine(_script); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); particleScriptable.emitUpdate(); @@ -884,7 +884,7 @@ void Particle::executeUpdateScripts() { void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetration) { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script, QString("")); + ScriptEngine engine(_script); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); ParticleScriptObject otherParticleScriptable(other); @@ -896,7 +896,7 @@ void Particle::collisionWithParticle(Particle* other, const glm::vec3& penetrati void Particle::collisionWithVoxel(VoxelDetail* voxelDetails, const glm::vec3& penetration) { // Only run this particle script if there's a script attached directly to the particle. if (!_script.isEmpty()) { - ScriptEngine engine(_script, QString("")); + ScriptEngine engine(_script); ParticleScriptObject particleScriptable(this); startParticleScriptContext(engine, particleScriptable); particleScriptable.emitCollisionWithVoxel(*voxelDetails, penetration); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 025f316d29..a4aae61248 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -93,7 +93,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam { } -ScriptEngine::ScriptEngine(const QString& fileNameString, +ScriptEngine::ScriptEngine(const QUrl& scriptURL, AbstractControllerScriptingInterface* controllerScriptingInterface) : _scriptContents(), _isFinished(false), @@ -110,19 +110,21 @@ ScriptEngine::ScriptEngine(const QString& fileNameString, _controllerScriptingInterface(controllerScriptingInterface), _avatarData(NULL), _scriptName(), - _fileNameString(fileNameString), + _fileNameString(), _quatLibrary(), _vec3Library(), _uuidLibrary(), _animationCache(this) { - QUrl url(fileNameString); - QString scriptUrlString = url.toString(); + QString scriptURLString = scriptURL.toString(); + _fileNameString = scriptURLString; + + QUrl url(scriptURL); // if the scheme length is one or lower, maybe they typed in a file, let's try const int WINDOWS_DRIVE_LETTER_SIZE = 1; if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptUrlString); + url = QUrl::fromLocalFile(scriptURLString); } // ok, let's see if it's valid... and if so, load it diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index f88017515e..bf2ac40568 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -40,7 +40,7 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10 class ScriptEngine : public QObject { Q_OBJECT public: - ScriptEngine(const QString& fileNameString, + ScriptEngine(const QUrl& scriptURL, AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); ScriptEngine(const QString& scriptContents = NO_SCRIPT, From 46f2ab73bccf6fa8669856534f0c20f96ee8c416 Mon Sep 17 00:00:00 2001 From: matsukaze Date: Tue, 10 Jun 2014 22:29:58 -0400 Subject: [PATCH 05/16] Job #19766 BUG: Stop or reload all scripts crashes interface fixed, part 3 Move the conversion of scriptName to QUrl to the beginning of Application::loadScript. Use the scriptURLString to query the _scriptEngineHash map. --- CMakeLists.txt | 4 + assignment-client/src/AssignmentClient.cpp | 123 +++++++++++++++------ assignment-client/src/AssignmentClient.h | 48 ++++++++ interface/src/Application.cpp | 9 +- interface/src/Audio.cpp | 29 ++++- 5 files changed, 175 insertions(+), 38 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb1e4224cf..298b9a791e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ if (NOT QT_CMAKE_PREFIX_PATH) set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) endif () +if (NOT ZLIB_ROOT) + set(ZLIB_ROOT $ENV{ZLIB_ROOT}) +endif () + set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) # set our Base SDK to 10.8 diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 009bd42e88..a2faaab651 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -33,6 +33,64 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); +template +class Parse : public Parser { +public: + Parse(const QString& option, bool required, T* value) : Parser(option, required), _value(value) {} + bool parse(const QStringList& argumentList); +private: + T* _value; +}; + +template<> +bool Parse::parse(const QStringList& argumentList) { + int argumentIndex = findToken(argumentList); + if (argumentIndex != -1) { + argumentIndex++; + if (argumentList.size() > argumentIndex) { + bool ok; + int value = argumentList[argumentIndex].toInt(&ok); + if (ok) { + *_value = static_cast(value); + } + validateValue(ok); + } else { + valueNotSpecified(); + } + } + return isValid(); +} + +template<> +bool Parse::parse(const QStringList& argumentList) { + int argumentIndex = findToken(argumentList); + if (argumentIndex != -1) { + argumentIndex++; + if (argumentList.size() > argumentIndex) { + *_value = QString(argumentList[argumentIndex]); + validateValue(!_value->isNull()); + } else { + valueNotSpecified(); + } + } + return isValid(); +} + +template<> +bool Parse::parse(const QStringList& argumentList) { + int argumentIndex = findToken(argumentList); + if (argumentIndex != -1) { + argumentIndex++; + if (argumentList.size() > argumentIndex) { + *_value = argumentList[argumentIndex]; + validateValue(true); + } else { + valueNotSpecified(); + } + } + return isValid(); +} + AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME) @@ -43,40 +101,42 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : QSettings::setDefaultFormat(QSettings::IniFormat); QStringList argumentList = arguments(); - + + // Define parser tokens + const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "-t"; + const QString ASSIGNMENT_POOL_OPTION = "--pool"; + const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "--wallet"; + const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "-a"; + + // Define parser results + Assignment::Type requestAssignmentType = Assignment::AllTypes; + QString assignmentPool; + QUuid walletUUID; + + // Define parsers + _parsers.insert(ASSIGNMENT_TYPE_OVERRIDE_OPTION, new Parse(ASSIGNMENT_TYPE_OVERRIDE_OPTION, false, &requestAssignmentType)); + _parsers.insert(ASSIGNMENT_POOL_OPTION, new Parse(ASSIGNMENT_POOL_OPTION, false, &assignmentPool)); + _parsers.insert(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION, new Parse(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION, false, &walletUUID)); + _parsers.insert(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION, new Parse(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION, false, &_assignmentServerHostname)); + // register meta type is required for queued invoke method on Assignment subclasses // set the logging target to the the CHILD_TARGET_NAME Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); - const QString ASSIGNMENT_TYPE_OVVERIDE_OPTION = "-t"; - int argumentIndex = argumentList.indexOf(ASSIGNMENT_TYPE_OVVERIDE_OPTION); - - Assignment::Type requestAssignmentType = Assignment::AllTypes; - - if (argumentIndex != -1) { - requestAssignmentType = (Assignment::Type) argumentList[argumentIndex + 1].toInt(); + foreach (Parser* option, _parsers) { + if (option) { + option->parse(argumentList); + } } - - const QString ASSIGNMENT_POOL_OPTION = "--pool"; - - argumentIndex = argumentList.indexOf(ASSIGNMENT_POOL_OPTION); - - QString assignmentPool; - - if (argumentIndex != -1) { - assignmentPool = argumentList[argumentIndex + 1]; - } - + // setup our _requestAssignment member variable from the passed arguments _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); // check if we were passed a wallet UUID on the command line // this would represent where the user running AC wants funds sent to - - const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "--wallet"; - if ((argumentIndex = argumentList.indexOf(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) != -1) { - QUuid walletUUID = QString(argumentList[argumentIndex + 1]); + if (_parsers[ASSIGNMENT_WALLET_DESTINATION_ID_OPTION]->exists() && + _parsers[ASSIGNMENT_WALLET_DESTINATION_ID_OPTION]->isValid()) { qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } @@ -84,14 +144,9 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); - // check for an overriden assignment server hostname - const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "-a"; - - argumentIndex = argumentList.indexOf(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION); - - if (argumentIndex != -1) { - _assignmentServerHostname = argumentList[argumentIndex + 1]; - + // check for an overriden assignment server hostname + if (_parsers[CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION]->exists() && + _parsers[CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION]->isValid()) { // set the custom assignment socket on our NodeList HifiSockAddr customAssignmentSocket = HifiSockAddr(_assignmentServerHostname, DEFAULT_DOMAIN_SERVER_PORT); @@ -113,6 +168,12 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : this, &AssignmentClient::handleAuthenticationRequest); } +AssignmentClient::~AssignmentClient() { + foreach (Parser* option, _parsers) { + delete option; + } +} + void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { NodeList::getInstance()->sendAssignment(_requestAssignment); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 9834402dbf..8951d44135 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -16,11 +16,57 @@ #include "ThreadedAssignment.h" +class Parser { +public: + Parser(const QString& option, bool required) : _option(option), _required(required), _exists(false), _isValid(false) {} + virtual bool parse(const QStringList& argumentList) { return false; } + bool exists() { return _exists; } + bool isValid() { return _isValid; } + +protected: + int findToken(const QStringList& argumentList) { + int argumentIndex = argumentList.indexOf(_option); + validateOption(argumentIndex); + return argumentIndex; + } + + void validateOption(int index) { + _exists = true; + if (index == -1) { + _exists = false; + if (_required) { + qDebug() << "Command line option " << _option << " is missing"; + } + } + } + + void valueNotSpecified() { + _isValid = false; + qDebug() << "Command line option " << _option << " value is missing"; + } + + void validateValue(bool ok) { + _isValid = ok; + if (!ok) { + qDebug() << "Command line option " << _option << " value is invalid"; + } + } + +private: + QString _option; + bool _required; + bool _exists; + bool _isValid; +}; + class AssignmentClient : public QCoreApplication { Q_OBJECT public: AssignmentClient(int &argc, char **argv); + ~AssignmentClient(); + static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } + private slots: void sendAssignmentRequest(); void readPendingDatagrams(); @@ -31,6 +77,8 @@ private: Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; + + QMap _parsers; }; #endif // hifi_AssignmentClient_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9fb821bff4..25a5ba8007 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3483,8 +3483,10 @@ void Application::saveScripts() { } ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) { - if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){ - return _scriptEnginesHash[scriptName]; + QUrl scriptUrl(scriptName); + const QString& scriptURLString = scriptUrl.toString(); + if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptURLString) && !_scriptEnginesHash[scriptURLString]->isFinished()){ + return _scriptEnginesHash[scriptURLString]; } ScriptEngine* scriptEngine; @@ -3492,9 +3494,8 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); } else { // start the script on a new thread... - QUrl scriptUrl(scriptName); scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); + _scriptEnginesHash.insert(scriptURLString, scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index ebc228a13d..1ecfad9007 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -219,8 +219,9 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { pPropertyStore->Release(); pPropertyStore = NULL; //QAudio devices seems to only take the 31 first characters of the Friendly Device Name. - const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; - deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); + //const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; + // deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); + deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal); qDebug() << (mode == QAudio::AudioOutput ? "output" : "input") << " device:" << deviceName; PropVariantClear(&pv); } @@ -1077,13 +1078,35 @@ void Audio::renderToolBox(int x, int y, bool boxed) { } _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); + + static quint64 last = 0; // Hold the last time sample + if (!_muted) { + last = 0; + glColor3f(1,1,1); glBindTexture(GL_TEXTURE_2D, _micTextureId); } else { + quint64 usecTimestampNow(); + static const float CYCLE_DURATION = 3.0f; // Seconds + quint64 now = usecTimestampNow(); + float delta = (float)(now - last) / 1000000.0f; + float from = 1.0f; // Linear fade down (upper bound) + float to = 0.3f; // Linear fade down (lower bound) + + if (delta > CYCLE_DURATION) { + last = now; + delta -= (int)delta; + } else if (delta > (CYCLE_DURATION * 0.5f)) { + // Linear fade up + from = 0.3f; // lower bound + to = 1.0f; // upper bound + } + // Compute a linear ramp to fade the color from full to partial saturation + float linearRamp = (from - to) * delta / CYCLE_DURATION + to; + glColor3f(linearRamp, linearRamp, linearRamp); glBindTexture(GL_TEXTURE_2D, _muteTextureId); } - glColor3f(1,1,1); glBegin(GL_QUADS); glTexCoord2f(1, 1); From 1e1cc69287d8cdaaf304bbfc05da56ae9564016f Mon Sep 17 00:00:00 2001 From: matsukaze Date: Tue, 10 Jun 2014 22:37:34 -0400 Subject: [PATCH 06/16] Revert "Job #19766 BUG: Stop or reload all scripts crashes interface fixed, part 3" This reverts commit 46f2ab73bccf6fa8669856534f0c20f96ee8c416. --- CMakeLists.txt | 4 - assignment-client/src/AssignmentClient.cpp | 123 ++++++--------------- assignment-client/src/AssignmentClient.h | 48 -------- interface/src/Application.cpp | 9 +- interface/src/Audio.cpp | 29 +---- 5 files changed, 38 insertions(+), 175 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 298b9a791e..cb1e4224cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,10 +20,6 @@ if (NOT QT_CMAKE_PREFIX_PATH) set(QT_CMAKE_PREFIX_PATH $ENV{QT_CMAKE_PREFIX_PATH}) endif () -if (NOT ZLIB_ROOT) - set(ZLIB_ROOT $ENV{ZLIB_ROOT}) -endif () - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${QT_CMAKE_PREFIX_PATH}) # set our Base SDK to 10.8 diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index a2faaab651..009bd42e88 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -33,64 +33,6 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -template -class Parse : public Parser { -public: - Parse(const QString& option, bool required, T* value) : Parser(option, required), _value(value) {} - bool parse(const QStringList& argumentList); -private: - T* _value; -}; - -template<> -bool Parse::parse(const QStringList& argumentList) { - int argumentIndex = findToken(argumentList); - if (argumentIndex != -1) { - argumentIndex++; - if (argumentList.size() > argumentIndex) { - bool ok; - int value = argumentList[argumentIndex].toInt(&ok); - if (ok) { - *_value = static_cast(value); - } - validateValue(ok); - } else { - valueNotSpecified(); - } - } - return isValid(); -} - -template<> -bool Parse::parse(const QStringList& argumentList) { - int argumentIndex = findToken(argumentList); - if (argumentIndex != -1) { - argumentIndex++; - if (argumentList.size() > argumentIndex) { - *_value = QString(argumentList[argumentIndex]); - validateValue(!_value->isNull()); - } else { - valueNotSpecified(); - } - } - return isValid(); -} - -template<> -bool Parse::parse(const QStringList& argumentList) { - int argumentIndex = findToken(argumentList); - if (argumentIndex != -1) { - argumentIndex++; - if (argumentList.size() > argumentIndex) { - *_value = argumentList[argumentIndex]; - validateValue(true); - } else { - valueNotSpecified(); - } - } - return isValid(); -} - AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME) @@ -101,42 +43,40 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : QSettings::setDefaultFormat(QSettings::IniFormat); QStringList argumentList = arguments(); - - // Define parser tokens - const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "-t"; - const QString ASSIGNMENT_POOL_OPTION = "--pool"; - const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "--wallet"; - const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "-a"; - - // Define parser results - Assignment::Type requestAssignmentType = Assignment::AllTypes; - QString assignmentPool; - QUuid walletUUID; - - // Define parsers - _parsers.insert(ASSIGNMENT_TYPE_OVERRIDE_OPTION, new Parse(ASSIGNMENT_TYPE_OVERRIDE_OPTION, false, &requestAssignmentType)); - _parsers.insert(ASSIGNMENT_POOL_OPTION, new Parse(ASSIGNMENT_POOL_OPTION, false, &assignmentPool)); - _parsers.insert(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION, new Parse(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION, false, &walletUUID)); - _parsers.insert(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION, new Parse(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION, false, &_assignmentServerHostname)); - + // register meta type is required for queued invoke method on Assignment subclasses // set the logging target to the the CHILD_TARGET_NAME Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME); - foreach (Parser* option, _parsers) { - if (option) { - option->parse(argumentList); - } + const QString ASSIGNMENT_TYPE_OVVERIDE_OPTION = "-t"; + int argumentIndex = argumentList.indexOf(ASSIGNMENT_TYPE_OVVERIDE_OPTION); + + Assignment::Type requestAssignmentType = Assignment::AllTypes; + + if (argumentIndex != -1) { + requestAssignmentType = (Assignment::Type) argumentList[argumentIndex + 1].toInt(); } - + + const QString ASSIGNMENT_POOL_OPTION = "--pool"; + + argumentIndex = argumentList.indexOf(ASSIGNMENT_POOL_OPTION); + + QString assignmentPool; + + if (argumentIndex != -1) { + assignmentPool = argumentList[argumentIndex + 1]; + } + // setup our _requestAssignment member variable from the passed arguments _requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool); // check if we were passed a wallet UUID on the command line // this would represent where the user running AC wants funds sent to - if (_parsers[ASSIGNMENT_WALLET_DESTINATION_ID_OPTION]->exists() && - _parsers[ASSIGNMENT_WALLET_DESTINATION_ID_OPTION]->isValid()) { + + const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "--wallet"; + if ((argumentIndex = argumentList.indexOf(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) != -1) { + QUuid walletUUID = QString(argumentList[argumentIndex + 1]); qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID); _requestAssignment.setWalletUUID(walletUUID); } @@ -144,9 +84,14 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // create a NodeList as an unassigned client NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned); - // check for an overriden assignment server hostname - if (_parsers[CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION]->exists() && - _parsers[CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION]->isValid()) { + // check for an overriden assignment server hostname + const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "-a"; + + argumentIndex = argumentList.indexOf(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION); + + if (argumentIndex != -1) { + _assignmentServerHostname = argumentList[argumentIndex + 1]; + // set the custom assignment socket on our NodeList HifiSockAddr customAssignmentSocket = HifiSockAddr(_assignmentServerHostname, DEFAULT_DOMAIN_SERVER_PORT); @@ -168,12 +113,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : this, &AssignmentClient::handleAuthenticationRequest); } -AssignmentClient::~AssignmentClient() { - foreach (Parser* option, _parsers) { - delete option; - } -} - void AssignmentClient::sendAssignmentRequest() { if (!_currentAssignment) { NodeList::getInstance()->sendAssignment(_requestAssignment); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 8951d44135..9834402dbf 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -16,57 +16,11 @@ #include "ThreadedAssignment.h" -class Parser { -public: - Parser(const QString& option, bool required) : _option(option), _required(required), _exists(false), _isValid(false) {} - virtual bool parse(const QStringList& argumentList) { return false; } - bool exists() { return _exists; } - bool isValid() { return _isValid; } - -protected: - int findToken(const QStringList& argumentList) { - int argumentIndex = argumentList.indexOf(_option); - validateOption(argumentIndex); - return argumentIndex; - } - - void validateOption(int index) { - _exists = true; - if (index == -1) { - _exists = false; - if (_required) { - qDebug() << "Command line option " << _option << " is missing"; - } - } - } - - void valueNotSpecified() { - _isValid = false; - qDebug() << "Command line option " << _option << " value is missing"; - } - - void validateValue(bool ok) { - _isValid = ok; - if (!ok) { - qDebug() << "Command line option " << _option << " value is invalid"; - } - } - -private: - QString _option; - bool _required; - bool _exists; - bool _isValid; -}; - class AssignmentClient : public QCoreApplication { Q_OBJECT public: AssignmentClient(int &argc, char **argv); - ~AssignmentClient(); - static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } - private slots: void sendAssignmentRequest(); void readPendingDatagrams(); @@ -77,8 +31,6 @@ private: Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; - - QMap _parsers; }; #endif // hifi_AssignmentClient_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 25a5ba8007..9fb821bff4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3483,10 +3483,8 @@ void Application::saveScripts() { } ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) { - QUrl scriptUrl(scriptName); - const QString& scriptURLString = scriptUrl.toString(); - if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptURLString) && !_scriptEnginesHash[scriptURLString]->isFinished()){ - return _scriptEnginesHash[scriptURLString]; + if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){ + return _scriptEnginesHash[scriptName]; } ScriptEngine* scriptEngine; @@ -3494,8 +3492,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); } else { // start the script on a new thread... + QUrl scriptUrl(scriptName); scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptURLString, scriptEngine); + _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 1ecfad9007..ebc228a13d 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -219,9 +219,8 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { pPropertyStore->Release(); pPropertyStore = NULL; //QAudio devices seems to only take the 31 first characters of the Friendly Device Name. - //const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; - // deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); - deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal); + const DWORD QT_WIN_MAX_AUDIO_DEVICENAME_LEN = 31; + deviceName = QString::fromWCharArray((wchar_t*)pv.pwszVal).left(QT_WIN_MAX_AUDIO_DEVICENAME_LEN); qDebug() << (mode == QAudio::AudioOutput ? "output" : "input") << " device:" << deviceName; PropVariantClear(&pv); } @@ -1078,35 +1077,13 @@ void Audio::renderToolBox(int x, int y, bool boxed) { } _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); - - static quint64 last = 0; // Hold the last time sample - if (!_muted) { - last = 0; - glColor3f(1,1,1); glBindTexture(GL_TEXTURE_2D, _micTextureId); } else { - quint64 usecTimestampNow(); - static const float CYCLE_DURATION = 3.0f; // Seconds - quint64 now = usecTimestampNow(); - float delta = (float)(now - last) / 1000000.0f; - float from = 1.0f; // Linear fade down (upper bound) - float to = 0.3f; // Linear fade down (lower bound) - - if (delta > CYCLE_DURATION) { - last = now; - delta -= (int)delta; - } else if (delta > (CYCLE_DURATION * 0.5f)) { - // Linear fade up - from = 0.3f; // lower bound - to = 1.0f; // upper bound - } - // Compute a linear ramp to fade the color from full to partial saturation - float linearRamp = (from - to) * delta / CYCLE_DURATION + to; - glColor3f(linearRamp, linearRamp, linearRamp); glBindTexture(GL_TEXTURE_2D, _muteTextureId); } + glColor3f(1,1,1); glBegin(GL_QUADS); glTexCoord2f(1, 1); From 679846267e32a0929045dd86cd914f8c4c80ff91 Mon Sep 17 00:00:00 2001 From: matsukaze Date: Tue, 10 Jun 2014 22:42:01 -0400 Subject: [PATCH 07/16] Job #19766 BUG: Stop or reload all scripts crashes interface fixed, part 3 Same comments as before, but without the local files changes mistakenly checked in. --- interface/src/Application.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9fb821bff4..25a5ba8007 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3483,8 +3483,10 @@ void Application::saveScripts() { } ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) { - if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){ - return _scriptEnginesHash[scriptName]; + QUrl scriptUrl(scriptName); + const QString& scriptURLString = scriptUrl.toString(); + if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptURLString) && !_scriptEnginesHash[scriptURLString]->isFinished()){ + return _scriptEnginesHash[scriptURLString]; } ScriptEngine* scriptEngine; @@ -3492,9 +3494,8 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); } else { // start the script on a new thread... - QUrl scriptUrl(scriptName); scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptUrl.toString(), scriptEngine); + _scriptEnginesHash.insert(scriptURLString, scriptEngine); if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; From 41b9c3b7049cc46732cafa9bf833c5c1537b0fd5 Mon Sep 17 00:00:00 2001 From: Dev5 Date: Wed, 11 Jun 2014 09:06:00 -0700 Subject: [PATCH 08/16] Removed empty update function --- examples/growTrees.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/examples/growTrees.js b/examples/growTrees.js index d853804e77..142c72300a 100644 --- a/examples/growTrees.js +++ b/examples/growTrees.js @@ -814,9 +814,6 @@ function mousePressEvent(event) { } -function update() { - -} function scriptEnding() { Overlays.deleteOverlay(linePreviewTop); @@ -832,6 +829,4 @@ Controller.mouseMoveEvent.connect(mouseMoveEvent); Script.scriptEnding.connect(scriptEnding); -Script.update.connect(update); - Voxels.setPacketsPerSecond(10000); From 760627003f353a1552e8e94b050698b2c233bd5a Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 11:11:04 -0700 Subject: [PATCH 09/16] killNode() to nodeKilled() --- libraries/networking/src/ReceivedPacketProcessor.cpp | 4 ++-- libraries/networking/src/ReceivedPacketProcessor.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index d556e8a059..e919017128 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -50,6 +50,6 @@ bool ReceivedPacketProcessor::process() { return isStillRunning(); // keep running till they terminate us } -void ReceivedPacketProcessor::killNode(const SharedNodePointer& node) { - _nodePacketCounts.remove(node->getUUID()); +void ReceivedPacketProcessor::nodeKilled(const SharedNodePointer& node) { + int numRemoved = _nodePacketCounts.remove(node->getUUID()); } diff --git a/libraries/networking/src/ReceivedPacketProcessor.h b/libraries/networking/src/ReceivedPacketProcessor.h index 80fe75aaa7..23303cbb55 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.h +++ b/libraries/networking/src/ReceivedPacketProcessor.h @@ -42,7 +42,7 @@ public: int packetsToProcessCount() const { return _packets.size(); } public slots: - void killNode(const SharedNodePointer& node); + void nodeKilled(const SharedNodePointer& node); protected: /// Callback for processing of recieved packets. Implement this to process the incoming packets. From decd6109fbda6682d97ae23432bfe9b2ac5c4cd8 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 11:57:54 -0700 Subject: [PATCH 10/16] made nodeKilled signatures match --- libraries/networking/src/ReceivedPacketProcessor.cpp | 2 +- libraries/networking/src/ReceivedPacketProcessor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index e919017128..59165b45b6 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -50,6 +50,6 @@ bool ReceivedPacketProcessor::process() { return isStillRunning(); // keep running till they terminate us } -void ReceivedPacketProcessor::nodeKilled(const SharedNodePointer& node) { +void ReceivedPacketProcessor::nodeKilled(SharedNodePointer node) { int numRemoved = _nodePacketCounts.remove(node->getUUID()); } diff --git a/libraries/networking/src/ReceivedPacketProcessor.h b/libraries/networking/src/ReceivedPacketProcessor.h index 23303cbb55..94ad2d9c41 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.h +++ b/libraries/networking/src/ReceivedPacketProcessor.h @@ -42,7 +42,7 @@ public: int packetsToProcessCount() const { return _packets.size(); } public slots: - void nodeKilled(const SharedNodePointer& node); + void nodeKilled(SharedNodePointer node); protected: /// Callback for processing of recieved packets. Implement this to process the incoming packets. From 2080cc3dee753d072b005bbac3e868ab8bd0716a Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 11:59:15 -0700 Subject: [PATCH 11/16] removed debug variable --- libraries/networking/src/ReceivedPacketProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index 59165b45b6..32fc4e26f3 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -51,5 +51,5 @@ bool ReceivedPacketProcessor::process() { } void ReceivedPacketProcessor::nodeKilled(SharedNodePointer node) { - int numRemoved = _nodePacketCounts.remove(node->getUUID()); + _nodePacketCounts.remove(node->getUUID()); } From a8c97800048043e4908743601ae95b3c92fe80d9 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 12:13:27 -0700 Subject: [PATCH 12/16] updated connect() to qt5 format --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2b3256141e..a5cb6a0c12 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -244,7 +244,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); - connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_octreeProcessor, SLOT(nodeKilled(SharedNodePointer))); + connect(NodeList::getInstance(), &NodeList::nodeKilled, &_octreeProcessor, &ReceivedPacketProcessor::nodeKilled); connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); connect(nodeList, SIGNAL(uuidChanged(const QUuid&)), _myAvatar, SLOT(setSessionUUID(const QUuid&))); connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); From 82bf6002e2c3c0aaa471b8f7f5233e645cfe5174 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 11 Jun 2014 14:57:05 -0700 Subject: [PATCH 13/16] only display the OAuthWebViewHandler when we need to ask user for authorization --- interface/src/Menu.cpp | 9 ++++++--- interface/src/Menu.h | 2 ++ interface/src/ui/OAuthWebViewHandler.cpp | 17 ++++++++++++++++- interface/src/ui/OAuthWebViewHandler.h | 1 + 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f791d20588..c2b6c293b9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -103,6 +103,7 @@ Menu::Menu() : _fastFPSAverage(ONE_SECOND_OF_FRAMES), _loginAction(NULL), _preferencesDialog(NULL), + _loginDialog(NULL), _snapshotsLocation() { Application *appInstance = Application::getInstance(); @@ -913,9 +914,11 @@ void sendFakeEnterEvent() { const float DIALOG_RATIO_OF_WINDOW = 0.30f; void Menu::loginForCurrentDomain() { - LoginDialog* loginDialog = new LoginDialog(Application::getInstance()->getWindow()); - loginDialog->show(); - loginDialog->resizeAndPosition(false); + if (!_loginDialog) { + _loginDialog = new LoginDialog(Application::getInstance()->getWindow()); + _loginDialog->show(); + _loginDialog->resizeAndPosition(false); + } } void Menu::editPreferences() { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 69015a938b..a0fafc0514 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -27,6 +27,7 @@ #include "ui/PreferencesDialog.h" #include "ui/ChatWindow.h" #include "ui/JSConsole.h" +#include "ui/LoginDialog.h" #include "ui/ScriptEditorWindow.h" const float ADJUST_LOD_DOWN_FPS = 40.0; @@ -270,6 +271,7 @@ private: QPointer _preferencesDialog; QPointer _attachmentsDialog; QPointer _animationsDialog; + QPointer _loginDialog; QAction* _chatAction; QString _snapshotsLocation; }; diff --git a/interface/src/ui/OAuthWebViewHandler.cpp b/interface/src/ui/OAuthWebViewHandler.cpp index 5415d5d9c3..5b4431bd0f 100644 --- a/interface/src/ui/OAuthWebViewHandler.cpp +++ b/interface/src/ui/OAuthWebViewHandler.cpp @@ -103,8 +103,9 @@ void OAuthWebViewHandler::displayWebviewForAuthorizationURL(const QUrl& authoriz codedAuthorizationURL.setQuery(authQuery); } + connect(_activeWebView.data(), &QWebView::urlChanged, this, &OAuthWebViewHandler::handleURLChanged); + _activeWebView->load(codedAuthorizationURL); - _activeWebView->show(); connect(_activeWebView->page()->networkAccessManager(), &QNetworkAccessManager::sslErrors, this, &OAuthWebViewHandler::handleSSLErrors); @@ -137,3 +138,17 @@ void OAuthWebViewHandler::handleLoadFinished(bool success) { void OAuthWebViewHandler::handleWebViewDestroyed(QObject* destroyedObject) { _webViewRedisplayTimer.restart(); } + +void OAuthWebViewHandler::handleURLChanged(const QUrl& url) { + // check if this is the authorization screen - if it is then we need to show the OAuthWebViewHandler + const QString ACCESS_TOKEN_URL_REGEX_STRING = "redirect_uri=[\\w:\\/\\.]+&access_token="; + QRegExp accessTokenRegex(ACCESS_TOKEN_URL_REGEX_STRING); + + if (accessTokenRegex.indexIn(url.toString()) != -1) { + _activeWebView->show(); + } else if (url.toString() == DEFAULT_NODE_AUTH_URL.toString() + "/login") { + // this is a login request - we're going to close the webview and signal the AccountManager that we need a login + _activeWebView->close(); + AccountManager::getInstance().checkAndSignalForAccessToken(); + } +} diff --git a/interface/src/ui/OAuthWebViewHandler.h b/interface/src/ui/OAuthWebViewHandler.h index 3a30705f88..8f0c01c90d 100644 --- a/interface/src/ui/OAuthWebViewHandler.h +++ b/interface/src/ui/OAuthWebViewHandler.h @@ -32,6 +32,7 @@ private slots: void handleSSLErrors(QNetworkReply* networkReply, const QList& errorList); void handleLoadFinished(bool success); void handleWebViewDestroyed(QObject* destroyedObject); + void handleURLChanged(const QUrl& url); private: QPointer _activeWebView; QElapsedTimer _webViewRedisplayTimer; From ac0b037f0f8398fc97efbe187dd50d845e3cad44 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 15:25:00 -0700 Subject: [PATCH 14/16] removed connect(); put call into Application::nodeKilled OctreePacketReceiver::nodeKilled() doesn't get called when NodeList::nodeKilled() is emitted for some unknown reason --- interface/src/Application.cpp | 6 +++++- libraries/networking/src/LimitedNodeList.cpp | 1 + libraries/networking/src/ReceivedPacketProcessor.cpp | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a5cb6a0c12..7a7d7c10f8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -244,7 +244,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer))); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer))); - connect(NodeList::getInstance(), &NodeList::nodeKilled, &_octreeProcessor, &ReceivedPacketProcessor::nodeKilled); connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); connect(nodeList, SIGNAL(uuidChanged(const QUuid&)), _myAvatar, SLOT(setSessionUUID(const QUuid&))); connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); @@ -3249,6 +3248,11 @@ void Application::nodeAdded(SharedNodePointer node) { } void Application::nodeKilled(SharedNodePointer node) { + + // this is here because connecting NodeList::nodeKilled to OctreePacketProcessor::nodeKilled doesn't work: + // OctreePacketProcessor::nodeKilled is not called when NodeList::nodeKilled is emitted for some reason. + _octreeProcessor.nodeKilled(node); + if (node->getType() == NodeType::VoxelServer) { QUuid nodeUUID = node->getUUID(); // see if this is the first we've heard of this node... diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c0d7941edf..e1babb24ce 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -367,6 +367,7 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { NodeHash::iterator LimitedNodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { qDebug() << "Killed" << *nodeItemToKill.value(); emit nodeKilled(nodeItemToKill.value()); +printf("\t\t\t emitting nodeKilled: %s\n", nodeItemToKill.value()->getUUID().toString().toLatin1().data()); return _nodeHash.erase(nodeItemToKill); } diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index 32fc4e26f3..28a9397c60 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -51,5 +51,9 @@ bool ReceivedPacketProcessor::process() { } void ReceivedPacketProcessor::nodeKilled(SharedNodePointer node) { - _nodePacketCounts.remove(node->getUUID()); + lock(); + int numRemoved = _nodePacketCounts.remove(node->getUUID()); + unlock(); + qDebug() << "RPP::killNode *************************************"; + printf("\t\t RPP::killNode: %s killed %d nodes\n", node->getUUID().toString().toLatin1().data(), numRemoved); } From 0601c24b2485370a8e01a7147f9a68ff09f42a23 Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 15:26:22 -0700 Subject: [PATCH 15/16] removed debug prints --- libraries/networking/src/LimitedNodeList.cpp | 1 - libraries/networking/src/ReceivedPacketProcessor.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index e1babb24ce..c0d7941edf 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -367,7 +367,6 @@ void LimitedNodeList::killNodeWithUUID(const QUuid& nodeUUID) { NodeHash::iterator LimitedNodeList::killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill) { qDebug() << "Killed" << *nodeItemToKill.value(); emit nodeKilled(nodeItemToKill.value()); -printf("\t\t\t emitting nodeKilled: %s\n", nodeItemToKill.value()->getUUID().toString().toLatin1().data()); return _nodeHash.erase(nodeItemToKill); } diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index 28a9397c60..5513376c65 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -54,6 +54,4 @@ void ReceivedPacketProcessor::nodeKilled(SharedNodePointer node) { lock(); int numRemoved = _nodePacketCounts.remove(node->getUUID()); unlock(); - qDebug() << "RPP::killNode *************************************"; - printf("\t\t RPP::killNode: %s killed %d nodes\n", node->getUUID().toString().toLatin1().data(), numRemoved); } From 7aef5edb8fcd7f9c2839101f33239eac8743556e Mon Sep 17 00:00:00 2001 From: wangyix Date: Wed, 11 Jun 2014 15:27:24 -0700 Subject: [PATCH 16/16] removed debug var --- libraries/networking/src/ReceivedPacketProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/ReceivedPacketProcessor.cpp b/libraries/networking/src/ReceivedPacketProcessor.cpp index 5513376c65..3ef518bbc2 100644 --- a/libraries/networking/src/ReceivedPacketProcessor.cpp +++ b/libraries/networking/src/ReceivedPacketProcessor.cpp @@ -52,6 +52,6 @@ bool ReceivedPacketProcessor::process() { void ReceivedPacketProcessor::nodeKilled(SharedNodePointer node) { lock(); - int numRemoved = _nodePacketCounts.remove(node->getUUID()); + _nodePacketCounts.remove(node->getUUID()); unlock(); }