From cd0ee0ff1db256882aacf2e5dc1654ecb19b237a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 23 Nov 2014 14:58:29 -0800 Subject: [PATCH 01/67] better support for includes in entity scripts --- interface/src/entities/EntityTreeRenderer.cpp | 15 +++++++++++++-- interface/src/entities/EntityTreeRenderer.h | 2 +- libraries/script-engine/src/ScriptEngine.cpp | 11 ++++++++--- libraries/script-engine/src/ScriptEngine.h | 3 +++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 192b42c58b..dfe9505c02 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -99,13 +99,15 @@ QScriptValue EntityTreeRenderer::loadEntityScript(const EntityItemID& entityItem } -QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText) { +QString EntityTreeRenderer::loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL) { QUrl url(scriptMaybeURLorText); // If the url is not valid, this must be script text... if (!url.isValid()) { + isURL = false; return scriptMaybeURLorText; } + isURL = true; QString scriptContents; // assume empty @@ -168,7 +170,8 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { return QScriptValue(); // no script } - QString scriptContents = loadScriptContents(entity->getScript()); + bool isURL = false; // loadScriptContents() will tell us if this is a URL or just text. + QString scriptContents = loadScriptContents(entity->getScript(), isURL); QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(scriptContents); if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) { @@ -179,6 +182,9 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { return QScriptValue(); // invalid script } + if (isURL) { + _entitiesScriptEngine->setParentURL(entity->getScript()); + } QScriptValue entityScriptConstructor = _entitiesScriptEngine->evaluate(scriptContents); if (!entityScriptConstructor.isFunction()) { @@ -189,9 +195,14 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity) { } QScriptValue entityScriptObject = entityScriptConstructor.construct(); + EntityScriptDetails newDetails = { entity->getScript(), entityScriptObject }; _entityScripts[entityID] = newDetails; + if (isURL) { + _entitiesScriptEngine->setParentURL(""); + } + return entityScriptObject; // newly constructed } diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index e5eba79e0d..8b2131691c 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -132,7 +132,7 @@ private: QScriptValue loadEntityScript(const EntityItemID& entityItemID); QScriptValue getPreviouslyLoadedEntityScript(const EntityItemID& entityItemID); QScriptValue getPreviouslyLoadedEntityScript(EntityItem* entity); - QString loadScriptContents(const QString& scriptMaybeURLorText); + QString loadScriptContents(const QString& scriptMaybeURLorText, bool& isURL); QScriptValueList createMouseEventArgs(const EntityItemID& entityID, QMouseEvent* event, unsigned int deviceID); QScriptValueList createMouseEventArgs(const EntityItemID& entityID, const MouseEvent& mouseEvent); diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e6002d7c10..fc1e8ce8bc 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -618,16 +618,20 @@ void ScriptEngine::stopTimer(QTimer *timer) { } QUrl ScriptEngine::resolvePath(const QString& include) const { - // first lets check to see if it's already a full URL QUrl url(include); + // first lets check to see if it's already a full URL if (!url.scheme().isEmpty()) { return url; } // we apparently weren't a fully qualified url, so, let's assume we're relative // to the original URL of our script - QUrl parentURL(_fileNameString); - + QUrl parentURL; + if (_parentURL.isEmpty()) { + parentURL = QUrl(_fileNameString); + } else { + parentURL = QUrl(_parentURL); + } // if the parent URL's scheme is empty, then this is probably a local file... if (parentURL.scheme().isEmpty()) { parentURL = QUrl::fromLocalFile(_fileNameString); @@ -660,6 +664,7 @@ void ScriptEngine::include(const QString& includeFile) { #else QString fileName = url.toLocalFile(); #endif + QFile scriptFile(fileName); if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { qDebug() << "Including file:" << fileName; diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bb279b8887..289436aada 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -93,6 +93,8 @@ public: void setUserLoaded(bool isUserLoaded) { _isUserLoaded = isUserLoaded; } bool isUserLoaded() const { return _isUserLoaded; } + void setParentURL(const QString& parentURL) { _parentURL = parentURL; } + public slots: void stop(); @@ -121,6 +123,7 @@ signals: protected: QString _scriptContents; + QString _parentURL; bool _isFinished; bool _isRunning; bool _isInitialized; From 3ee6d6a6dbb1b661555a81bcff16e444cd9b464e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 23 Nov 2014 20:12:52 -0800 Subject: [PATCH 02/67] work in making entity script mixable and inheritable --- examples/entityScripts/changeColorOnHover.js | 35 +- .../entityScripts/changeColorOnHoverClass.js | 55 +++ examples/entityScripts/movable.js | 410 +---------------- examples/entityScripts/movableClass.js | 426 ++++++++++++++++++ examples/entityScripts/sitOnEntity.js | 363 +-------------- examples/entityScripts/sittable.js | 15 + examples/entityScripts/sittableClass.js | 381 ++++++++++++++++ 7 files changed, 888 insertions(+), 797 deletions(-) create mode 100644 examples/entityScripts/changeColorOnHoverClass.js create mode 100644 examples/entityScripts/movableClass.js create mode 100644 examples/entityScripts/sittable.js create mode 100644 examples/entityScripts/sittableClass.js diff --git a/examples/entityScripts/changeColorOnHover.js b/examples/entityScripts/changeColorOnHover.js index 638c1bece4..0cf08adf1d 100644 --- a/examples/entityScripts/changeColorOnHover.js +++ b/examples/entityScripts/changeColorOnHover.js @@ -13,34 +13,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function(){ - this.oldColor = {}; - this.oldColorKnown = false; - this.storeOldColor = function(entityID) { - var oldProperties = Entities.getEntityProperties(entityID); - this.oldColor = oldProperties.color; - this.oldColorKnown = true; - print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); - }; - - this.preload = function(entityID) { - print("preload"); - this.storeOldColor(entityID); - }; - - this.hoverEnterEntity = function(entityID, mouseEvent) { - print("hoverEnterEntity"); - if (!this.oldColorKnown) { - this.storeOldColor(entityID); - } - Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} }); - }; - this.hoverLeaveEntity = function(entityID, mouseEvent) { - print("hoverLeaveEntity"); - if (this.oldColorKnown) { - print("leave restoring old color... this.oldColor=" - + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); - Entities.editEntity(entityID, { color: this.oldColor }); - } - }; -}) \ No newline at end of file +(function() { + Script.include("changeColorOnHoverClass.js"); + return new ChangeColorOnHover(); +}) diff --git a/examples/entityScripts/changeColorOnHoverClass.js b/examples/entityScripts/changeColorOnHoverClass.js new file mode 100644 index 0000000000..231469f7e8 --- /dev/null +++ b/examples/entityScripts/changeColorOnHoverClass.js @@ -0,0 +1,55 @@ +// +// changeColorOnHover.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/1/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example of an entity script which when assigned to a non-model entity like a box or sphere, will +// change the color of the entity when you hover over it. This script uses the JavaScript prototype/class functionality +// to construct an object that has methods for hoverEnterEntity and hoverLeaveEntity; +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +ChangeColorOnHover = function(){ + this.oldColor = {}; + this.oldColorKnown = false; +}; + +ChangeColorOnHover.prototype = { + + storeOldColor: function(entityID) { + var oldProperties = Entities.getEntityProperties(entityID); + this.oldColor = oldProperties.color; + this.oldColorKnown = true; + print("storing old color... this.oldColor=" + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + }, + + preload: function(entityID) { + print("preload"); + this.storeOldColor(entityID); + }, + + hoverEnterEntity: function(entityID, mouseEvent) { + print("hoverEnterEntity"); + if (!this.oldColorKnown) { + this.storeOldColor(entityID); + } + Entities.editEntity(entityID, { color: { red: 0, green: 255, blue: 255} }); + }, + + + hoverLeaveEntity: function(entityID, mouseEvent) { + print("hoverLeaveEntity"); + if (this.oldColorKnown) { + print("leave restoring old color... this.oldColor=" + + this.oldColor.red + "," + this.oldColor.green + "," + this.oldColor.blue); + Entities.editEntity(entityID, { color: this.oldColor }); + } + } +}; + + diff --git a/examples/entityScripts/movable.js b/examples/entityScripts/movable.js index 21e6261179..0ea3641c6f 100644 --- a/examples/entityScripts/movable.js +++ b/examples/entityScripts/movable.js @@ -8,412 +8,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function(){ - - this.entityID = null; - this.properties = null; - this.graboffset = null; - this.clickedAt = null; - this.firstHolding = true; - this.clicked = { x: -1, y: -1}; - this.lastMovedPosition = { x: -1, y: -1}; - this.lastMovedTime = 0; - this.rotateOverlayTarget = null; - this.rotateOverlayInner = null; - this.rotateOverlayOuter = null; - this.rotateOverlayCurrent = null; - this.rotateMode = false; - this.originalRotation = null; - - this.moveSoundURLS = [ - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" - ]; - - this.turnSoundURLS = [ - - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" - - // TODO: determine if these or other turn sounds work better than move sounds. - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn1.wav", - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn2.wav", - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn3.wav" - ]; - - - this.moveSounds = new Array(); - this.turnSounds = new Array(); - this.moveSound = null; - this.turnSound = null; - this.injector = null; - - var debug = false; - var displayRotateTargets = true; // change to false if you don't want the rotate targets - var rotateOverlayTargetSize = 10000; // really big target - var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool - var innerRadius; - var outerRadius; - var yawCenter; - var yawZero; - var rotationNormal; - var yawNormal; - var stopSoundDelay = 100; // number of msecs of not moving to have sound stop - - this.getRandomInt = function(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - } - - this.downloadSounds = function() { - for (var i = 0; i < this.moveSoundURLS.length; i++) { - this.moveSounds[i] = SoundCache.getSound(this.moveSoundURLS[i]); - } - for (var i = 0; i < this.turnSoundURLS.length; i++) { - this.turnSounds[i] = SoundCache.getSound(this.turnSoundURLS[i]); - } - } - - this.pickRandomSounds = function() { - var moveIndex = this.getRandomInt(0, this.moveSounds.length - 1); - var turnIndex = this.getRandomInt(0, this.turnSounds.length - 1); - if (debug) { - print("Random sounds -- turn:" + turnIndex + " move:" + moveIndex); - } - this.moveSound = this.moveSounds[moveIndex]; - this.turnSound = this.turnSounds[turnIndex]; - } - - // Play move sound - this.playMoveSound = function() { - if (debug) { - print("playMoveSound()"); - } - if (this.moveSound && this.moveSound.downloaded) { - if (debug) { - print("playMoveSound() --- calling this.injector = Audio.playSound(this.moveSound...)"); - } - this.injector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 }); - } - } - - // Play turn sound - this.playTurnSound = function() { - if (debug) { - print("playTurnSound()"); - } - if (this.turnSound && this.turnSound.downloaded) { - if (debug) { - print("playTurnSound() --- calling this.injector = Audio.playSound(this.turnSound...)"); - } - this.injector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 }); - } - } - - // stop sound - this.stopSound = function() { - if (debug) { - print("stopSound()"); - } - if (this.injector) { - Audio.stopInjector(this.injector); - this.injector = null; - } - } - - // Pr, Vr are respectively the Ray's Point of origin and Vector director - // Pp, Np are respectively the Plane's Point of origin and Normal vector - this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) { - var d = -Vec3.dot(Pp, Np); - var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np); - return Vec3.sum(Pr, Vec3.multiply(t, Vr)); - }; - - // updates the piece position based on mouse input - this.updatePosition = function(mouseEvent) { - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var upVector = { x: 0, y: 1, z: 0 }; - var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, - this.properties.position, upVector); - - var newPosition = Vec3.sum(intersection, this.graboffset); - Entities.editEntity(this.entityID, { position: newPosition }); - }; - - this.grab = function(mouseEvent) { - // first calculate the offset - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var upVector = { x: 0, y: 1, z: 0 }; - var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, - this.properties.position, upVector); - this.graboffset = Vec3.subtract(this.properties.position, intersection); - }; - - this.stopSoundIfNotMoving = function(mouseEvent) { - var nowDate = new Date(); - var nowMSecs = nowDate.getTime(); - if(mouseEvent.x == this.lastMovedPosition.x && mouseEvent.y == this.lastMovedPosition.y) { - var elapsedSinceLastMove = nowMSecs - this.lastMovedMSecs; - if (debug) { - print("elapsedSinceLastMove:" + elapsedSinceLastMove); - } - if (elapsedSinceLastMove > stopSoundDelay) { - if (debug) { - print("calling stopSound()..."); - } - this.stopSound(); - } - } else { - // if we've moved, then track our last move position and time... - this.lastMovedMSecs = nowMSecs; - this.lastMovedPosition.x = mouseEvent.x; - this.lastMovedPosition.y = mouseEvent.y; - } - } - - this.move = function(mouseEvent) { - this.updatePosition(mouseEvent); - if (this.injector === null) { - this.playMoveSound(); - } - }; - - this.release = function(mouseEvent) { - this.updatePosition(mouseEvent); - }; - - this.rotate = function(mouseEvent) { - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var result = Overlays.findRayIntersection(pickRay); - - if (result.intersects) { - var center = yawCenter; - var zero = yawZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - - var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - // var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } - - var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); - Entities.editEntity(this.entityID, { rotation: Quat.multiply(yawChange, this.originalRotation) }); - - - // update the rotation display accordingly... - var startAtCurrent = 360-angleFromZero; - var endAtCurrent = 360; - var startAtRemainder = 0; - var endAtRemainder = 360-angleFromZero; - if (angleFromZero < 0) { - startAtCurrent = 0; - endAtCurrent = -angleFromZero; - startAtRemainder = -angleFromZero; - endAtRemainder = 360; - } - - if (snapToInner) { - Overlays.editOverlay(this.rotateOverlayOuter, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(this.rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, - majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); - } else { - Overlays.editOverlay(this.rotateOverlayInner, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(this.rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, - majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); - } - } - - if (this.injector === null) { - this.playTurnSound(); - } - }; - // All callbacks start by updating the properties - this.updateProperties = function(entityID) { - if (this.entityID === null || !this.entityID.isKnownID) { - this.entityID = Entities.identifyEntity(entityID); - } - this.properties = Entities.getEntityProperties(this.entityID); - }; - - this.cleanupRotateOverlay = function() { - Overlays.deleteOverlay(this.rotateOverlayTarget); - Overlays.deleteOverlay(this.rotateOverlayInner); - Overlays.deleteOverlay(this.rotateOverlayOuter); - Overlays.deleteOverlay(this.rotateOverlayCurrent); - this.rotateOverlayTarget = null; - this.rotateOverlayInner = null; - this.rotateOverlayOuter = null; - this.rotateOverlayCurrent = null; - } - - this.displayRotateOverlay = function(mouseEvent) { - var yawOverlayAngles = { x: 90, y: 0, z: 0 }; - var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles); - - yawNormal = { x: 0, y: 1, z: 0 }; - yawCenter = this.properties.position; - rotationNormal = yawNormal; - - // Size the overlays to the current selection size - var diagonal = (Vec3.length(this.properties.dimensions) / 2) * 1.1; - var halfDimensions = Vec3.multiply(this.properties.dimensions, 0.5); - innerRadius = diagonal; - outerRadius = diagonal * 1.15; - var innerAlpha = 0.2; - var outerAlpha = 0.2; - - this.rotateOverlayTarget = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: rotateOverlayTargetSize, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.0, - solid: true, - visible: true, - rotation: yawOverlayRotation, - ignoreRayIntersection: false - }); - - this.rotateOverlayInner = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: innerRadius, - innerRadius: 0.9, - alpha: innerAlpha, - color: { red: 51, green: 152, blue: 203 }, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - hasTickMarks: true, - majorTickMarksAngle: innerSnapAngle, - minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, - minorTickMarksLength: 0, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - ignoreRayIntersection: true, // always ignore this - }); - - this.rotateOverlayOuter = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: outerRadius, - innerRadius: 0.9, - startAt: 0, - endAt: 360, - alpha: outerAlpha, - color: { red: 51, green: 152, blue: 203 }, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - - hasTickMarks: true, - majorTickMarksAngle: 45.0, - minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, - minorTickMarksLength: 0.1, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - ignoreRayIntersection: true, // always ignore this - }); - - this.rotateOverlayCurrent = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: outerRadius, - startAt: 0, - endAt: 0, - innerRadius: 0.9, - color: { red: 224, green: 67, blue: 36}, - alpha: 0.8, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - ignoreRayIntersection: true, // always ignore this - hasTickMarks: true, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - }); - - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var result = Overlays.findRayIntersection(pickRay); - yawZero = result.intersection; - - }; - - this.preload = function(entityID) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.downloadSounds(); - }; - - this.clickDownOnEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.grab(mouseEvent); - - var nowDate = new Date(); - var nowMSecs = nowDate.getTime(); - this.clickedAt = nowMSecs; - this.firstHolding = true; - - this.clicked.x = mouseEvent.x; - this.clicked.y = mouseEvent.y; - this.lastMovedPosition.x = mouseEvent.x; - this.lastMovedPosition.y = mouseEvent.y; - this.lastMovedMSecs = nowMSecs; - - this.pickRandomSounds(); - }; - - this.holdingClickOnEntity = function(entityID, mouseEvent) { - - this.updateProperties(entityID); // All callbacks start by updating the properties - - if (this.firstHolding) { - // if we haven't moved yet... - if (this.clicked.x == mouseEvent.x && this.clicked.y == mouseEvent.y) { - var d = new Date(); - var now = d.getTime(); - - if (now - this.clickedAt > 500) { - this.displayRotateOverlay(mouseEvent); - this.firstHolding = false; - this.rotateMode = true; - this.originalRotation = this.properties.rotation; - } - } else { - this.firstHolding = false; - } - } - - if (this.rotateMode) { - this.rotate(mouseEvent); - } else { - this.move(mouseEvent); - } - - this.stopSoundIfNotMoving(mouseEvent); - }; - this.clickReleaseOnEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - if (this.rotateMode) { - this.rotate(mouseEvent); - } else { - this.release(mouseEvent); - } - - if (this.rotateOverlayTarget != null) { - this.cleanupRotateOverlay(); - this.rotateMode = false; - } - - this.firstHolding = false; - this.stopSound(); - }; +(function() { + Script.include("movableClass.js"); + return new Movable(); }) diff --git a/examples/entityScripts/movableClass.js b/examples/entityScripts/movableClass.js new file mode 100644 index 0000000000..26fb643826 --- /dev/null +++ b/examples/entityScripts/movableClass.js @@ -0,0 +1,426 @@ +// +// movableClass.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/17/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +Movable = function() { + + this.entityID = null; + this.properties = null; + this.graboffset = null; + this.clickedAt = null; + this.firstHolding = true; + this.clicked = { x: -1, y: -1}; + this.lastMovedPosition = { x: -1, y: -1}; + this.lastMovedTime = 0; + this.rotateOverlayTarget = null; + this.rotateOverlayInner = null; + this.rotateOverlayOuter = null; + this.rotateOverlayCurrent = null; + this.rotateMode = false; + this.originalRotation = null; + + this.moveSoundURLS = [ + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" + ]; + + this.turnSoundURLS = [ + + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" + + // TODO: determine if these or other turn sounds work better than move sounds. + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn1.wav", + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn2.wav", + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn3.wav" + ]; + + + this.moveSounds = new Array(); + this.turnSounds = new Array(); + this.moveSound = null; + this.turnSound = null; + this.injector = null; + + var debug = false; + var displayRotateTargets = true; // change to false if you don't want the rotate targets + var rotateOverlayTargetSize = 10000; // really big target + var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool + var innerRadius; + var outerRadius; + var yawCenter; + var yawZero; + var rotationNormal; + var yawNormal; + var stopSoundDelay = 100; // number of msecs of not moving to have sound stop + + this.getRandomInt = function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + this.downloadSounds = function() { + for (var i = 0; i < this.moveSoundURLS.length; i++) { + this.moveSounds[i] = SoundCache.getSound(this.moveSoundURLS[i]); + } + for (var i = 0; i < this.turnSoundURLS.length; i++) { + this.turnSounds[i] = SoundCache.getSound(this.turnSoundURLS[i]); + } + } + + this.pickRandomSounds = function() { + var moveIndex = this.getRandomInt(0, this.moveSounds.length - 1); + var turnIndex = this.getRandomInt(0, this.turnSounds.length - 1); + if (debug) { + print("Random sounds -- turn:" + turnIndex + " move:" + moveIndex); + } + this.moveSound = this.moveSounds[moveIndex]; + this.turnSound = this.turnSounds[turnIndex]; + } + + // Play move sound + this.playMoveSound = function() { + if (debug) { + print("playMoveSound()"); + } + if (this.moveSound && this.moveSound.downloaded) { + if (debug) { + print("playMoveSound() --- calling this.injector = Audio.playSound(this.moveSound...)"); + } + this.injector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 }); + } + } + + // Play turn sound + this.playTurnSound = function() { + if (debug) { + print("playTurnSound()"); + } + if (this.turnSound && this.turnSound.downloaded) { + if (debug) { + print("playTurnSound() --- calling this.injector = Audio.playSound(this.turnSound...)"); + } + this.injector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 }); + } + } + + // stop sound + this.stopSound = function() { + if (debug) { + print("stopSound()"); + } + if (this.injector) { + Audio.stopInjector(this.injector); + this.injector = null; + } + } + + // Pr, Vr are respectively the Ray's Point of origin and Vector director + // Pp, Np are respectively the Plane's Point of origin and Normal vector + this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) { + var d = -Vec3.dot(Pp, Np); + var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np); + return Vec3.sum(Pr, Vec3.multiply(t, Vr)); + }; + + // updates the piece position based on mouse input + this.updatePosition = function(mouseEvent) { + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var upVector = { x: 0, y: 1, z: 0 }; + var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, + this.properties.position, upVector); + + var newPosition = Vec3.sum(intersection, this.graboffset); + Entities.editEntity(this.entityID, { position: newPosition }); + }; + + this.grab = function(mouseEvent) { + // first calculate the offset + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var upVector = { x: 0, y: 1, z: 0 }; + var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, + this.properties.position, upVector); + this.graboffset = Vec3.subtract(this.properties.position, intersection); + }; + + this.stopSoundIfNotMoving = function(mouseEvent) { + var nowDate = new Date(); + var nowMSecs = nowDate.getTime(); + if(mouseEvent.x == this.lastMovedPosition.x && mouseEvent.y == this.lastMovedPosition.y) { + var elapsedSinceLastMove = nowMSecs - this.lastMovedMSecs; + if (debug) { + print("elapsedSinceLastMove:" + elapsedSinceLastMove); + } + if (elapsedSinceLastMove > stopSoundDelay) { + if (debug) { + print("calling stopSound()..."); + } + this.stopSound(); + } + } else { + // if we've moved, then track our last move position and time... + this.lastMovedMSecs = nowMSecs; + this.lastMovedPosition.x = mouseEvent.x; + this.lastMovedPosition.y = mouseEvent.y; + } + } + + this.move = function(mouseEvent) { + this.updatePosition(mouseEvent); + if (this.injector === null) { + this.playMoveSound(); + } + }; + + this.release = function(mouseEvent) { + this.updatePosition(mouseEvent); + }; + + this.rotate = function(mouseEvent) { + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var result = Overlays.findRayIntersection(pickRay); + + if (result.intersects) { + var center = yawCenter; + var zero = yawZero; + var centerToZero = Vec3.subtract(center, zero); + var centerToIntersect = Vec3.subtract(center, result.intersection); + var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + + var distanceFromCenter = Vec3.distance(center, result.intersection); + var snapToInner = false; + // var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; + if (distanceFromCenter < innerRadius) { + angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; + snapToInner = true; + } + + var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); + Entities.editEntity(this.entityID, { rotation: Quat.multiply(yawChange, this.originalRotation) }); + + + // update the rotation display accordingly... + var startAtCurrent = 360-angleFromZero; + var endAtCurrent = 360; + var startAtRemainder = 0; + var endAtRemainder = 360-angleFromZero; + if (angleFromZero < 0) { + startAtCurrent = 0; + endAtCurrent = -angleFromZero; + startAtRemainder = -angleFromZero; + endAtRemainder = 360; + } + + if (snapToInner) { + Overlays.editOverlay(this.rotateOverlayOuter, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(this.rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + } else { + Overlays.editOverlay(this.rotateOverlayInner, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(this.rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + } + } + + if (this.injector === null) { + this.playTurnSound(); + } + }; + // All callbacks start by updating the properties + this.updateProperties = function(entityID) { + if (this.entityID === null || !this.entityID.isKnownID) { + this.entityID = Entities.identifyEntity(entityID); + } + this.properties = Entities.getEntityProperties(this.entityID); + }; + + this.cleanupRotateOverlay = function() { + Overlays.deleteOverlay(this.rotateOverlayTarget); + Overlays.deleteOverlay(this.rotateOverlayInner); + Overlays.deleteOverlay(this.rotateOverlayOuter); + Overlays.deleteOverlay(this.rotateOverlayCurrent); + this.rotateOverlayTarget = null; + this.rotateOverlayInner = null; + this.rotateOverlayOuter = null; + this.rotateOverlayCurrent = null; + } + + this.displayRotateOverlay = function(mouseEvent) { + var yawOverlayAngles = { x: 90, y: 0, z: 0 }; + var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles); + + yawNormal = { x: 0, y: 1, z: 0 }; + yawCenter = this.properties.position; + rotationNormal = yawNormal; + + // Size the overlays to the current selection size + var diagonal = (Vec3.length(this.properties.dimensions) / 2) * 1.1; + var halfDimensions = Vec3.multiply(this.properties.dimensions, 0.5); + innerRadius = diagonal; + outerRadius = diagonal * 1.15; + var innerAlpha = 0.2; + var outerAlpha = 0.2; + + this.rotateOverlayTarget = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: rotateOverlayTargetSize, + color: { red: 0, green: 0, blue: 0 }, + alpha: 0.0, + solid: true, + visible: true, + rotation: yawOverlayRotation, + ignoreRayIntersection: false + }); + + this.rotateOverlayInner = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: innerRadius, + innerRadius: 0.9, + alpha: innerAlpha, + color: { red: 51, green: 152, blue: 203 }, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + hasTickMarks: true, + majorTickMarksAngle: innerSnapAngle, + minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, + minorTickMarksLength: 0, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + }); + + this.rotateOverlayOuter = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: outerRadius, + innerRadius: 0.9, + startAt: 0, + endAt: 360, + alpha: outerAlpha, + color: { red: 51, green: 152, blue: 203 }, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + + hasTickMarks: true, + majorTickMarksAngle: 45.0, + minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, + minorTickMarksLength: 0.1, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + }); + + this.rotateOverlayCurrent = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: outerRadius, + startAt: 0, + endAt: 0, + innerRadius: 0.9, + color: { red: 224, green: 67, blue: 36}, + alpha: 0.8, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + ignoreRayIntersection: true, // always ignore this + hasTickMarks: true, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + }); + + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var result = Overlays.findRayIntersection(pickRay); + yawZero = result.intersection; + + }; +}; + +Movable.prototype = { + preload : function(entityID) { + print("Movable.preload()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + this.downloadSounds(); + }, + + clickDownOnEntity : function(entityID, mouseEvent) { + print("Movable.clickDownOnEntity()"); + + this.updateProperties(entityID); // All callbacks start by updating the properties + this.grab(mouseEvent); + + var nowDate = new Date(); + var nowMSecs = nowDate.getTime(); + this.clickedAt = nowMSecs; + this.firstHolding = true; + + this.clicked.x = mouseEvent.x; + this.clicked.y = mouseEvent.y; + this.lastMovedPosition.x = mouseEvent.x; + this.lastMovedPosition.y = mouseEvent.y; + this.lastMovedMSecs = nowMSecs; + + this.pickRandomSounds(); + }, + + holdingClickOnEntity : function(entityID, mouseEvent) { + print("Movable.holdingClickOnEntity()"); + + this.updateProperties(entityID); // All callbacks start by updating the properties + + if (this.firstHolding) { + // if we haven't moved yet... + if (this.clicked.x == mouseEvent.x && this.clicked.y == mouseEvent.y) { + var d = new Date(); + var now = d.getTime(); + + if (now - this.clickedAt > 500) { + this.displayRotateOverlay(mouseEvent); + this.firstHolding = false; + this.rotateMode = true; + this.originalRotation = this.properties.rotation; + } + } else { + this.firstHolding = false; + } + } + + if (this.rotateMode) { + this.rotate(mouseEvent); + } else { + this.move(mouseEvent); + } + + this.stopSoundIfNotMoving(mouseEvent); + }, + + clickReleaseOnEntity : function(entityID, mouseEvent) { + print("Movable.clickReleaseOnEntity()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + if (this.rotateMode) { + this.rotate(mouseEvent); + } else { + this.release(mouseEvent); + } + + if (this.rotateOverlayTarget != null) { + this.cleanupRotateOverlay(); + this.rotateMode = false; + } + + this.firstHolding = false; + this.stopSound(); + }, +}; diff --git a/examples/entityScripts/sitOnEntity.js b/examples/entityScripts/sitOnEntity.js index d5c4fa9c52..080acf61a8 100644 --- a/examples/entityScripts/sitOnEntity.js +++ b/examples/entityScripts/sitOnEntity.js @@ -11,362 +11,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function(){ - - this.entityID = null; - this.properties = null; - this.standUpButton = null; - this.indicatorsAdded = false; - this.indicator = new Array(); - - - var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; - var windowDimensions = Controller.getViewportDimensions(); - var buttonWidth = 37; - var buttonHeight = 46; - var buttonPadding = 50; // inside the normal toolbar position - var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth; - var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 - (buttonHeight + buttonPadding); - - var passedTime = 0.0; - var startPosition = null; - var startRotation = null; - var animationLenght = 2.0; - - var avatarOldPosition = { x: 0, y: 0, z: 0 }; - - var sittingSettingsHandle = "SitJsSittingPosition"; - var sitting = Settings.getValue(sittingSettingsHandle, false) == "true"; - print("Original sitting status: " + sitting); - var frame = 0; - - var seat = new Object(); - var hiddingSeats = false; - - // This is the pose we would like to end up - var pose = [ - {joint:"RightUpLeg", rotation: {x:100.0, y:15.0, z:0.0}}, - {joint:"RightLeg", rotation: {x:-130.0, y:15.0, z:0.0}}, - {joint:"RightFoot", rotation: {x:30, y:15.0, z:0.0}}, - {joint:"LeftUpLeg", rotation: {x:100.0, y:-15.0, z:0.0}}, - {joint:"LeftLeg", rotation: {x:-130.0, y:-15.0, z:0.0}}, - {joint:"LeftFoot", rotation: {x:30, y:15.0, z:0.0}} - ]; - - var startPoseAndTransition = []; - - function storeStartPoseAndTransition() { - for (var i = 0; i < pose.length; i++){ - var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(pose[i].joint)); - var transitionVector = Vec3.subtract( pose[i].rotation, startRotation ); - startPoseAndTransition.push({joint: pose[i].joint, start: startRotation, transition: transitionVector}); - } - } - - function updateJoints(factor){ - for (var i = 0; i < startPoseAndTransition.length; i++){ - var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor); - var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition); - MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation )); - } - } - - var sittingDownAnimation = function(deltaTime) { - - passedTime += deltaTime; - var factor = passedTime/animationLenght; - - if ( passedTime <= animationLenght ) { - updateJoints(factor); - - var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z}; - MyAvatar.position = pos; - } else { - Script.update.disconnect(sittingDownAnimation); - if (seat.model) { - MyAvatar.setModelReferential(seat.model.id); - } - } - } - - var standingUpAnimation = function(deltaTime) { - - passedTime += deltaTime; - var factor = 1 - passedTime/animationLenght; - - if ( passedTime <= animationLenght ) { - - updateJoints(factor); - - var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z}; - MyAvatar.position = pos; - } else { - Script.update.disconnect(standingUpAnimation); - - } - } - - var externalThis = this; - - var goToSeatAnimation = function(deltaTime) { - passedTime += deltaTime; - var factor = passedTime/animationLenght; - - if (passedTime <= animationLenght) { - var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); - MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); - } else if (passedTime <= 2 * animationLenght) { - //Quat.print("MyAvatar: ", MyAvatar.orientation); - //Quat.print("Seat: ", seat.rotation); - MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); - } else { - Script.update.disconnect(goToSeatAnimation); - externalThis.sitDown(); - externalThis.showIndicators(false); - } - } - - var globalMouseClick = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - if (clickedOverlay == externalThis.standUpButton) { - seat.model = null; - externalThis.standUp(); - Controller.mousePressEvent.disconnect(globalMouseClick); - } - }; - - this.sitDown = function() { - sitting = true; - Settings.setValue(sittingSettingsHandle, sitting); - print("sitDown sitting status: " + Settings.getValue(sittingSettingsHandle, false)); - passedTime = 0.0; - startPosition = MyAvatar.position; - storeStartPoseAndTransition(); - try { - Script.update.disconnect(standingUpAnimation); - } catch(e){ - // no need to handle. if it wasn't connected no harm done - } - Script.update.connect(sittingDownAnimation); - Overlays.editOverlay(this.standUpButton, { visible: true }); - Controller.mousePressEvent.connect(globalMouseClick); - } - - this.standUp = function() { - sitting = false; - Settings.setValue(sittingSettingsHandle, sitting); - print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false)); - passedTime = 0.0; - startPosition = MyAvatar.position; - MyAvatar.clearReferential(); - try{ - Script.update.disconnect(sittingDownAnimation); - } catch (e){} - Script.update.connect(standingUpAnimation); - Overlays.editOverlay(this.standUpButton, { visible: false }); - Controller.mousePressEvent.disconnect(globalMouseClick); - } - - function SeatIndicator(modelProperties, seatIndex) { - var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; - - this.position = Vec3.sum(modelProperties.position, - Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), - halfDiagonal)); // hack - - this.orientation = Quat.multiply(modelProperties.rotation, - modelProperties.sittingPoints[seatIndex].rotation); - this.scale = MyAvatar.scale / 3; - - this.sphere = Overlays.addOverlay("billboard", { - subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, - url: buttonImageUrl, - position: this.position, - scale: this.scale, - size: this.scale, - solid: true, - color: { red: 255, green: 255, blue: 255 }, - alpha: 0.8, - visible: true, - isFacingAvatar: true - }); - - this.show = function(doShow) { - Overlays.editOverlay(this.sphere, { visible: doShow }); - } - - this.update = function() { - Overlays.editOverlay(this.sphere, { - position: this.position, - size: this.scale - }); - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.sphere); - } - } - - function update(deltaTime){ - var newWindowDimensions = Controller.getViewportDimensions(); - if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ - windowDimensions = newWindowDimensions; - var newX = windowDimensions.x - buttonPadding - buttonWidth; - var newY = (windowDimensions.y - buttonHeight) / 2 ; - Overlays.editOverlay( this.standUpButton, {x: newX, y: newY} ); - } - - // For a weird reason avatar joint don't update till the 10th frame - // Set the update frame to 20 to be safe - var UPDATE_FRAME = 20; - if (frame <= UPDATE_FRAME) { - if (frame == UPDATE_FRAME) { - if (sitting == true) { - print("Was seated: " + sitting); - storeStartPoseAndTransition(); - updateJoints(1.0); - } - } - frame++; - } - } - - this.addIndicators = function() { - if (!this.indicatorsAdded) { - if (this.properties.sittingPoints.length > 0) { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i] = new SeatIndicator(this.properties, i); - } - this.indicatorsAdded = true; - } - } - } - - this.removeIndicators = function() { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i].cleanup(); - } - } - - this.showIndicators = function(doShow) { - this.addIndicators(); - if (this.indicatorsAdded) { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i].show(doShow); - } - } - hiddingSeats = !doShow; - } - - function raySphereIntersection(origin, direction, center, radius) { - var A = origin; - var B = Vec3.normalize(direction); - var P = center; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - - return (x > 0 && d <= radius); - } - - this.cleanup = function() { - this.standUp(); - MyAvatar.clearReferential(); - for (var i = 0; i < pose.length; i++){ - MyAvatar.clearJointData(pose[i].joint); - } - Overlays.deleteOverlay(this.standUpButton); - for (var i = 0; i < this.indicator.length; ++i) { - this.indicator[i].cleanup(); - } - }; - - - this.createStandupButton = function() { - this.standUpButton = Overlays.addOverlay("image", { - x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight, - subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight}, - imageURL: buttonImageUrl, - visible: false, - alpha: 1.0 - }); - }; - - this.handleClickEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == this.standUpButton) { - seat.model = null; - this.standUp(); - } else { - this.addIndicators(); - if (this.indicatorsAdded) { - var pickRay = Camera.computePickRay(event.x, event.y); - - var clickedOnSeat = false; - - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - if (raySphereIntersection(pickRay.origin, - pickRay.direction, - this.indicator[i].position, - this.indicator[i].scale / 2)) { - clickedOnSeat = true; - seat.model = this.entityID; // ?? - seat.position = this.indicator[i].position; - seat.rotation = this.indicator[i].orientation; - } - } - - if (clickedOnSeat) { - passedTime = 0.0; - startPosition = MyAvatar.position; - startRotation = MyAvatar.orientation; - try{ Script.update.disconnect(standingUpAnimation); } catch(e){} - try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} - Script.update.connect(goToSeatAnimation); - } - } - } - }; - - - // All callbacks start by updating the properties - this.updateProperties = function(entityID) { - if (this.entityID === null || !this.entityID.isKnownID) { - this.entityID = Entities.identifyEntity(entityID); - } - this.properties = Entities.getEntityProperties(this.entityID); - }; - - this.unload = function(entityID) { - this.cleanup(); - Script.update.disconnect(update); - }; - - this.preload = function(entityID) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.createStandupButton(); - Script.update.connect(update); - }; - - - this.hoverOverEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.showIndicators(true); - }; - this.hoverLeaveEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.showIndicators(false); - }; - - this.clickDownOnEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - this.handleClickEvent(mouseEvent); - }; - - this.clickReleaseOnEntity = function(entityID, mouseEvent) { - this.updateProperties(entityID); // All callbacks start by updating the properties - }; - -}) \ No newline at end of file +(function() { + Script.include("sittableClass.js"); + return new Sittable(); +}) diff --git a/examples/entityScripts/sittable.js b/examples/entityScripts/sittable.js new file mode 100644 index 0000000000..0753a46d2a --- /dev/null +++ b/examples/entityScripts/sittable.js @@ -0,0 +1,15 @@ +// +// sittable.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/17/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("sittableClass.js"); + return new Sittable(); +}) diff --git a/examples/entityScripts/sittableClass.js b/examples/entityScripts/sittableClass.js new file mode 100644 index 0000000000..c16e026f96 --- /dev/null +++ b/examples/entityScripts/sittableClass.js @@ -0,0 +1,381 @@ +// +// sitOnEntity.js +// examples/entityScripts +// +// Created by Brad Hefta-Gaub on 11/1/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example of an entity script for sitting. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Sittable = function() { + + this.entityID = null; + this.properties = null; + this.standUpButton = null; + this.indicatorsAdded = false; + this.indicator = new Array(); + + + var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 37; + var buttonHeight = 46; + var buttonPadding = 50; // inside the normal toolbar position + var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth; + var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 - (buttonHeight + buttonPadding); + + var passedTime = 0.0; + var startPosition = null; + var startRotation = null; + var animationLenght = 2.0; + + var avatarOldPosition = { x: 0, y: 0, z: 0 }; + + var sittingSettingsHandle = "SitJsSittingPosition"; + var sitting = Settings.getValue(sittingSettingsHandle, false) == "true"; + print("Original sitting status: " + sitting); + var frame = 0; + + var seat = new Object(); + var hiddingSeats = false; + + // This is the pose we would like to end up + var pose = [ + {joint:"RightUpLeg", rotation: {x:100.0, y:15.0, z:0.0}}, + {joint:"RightLeg", rotation: {x:-130.0, y:15.0, z:0.0}}, + {joint:"RightFoot", rotation: {x:30, y:15.0, z:0.0}}, + {joint:"LeftUpLeg", rotation: {x:100.0, y:-15.0, z:0.0}}, + {joint:"LeftLeg", rotation: {x:-130.0, y:-15.0, z:0.0}}, + {joint:"LeftFoot", rotation: {x:30, y:15.0, z:0.0}} + ]; + + var startPoseAndTransition = []; + + function storeStartPoseAndTransition() { + for (var i = 0; i < pose.length; i++){ + var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(pose[i].joint)); + var transitionVector = Vec3.subtract( pose[i].rotation, startRotation ); + startPoseAndTransition.push({joint: pose[i].joint, start: startRotation, transition: transitionVector}); + } + } + + function updateJoints(factor){ + for (var i = 0; i < startPoseAndTransition.length; i++){ + var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor); + var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition); + MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation )); + } + } + + var sittingDownAnimation = function(deltaTime) { + + passedTime += deltaTime; + var factor = passedTime/animationLenght; + + if ( passedTime <= animationLenght ) { + updateJoints(factor); + + var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z}; + MyAvatar.position = pos; + } else { + Script.update.disconnect(sittingDownAnimation); + if (seat.model) { + MyAvatar.setModelReferential(seat.model.id); + } + } + } + + var standingUpAnimation = function(deltaTime) { + + passedTime += deltaTime; + var factor = 1 - passedTime/animationLenght; + + if ( passedTime <= animationLenght ) { + + updateJoints(factor); + + var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z}; + MyAvatar.position = pos; + } else { + Script.update.disconnect(standingUpAnimation); + + } + } + + var externalThis = this; + + var goToSeatAnimation = function(deltaTime) { + passedTime += deltaTime; + var factor = passedTime/animationLenght; + + if (passedTime <= animationLenght) { + var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); + MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); + } else if (passedTime <= 2 * animationLenght) { + //Quat.print("MyAvatar: ", MyAvatar.orientation); + //Quat.print("Seat: ", seat.rotation); + MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); + } else { + Script.update.disconnect(goToSeatAnimation); + externalThis.sitDown(); + externalThis.showIndicators(false); + } + } + + var globalMouseClick = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + if (clickedOverlay == externalThis.standUpButton) { + seat.model = null; + externalThis.standUp(); + Controller.mousePressEvent.disconnect(globalMouseClick); + } + }; + + this.sitDown = function() { + sitting = true; + Settings.setValue(sittingSettingsHandle, sitting); + print("sitDown sitting status: " + Settings.getValue(sittingSettingsHandle, false)); + passedTime = 0.0; + startPosition = MyAvatar.position; + storeStartPoseAndTransition(); + try { + Script.update.disconnect(standingUpAnimation); + } catch(e){ + // no need to handle. if it wasn't connected no harm done + } + Script.update.connect(sittingDownAnimation); + Overlays.editOverlay(this.standUpButton, { visible: true }); + Controller.mousePressEvent.connect(globalMouseClick); + } + + this.standUp = function() { + sitting = false; + Settings.setValue(sittingSettingsHandle, sitting); + print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false)); + passedTime = 0.0; + startPosition = MyAvatar.position; + MyAvatar.clearReferential(); + try{ + Script.update.disconnect(sittingDownAnimation); + } catch (e){} + Script.update.connect(standingUpAnimation); + Overlays.editOverlay(this.standUpButton, { visible: false }); + Controller.mousePressEvent.disconnect(globalMouseClick); + } + + function SeatIndicator(modelProperties, seatIndex) { + var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; + + this.position = Vec3.sum(modelProperties.position, + Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), + halfDiagonal)); // hack + + this.orientation = Quat.multiply(modelProperties.rotation, + modelProperties.sittingPoints[seatIndex].rotation); + this.scale = MyAvatar.scale / 3; + + this.sphere = Overlays.addOverlay("billboard", { + subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + url: buttonImageUrl, + position: this.position, + scale: this.scale, + size: this.scale, + solid: true, + color: { red: 255, green: 255, blue: 255 }, + alpha: 0.8, + visible: true, + isFacingAvatar: true + }); + + this.show = function(doShow) { + Overlays.editOverlay(this.sphere, { visible: doShow }); + } + + this.update = function() { + Overlays.editOverlay(this.sphere, { + position: this.position, + size: this.scale + }); + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.sphere); + } + } + + function update(deltaTime){ + var newWindowDimensions = Controller.getViewportDimensions(); + if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ + windowDimensions = newWindowDimensions; + var newX = windowDimensions.x - buttonPadding - buttonWidth; + var newY = (windowDimensions.y - buttonHeight) / 2 ; + Overlays.editOverlay( this.standUpButton, {x: newX, y: newY} ); + } + + // For a weird reason avatar joint don't update till the 10th frame + // Set the update frame to 20 to be safe + var UPDATE_FRAME = 20; + if (frame <= UPDATE_FRAME) { + if (frame == UPDATE_FRAME) { + if (sitting == true) { + print("Was seated: " + sitting); + storeStartPoseAndTransition(); + updateJoints(1.0); + } + } + frame++; + } + } + + this.addIndicators = function() { + if (!this.indicatorsAdded) { + if (this.properties.sittingPoints.length > 0) { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i] = new SeatIndicator(this.properties, i); + } + this.indicatorsAdded = true; + } + } + } + + this.removeIndicators = function() { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i].cleanup(); + } + } + + this.showIndicators = function(doShow) { + this.addIndicators(); + if (this.indicatorsAdded) { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i].show(doShow); + } + } + hiddingSeats = !doShow; + } + + function raySphereIntersection(origin, direction, center, radius) { + var A = origin; + var B = Vec3.normalize(direction); + var P = center; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + + return (x > 0 && d <= radius); + } + + this.cleanup = function() { + this.standUp(); + MyAvatar.clearReferential(); + for (var i = 0; i < pose.length; i++){ + MyAvatar.clearJointData(pose[i].joint); + } + Overlays.deleteOverlay(this.standUpButton); + for (var i = 0; i < this.indicator.length; ++i) { + this.indicator[i].cleanup(); + } + }; + + + this.createStandupButton = function() { + this.standUpButton = Overlays.addOverlay("image", { + x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight, + subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + imageURL: buttonImageUrl, + visible: false, + alpha: 1.0 + }); + }; + + this.handleClickEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == this.standUpButton) { + seat.model = null; + this.standUp(); + } else { + this.addIndicators(); + if (this.indicatorsAdded) { + var pickRay = Camera.computePickRay(event.x, event.y); + + var clickedOnSeat = false; + + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + if (raySphereIntersection(pickRay.origin, + pickRay.direction, + this.indicator[i].position, + this.indicator[i].scale / 2)) { + clickedOnSeat = true; + seat.model = this.entityID; // ?? + seat.position = this.indicator[i].position; + seat.rotation = this.indicator[i].orientation; + } + } + + if (clickedOnSeat) { + passedTime = 0.0; + startPosition = MyAvatar.position; + startRotation = MyAvatar.orientation; + try{ Script.update.disconnect(standingUpAnimation); } catch(e){} + try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} + Script.update.connect(goToSeatAnimation); + } + } + } + }; + + + // All callbacks start by updating the properties + this.updateProperties = function(entityID) { + if (this.entityID === null || !this.entityID.isKnownID) { + this.entityID = Entities.identifyEntity(entityID); + } + this.properties = Entities.getEntityProperties(this.entityID); + }; +}; + +Sittable.prototype = { + + unload : function(entityID) { + print("Sittable.unload()"); + this.cleanup(); + //Script.update.disconnect(update); + }, + + preload : function(entityID) { + print("Sittable.preload()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + this.createStandupButton(); + //Script.update.connect(update); + }, + + + hoverOverEntity : function(entityID, mouseEvent) { + print("Sittable.hoverOverEntity()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + this.showIndicators(true); + }, + + hoverLeaveEntity : function(entityID, mouseEvent) { + print("Sittable.hoverLeaveEntity()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + this.showIndicators(false); + }, + + clickDownOnEntity : function(entityID, mouseEvent) { + print("Sittable.clickDownOnEntity()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + this.handleClickEvent(mouseEvent); + }, + + clickReleaseOnEntity : function(entityID, mouseEvent) { + print("Sittable.clickReleaseOnEntity()"); + this.updateProperties(entityID); // All callbacks start by updating the properties + } +}; \ No newline at end of file From a95b6dbabd904b220b57cca5ec24b775929fa07d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 23 Nov 2014 20:36:33 -0800 Subject: [PATCH 03/67] hacking on global functions --- examples/entityScripts/sittableClass.js | 62 ++++++++++++++----------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/examples/entityScripts/sittableClass.js b/examples/entityScripts/sittableClass.js index c16e026f96..591b7515cb 100644 --- a/examples/entityScripts/sittableClass.js +++ b/examples/entityScripts/sittableClass.js @@ -11,6 +11,40 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +var activeSittable = null; +function SittableUpdate(deltaTime){ + + // This keeps the standup button in a reasonable place. + var newWindowDimensions = Controller.getViewportDimensions(); + if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ + windowDimensions = newWindowDimensions; + var newX = windowDimensions.x - buttonPadding - buttonWidth; + var newY = (windowDimensions.y - buttonHeight) / 2 ; + Overlays.editOverlay( activeSittable.standUpButton, {x: newX, y: newY} ); + } + + + // this appears to be some logic related to storing the original position + /* + + // For a weird reason avatar joint don't update till the 10th frame + // Set the update frame to 20 to be safe + var UPDATE_FRAME = 20; + if (frame <= UPDATE_FRAME) { + if (frame == UPDATE_FRAME) { + if (sitting == true) { + print("Was seated: " + sitting); + activeSittable.storeStartPoseAndTransition(); + activeSittable.updateJoints(1.0); + } + } + frame++; + } + */ +} + + + Sittable = function() { this.entityID = null; @@ -207,30 +241,6 @@ Sittable = function() { } } - function update(deltaTime){ - var newWindowDimensions = Controller.getViewportDimensions(); - if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ - windowDimensions = newWindowDimensions; - var newX = windowDimensions.x - buttonPadding - buttonWidth; - var newY = (windowDimensions.y - buttonHeight) / 2 ; - Overlays.editOverlay( this.standUpButton, {x: newX, y: newY} ); - } - - // For a weird reason avatar joint don't update till the 10th frame - // Set the update frame to 20 to be safe - var UPDATE_FRAME = 20; - if (frame <= UPDATE_FRAME) { - if (frame == UPDATE_FRAME) { - if (sitting == true) { - print("Was seated: " + sitting); - storeStartPoseAndTransition(); - updateJoints(1.0); - } - } - frame++; - } - } - this.addIndicators = function() { if (!this.indicatorsAdded) { if (this.properties.sittingPoints.length > 0) { @@ -345,14 +355,14 @@ Sittable.prototype = { unload : function(entityID) { print("Sittable.unload()"); this.cleanup(); - //Script.update.disconnect(update); + //Script.update.disconnect(SittableUpdate); }, preload : function(entityID) { print("Sittable.preload()"); this.updateProperties(entityID); // All callbacks start by updating the properties this.createStandupButton(); - //Script.update.connect(update); + //Script.update.connect(SittableUpdate); }, From 345735fa8c33df7c437638426eb1e578b7504b14 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 23 Nov 2014 20:50:39 -0800 Subject: [PATCH 04/67] tweaks --- examples/entityScripts/sittableClass.js | 100 ++++++++++++------------ 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/examples/entityScripts/sittableClass.js b/examples/entityScripts/sittableClass.js index 591b7515cb..1a7b1df25a 100644 --- a/examples/entityScripts/sittableClass.js +++ b/examples/entityScripts/sittableClass.js @@ -43,7 +43,49 @@ function SittableUpdate(deltaTime){ */ } +SeatIndicator = function(modelProperties, seatIndex) { + var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; + var buttonWidth = 37; + var buttonHeight = 46; + var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; + + this.position = Vec3.sum(modelProperties.position, + Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), + halfDiagonal)); // hack + + this.orientation = Quat.multiply(modelProperties.rotation, + modelProperties.sittingPoints[seatIndex].rotation); + this.scale = MyAvatar.scale / 3; + + this.sphere = Overlays.addOverlay("billboard", { + subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + url: buttonImageUrl, + position: this.position, + scale: this.scale, + size: this.scale, + solid: true, + color: { red: 255, green: 255, blue: 255 }, + alpha: 0.8, + visible: true, + isFacingAvatar: true + }); + + this.show = function(doShow) { + Overlays.editOverlay(this.sphere, { visible: doShow }); + } + + this.update = function() { + Overlays.editOverlay(this.sphere, { + position: this.position, + size: this.scale + }); + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.sphere); + } +}; Sittable = function() { @@ -65,7 +107,7 @@ Sittable = function() { var passedTime = 0.0; var startPosition = null; var startRotation = null; - var animationLenght = 2.0; + var animationLength = 2.0; var avatarOldPosition = { x: 0, y: 0, z: 0 }; @@ -108,9 +150,9 @@ Sittable = function() { var sittingDownAnimation = function(deltaTime) { passedTime += deltaTime; - var factor = passedTime/animationLenght; + var factor = passedTime/animationLength; - if ( passedTime <= animationLenght ) { + if ( passedTime <= animationLength ) { updateJoints(factor); var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z}; @@ -126,13 +168,13 @@ Sittable = function() { var standingUpAnimation = function(deltaTime) { passedTime += deltaTime; - var factor = 1 - passedTime/animationLenght; + var factor = 1 - passedTime/animationLength; - if ( passedTime <= animationLenght ) { + if ( passedTime <= animationLength ) { updateJoints(factor); - var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z}; + var pos = { x: startPosition.x + 0.3 * (passedTime/animationLength), y: startPosition.y + 0.5 * (passedTime/animationLength), z: startPosition.z}; MyAvatar.position = pos; } else { Script.update.disconnect(standingUpAnimation); @@ -144,12 +186,12 @@ Sittable = function() { var goToSeatAnimation = function(deltaTime) { passedTime += deltaTime; - var factor = passedTime/animationLenght; + var factor = passedTime/animationLength; - if (passedTime <= animationLenght) { + if (passedTime <= animationLength) { var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); - } else if (passedTime <= 2 * animationLenght) { + } else if (passedTime <= 2 * animationLength) { //Quat.print("MyAvatar: ", MyAvatar.orientation); //Quat.print("Seat: ", seat.rotation); MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); @@ -201,46 +243,6 @@ Sittable = function() { Controller.mousePressEvent.disconnect(globalMouseClick); } - function SeatIndicator(modelProperties, seatIndex) { - var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; - - this.position = Vec3.sum(modelProperties.position, - Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), - halfDiagonal)); // hack - - this.orientation = Quat.multiply(modelProperties.rotation, - modelProperties.sittingPoints[seatIndex].rotation); - this.scale = MyAvatar.scale / 3; - - this.sphere = Overlays.addOverlay("billboard", { - subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, - url: buttonImageUrl, - position: this.position, - scale: this.scale, - size: this.scale, - solid: true, - color: { red: 255, green: 255, blue: 255 }, - alpha: 0.8, - visible: true, - isFacingAvatar: true - }); - - this.show = function(doShow) { - Overlays.editOverlay(this.sphere, { visible: doShow }); - } - - this.update = function() { - Overlays.editOverlay(this.sphere, { - position: this.position, - size: this.scale - }); - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.sphere); - } - } - this.addIndicators = function() { if (!this.indicatorsAdded) { if (this.properties.sittingPoints.length > 0) { From af1591277c41dd38c8365c40ae1538b6f7ed0bb8 Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Fri, 19 Dec 2014 04:17:36 +1000 Subject: [PATCH 05/67] changes as per list removed dummy code, remove mic mute state at startup, some text changes. --- examples/notifications.js | 107 +++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 60 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 2c2c4a5c0b..7946213abd 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -1,25 +1,32 @@ // -// notifications.js +// notifications.js +// Version 0.801 // Created by Adrian // // Adrian McCarlie 8-10-14 // This script demonstrates on-screen overlay type notifications. // Copyright 2014 High Fidelity, Inc. // +// // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// This script demonstrates notifications created via a number of ways, such as: -// Simple key press alerts, which only depend on a key being pressed, -// dummy examples of this are "q", "w", "e", "r", and "SPACEBAR". -// actual working examples are "a" for left turn, "d" for right turn and Ctrl/s for snapshot. - -// System generated alerts such as users joining and leaving and chat messages which mention this user. -// System generated alerts which originate with a user interface event such as Window Resize, and Mic Mute/Unmute. -// Mic Mute/Unmute may appear to be a key press alert, but it actually gets the call from the system as mic is muted and unmuted, -// so the mic mute/unmute will also trigger the notification by clicking the Mic Mute button at the top of the screen. +// This script generates notifications created via a number of ways, such as: +// keystroke: +// +// "q" returns number of users currently online (for debug purposes) +// CTRL/s for snapshot. +// CTRL/m for mic mute and unmute. +// System generated notifications: +// Displays users online at startup. +// If Screen is resized. +// Triggers notification if @MyUserName is mentioned in chat. +// Announces existing user logging out. +// Announces new user logging in. +// If mic is muted for any reason. +// // To add a new System notification type: // // 1. Set the Event Connector at the bottom of the script. @@ -45,22 +52,23 @@ // 2. Declare a text string. // 3. Call createNotifications(text) parsing the text. // example: -// if (key.text == "a") { -// var noteString = "Turning to the Left"; -// createNotification(noteString); -// } +// if (key.text == "q") { //queries number of users online +// var numUsers = GlobalServices.onlineUsers.length; +// var welcome = "There are " + numUsers + " users online now."; +// createNotification(welcome); +// } var width = 340.0; //width of notification overlay var height = 40.0; // height of a single line notification overlay var windowDimensions = Controller.getViewportDimensions(); // get the size of the interface window -var overlayLocationX = (windowDimensions.x - (width + 60.0));// positions window 60px from the right of the interface window +var overlayLocationX = (windowDimensions.x - (width + 20.0));// positions window 20px from the right of the interface window var buttonLocationX = overlayLocationX + (width - 28.0); var locationY = 20.0; // position down from top of interface window var topMargin = 13.0; var leftMargin = 10.0; var textColor = { red: 228, green: 228, blue: 228}; // text color -var backColor = { red: 38, green: 38, blue: 38}; // background color +var backColor = { red: 2, green: 2, blue: 2}; // background color was 38,38,38 var backgroundAlpha = 0; var fontSize = 12.0; var persistTime = 10.0; // time in seconds before notification fades @@ -115,7 +123,6 @@ function createNotification(text) { color: textColor, backgroundColor: backColor, alpha: backgroundAlpha, - backgroundAlpha: backgroundAlpha, topMargin: topMargin, leftMargin: leftMargin, font: {size: fontSize}, @@ -125,8 +132,8 @@ function createNotification(text) { var buttonProperties = { x: buttonLocationX, y: bLevel, - width: 15.0, - height: 15.0, + width: 10.0, + height: 10.0, subImage: { x: 0, y: 0, width: 10, height: 10 }, imageURL: "http://hifi-public.s3.amazonaws.com/images/close-small-light.svg", color: { red: 255, green: 255, blue: 255}, @@ -161,7 +168,7 @@ function fadeIn(noticeIn, buttonIn) { pauseTimer = Script.setInterval(function() { q++; qFade = q / 10.0; - Overlays.editOverlay(noticeIn, {alpha: qFade, backgroundAlpha: qFade}); + Overlays.editOverlay(noticeIn, {alpha: qFade}); Overlays.editOverlay(buttonIn, {alpha: qFade}); if (q >= 9.0) { Script.clearInterval(pauseTimer); @@ -203,41 +210,18 @@ function keyPressEvent(key) { if (key.key == 16777249) { ctrlIsPressed = true; } - if (key.text == "a") { - var noteString = "Turning to the Left"; - createNotification(noteString); - } - if (key.text == "d") { - var noteString = "Turning to the Right"; - createNotification(noteString); - } + if (key.text == "q") { //queries number of users online + var numUsers = GlobalServices.onlineUsers.length; + var welcome = "There are " + numUsers + " users online now."; + createNotification(welcome); + } + if (key.text == "s") { if (ctrlIsPressed == true){ - var noteString = "You have taken a snapshot"; + var noteString = "Snapshot taken."; createNotification(noteString); } } - if (key.text == "q") { - var noteString = "Enable Scripted Motor control is now on."; - wordWrap(noteString); - } - if (key.text == "w") { - var noteString = "This notification spans 2 lines. The overlay will resize to fit new lines."; - var noteString = "editVoxels.js stopped, editModels.js stopped, selectAudioDevice.js stopped."; - wordWrap(noteString); - } - if (key.text == "e") { - var noteString = "This is an example of a multiple line notification. This notification will span 3 lines." - wordWrap(noteString); - } - if (key.text == "r") { - var noteString = "This is a very long line of text that we are going to use in this example to divide it into rows of maximum 43 chars and see how many lines we use."; - wordWrap(noteString); - } - if (key.text == "SPACE") { - var noteString = "You have pressed the Spacebar, This is an example of a multiple line notification. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam."; - wordWrap(noteString); - } } // formats string to add newline every 43 chars @@ -275,18 +259,14 @@ function checkSize(){ // Triggers notification if a user logs on or off function onOnlineUsersChanged(users) { - var joiners = []; - var leavers = []; for (user in users) { if (last_users.indexOf(users[user]) == -1.0) { - joiners.push(users[user]); - createNotification(users[user] + " Has joined"); + createNotification(users[user] + " has joined"); } } for (user in last_users) { if (users.indexOf(last_users[user]) == -1.0) { - leavers.push(last_users[user]); - createNotification(last_users[user] + " Has left"); + createNotification(last_users[user] + " has left"); } } last_users = users; @@ -303,8 +283,8 @@ function onIncomingMessage(user, message) { } // Triggers mic mute notification function onMuteStateChanged() { - var muteState = AudioDevice.getMuted() ? "Muted" : "Unmuted"; - var muteString = "Microphone is set to " + muteState; + var muteState = AudioDevice.getMuted() ? "muted" : "unmuted"; + var muteString = "Microphone is now " + muteState; createNotification(muteString); } @@ -345,7 +325,7 @@ function fadeOut(noticeOut, buttonOut, arraysOut) { pauseTimer = Script.setInterval(function() { r--; rFade = r / 10.0; - Overlays.editOverlay(noticeOut, {alpha: rFade, backgroundAlpha: rFade}); + Overlays.editOverlay(noticeOut, {alpha: rFade}); Overlays.editOverlay(buttonOut, {alpha: rFade}); if (r < 0) { dismiss(noticeOut, buttonOut, arraysOut); @@ -368,10 +348,17 @@ function dismiss(firstNoteOut, firstButOut, firstOut) { myAlpha.splice(firstOut,1); } -onMuteStateChanged(); +// This is meant to show users online at startup but currently shows 0 users. +function onConnected() { + var numUsers = GlobalServices.onlineUsers.length; + var welcome = "Welcome! There are " + numUsers + " users online now."; + createNotification(welcome); +} + AudioDevice.muteToggled.connect(onMuteStateChanged); Controller.keyPressEvent.connect(keyPressEvent); Controller.mousePressEvent.connect(mousePressEvent); +GlobalServices.connected.connect(onConnected); GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged); GlobalServices.incomingMessage.connect(onIncomingMessage); Controller.keyReleaseEvent.connect(keyReleaseEvent); From 6beaa3d59a061ee9f111668ee7c90a32f9eb6c95 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:36:15 -0800 Subject: [PATCH 06/67] set policy for shared lib creation on OS X --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a6118bb87..a0d463b766 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,10 @@ if (POLICY CMP0043) cmake_policy(SET CMP0043 OLD) endif () +if (POLICY CMP0042) + cmake_policy(SET CMP0042 OLD) +endif () + project(hifi) add_definitions(-DGLM_FORCE_RADIANS) From 6a604ca340f24d514fccdd9f83c776ad43d98f98 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:36:31 -0800 Subject: [PATCH 07/67] fix missing script dependency from shared --- libraries/shared/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 17ccbdc6ce..b5a44c96e2 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -1,7 +1,8 @@ set(TARGET_NAME shared) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(Network Widgets) +# TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) +setup_hifi_library(Network Script Widgets) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file From ecb17a61d6c7609b218ff92e8bad03a62d404223 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:39:35 -0800 Subject: [PATCH 08/67] fix missing render-utils dependencies --- libraries/render-utils/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index a6943addcc..881a75636b 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -5,11 +5,15 @@ setup_hifi_library(Widgets OpenGL Network Script) include_glm() -link_hifi_libraries(shared gpu) +link_hifi_libraries(fbx shared gpu) -if (WIN32) +if (APPLE) + find_library(GLUT GLUT) + target_link_libraries(${TARGET_NAME} GLUT) +else () find_package(GLUT REQUIRED) include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") + target_link_libraries(${TARGET_NAME} ${GLUT_LIBRARIES}) endif () # call macro to link our dependencies and bubble them up via a property on our target From 1b5552de1a9e2f0225cde7faf7a4a70284c520b2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:42:08 -0800 Subject: [PATCH 09/67] fix GLUT library link in render-utils --- libraries/render-utils/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 881a75636b..4108462000 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -9,7 +9,7 @@ link_hifi_libraries(fbx shared gpu) if (APPLE) find_library(GLUT GLUT) - target_link_libraries(${TARGET_NAME} GLUT) + target_link_libraries(${TARGET_NAME} ${GLUT}) else () find_package(GLUT REQUIRED) include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") From 4f4ffc42d35d269ce871d25146edc86eb5829726 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:52:16 -0800 Subject: [PATCH 10/67] add missing link to fbx from avatars --- libraries/avatars/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 42b3cf7d3c..20aba226e0 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -5,8 +5,7 @@ setup_hifi_library(Network Script) include_glm() -link_hifi_libraries(shared octree voxels networking physics) -include_hifi_library_headers(fbx) +link_hifi_libraries(audio shared octree voxels networking physics fbx) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From e8adc19ac67088c386b56b21c528925829a04644 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:52:31 -0800 Subject: [PATCH 11/67] fix more missing dependencies in render-utils --- libraries/render-utils/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 4108462000..211c7266b3 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Widgets OpenGL Network Script) include_glm() -link_hifi_libraries(fbx shared gpu) +link_hifi_libraries(animation fbx shared gpu) if (APPLE) find_library(GLUT GLUT) From 4bd3a94794ba8352c4dbc69227455587dd5bd7cb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:53:52 -0800 Subject: [PATCH 12/67] add missing avatars link to entities --- libraries/entities/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index e48baa7615..d6f503f2ca 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Network Script) include_glm() -link_hifi_libraries(shared octree fbx networking animation physics) +link_hifi_libraries(avatars shared octree fbx networking animation physics) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From d87e06a9d36ff91f51905f05749c74c55e6ec3f2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 14:54:05 -0800 Subject: [PATCH 13/67] add missing metavoxels link to script-engine --- libraries/script-engine/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 3b3a63549d..7118e84443 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Gui Network Script Widgets) include_glm() -link_hifi_libraries(shared octree voxels fbx entities animation audio physics) +link_hifi_libraries(shared octree voxels fbx entities animation audio physics metavoxels) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From f474cfc9d0e89abf3ec52758582db575e08514da Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 15:06:44 -0800 Subject: [PATCH 14/67] link to render-utils from entities renderer --- libraries/entities-renderer/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 1e77afe544..3b8a214675 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Widgets OpenGL Network Script) include_glm() -link_hifi_libraries(shared gpu script-engine) +link_hifi_libraries(shared gpu script-engine render-utils) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() From 087ac1db90394ee8dff79e2c97dcbcb9bb324ea1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 16:03:13 -0800 Subject: [PATCH 15/67] send port along with domain hostname lookup --- libraries/networking/src/AddressManager.cpp | 25 +++++++++++---------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 81b3a1328b..1352c54c79 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -107,7 +107,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) { if (!handleUsername(lookupUrl.authority())) { // we're assuming this is either a network address or global place name // check if it is a network address first - if (!handleNetworkAddress(lookupUrl.host())) { + if (!handleNetworkAddress(lookupUrl.host() + + (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) { // wasn't an address - lookup the place name attemptPlaceNameLookup(lookupUrl.host()); } @@ -246,17 +247,6 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { const QString HOSTNAME_REGEX_STRING = "^((?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9])" "(?:\\.(?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9]))+|localhost)(:{1}\\d{1,5})?$"; - QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive); - - if (hostnameRegex.indexIn(lookupString) != -1) { - QString domainHostname = hostnameRegex.cap(0); - - emit lookupResultsFinished(); - setDomainHostnameAndName(domainHostname); - - return true; - } - QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING); if (ipAddressRegex.indexIn(lookupString) != -1) { @@ -268,6 +258,17 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { return true; } + QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive); + + if (hostnameRegex.indexIn(lookupString) != -1) { + QString domainHostname = hostnameRegex.cap(0); + + emit lookupResultsFinished(); + setDomainHostnameAndName(domainHostname); + + return true; + } + return false; } From 1ab66c2bfefb038824938ccf765afb428a3922b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 16:17:03 -0800 Subject: [PATCH 16/67] split port and hostname for cleaner domain changes --- interface/src/Application.cpp | 22 +------------ interface/src/Application.h | 1 - libraries/networking/src/AddressManager.cpp | 24 ++++++++++---- libraries/networking/src/AddressManager.h | 4 +-- libraries/networking/src/DomainHandler.cpp | 36 +++++---------------- libraries/networking/src/DomainHandler.h | 6 ++-- libraries/networking/src/NodeList.cpp | 10 ++++++ 7 files changed, 40 insertions(+), 63 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c3ec763426..a975716f9c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -309,13 +309,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // use our MyAvatar position and quat for address manager path addressManager.setPositionGetter(getPositionForPath); addressManager.setOrientationGetter(getOrientationForPath); - - // handle domain change signals from AddressManager - connect(&addressManager, &AddressManager::possibleDomainChangeRequiredToHostname, - this, &Application::changeDomainHostname); - - connect(&addressManager, &AddressManager::possibleDomainChangeRequiredViaICEForID, - &domainHandler, &DomainHandler::setIceServerHostnameAndID); _settings = new QSettings(this); _numChangedSettings = 0; @@ -1435,7 +1428,7 @@ void Application::dropEvent(QDropEvent *event) { SnapshotMetaData* snapshotData = Snapshot::parseSnapshotData(snapshotPath); if (snapshotData) { if (!snapshotData->getDomain().isEmpty()) { - changeDomainHostname(snapshotData->getDomain()); + NodeList::getInstance()->getDomainHandler().setHostnameAndPort(snapshotData->getDomain()); } _myAvatar->setPosition(snapshotData->getLocation()); @@ -3700,19 +3693,6 @@ void Application::updateLocationInServer() { } } -void Application::changeDomainHostname(const QString &newDomainHostname) { - NodeList* nodeList = NodeList::getInstance(); - - if (!nodeList->getDomainHandler().isCurrentHostname(newDomainHostname)) { - // tell the MyAvatar object to send a kill packet so that it dissapears from its old avatar mixer immediately - _myAvatar->sendKillAvatar(); - - // call the domain hostname change as a queued connection on the nodelist - QMetaObject::invokeMethod(&NodeList::getInstance()->getDomainHandler(), "setHostname", - Q_ARG(const QString&, newDomainHostname)); - } -} - void Application::clearDomainOctreeDetails() { qDebug() << "Clearing domain octree details..."; // reset the environment so that we don't erroneously end up with multiple diff --git a/interface/src/Application.h b/interface/src/Application.h index 111f03c7c6..041e5e6b5b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -335,7 +335,6 @@ signals: void importDone(); public slots: - void changeDomainHostname(const QString& newDomainHostname); void domainChanged(const QString& domainHostname); void updateWindowTitle(); void updateLocationInServer(); diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 1352c54c79..f3c14a4597 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -173,7 +173,7 @@ void AddressManager::goToAddressFromObject(const QVariantMap& addressMap) { if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) { QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString(); - emit possibleDomainChangeRequiredToHostname(domainHostname); + emit possibleDomainChangeRequired(domainHostname, DEFAULT_DOMAIN_SERVER_PORT); } else { QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString(); @@ -250,10 +250,15 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING); if (ipAddressRegex.indexIn(lookupString) != -1) { - QString domainIPString = ipAddressRegex.cap(0); + QString domainIPString = ipAddressRegex.cap(1); + + qint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + if (ipAddressRegex.captureCount() > 1) { + domainPort = (qint16) ipAddressRegex.cap(2).toInt(); + } emit lookupResultsFinished(); - setDomainHostnameAndName(domainIPString); + setDomainInfo(domainIPString, domainPort); return true; } @@ -261,10 +266,15 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { QRegExp hostnameRegex(HOSTNAME_REGEX_STRING, Qt::CaseInsensitive); if (hostnameRegex.indexIn(lookupString) != -1) { - QString domainHostname = hostnameRegex.cap(0); + QString domainHostname = hostnameRegex.cap(1); + + qint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; + if (ipAddressRegex.captureCount() > 1) { + domainPort = (qint16) ipAddressRegex.cap(2).toInt(); + } emit lookupResultsFinished(); - setDomainHostnameAndName(domainHostname); + setDomainInfo(domainHostname, domainPort); return true; } @@ -340,9 +350,9 @@ bool AddressManager::handleUsername(const QString& lookupString) { } -void AddressManager::setDomainHostnameAndName(const QString& hostname, const QString& domainName) { +void AddressManager::setDomainInfo(const QString &hostname, quint16 port, const QString& domainName) { _currentDomain = domainName.isEmpty() ? hostname : domainName; - emit possibleDomainChangeRequiredToHostname(hostname); + emit possibleDomainChangeRequired(hostname, port); } void AddressManager::goToUser(const QString& username) { diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index cfdaaa7d41..7a83144488 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -59,7 +59,7 @@ signals: void lookupResultsFinished(); void lookupResultIsOffline(); void lookupResultIsNotFound(); - void possibleDomainChangeRequiredToHostname(const QString& newHostname); + void possibleDomainChangeRequired(const QString& newHostname, quint16 newPort); void possibleDomainChangeRequiredViaICEForID(const QString& iceServerHostname, const QUuid& domainID); void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::quat& newOrientation, @@ -70,7 +70,7 @@ private slots: private: AddressManager(); - void setDomainHostnameAndName(const QString& hostname, const QString& domainName = QString()); + void setDomainInfo(const QString& hostname, quint16 port, const QString& domainName = QString()); const JSONCallbackParameters& apiCallbackParameters(); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 6091b0cdd2..34aef8b98f 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -97,39 +97,19 @@ void DomainHandler::setUUID(const QUuid& uuid) { } } -QString DomainHandler::hostnameWithoutPort(const QString& hostname) { - int colonIndex = hostname.indexOf(':'); - return colonIndex > 0 ? hostname.left(colonIndex) : hostname; -} - -bool DomainHandler::isCurrentHostname(const QString& hostname) { - return hostnameWithoutPort(hostname) == _hostname; -} - -void DomainHandler::setHostname(const QString& hostname) { +void DomainHandler::setHostnameAndPort(const QString& hostname, quint16 port) { - if (hostname != _hostname) { + if (hostname != _hostname || _sockAddr.getPort() != port) { // re-set the domain info so that auth information is reloaded hardReset(); - int colonIndex = hostname.indexOf(':'); + // the new hostname is everything up to the colon + _hostname = hostname; - if (colonIndex > 0) { - // the user has included a custom DS port with the hostname - - // the new hostname is everything up to the colon - _hostname = hostname.left(colonIndex); - - // grab the port by reading the string after the colon - _sockAddr.setPort(atoi(hostname.mid(colonIndex + 1, hostname.size()).toLocal8Bit().constData())); - - qDebug() << "Updated hostname to" << _hostname << "and port to" << _sockAddr.getPort(); - - } else { - // no port included with the hostname, simply set the member variable and reset the domain server port to default - _hostname = hostname; - _sockAddr.setPort(DEFAULT_DOMAIN_SERVER_PORT); - } + // grab the port by reading the string after the colon + _sockAddr.setPort(port); + + qDebug() << "Updated hostname to" << _hostname << "and port to" << _sockAddr.getPort(); // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname qDebug("Looking up DS hostname %s.", _hostname.toLocal8Bit().constData()); diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index a27a5d1dd8..295e6eac01 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -37,9 +37,7 @@ public: const QUuid& getUUID() const { return _uuid; } void setUUID(const QUuid& uuid); - - static QString hostnameWithoutPort(const QString& hostname); - bool isCurrentHostname(const QString& hostname); + const QString& getHostname() const { return _hostname; } const QHostAddress& getIP() const { return _sockAddr.getAddress(); } @@ -75,7 +73,7 @@ public: void softReset(); public slots: - void setHostname(const QString& hostname); + void setHostnameAndPort(const QString& hostname, quint16 port = DEFAULT_DOMAIN_SERVER_PORT); void setIceServerHostnameAndID(const QString& iceServerHostname, const QUuid& id); private slots: diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index bf992e7b88..6f6c84f947 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -18,6 +18,7 @@ #include #include "AccountManager.h" +#include "AddressManager.h" #include "Assignment.h" #include "HifiSockAddr.h" #include "NodeList.h" @@ -62,6 +63,15 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned _hasCompletedInitialSTUNFailure(false), _stunRequestsSinceSuccess(0) { + AddressManager& addressManager = AddressManager::getInstance(); + + // handle domain change signals from AddressManager + connect(&addressManager, &AddressManager::possibleDomainChangeRequired, + &_domainHandler, &DomainHandler::setHostnameAndPort); + + connect(&addressManager, &AddressManager::possibleDomainChangeRequiredViaICEForID, + &_domainHandler, &DomainHandler::setIceServerHostnameAndID); + // clear our NodeList when the domain changes connect(&_domainHandler, &DomainHandler::disconnectedFromDomain, this, &NodeList::reset); From 3a4f75ff62ead277e5206110e5125c3f129c212e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 16:40:02 -0800 Subject: [PATCH 17/67] fix AddressManager domain lookup to handle port --- libraries/networking/src/AddressManager.cpp | 12 ++++----- libraries/networking/src/DomainHandler.cpp | 28 +++++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index f3c14a4597..57412b645f 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -241,11 +241,11 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString) { } bool AddressManager::handleNetworkAddress(const QString& lookupString) { - const QString IP_ADDRESS_REGEX_STRING = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" - "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(:\\d{1,5})?$"; + const QString IP_ADDRESS_REGEX_STRING = "^((?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(?::(\\d{1,5}))?$"; const QString HOSTNAME_REGEX_STRING = "^((?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9])" - "(?:\\.(?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9]))+|localhost)(:{1}\\d{1,5})?$"; + "(?:\\.(?:[A-Z0-9]|[A-Z0-9][A-Z0-9\\-]{0,61}[A-Z0-9]))+|localhost)(?::(\\d{1,5}))?$"; QRegExp ipAddressRegex(IP_ADDRESS_REGEX_STRING); @@ -253,7 +253,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { QString domainIPString = ipAddressRegex.cap(1); qint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; - if (ipAddressRegex.captureCount() > 1) { + if (!ipAddressRegex.cap(2).isEmpty()) { domainPort = (qint16) ipAddressRegex.cap(2).toInt(); } @@ -269,8 +269,8 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) { QString domainHostname = hostnameRegex.cap(1); qint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; - if (ipAddressRegex.captureCount() > 1) { - domainPort = (qint16) ipAddressRegex.cap(2).toInt(); + if (!hostnameRegex.cap(2).isEmpty()) { + domainPort = (qint16) hostnameRegex.cap(2).toInt(); } emit lookupResultsFinished(); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 34aef8b98f..126ef27414 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -103,20 +103,26 @@ void DomainHandler::setHostnameAndPort(const QString& hostname, quint16 port) { // re-set the domain info so that auth information is reloaded hardReset(); - // the new hostname is everything up to the colon - _hostname = hostname; + if (hostname != _hostname) { + // set the new hostname + _hostname = hostname; + + qDebug() << "Updated domain hostname to" << _hostname; + + // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname + qDebug("Looking up DS hostname %s.", _hostname.toLocal8Bit().constData()); + QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&))); + + UserActivityLogger::getInstance().changedDomain(_hostname); + emit hostnameChanged(_hostname); + } + + if (_sockAddr.getPort() != port) { + qDebug() << "Updated domain port to" << port; + } // grab the port by reading the string after the colon _sockAddr.setPort(port); - - qDebug() << "Updated hostname to" << _hostname << "and port to" << _sockAddr.getPort(); - - // re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname - qDebug("Looking up DS hostname %s.", _hostname.toLocal8Bit().constData()); - QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&))); - - UserActivityLogger::getInstance().changedDomain(_hostname); - emit hostnameChanged(_hostname); } } From 0b1445f8b52139394dde411ea3ea066466e28cab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 16:41:37 -0800 Subject: [PATCH 18/67] show the address dialog with current address selected --- interface/src/ui/AddressBarDialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 5f55aa5210..75049f9ed4 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -116,8 +116,9 @@ void AddressBarDialog::setupUI() { void AddressBarDialog::showEvent(QShowEvent* event) { _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); - _addressLineEdit->setText(QString()); + _addressLineEdit->setText(AddressManager::getInstance().currentAddress().toString()); _addressLineEdit->setFocus(); + _addressLineEdit->selectAll(); FramelessDialog::showEvent(event); } From 114e3bb2ff27ea5e8f9ac67e29cf5ac78c64e60e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 18 Dec 2014 16:51:20 -0800 Subject: [PATCH 19/67] rename cmake macro to represent actual purpose --- assignment-client/CMakeLists.txt | 2 +- ...edDependencies.cmake => IncludeDependencyIncludes.cmake} | 6 +++--- domain-server/CMakeLists.txt | 2 +- ice-server/CMakeLists.txt | 2 +- interface/CMakeLists.txt | 2 +- libraries/animation/CMakeLists.txt | 4 ++-- libraries/audio/CMakeLists.txt | 4 ++-- libraries/avatars/CMakeLists.txt | 4 ++-- libraries/embedded-webserver/CMakeLists.txt | 4 ++-- libraries/entities-renderer/CMakeLists.txt | 4 ++-- libraries/entities/CMakeLists.txt | 4 ++-- libraries/fbx/CMakeLists.txt | 4 ++-- libraries/gpu/CMakeLists.txt | 4 ++-- libraries/metavoxels/CMakeLists.txt | 4 ++-- libraries/networking/CMakeLists.txt | 4 ++-- libraries/octree/CMakeLists.txt | 4 ++-- libraries/physics/CMakeLists.txt | 4 ++-- libraries/render-utils/CMakeLists.txt | 4 ++-- libraries/script-engine/CMakeLists.txt | 4 ++-- libraries/shared/CMakeLists.txt | 4 ++-- libraries/voxels/CMakeLists.txt | 4 ++-- tests/audio/CMakeLists.txt | 2 +- tests/jitter/CMakeLists.txt | 2 +- tests/metavoxels/CMakeLists.txt | 2 +- tests/networking/CMakeLists.txt | 2 +- tests/octree/CMakeLists.txt | 2 +- tests/physics/CMakeLists.txt | 2 +- tests/shared/CMakeLists.txt | 2 +- tools/bitstream2json/CMakeLists.txt | 2 +- tools/json2bitstream/CMakeLists.txt | 2 +- tools/mtc/CMakeLists.txt | 2 +- 31 files changed, 49 insertions(+), 49 deletions(-) rename cmake/macros/{LinkSharedDependencies.cmake => IncludeDependencyIncludes.cmake} (86%) diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 6e31182f0d..88b2b62bd9 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -15,4 +15,4 @@ if (UNIX) target_link_libraries(${TARGET_NAME} ${CMAKE_DL_LIBS}) endif (UNIX) -link_shared_dependencies() +include_dependency_includes() diff --git a/cmake/macros/LinkSharedDependencies.cmake b/cmake/macros/IncludeDependencyIncludes.cmake similarity index 86% rename from cmake/macros/LinkSharedDependencies.cmake rename to cmake/macros/IncludeDependencyIncludes.cmake index 9168c5a921..a375404164 100644 --- a/cmake/macros/LinkSharedDependencies.cmake +++ b/cmake/macros/IncludeDependencyIncludes.cmake @@ -1,5 +1,5 @@ # -# LinkSharedDependencies.cmake +# IncludeDependencyIncludes.cmake # cmake/macros # # Copyright 2014 High Fidelity, Inc. @@ -9,7 +9,7 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -macro(LINK_SHARED_DEPENDENCIES) +macro(INCLUDE_DEPENDENCY_INCLUDES) if (${TARGET_NAME}_DEPENDENCY_INCLUDES) list(REMOVE_DUPLICATES ${TARGET_NAME}_DEPENDENCY_INCLUDES) @@ -19,4 +19,4 @@ macro(LINK_SHARED_DEPENDENCIES) # set the property on this target so it can be retreived by targets linking to us set_target_properties(${TARGET_NAME} PROPERTIES DEPENDENCY_INCLUDES "${${TARGET_NAME}_DEPENDENCY_INCLUDES}") -endmacro(LINK_SHARED_DEPENDENCIES) \ No newline at end of file +endmacro(INCLUDE_DEPENDENCY_INCLUDES) \ No newline at end of file diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index 482c397b14..421a1da2d4 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -52,4 +52,4 @@ include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") # append OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/ice-server/CMakeLists.txt b/ice-server/CMakeLists.txt index c81ba16248..24e780f9aa 100644 --- a/ice-server/CMakeLists.txt +++ b/ice-server/CMakeLists.txt @@ -6,4 +6,4 @@ setup_hifi_project(Network) # link the shared hifi libraries link_hifi_libraries(networking shared) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a9688a5919..659ecf600f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -246,4 +246,4 @@ else (APPLE) endif (APPLE) # link any dependencies bubbled up from our linked dependencies -link_shared_dependencies() +include_dependency_includes() diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 3f65c1ab6c..d7cbe43e28 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -5,5 +5,5 @@ setup_hifi_library(Network Script) link_hifi_libraries(shared fbx) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/audio/CMakeLists.txt b/libraries/audio/CMakeLists.txt index 6ade1fc423..b08d9e88f4 100644 --- a/libraries/audio/CMakeLists.txt +++ b/libraries/audio/CMakeLists.txt @@ -7,5 +7,5 @@ include_glm() link_hifi_libraries(networking shared) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 20aba226e0..69d0f23717 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -7,5 +7,5 @@ include_glm() link_hifi_libraries(audio shared octree voxels networking physics fbx) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/embedded-webserver/CMakeLists.txt b/libraries/embedded-webserver/CMakeLists.txt index 6e4b92e217..ef2cf1054c 100644 --- a/libraries/embedded-webserver/CMakeLists.txt +++ b/libraries/embedded-webserver/CMakeLists.txt @@ -3,5 +3,5 @@ set(TARGET_NAME embedded-webserver) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/entities-renderer/CMakeLists.txt b/libraries/entities-renderer/CMakeLists.txt index 3b8a214675..6d7f5ee960 100644 --- a/libraries/entities-renderer/CMakeLists.txt +++ b/libraries/entities-renderer/CMakeLists.txt @@ -7,5 +7,5 @@ include_glm() link_hifi_libraries(shared gpu script-engine render-utils) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index d6f503f2ca..10aba41ebb 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -7,5 +7,5 @@ include_glm() link_hifi_libraries(avatars shared octree fbx networking animation physics) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 5a151deb8b..4f4cb6eb76 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -11,5 +11,5 @@ find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 340adcc9e6..1264c1bf5c 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -44,5 +44,5 @@ else () list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${OPENGL_INCLUDE_DIR}") endif (APPLE) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/metavoxels/CMakeLists.txt b/libraries/metavoxels/CMakeLists.txt index aab8d2184d..4ead36e51a 100644 --- a/libraries/metavoxels/CMakeLists.txt +++ b/libraries/metavoxels/CMakeLists.txt @@ -10,5 +10,5 @@ link_hifi_libraries(shared networking) include_glm() -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/networking/CMakeLists.txt b/libraries/networking/CMakeLists.txt index 934e3e69b9..bc251a42d4 100644 --- a/libraries/networking/CMakeLists.txt +++ b/libraries/networking/CMakeLists.txt @@ -28,5 +28,5 @@ target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES} ${TBB_LIBRARIES}) # append libcuckoo includes to our list of includes to bubble list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${TBB_INCLUDE_DIRS}") -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/octree/CMakeLists.txt b/libraries/octree/CMakeLists.txt index e8c6554ff4..cd90857637 100644 --- a/libraries/octree/CMakeLists.txt +++ b/libraries/octree/CMakeLists.txt @@ -15,5 +15,5 @@ include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # append ZLIB and OpenSSL to our list of libraries to link target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/physics/CMakeLists.txt b/libraries/physics/CMakeLists.txt index 5270f08730..4f74038ff5 100644 --- a/libraries/physics/CMakeLists.txt +++ b/libraries/physics/CMakeLists.txt @@ -15,5 +15,5 @@ link_hifi_libraries(shared) ## append BULLET to our list of libraries to link #list(APPEND ${TARGET_NAME}_LIBRARIES_TO_LINK "${BULLET_LIBRARIES}") -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 211c7266b3..99d01760f8 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -16,5 +16,5 @@ else () target_link_libraries(${TARGET_NAME} ${GLUT_LIBRARIES}) endif () -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 7118e84443..86e6c83b5d 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -7,5 +7,5 @@ include_glm() link_hifi_libraries(shared octree voxels fbx entities animation audio physics metavoxels) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index b5a44c96e2..4b271bfeda 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -4,5 +4,5 @@ set(TARGET_NAME shared) # TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp) setup_hifi_library(Network Script Widgets) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/libraries/voxels/CMakeLists.txt b/libraries/voxels/CMakeLists.txt index 7980094884..75b5143321 100644 --- a/libraries/voxels/CMakeLists.txt +++ b/libraries/voxels/CMakeLists.txt @@ -14,5 +14,5 @@ include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") # add it to our list of libraries to link target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES}) -# call macro to link our dependencies and bubble them up via a property on our target -link_shared_dependencies() \ No newline at end of file +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/tests/audio/CMakeLists.txt b/tests/audio/CMakeLists.txt index 974b4dcd09..fb6b9c2e11 100644 --- a/tests/audio/CMakeLists.txt +++ b/tests/audio/CMakeLists.txt @@ -7,4 +7,4 @@ include_glm() # link in the shared libraries link_hifi_libraries(shared audio networking) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tests/jitter/CMakeLists.txt b/tests/jitter/CMakeLists.txt index d0b366e7ef..93f7caefdd 100644 --- a/tests/jitter/CMakeLists.txt +++ b/tests/jitter/CMakeLists.txt @@ -5,4 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tests/metavoxels/CMakeLists.txt b/tests/metavoxels/CMakeLists.txt index 732c974f95..7524c5c87c 100644 --- a/tests/metavoxels/CMakeLists.txt +++ b/tests/metavoxels/CMakeLists.txt @@ -9,4 +9,4 @@ setup_hifi_project(Network Script Widgets) # link in the shared libraries link_hifi_libraries(metavoxels networking shared) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tests/networking/CMakeLists.txt b/tests/networking/CMakeLists.txt index a7293226b3..113a75ab50 100644 --- a/tests/networking/CMakeLists.txt +++ b/tests/networking/CMakeLists.txt @@ -5,4 +5,4 @@ setup_hifi_project() # link in the shared libraries link_hifi_libraries(shared networking) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 7139d4edb6..3382f684cb 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -7,4 +7,4 @@ include_glm() # link in the shared libraries link_hifi_libraries(shared octree voxels fbx metavoxels networking entities avatars audio animation script-engine physics) -link_shared_dependencies() +include_dependency_includes() diff --git a/tests/physics/CMakeLists.txt b/tests/physics/CMakeLists.txt index d47b979459..31c741eecf 100644 --- a/tests/physics/CMakeLists.txt +++ b/tests/physics/CMakeLists.txt @@ -7,4 +7,4 @@ include_glm() # link in the shared libraries link_hifi_libraries(shared physics) -link_shared_dependencies() +include_dependency_includes() diff --git a/tests/shared/CMakeLists.txt b/tests/shared/CMakeLists.txt index fe3843e9eb..f067fa52b5 100644 --- a/tests/shared/CMakeLists.txt +++ b/tests/shared/CMakeLists.txt @@ -7,4 +7,4 @@ include_glm() # link in the shared libraries link_hifi_libraries(shared) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tools/bitstream2json/CMakeLists.txt b/tools/bitstream2json/CMakeLists.txt index bc23a1e193..2e8bb213be 100644 --- a/tools/bitstream2json/CMakeLists.txt +++ b/tools/bitstream2json/CMakeLists.txt @@ -5,4 +5,4 @@ include_glm() link_hifi_libraries(metavoxels) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tools/json2bitstream/CMakeLists.txt b/tools/json2bitstream/CMakeLists.txt index 91b56c18fd..283d450e11 100644 --- a/tools/json2bitstream/CMakeLists.txt +++ b/tools/json2bitstream/CMakeLists.txt @@ -5,4 +5,4 @@ include_glm() link_hifi_libraries(metavoxels) -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file diff --git a/tools/mtc/CMakeLists.txt b/tools/mtc/CMakeLists.txt index 4dfa8421ff..06b9f86d06 100644 --- a/tools/mtc/CMakeLists.txt +++ b/tools/mtc/CMakeLists.txt @@ -1,4 +1,4 @@ set(TARGET_NAME mtc) setup_hifi_project() -link_shared_dependencies() \ No newline at end of file +include_dependency_includes() \ No newline at end of file From dd06d1f4a9f5ca9b1d4cf6ce806ece502d530aba Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 10:01:14 -0800 Subject: [PATCH 20/67] added comments to explain hand state --- libraries/avatars/src/AvatarData.cpp | 7 +++++++ libraries/avatars/src/AvatarData.h | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 01f84ca246..a5ee3f7fff 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -443,7 +443,14 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { // key state, stored as a semi-nibble in the bitItems _keyState = (KeyState)getSemiNibbleAt(bitItems,KEY_STATE_START_BIT); + // hand state, stored as a semi-nibble plus a bit in the bitItems + // we store the hand state as well as other items in a shared bitset. The hand state is an octal, but is split + // into two sections to maintain backward compatibility. The bits are ordered as such (0-7 left to right). + // +---+-----+-----+--+ + // |x,x|H0,H1|x,x,x|H2| + // +---+-----+-----+--+ + // Hand state - H0,H1,H2 is found in the 3rd, 4th, and 8th bits _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 55b35377c0..6564d53317 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -76,7 +76,17 @@ const quint32 AVATAR_MOTION_SCRIPTABLE_BITS = AVATAR_MOTION_STAND_ON_NEARBY_FLOORS; -// First bitset +// Bitset of state flags - we store the key state, hand state, faceshift, chat circling, and existance of +// referential data in this bit set. The hand state is an octal, but is split into two sections to maintain +// backward compatibility. The bits are ordered as such (0-7 left to right). +// +-----+-----+-+-+-+--+ +// |K0,K1|H0,H1|F|C|R|H2| +// +-----+-----+-+-+-+--+ +// Key state - K0,K1 is found in the 1st and 2nd bits +// Hand state - H0,H1,H2 is found in the 3rd, 4th, and 8th bits +// Faceshift - F is found in the 5th bit +// Chat Circling - C is found in the 6th bit +// Referential Data - R is found in the 7th bit const int KEY_STATE_START_BIT = 0; // 1st and 2nd bits const int HAND_STATE_START_BIT = 2; // 3rd and 4th bits const int IS_FACESHIFT_CONNECTED = 4; // 5th bit From 51121554e51cc13d223d3ace1f47b6e453f8208a Mon Sep 17 00:00:00 2001 From: Adrianl3d Date: Sat, 20 Dec 2014 04:28:39 +1000 Subject: [PATCH 21/67] clean up code intentations lines 263 264 --- examples/notifications.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/notifications.js b/examples/notifications.js index 7946213abd..5527fc35fc 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -260,8 +260,8 @@ function checkSize(){ // Triggers notification if a user logs on or off function onOnlineUsersChanged(users) { for (user in users) { - if (last_users.indexOf(users[user]) == -1.0) { - createNotification(users[user] + " has joined"); + if (last_users.indexOf(users[user]) == -1.0) { + createNotification(users[user] + " has joined"); } } for (user in last_users) { From 715b3a245e39e1437c242f10ea00d21cb5a8f595 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 10:53:36 -0800 Subject: [PATCH 22/67] remove GLUT from Cmake files --- cmake/modules/FindGLUT.cmake | 47 --------------------------- interface/CMakeLists.txt | 14 +++----- libraries/render-utils/CMakeLists.txt | 9 ----- 3 files changed, 5 insertions(+), 65 deletions(-) delete mode 100644 cmake/modules/FindGLUT.cmake diff --git a/cmake/modules/FindGLUT.cmake b/cmake/modules/FindGLUT.cmake deleted file mode 100644 index e7bf752aca..0000000000 --- a/cmake/modules/FindGLUT.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# -# FindGLUT.cmake -# -# Try to find GLUT library and include path. -# Once done this will define -# -# GLUT_FOUND -# GLUT_INCLUDE_DIRS -# GLUT_LIBRARIES -# -# Created on 2/6/2014 by Stephen Birarda -# Copyright 2014 High Fidelity, Inc. -# -# Adapted from FindGLUT.cmake available in tlorach's OpenGLText Repository -# https://raw.github.com/tlorach/OpenGLText/master/cmake/FindGLUT.cmake -# -# Distributed under the Apache License, Version 2.0. -# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -# - -include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") -hifi_library_search_hints("freeglut") - -if (WIN32) - set(GLUT_HINT_DIRS "${FREEGLUT_SEARCH_DIRS} ${OPENGL_INCLUDE_DIR}") - - find_path(GLUT_INCLUDE_DIRS GL/glut.h PATH_SUFFIXES include HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(GLUT_LIBRARY freeglut PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) -else () - find_path(GLUT_INCLUDE_DIRS GL/glut.h PATH_SUFFIXES include HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(GLUT_LIBRARY glut PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) -endif () - -include(FindPackageHandleStandardArgs) - -set(GLUT_LIBRARIES "${GLUT_LIBRARY}" "${XMU_LIBRARY}" "${XI_LIBRARY}") - -if (UNIX) - find_library(XI_LIBRARY Xi PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) - find_library(XMU_LIBRARY Xmu PATH_SUFFIXES lib HINTS ${FREEGLUT_SEARCH_DIRS}) - - find_package_handle_standard_args(GLUT DEFAULT_MSG GLUT_INCLUDE_DIRS GLUT_LIBRARIES XI_LIBRARY XMU_LIBRARY) -else () - find_package_handle_standard_args(GLUT DEFAULT_MSG GLUT_INCLUDE_DIRS GLUT_LIBRARIES) -endif () - -mark_as_advanced(GLUT_INCLUDE_DIRS GLUT_LIBRARIES GLUT_LIBRARY XI_LIBRARY XMU_LIBRARY FREEGLUT_SEARCH_DIRS) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 659ecf600f..ebbce669ea 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -25,15 +25,15 @@ else () endif () if (APPLE) - set(GL_HEADERS "#include \n#include ") + set(GL_HEADERS "#include ") elseif (UNIX) # include the right GL headers for UNIX - set(GL_HEADERS "#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include ") elseif (WIN32) add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines - set(GL_HEADERS "#include \n#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include \n#include ") endif () # set up the external glm library @@ -194,11 +194,10 @@ if (APPLE) # link in required OS X frameworks and include the right GL headers find_library(CoreAudio CoreAudio) find_library(CoreFoundation CoreFoundation) - find_library(GLUT GLUT) find_library(OpenGL OpenGL) find_library(AppKit AppKit) - target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation} ${GLUT} ${OpenGL} ${AppKit}) + target_link_libraries(${TARGET_NAME} ${CoreAudio} ${CoreFoundation} ${OpenGL} ${AppKit}) # install command for OS X bundle INSTALL(TARGETS ${TARGET_NAME} @@ -214,15 +213,12 @@ else (APPLE) ) find_package(OpenGL REQUIRED) - find_package(GLUT REQUIRED) - - include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") if (${OPENGL_INCLUDE_DIR}) include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") endif () - target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}" "${GLUT_LIBRARIES}") + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") # link target to external libraries if (WIN32) diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 99d01760f8..97dc9c7bc8 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -7,14 +7,5 @@ include_glm() link_hifi_libraries(animation fbx shared gpu) -if (APPLE) - find_library(GLUT GLUT) - target_link_libraries(${TARGET_NAME} ${GLUT}) -else () - find_package(GLUT REQUIRED) - include_directories(SYSTEM "${GLUT_INCLUDE_DIRS}") - target_link_libraries(${TARGET_NAME} ${GLUT_LIBRARIES}) -endif () - # call macro to include our dependency includes and bubble them up via a property on our target include_dependency_includes() From 115dc28c9cabe9e5d35bcb881f7ae93d76f05ea1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 10:54:00 -0800 Subject: [PATCH 23/67] add glu includes on OS X to stopgap GLUT removal --- interface/src/Hair.cpp | 5 ++++- interface/src/avatar/Avatar.cpp | 5 +++++ interface/src/ui/ApplicationOverlay.cpp | 5 +++++ interface/src/ui/RearMirrorTools.cpp | 5 +++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/interface/src/Hair.cpp b/interface/src/Hair.cpp index cb664f39ed..c2d3f78b98 100644 --- a/interface/src/Hair.cpp +++ b/interface/src/Hair.cpp @@ -10,11 +10,14 @@ // // Creates single flexible verlet-integrated strands that can be used for hair/fur/grass -#include "Hair.h" +#include #include "Util.h" #include "world.h" +#include "Hair.h" + + const float HAIR_DAMPING = 0.99f; const float CONSTRAINT_RELAXATION = 10.0f; const float HAIR_ACCELERATION_COUPLING = 0.045f; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 39c528d080..aa94b21d71 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -13,6 +13,11 @@ #include +// TODO: remove calls to gluProject to remove this include +#ifdef __APPLE__ +#include +#endif + #include #include diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ab85da125c..f82b44a403 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -11,6 +11,11 @@ #include "InterfaceConfig.h" +// TODO: remove calls to gluProject to remove this include +#ifdef __APPLE__ +#include +#endif + #include #include diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index fd3fc34adb..2c671ef548 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -11,6 +11,11 @@ #include "InterfaceConfig.h" +// TODO: remove calls to gluProject to remove this include +#ifdef __APPLE__ +#include +#endif + #include #include From d43ec2ee28cc9b7c9c4c11371631e7d1355cab0f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 11:00:41 -0800 Subject: [PATCH 24/67] revert some prototype script stuff for now --- examples/entityScripts/movable.js | 412 ++++++++++++++++++++++- examples/entityScripts/movableClass.js | 426 ------------------------ examples/entityScripts/sitOnEntity.js | 363 +++++++++++++++++++- examples/entityScripts/sittable.js | 15 - examples/entityScripts/sittableClass.js | 393 ---------------------- 5 files changed, 767 insertions(+), 842 deletions(-) delete mode 100644 examples/entityScripts/movableClass.js delete mode 100644 examples/entityScripts/sittable.js delete mode 100644 examples/entityScripts/sittableClass.js diff --git a/examples/entityScripts/movable.js b/examples/entityScripts/movable.js index 0ea3641c6f..35d11116eb 100644 --- a/examples/entityScripts/movable.js +++ b/examples/entityScripts/movable.js @@ -8,8 +8,412 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +(function(){ -(function() { - Script.include("movableClass.js"); - return new Movable(); -}) + this.entityID = null; + this.properties = null; + this.graboffset = null; + this.clickedAt = null; + this.firstHolding = true; + this.clicked = { x: -1, y: -1}; + this.lastMovedPosition = { x: -1, y: -1}; + this.lastMovedTime = 0; + this.rotateOverlayTarget = null; + this.rotateOverlayInner = null; + this.rotateOverlayOuter = null; + this.rotateOverlayCurrent = null; + this.rotateMode = false; + this.originalRotation = null; + + this.moveSoundURLS = [ + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" + ]; + + this.turnSoundURLS = [ + + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", + "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" + + // TODO: determine if these or other turn sounds work better than move sounds. + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn1.wav", + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn2.wav", + //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn3.wav" + ]; + + + this.moveSounds = new Array(); + this.turnSounds = new Array(); + this.moveSound = null; + this.turnSound = null; + this.injector = null; + + var debug = false; + var displayRotateTargets = true; // change to false if you don't want the rotate targets + var rotateOverlayTargetSize = 10000; // really big target + var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool + var innerRadius; + var outerRadius; + var yawCenter; + var yawZero; + var rotationNormal; + var yawNormal; + var stopSoundDelay = 100; // number of msecs of not moving to have sound stop + + this.getRandomInt = function(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + } + + this.downloadSounds = function() { + for (var i = 0; i < this.moveSoundURLS.length; i++) { + this.moveSounds[i] = SoundCache.getSound(this.moveSoundURLS[i]); + } + for (var i = 0; i < this.turnSoundURLS.length; i++) { + this.turnSounds[i] = SoundCache.getSound(this.turnSoundURLS[i]); + } + } + + this.pickRandomSounds = function() { + var moveIndex = this.getRandomInt(0, this.moveSounds.length - 1); + var turnIndex = this.getRandomInt(0, this.turnSounds.length - 1); + if (debug) { + print("Random sounds -- turn:" + turnIndex + " move:" + moveIndex); + } + this.moveSound = this.moveSounds[moveIndex]; + this.turnSound = this.turnSounds[turnIndex]; + } + + // Play move sound + this.playMoveSound = function() { + if (debug) { + print("playMoveSound()"); + } + if (this.moveSound && this.moveSound.downloaded) { + if (debug) { + print("playMoveSound() --- calling this.injector = Audio.playSound(this.moveSound...)"); + } + this.injector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 }); + } + } + + // Play turn sound + this.playTurnSound = function() { + if (debug) { + print("playTurnSound()"); + } + if (this.turnSound && this.turnSound.downloaded) { + if (debug) { + print("playTurnSound() --- calling this.injector = Audio.playSound(this.turnSound...)"); + } + this.injector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 }); + } + } + + // stop sound + this.stopSound = function() { + if (debug) { + print("stopSound()"); + } + if (this.injector) { + Audio.stopInjector(this.injector); + this.injector = null; + } + } + + // Pr, Vr are respectively the Ray's Point of origin and Vector director + // Pp, Np are respectively the Plane's Point of origin and Normal vector + this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) { + var d = -Vec3.dot(Pp, Np); + var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np); + return Vec3.sum(Pr, Vec3.multiply(t, Vr)); + }; + + // updates the piece position based on mouse input + this.updatePosition = function(mouseEvent) { + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var upVector = { x: 0, y: 1, z: 0 }; + var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, + this.properties.position, upVector); + + var newPosition = Vec3.sum(intersection, this.graboffset); + Entities.editEntity(this.entityID, { position: newPosition }); + }; + + this.grab = function(mouseEvent) { + // first calculate the offset + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var upVector = { x: 0, y: 1, z: 0 }; + var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, + this.properties.position, upVector); + this.graboffset = Vec3.subtract(this.properties.position, intersection); + }; + + this.stopSoundIfNotMoving = function(mouseEvent) { + var nowDate = new Date(); + var nowMSecs = nowDate.getTime(); + if(mouseEvent.x == this.lastMovedPosition.x && mouseEvent.y == this.lastMovedPosition.y) { + var elapsedSinceLastMove = nowMSecs - this.lastMovedMSecs; + if (debug) { + print("elapsedSinceLastMove:" + elapsedSinceLastMove); + } + if (elapsedSinceLastMove > stopSoundDelay) { + if (debug) { + print("calling stopSound()..."); + } + this.stopSound(); + } + } else { + // if we've moved, then track our last move position and time... + this.lastMovedMSecs = nowMSecs; + this.lastMovedPosition.x = mouseEvent.x; + this.lastMovedPosition.y = mouseEvent.y; + } + } + + this.move = function(mouseEvent) { + this.updatePosition(mouseEvent); + if (this.injector === null) { + this.playMoveSound(); + } + }; + + this.release = function(mouseEvent) { + this.updatePosition(mouseEvent); + }; + + this.rotate = function(mouseEvent) { + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var result = Overlays.findRayIntersection(pickRay); + + if (result.intersects) { + var center = yawCenter; + var zero = yawZero; + var centerToZero = Vec3.subtract(center, zero); + var centerToIntersect = Vec3.subtract(center, result.intersection); + var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); + + var distanceFromCenter = Vec3.distance(center, result.intersection); + var snapToInner = false; + // var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; + if (distanceFromCenter < innerRadius) { + angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; + snapToInner = true; + } + + var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); + Entities.editEntity(this.entityID, { rotation: Quat.multiply(yawChange, this.originalRotation) }); + + + // update the rotation display accordingly... + var startAtCurrent = 360-angleFromZero; + var endAtCurrent = 360; + var startAtRemainder = 0; + var endAtRemainder = 360-angleFromZero; + if (angleFromZero < 0) { + startAtCurrent = 0; + endAtCurrent = -angleFromZero; + startAtRemainder = -angleFromZero; + endAtRemainder = 360; + } + + if (snapToInner) { + Overlays.editOverlay(this.rotateOverlayOuter, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(this.rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, + majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); + } else { + Overlays.editOverlay(this.rotateOverlayInner, { startAt: 0, endAt: 360 }); + Overlays.editOverlay(this.rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); + Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, + majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); + } + } + + if (this.injector === null) { + this.playTurnSound(); + } + }; + // All callbacks start by updating the properties + this.updateProperties = function(entityID) { + if (this.entityID === null || !this.entityID.isKnownID) { + this.entityID = Entities.identifyEntity(entityID); + } + this.properties = Entities.getEntityProperties(this.entityID); + }; + + this.cleanupRotateOverlay = function() { + Overlays.deleteOverlay(this.rotateOverlayTarget); + Overlays.deleteOverlay(this.rotateOverlayInner); + Overlays.deleteOverlay(this.rotateOverlayOuter); + Overlays.deleteOverlay(this.rotateOverlayCurrent); + this.rotateOverlayTarget = null; + this.rotateOverlayInner = null; + this.rotateOverlayOuter = null; + this.rotateOverlayCurrent = null; + } + + this.displayRotateOverlay = function(mouseEvent) { + var yawOverlayAngles = { x: 90, y: 0, z: 0 }; + var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles); + + yawNormal = { x: 0, y: 1, z: 0 }; + yawCenter = this.properties.position; + rotationNormal = yawNormal; + + // Size the overlays to the current selection size + var diagonal = (Vec3.length(this.properties.dimensions) / 2) * 1.1; + var halfDimensions = Vec3.multiply(this.properties.dimensions, 0.5); + innerRadius = diagonal; + outerRadius = diagonal * 1.15; + var innerAlpha = 0.2; + var outerAlpha = 0.2; + + this.rotateOverlayTarget = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: rotateOverlayTargetSize, + color: { red: 0, green: 0, blue: 0 }, + alpha: 0.0, + solid: true, + visible: true, + rotation: yawOverlayRotation, + ignoreRayIntersection: false + }); + + this.rotateOverlayInner = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: innerRadius, + innerRadius: 0.9, + alpha: innerAlpha, + color: { red: 51, green: 152, blue: 203 }, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + hasTickMarks: true, + majorTickMarksAngle: innerSnapAngle, + minorTickMarksAngle: 0, + majorTickMarksLength: -0.25, + minorTickMarksLength: 0, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + }); + + this.rotateOverlayOuter = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: outerRadius, + innerRadius: 0.9, + startAt: 0, + endAt: 360, + alpha: outerAlpha, + color: { red: 51, green: 152, blue: 203 }, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + + hasTickMarks: true, + majorTickMarksAngle: 45.0, + minorTickMarksAngle: 5, + majorTickMarksLength: 0.25, + minorTickMarksLength: 0.1, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + ignoreRayIntersection: true, // always ignore this + }); + + this.rotateOverlayCurrent = Overlays.addOverlay("circle3d", { + position: this.properties.position, + size: outerRadius, + startAt: 0, + endAt: 0, + innerRadius: 0.9, + color: { red: 224, green: 67, blue: 36}, + alpha: 0.8, + solid: true, + visible: displayRotateTargets, + rotation: yawOverlayRotation, + ignoreRayIntersection: true, // always ignore this + hasTickMarks: true, + majorTickMarksColor: { red: 0, green: 0, blue: 0 }, + minorTickMarksColor: { red: 0, green: 0, blue: 0 }, + }); + + var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) + var result = Overlays.findRayIntersection(pickRay); + yawZero = result.intersection; + + }; + + this.preload = function(entityID) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.downloadSounds(); + }; + + this.clickDownOnEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.grab(mouseEvent); + + var nowDate = new Date(); + var nowMSecs = nowDate.getTime(); + this.clickedAt = nowMSecs; + this.firstHolding = true; + + this.clicked.x = mouseEvent.x; + this.clicked.y = mouseEvent.y; + this.lastMovedPosition.x = mouseEvent.x; + this.lastMovedPosition.y = mouseEvent.y; + this.lastMovedMSecs = nowMSecs; + + this.pickRandomSounds(); + }; + + this.holdingClickOnEntity = function(entityID, mouseEvent) { + + this.updateProperties(entityID); // All callbacks start by updating the properties + + if (this.firstHolding) { + // if we haven't moved yet... + if (this.clicked.x == mouseEvent.x && this.clicked.y == mouseEvent.y) { + var d = new Date(); + var now = d.getTime(); + + if (now - this.clickedAt > 500) { + this.displayRotateOverlay(mouseEvent); + this.firstHolding = false; + this.rotateMode = true; + this.originalRotation = this.properties.rotation; + } + } else { + this.firstHolding = false; + } + } + + if (this.rotateMode) { + this.rotate(mouseEvent); + } else { + this.move(mouseEvent); + } + + this.stopSoundIfNotMoving(mouseEvent); + }; + this.clickReleaseOnEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + if (this.rotateMode) { + this.rotate(mouseEvent); + } else { + this.release(mouseEvent); + } + + if (this.rotateOverlayTarget != null) { + this.cleanupRotateOverlay(); + this.rotateMode = false; + } + + this.firstHolding = false; + this.stopSound(); + }; + +}) \ No newline at end of file diff --git a/examples/entityScripts/movableClass.js b/examples/entityScripts/movableClass.js deleted file mode 100644 index 26fb643826..0000000000 --- a/examples/entityScripts/movableClass.js +++ /dev/null @@ -1,426 +0,0 @@ -// -// movableClass.js -// examples/entityScripts -// -// Created by Brad Hefta-Gaub on 11/17/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -Movable = function() { - - this.entityID = null; - this.properties = null; - this.graboffset = null; - this.clickedAt = null; - this.firstHolding = true; - this.clicked = { x: -1, y: -1}; - this.lastMovedPosition = { x: -1, y: -1}; - this.lastMovedTime = 0; - this.rotateOverlayTarget = null; - this.rotateOverlayInner = null; - this.rotateOverlayOuter = null; - this.rotateOverlayCurrent = null; - this.rotateMode = false; - this.originalRotation = null; - - this.moveSoundURLS = [ - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" - ]; - - this.turnSoundURLS = [ - - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove1.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove2.wav", - "http://public.highfidelity.io/sounds/MovingFurniture/FurnitureMove3.wav" - - // TODO: determine if these or other turn sounds work better than move sounds. - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn1.wav", - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn2.wav", - //"http://public.highfidelity.io/sounds/MovingFurniture/FurnitureTurn3.wav" - ]; - - - this.moveSounds = new Array(); - this.turnSounds = new Array(); - this.moveSound = null; - this.turnSound = null; - this.injector = null; - - var debug = false; - var displayRotateTargets = true; // change to false if you don't want the rotate targets - var rotateOverlayTargetSize = 10000; // really big target - var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool - var innerRadius; - var outerRadius; - var yawCenter; - var yawZero; - var rotationNormal; - var yawNormal; - var stopSoundDelay = 100; // number of msecs of not moving to have sound stop - - this.getRandomInt = function(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; - } - - this.downloadSounds = function() { - for (var i = 0; i < this.moveSoundURLS.length; i++) { - this.moveSounds[i] = SoundCache.getSound(this.moveSoundURLS[i]); - } - for (var i = 0; i < this.turnSoundURLS.length; i++) { - this.turnSounds[i] = SoundCache.getSound(this.turnSoundURLS[i]); - } - } - - this.pickRandomSounds = function() { - var moveIndex = this.getRandomInt(0, this.moveSounds.length - 1); - var turnIndex = this.getRandomInt(0, this.turnSounds.length - 1); - if (debug) { - print("Random sounds -- turn:" + turnIndex + " move:" + moveIndex); - } - this.moveSound = this.moveSounds[moveIndex]; - this.turnSound = this.turnSounds[turnIndex]; - } - - // Play move sound - this.playMoveSound = function() { - if (debug) { - print("playMoveSound()"); - } - if (this.moveSound && this.moveSound.downloaded) { - if (debug) { - print("playMoveSound() --- calling this.injector = Audio.playSound(this.moveSound...)"); - } - this.injector = Audio.playSound(this.moveSound, { position: this.properties.position, loop: true, volume: 0.1 }); - } - } - - // Play turn sound - this.playTurnSound = function() { - if (debug) { - print("playTurnSound()"); - } - if (this.turnSound && this.turnSound.downloaded) { - if (debug) { - print("playTurnSound() --- calling this.injector = Audio.playSound(this.turnSound...)"); - } - this.injector = Audio.playSound(this.turnSound, { position: this.properties.position, loop: true, volume: 0.1 }); - } - } - - // stop sound - this.stopSound = function() { - if (debug) { - print("stopSound()"); - } - if (this.injector) { - Audio.stopInjector(this.injector); - this.injector = null; - } - } - - // Pr, Vr are respectively the Ray's Point of origin and Vector director - // Pp, Np are respectively the Plane's Point of origin and Normal vector - this.rayPlaneIntersection = function(Pr, Vr, Pp, Np) { - var d = -Vec3.dot(Pp, Np); - var t = -(Vec3.dot(Pr, Np) + d) / Vec3.dot(Vr, Np); - return Vec3.sum(Pr, Vec3.multiply(t, Vr)); - }; - - // updates the piece position based on mouse input - this.updatePosition = function(mouseEvent) { - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var upVector = { x: 0, y: 1, z: 0 }; - var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, - this.properties.position, upVector); - - var newPosition = Vec3.sum(intersection, this.graboffset); - Entities.editEntity(this.entityID, { position: newPosition }); - }; - - this.grab = function(mouseEvent) { - // first calculate the offset - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var upVector = { x: 0, y: 1, z: 0 }; - var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction, - this.properties.position, upVector); - this.graboffset = Vec3.subtract(this.properties.position, intersection); - }; - - this.stopSoundIfNotMoving = function(mouseEvent) { - var nowDate = new Date(); - var nowMSecs = nowDate.getTime(); - if(mouseEvent.x == this.lastMovedPosition.x && mouseEvent.y == this.lastMovedPosition.y) { - var elapsedSinceLastMove = nowMSecs - this.lastMovedMSecs; - if (debug) { - print("elapsedSinceLastMove:" + elapsedSinceLastMove); - } - if (elapsedSinceLastMove > stopSoundDelay) { - if (debug) { - print("calling stopSound()..."); - } - this.stopSound(); - } - } else { - // if we've moved, then track our last move position and time... - this.lastMovedMSecs = nowMSecs; - this.lastMovedPosition.x = mouseEvent.x; - this.lastMovedPosition.y = mouseEvent.y; - } - } - - this.move = function(mouseEvent) { - this.updatePosition(mouseEvent); - if (this.injector === null) { - this.playMoveSound(); - } - }; - - this.release = function(mouseEvent) { - this.updatePosition(mouseEvent); - }; - - this.rotate = function(mouseEvent) { - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var result = Overlays.findRayIntersection(pickRay); - - if (result.intersects) { - var center = yawCenter; - var zero = yawZero; - var centerToZero = Vec3.subtract(center, zero); - var centerToIntersect = Vec3.subtract(center, result.intersection); - var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); - - var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - // var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } - - var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); - Entities.editEntity(this.entityID, { rotation: Quat.multiply(yawChange, this.originalRotation) }); - - - // update the rotation display accordingly... - var startAtCurrent = 360-angleFromZero; - var endAtCurrent = 360; - var startAtRemainder = 0; - var endAtRemainder = 360-angleFromZero; - if (angleFromZero < 0) { - startAtCurrent = 0; - endAtCurrent = -angleFromZero; - startAtRemainder = -angleFromZero; - endAtRemainder = 360; - } - - if (snapToInner) { - Overlays.editOverlay(this.rotateOverlayOuter, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(this.rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius, - majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, minorTickMarksLength: 0, }); - } else { - Overlays.editOverlay(this.rotateOverlayInner, { startAt: 0, endAt: 360 }); - Overlays.editOverlay(this.rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder }); - Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius, - majorTickMarksAngle: 45.0, minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, }); - } - } - - if (this.injector === null) { - this.playTurnSound(); - } - }; - // All callbacks start by updating the properties - this.updateProperties = function(entityID) { - if (this.entityID === null || !this.entityID.isKnownID) { - this.entityID = Entities.identifyEntity(entityID); - } - this.properties = Entities.getEntityProperties(this.entityID); - }; - - this.cleanupRotateOverlay = function() { - Overlays.deleteOverlay(this.rotateOverlayTarget); - Overlays.deleteOverlay(this.rotateOverlayInner); - Overlays.deleteOverlay(this.rotateOverlayOuter); - Overlays.deleteOverlay(this.rotateOverlayCurrent); - this.rotateOverlayTarget = null; - this.rotateOverlayInner = null; - this.rotateOverlayOuter = null; - this.rotateOverlayCurrent = null; - } - - this.displayRotateOverlay = function(mouseEvent) { - var yawOverlayAngles = { x: 90, y: 0, z: 0 }; - var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles); - - yawNormal = { x: 0, y: 1, z: 0 }; - yawCenter = this.properties.position; - rotationNormal = yawNormal; - - // Size the overlays to the current selection size - var diagonal = (Vec3.length(this.properties.dimensions) / 2) * 1.1; - var halfDimensions = Vec3.multiply(this.properties.dimensions, 0.5); - innerRadius = diagonal; - outerRadius = diagonal * 1.15; - var innerAlpha = 0.2; - var outerAlpha = 0.2; - - this.rotateOverlayTarget = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: rotateOverlayTargetSize, - color: { red: 0, green: 0, blue: 0 }, - alpha: 0.0, - solid: true, - visible: true, - rotation: yawOverlayRotation, - ignoreRayIntersection: false - }); - - this.rotateOverlayInner = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: innerRadius, - innerRadius: 0.9, - alpha: innerAlpha, - color: { red: 51, green: 152, blue: 203 }, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - hasTickMarks: true, - majorTickMarksAngle: innerSnapAngle, - minorTickMarksAngle: 0, - majorTickMarksLength: -0.25, - minorTickMarksLength: 0, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - ignoreRayIntersection: true, // always ignore this - }); - - this.rotateOverlayOuter = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: outerRadius, - innerRadius: 0.9, - startAt: 0, - endAt: 360, - alpha: outerAlpha, - color: { red: 51, green: 152, blue: 203 }, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - - hasTickMarks: true, - majorTickMarksAngle: 45.0, - minorTickMarksAngle: 5, - majorTickMarksLength: 0.25, - minorTickMarksLength: 0.1, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - ignoreRayIntersection: true, // always ignore this - }); - - this.rotateOverlayCurrent = Overlays.addOverlay("circle3d", { - position: this.properties.position, - size: outerRadius, - startAt: 0, - endAt: 0, - innerRadius: 0.9, - color: { red: 224, green: 67, blue: 36}, - alpha: 0.8, - solid: true, - visible: displayRotateTargets, - rotation: yawOverlayRotation, - ignoreRayIntersection: true, // always ignore this - hasTickMarks: true, - majorTickMarksColor: { red: 0, green: 0, blue: 0 }, - minorTickMarksColor: { red: 0, green: 0, blue: 0 }, - }); - - var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y) - var result = Overlays.findRayIntersection(pickRay); - yawZero = result.intersection; - - }; -}; - -Movable.prototype = { - preload : function(entityID) { - print("Movable.preload()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - this.downloadSounds(); - }, - - clickDownOnEntity : function(entityID, mouseEvent) { - print("Movable.clickDownOnEntity()"); - - this.updateProperties(entityID); // All callbacks start by updating the properties - this.grab(mouseEvent); - - var nowDate = new Date(); - var nowMSecs = nowDate.getTime(); - this.clickedAt = nowMSecs; - this.firstHolding = true; - - this.clicked.x = mouseEvent.x; - this.clicked.y = mouseEvent.y; - this.lastMovedPosition.x = mouseEvent.x; - this.lastMovedPosition.y = mouseEvent.y; - this.lastMovedMSecs = nowMSecs; - - this.pickRandomSounds(); - }, - - holdingClickOnEntity : function(entityID, mouseEvent) { - print("Movable.holdingClickOnEntity()"); - - this.updateProperties(entityID); // All callbacks start by updating the properties - - if (this.firstHolding) { - // if we haven't moved yet... - if (this.clicked.x == mouseEvent.x && this.clicked.y == mouseEvent.y) { - var d = new Date(); - var now = d.getTime(); - - if (now - this.clickedAt > 500) { - this.displayRotateOverlay(mouseEvent); - this.firstHolding = false; - this.rotateMode = true; - this.originalRotation = this.properties.rotation; - } - } else { - this.firstHolding = false; - } - } - - if (this.rotateMode) { - this.rotate(mouseEvent); - } else { - this.move(mouseEvent); - } - - this.stopSoundIfNotMoving(mouseEvent); - }, - - clickReleaseOnEntity : function(entityID, mouseEvent) { - print("Movable.clickReleaseOnEntity()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - if (this.rotateMode) { - this.rotate(mouseEvent); - } else { - this.release(mouseEvent); - } - - if (this.rotateOverlayTarget != null) { - this.cleanupRotateOverlay(); - this.rotateMode = false; - } - - this.firstHolding = false; - this.stopSound(); - }, -}; diff --git a/examples/entityScripts/sitOnEntity.js b/examples/entityScripts/sitOnEntity.js index 080acf61a8..d5c4fa9c52 100644 --- a/examples/entityScripts/sitOnEntity.js +++ b/examples/entityScripts/sitOnEntity.js @@ -11,7 +11,362 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -(function() { - Script.include("sittableClass.js"); - return new Sittable(); -}) +(function(){ + + this.entityID = null; + this.properties = null; + this.standUpButton = null; + this.indicatorsAdded = false; + this.indicator = new Array(); + + + var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; + var windowDimensions = Controller.getViewportDimensions(); + var buttonWidth = 37; + var buttonHeight = 46; + var buttonPadding = 50; // inside the normal toolbar position + var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth; + var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 - (buttonHeight + buttonPadding); + + var passedTime = 0.0; + var startPosition = null; + var startRotation = null; + var animationLenght = 2.0; + + var avatarOldPosition = { x: 0, y: 0, z: 0 }; + + var sittingSettingsHandle = "SitJsSittingPosition"; + var sitting = Settings.getValue(sittingSettingsHandle, false) == "true"; + print("Original sitting status: " + sitting); + var frame = 0; + + var seat = new Object(); + var hiddingSeats = false; + + // This is the pose we would like to end up + var pose = [ + {joint:"RightUpLeg", rotation: {x:100.0, y:15.0, z:0.0}}, + {joint:"RightLeg", rotation: {x:-130.0, y:15.0, z:0.0}}, + {joint:"RightFoot", rotation: {x:30, y:15.0, z:0.0}}, + {joint:"LeftUpLeg", rotation: {x:100.0, y:-15.0, z:0.0}}, + {joint:"LeftLeg", rotation: {x:-130.0, y:-15.0, z:0.0}}, + {joint:"LeftFoot", rotation: {x:30, y:15.0, z:0.0}} + ]; + + var startPoseAndTransition = []; + + function storeStartPoseAndTransition() { + for (var i = 0; i < pose.length; i++){ + var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(pose[i].joint)); + var transitionVector = Vec3.subtract( pose[i].rotation, startRotation ); + startPoseAndTransition.push({joint: pose[i].joint, start: startRotation, transition: transitionVector}); + } + } + + function updateJoints(factor){ + for (var i = 0; i < startPoseAndTransition.length; i++){ + var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor); + var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition); + MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation )); + } + } + + var sittingDownAnimation = function(deltaTime) { + + passedTime += deltaTime; + var factor = passedTime/animationLenght; + + if ( passedTime <= animationLenght ) { + updateJoints(factor); + + var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z}; + MyAvatar.position = pos; + } else { + Script.update.disconnect(sittingDownAnimation); + if (seat.model) { + MyAvatar.setModelReferential(seat.model.id); + } + } + } + + var standingUpAnimation = function(deltaTime) { + + passedTime += deltaTime; + var factor = 1 - passedTime/animationLenght; + + if ( passedTime <= animationLenght ) { + + updateJoints(factor); + + var pos = { x: startPosition.x + 0.3 * (passedTime/animationLenght), y: startPosition.y + 0.5 * (passedTime/animationLenght), z: startPosition.z}; + MyAvatar.position = pos; + } else { + Script.update.disconnect(standingUpAnimation); + + } + } + + var externalThis = this; + + var goToSeatAnimation = function(deltaTime) { + passedTime += deltaTime; + var factor = passedTime/animationLenght; + + if (passedTime <= animationLenght) { + var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); + MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); + } else if (passedTime <= 2 * animationLenght) { + //Quat.print("MyAvatar: ", MyAvatar.orientation); + //Quat.print("Seat: ", seat.rotation); + MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); + } else { + Script.update.disconnect(goToSeatAnimation); + externalThis.sitDown(); + externalThis.showIndicators(false); + } + } + + var globalMouseClick = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + if (clickedOverlay == externalThis.standUpButton) { + seat.model = null; + externalThis.standUp(); + Controller.mousePressEvent.disconnect(globalMouseClick); + } + }; + + this.sitDown = function() { + sitting = true; + Settings.setValue(sittingSettingsHandle, sitting); + print("sitDown sitting status: " + Settings.getValue(sittingSettingsHandle, false)); + passedTime = 0.0; + startPosition = MyAvatar.position; + storeStartPoseAndTransition(); + try { + Script.update.disconnect(standingUpAnimation); + } catch(e){ + // no need to handle. if it wasn't connected no harm done + } + Script.update.connect(sittingDownAnimation); + Overlays.editOverlay(this.standUpButton, { visible: true }); + Controller.mousePressEvent.connect(globalMouseClick); + } + + this.standUp = function() { + sitting = false; + Settings.setValue(sittingSettingsHandle, sitting); + print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false)); + passedTime = 0.0; + startPosition = MyAvatar.position; + MyAvatar.clearReferential(); + try{ + Script.update.disconnect(sittingDownAnimation); + } catch (e){} + Script.update.connect(standingUpAnimation); + Overlays.editOverlay(this.standUpButton, { visible: false }); + Controller.mousePressEvent.disconnect(globalMouseClick); + } + + function SeatIndicator(modelProperties, seatIndex) { + var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; + + this.position = Vec3.sum(modelProperties.position, + Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), + halfDiagonal)); // hack + + this.orientation = Quat.multiply(modelProperties.rotation, + modelProperties.sittingPoints[seatIndex].rotation); + this.scale = MyAvatar.scale / 3; + + this.sphere = Overlays.addOverlay("billboard", { + subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + url: buttonImageUrl, + position: this.position, + scale: this.scale, + size: this.scale, + solid: true, + color: { red: 255, green: 255, blue: 255 }, + alpha: 0.8, + visible: true, + isFacingAvatar: true + }); + + this.show = function(doShow) { + Overlays.editOverlay(this.sphere, { visible: doShow }); + } + + this.update = function() { + Overlays.editOverlay(this.sphere, { + position: this.position, + size: this.scale + }); + } + + this.cleanup = function() { + Overlays.deleteOverlay(this.sphere); + } + } + + function update(deltaTime){ + var newWindowDimensions = Controller.getViewportDimensions(); + if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ + windowDimensions = newWindowDimensions; + var newX = windowDimensions.x - buttonPadding - buttonWidth; + var newY = (windowDimensions.y - buttonHeight) / 2 ; + Overlays.editOverlay( this.standUpButton, {x: newX, y: newY} ); + } + + // For a weird reason avatar joint don't update till the 10th frame + // Set the update frame to 20 to be safe + var UPDATE_FRAME = 20; + if (frame <= UPDATE_FRAME) { + if (frame == UPDATE_FRAME) { + if (sitting == true) { + print("Was seated: " + sitting); + storeStartPoseAndTransition(); + updateJoints(1.0); + } + } + frame++; + } + } + + this.addIndicators = function() { + if (!this.indicatorsAdded) { + if (this.properties.sittingPoints.length > 0) { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i] = new SeatIndicator(this.properties, i); + } + this.indicatorsAdded = true; + } + } + } + + this.removeIndicators = function() { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i].cleanup(); + } + } + + this.showIndicators = function(doShow) { + this.addIndicators(); + if (this.indicatorsAdded) { + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + this.indicator[i].show(doShow); + } + } + hiddingSeats = !doShow; + } + + function raySphereIntersection(origin, direction, center, radius) { + var A = origin; + var B = Vec3.normalize(direction); + var P = center; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + var X = Vec3.sum(A, Vec3.multiply(B, x)); + var d = Vec3.length(Vec3.subtract(P, X)); + + return (x > 0 && d <= radius); + } + + this.cleanup = function() { + this.standUp(); + MyAvatar.clearReferential(); + for (var i = 0; i < pose.length; i++){ + MyAvatar.clearJointData(pose[i].joint); + } + Overlays.deleteOverlay(this.standUpButton); + for (var i = 0; i < this.indicator.length; ++i) { + this.indicator[i].cleanup(); + } + }; + + + this.createStandupButton = function() { + this.standUpButton = Overlays.addOverlay("image", { + x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight, + subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight}, + imageURL: buttonImageUrl, + visible: false, + alpha: 1.0 + }); + }; + + this.handleClickEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + if (clickedOverlay == this.standUpButton) { + seat.model = null; + this.standUp(); + } else { + this.addIndicators(); + if (this.indicatorsAdded) { + var pickRay = Camera.computePickRay(event.x, event.y); + + var clickedOnSeat = false; + + for (var i = 0; i < this.properties.sittingPoints.length; ++i) { + if (raySphereIntersection(pickRay.origin, + pickRay.direction, + this.indicator[i].position, + this.indicator[i].scale / 2)) { + clickedOnSeat = true; + seat.model = this.entityID; // ?? + seat.position = this.indicator[i].position; + seat.rotation = this.indicator[i].orientation; + } + } + + if (clickedOnSeat) { + passedTime = 0.0; + startPosition = MyAvatar.position; + startRotation = MyAvatar.orientation; + try{ Script.update.disconnect(standingUpAnimation); } catch(e){} + try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} + Script.update.connect(goToSeatAnimation); + } + } + } + }; + + + // All callbacks start by updating the properties + this.updateProperties = function(entityID) { + if (this.entityID === null || !this.entityID.isKnownID) { + this.entityID = Entities.identifyEntity(entityID); + } + this.properties = Entities.getEntityProperties(this.entityID); + }; + + this.unload = function(entityID) { + this.cleanup(); + Script.update.disconnect(update); + }; + + this.preload = function(entityID) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.createStandupButton(); + Script.update.connect(update); + }; + + + this.hoverOverEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.showIndicators(true); + }; + this.hoverLeaveEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.showIndicators(false); + }; + + this.clickDownOnEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + this.handleClickEvent(mouseEvent); + }; + + this.clickReleaseOnEntity = function(entityID, mouseEvent) { + this.updateProperties(entityID); // All callbacks start by updating the properties + }; + +}) \ No newline at end of file diff --git a/examples/entityScripts/sittable.js b/examples/entityScripts/sittable.js deleted file mode 100644 index 0753a46d2a..0000000000 --- a/examples/entityScripts/sittable.js +++ /dev/null @@ -1,15 +0,0 @@ -// -// sittable.js -// examples/entityScripts -// -// Created by Brad Hefta-Gaub on 11/17/14. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -(function() { - Script.include("sittableClass.js"); - return new Sittable(); -}) diff --git a/examples/entityScripts/sittableClass.js b/examples/entityScripts/sittableClass.js deleted file mode 100644 index 1a7b1df25a..0000000000 --- a/examples/entityScripts/sittableClass.js +++ /dev/null @@ -1,393 +0,0 @@ -// -// sitOnEntity.js -// examples/entityScripts -// -// Created by Brad Hefta-Gaub on 11/1/14. -// Copyright 2014 High Fidelity, Inc. -// -// This is an example of an entity script for sitting. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -var activeSittable = null; -function SittableUpdate(deltaTime){ - - // This keeps the standup button in a reasonable place. - var newWindowDimensions = Controller.getViewportDimensions(); - if( newWindowDimensions.x != windowDimensions.x || newWindowDimensions.y != windowDimensions.y ){ - windowDimensions = newWindowDimensions; - var newX = windowDimensions.x - buttonPadding - buttonWidth; - var newY = (windowDimensions.y - buttonHeight) / 2 ; - Overlays.editOverlay( activeSittable.standUpButton, {x: newX, y: newY} ); - } - - - // this appears to be some logic related to storing the original position - /* - - // For a weird reason avatar joint don't update till the 10th frame - // Set the update frame to 20 to be safe - var UPDATE_FRAME = 20; - if (frame <= UPDATE_FRAME) { - if (frame == UPDATE_FRAME) { - if (sitting == true) { - print("Was seated: " + sitting); - activeSittable.storeStartPoseAndTransition(); - activeSittable.updateJoints(1.0); - } - } - frame++; - } - */ -} - -SeatIndicator = function(modelProperties, seatIndex) { - var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; - var buttonWidth = 37; - var buttonHeight = 46; - - var halfDiagonal = Vec3.length(modelProperties.dimensions) / 2.0; - - this.position = Vec3.sum(modelProperties.position, - Vec3.multiply(Vec3.multiplyQbyV(modelProperties.rotation, modelProperties.sittingPoints[seatIndex].position), - halfDiagonal)); // hack - - this.orientation = Quat.multiply(modelProperties.rotation, - modelProperties.sittingPoints[seatIndex].rotation); - this.scale = MyAvatar.scale / 3; - - this.sphere = Overlays.addOverlay("billboard", { - subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight}, - url: buttonImageUrl, - position: this.position, - scale: this.scale, - size: this.scale, - solid: true, - color: { red: 255, green: 255, blue: 255 }, - alpha: 0.8, - visible: true, - isFacingAvatar: true - }); - - this.show = function(doShow) { - Overlays.editOverlay(this.sphere, { visible: doShow }); - } - - this.update = function() { - Overlays.editOverlay(this.sphere, { - position: this.position, - size: this.scale - }); - } - - this.cleanup = function() { - Overlays.deleteOverlay(this.sphere); - } -}; - -Sittable = function() { - - this.entityID = null; - this.properties = null; - this.standUpButton = null; - this.indicatorsAdded = false; - this.indicator = new Array(); - - - var buttonImageUrl = "https://worklist-prod.s3.amazonaws.com/attachment/0aca88e1-9bd8-5c1d.svg"; - var windowDimensions = Controller.getViewportDimensions(); - var buttonWidth = 37; - var buttonHeight = 46; - var buttonPadding = 50; // inside the normal toolbar position - var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth; - var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 - (buttonHeight + buttonPadding); - - var passedTime = 0.0; - var startPosition = null; - var startRotation = null; - var animationLength = 2.0; - - var avatarOldPosition = { x: 0, y: 0, z: 0 }; - - var sittingSettingsHandle = "SitJsSittingPosition"; - var sitting = Settings.getValue(sittingSettingsHandle, false) == "true"; - print("Original sitting status: " + sitting); - var frame = 0; - - var seat = new Object(); - var hiddingSeats = false; - - // This is the pose we would like to end up - var pose = [ - {joint:"RightUpLeg", rotation: {x:100.0, y:15.0, z:0.0}}, - {joint:"RightLeg", rotation: {x:-130.0, y:15.0, z:0.0}}, - {joint:"RightFoot", rotation: {x:30, y:15.0, z:0.0}}, - {joint:"LeftUpLeg", rotation: {x:100.0, y:-15.0, z:0.0}}, - {joint:"LeftLeg", rotation: {x:-130.0, y:-15.0, z:0.0}}, - {joint:"LeftFoot", rotation: {x:30, y:15.0, z:0.0}} - ]; - - var startPoseAndTransition = []; - - function storeStartPoseAndTransition() { - for (var i = 0; i < pose.length; i++){ - var startRotation = Quat.safeEulerAngles(MyAvatar.getJointRotation(pose[i].joint)); - var transitionVector = Vec3.subtract( pose[i].rotation, startRotation ); - startPoseAndTransition.push({joint: pose[i].joint, start: startRotation, transition: transitionVector}); - } - } - - function updateJoints(factor){ - for (var i = 0; i < startPoseAndTransition.length; i++){ - var scaledTransition = Vec3.multiply(startPoseAndTransition[i].transition, factor); - var rotation = Vec3.sum(startPoseAndTransition[i].start, scaledTransition); - MyAvatar.setJointData(startPoseAndTransition[i].joint, Quat.fromVec3Degrees( rotation )); - } - } - - var sittingDownAnimation = function(deltaTime) { - - passedTime += deltaTime; - var factor = passedTime/animationLength; - - if ( passedTime <= animationLength ) { - updateJoints(factor); - - var pos = { x: startPosition.x - 0.3 * factor, y: startPosition.y - 0.5 * factor, z: startPosition.z}; - MyAvatar.position = pos; - } else { - Script.update.disconnect(sittingDownAnimation); - if (seat.model) { - MyAvatar.setModelReferential(seat.model.id); - } - } - } - - var standingUpAnimation = function(deltaTime) { - - passedTime += deltaTime; - var factor = 1 - passedTime/animationLength; - - if ( passedTime <= animationLength ) { - - updateJoints(factor); - - var pos = { x: startPosition.x + 0.3 * (passedTime/animationLength), y: startPosition.y + 0.5 * (passedTime/animationLength), z: startPosition.z}; - MyAvatar.position = pos; - } else { - Script.update.disconnect(standingUpAnimation); - - } - } - - var externalThis = this; - - var goToSeatAnimation = function(deltaTime) { - passedTime += deltaTime; - var factor = passedTime/animationLength; - - if (passedTime <= animationLength) { - var targetPosition = Vec3.sum(seat.position, { x: 0.3, y: 0.5, z: 0 }); - MyAvatar.position = Vec3.sum(Vec3.multiply(startPosition, 1 - factor), Vec3.multiply(targetPosition, factor)); - } else if (passedTime <= 2 * animationLength) { - //Quat.print("MyAvatar: ", MyAvatar.orientation); - //Quat.print("Seat: ", seat.rotation); - MyAvatar.orientation = Quat.mix(startRotation, seat.rotation, factor - 1); - } else { - Script.update.disconnect(goToSeatAnimation); - externalThis.sitDown(); - externalThis.showIndicators(false); - } - } - - var globalMouseClick = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - if (clickedOverlay == externalThis.standUpButton) { - seat.model = null; - externalThis.standUp(); - Controller.mousePressEvent.disconnect(globalMouseClick); - } - }; - - this.sitDown = function() { - sitting = true; - Settings.setValue(sittingSettingsHandle, sitting); - print("sitDown sitting status: " + Settings.getValue(sittingSettingsHandle, false)); - passedTime = 0.0; - startPosition = MyAvatar.position; - storeStartPoseAndTransition(); - try { - Script.update.disconnect(standingUpAnimation); - } catch(e){ - // no need to handle. if it wasn't connected no harm done - } - Script.update.connect(sittingDownAnimation); - Overlays.editOverlay(this.standUpButton, { visible: true }); - Controller.mousePressEvent.connect(globalMouseClick); - } - - this.standUp = function() { - sitting = false; - Settings.setValue(sittingSettingsHandle, sitting); - print("standUp sitting status: " + Settings.getValue(sittingSettingsHandle, false)); - passedTime = 0.0; - startPosition = MyAvatar.position; - MyAvatar.clearReferential(); - try{ - Script.update.disconnect(sittingDownAnimation); - } catch (e){} - Script.update.connect(standingUpAnimation); - Overlays.editOverlay(this.standUpButton, { visible: false }); - Controller.mousePressEvent.disconnect(globalMouseClick); - } - - this.addIndicators = function() { - if (!this.indicatorsAdded) { - if (this.properties.sittingPoints.length > 0) { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i] = new SeatIndicator(this.properties, i); - } - this.indicatorsAdded = true; - } - } - } - - this.removeIndicators = function() { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i].cleanup(); - } - } - - this.showIndicators = function(doShow) { - this.addIndicators(); - if (this.indicatorsAdded) { - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - this.indicator[i].show(doShow); - } - } - hiddingSeats = !doShow; - } - - function raySphereIntersection(origin, direction, center, radius) { - var A = origin; - var B = Vec3.normalize(direction); - var P = center; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - var X = Vec3.sum(A, Vec3.multiply(B, x)); - var d = Vec3.length(Vec3.subtract(P, X)); - - return (x > 0 && d <= radius); - } - - this.cleanup = function() { - this.standUp(); - MyAvatar.clearReferential(); - for (var i = 0; i < pose.length; i++){ - MyAvatar.clearJointData(pose[i].joint); - } - Overlays.deleteOverlay(this.standUpButton); - for (var i = 0; i < this.indicator.length; ++i) { - this.indicator[i].cleanup(); - } - }; - - - this.createStandupButton = function() { - this.standUpButton = Overlays.addOverlay("image", { - x: buttonPositionX, y: buttonPositionY, width: buttonWidth, height: buttonHeight, - subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight}, - imageURL: buttonImageUrl, - visible: false, - alpha: 1.0 - }); - }; - - this.handleClickEvent = function(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if (clickedOverlay == this.standUpButton) { - seat.model = null; - this.standUp(); - } else { - this.addIndicators(); - if (this.indicatorsAdded) { - var pickRay = Camera.computePickRay(event.x, event.y); - - var clickedOnSeat = false; - - for (var i = 0; i < this.properties.sittingPoints.length; ++i) { - if (raySphereIntersection(pickRay.origin, - pickRay.direction, - this.indicator[i].position, - this.indicator[i].scale / 2)) { - clickedOnSeat = true; - seat.model = this.entityID; // ?? - seat.position = this.indicator[i].position; - seat.rotation = this.indicator[i].orientation; - } - } - - if (clickedOnSeat) { - passedTime = 0.0; - startPosition = MyAvatar.position; - startRotation = MyAvatar.orientation; - try{ Script.update.disconnect(standingUpAnimation); } catch(e){} - try{ Script.update.disconnect(sittingDownAnimation); } catch(e){} - Script.update.connect(goToSeatAnimation); - } - } - } - }; - - - // All callbacks start by updating the properties - this.updateProperties = function(entityID) { - if (this.entityID === null || !this.entityID.isKnownID) { - this.entityID = Entities.identifyEntity(entityID); - } - this.properties = Entities.getEntityProperties(this.entityID); - }; -}; - -Sittable.prototype = { - - unload : function(entityID) { - print("Sittable.unload()"); - this.cleanup(); - //Script.update.disconnect(SittableUpdate); - }, - - preload : function(entityID) { - print("Sittable.preload()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - this.createStandupButton(); - //Script.update.connect(SittableUpdate); - }, - - - hoverOverEntity : function(entityID, mouseEvent) { - print("Sittable.hoverOverEntity()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - this.showIndicators(true); - }, - - hoverLeaveEntity : function(entityID, mouseEvent) { - print("Sittable.hoverLeaveEntity()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - this.showIndicators(false); - }, - - clickDownOnEntity : function(entityID, mouseEvent) { - print("Sittable.clickDownOnEntity()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - this.handleClickEvent(mouseEvent); - }, - - clickReleaseOnEntity : function(entityID, mouseEvent) { - print("Sittable.clickReleaseOnEntity()"); - this.updateProperties(entityID); // All callbacks start by updating the properties - } -}; \ No newline at end of file From 97d617bd174767a9aeb12eee0f900a5665662338 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 11:01:35 -0800 Subject: [PATCH 25/67] revert some prototype script stuff for now --- examples/entityScripts/movable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/entityScripts/movable.js b/examples/entityScripts/movable.js index 35d11116eb..21e6261179 100644 --- a/examples/entityScripts/movable.js +++ b/examples/entityScripts/movable.js @@ -416,4 +416,4 @@ this.stopSound(); }; -}) \ No newline at end of file +}) From e4ce7d11dc8b744dec8ec1c04cb0ee87a21ee055 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Dec 2014 11:32:52 -0800 Subject: [PATCH 26/67] Fix default scripts url to use s3.amazonaws.com --- 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 a7b91db315..aae01681e0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -130,7 +130,7 @@ static QTimer* idleTimer = NULL; const QString CHECK_VERSION_URL = "https://highfidelity.io/latestVersion.xml"; const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/hifi.skipversion"; -const QString DEFAULT_SCRIPTS_JS_URL = "http://public.highfidelity.io/scripts/defaultScripts.js"; +const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js"; void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message); From 32ea38b93805d1abd260b1d33f5739dd587661a8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 11:33:25 -0800 Subject: [PATCH 27/67] added leaveAllEntities support --- .../entityScripts/playSoundOnEnterOrLeave.js | 2 ++ .../src/EntityTreeRenderer.cpp | 25 +++++++++++++++++-- .../src/EntityTreeRenderer.h | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/examples/entityScripts/playSoundOnEnterOrLeave.js b/examples/entityScripts/playSoundOnEnterOrLeave.js index f82c05c580..b95e35ab1d 100644 --- a/examples/entityScripts/playSoundOnEnterOrLeave.js +++ b/examples/entityScripts/playSoundOnEnterOrLeave.js @@ -27,10 +27,12 @@ }; this.enterEntity = function(entityID) { + print("enterEntity("+entityID.id+")"); playSound(); }; this.leaveEntity = function(entityID) { + print("leaveEntity("+entityID.id+")"); playSound(); }; }) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index e8530d5639..9f1185cfb9 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -62,6 +62,7 @@ EntityTreeRenderer::~EntityTreeRenderer() { } void EntityTreeRenderer::clear() { + leaveAllEntities(); foreach (const EntityItemID& entityID, _entityScripts.keys()) { checkAndCallUnload(entityID); } @@ -82,8 +83,7 @@ void EntityTreeRenderer::init() { // make sure our "last avatar position" is something other than our current position, so that on our // first chance, we'll check for enter/leave entity events. - glm::vec3 avatarPosition = _viewState->getAvatarPosition(); - _lastAvatarPosition = avatarPosition + glm::vec3(1.0f, 1.0f, 1.0f); + _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3(1.0f, 1.0f, 1.0f); connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity); connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload); @@ -297,6 +297,27 @@ void EntityTreeRenderer::checkEnterLeaveEntities() { } } +void EntityTreeRenderer::leaveAllEntities() { + if (_tree) { + _tree->lockForWrite(); // so that our scripts can do edits if they want + + // for all of our previous containing entities, if they are no longer containing then send them a leave event + foreach(const EntityItemID& entityID, _currentEntitiesInside) { + emit leaveEntity(entityID); + QScriptValueList entityArgs = createEntityArgs(entityID); + QScriptValue entityScript = loadEntityScript(entityID); + if (entityScript.property("leaveEntity").isValid()) { + entityScript.property("leaveEntity").call(entityScript, entityArgs); + } + } + _currentEntitiesInside.clear(); + + // make sure our "last avatar position" is something other than our current position, so that on our + // first chance, we'll check for enter/leave entity events. + _lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3(1.0f, 1.0f, 1.0f); + _tree->unlock(); + } +} void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::RenderSide renderSide) { if (_tree) { Model::startScene(renderSide); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 46c333d70d..92cc2c4dcc 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -129,6 +129,7 @@ private: QScriptValueList createEntityArgs(const EntityItemID& entityID); void checkEnterLeaveEntities(); + void leaveAllEntities(); glm::vec3 _lastAvatarPosition; QVector _currentEntitiesInside; From d585f8c7073a55915c3de4a76e89c769b18f42d7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 12:10:40 -0800 Subject: [PATCH 28/67] replace gluOrtho2D() with glOrtho() --- interface/src/devices/OculusManager.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- interface/src/ui/RearMirrorTools.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 1854c9539d..76a54eb9d8 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -582,7 +582,7 @@ void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); GLCanvas::SharedPointer glCanvas = DependencyManager::get(); - gluOrtho2D(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight()); + glOrtho(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight(), -1.0f, 1.0f); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ab85da125c..0350726d9c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -180,7 +180,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glPushMatrix(); { glLoadIdentity(); - gluOrtho2D(0, glCanvas->width(), glCanvas->height(), 0); + glOrtho(0, glCanvas->width(), glCanvas->height(), 0, -1.0f, 1.0f); renderAudioMeter(); @@ -224,7 +224,7 @@ void ApplicationOverlay::displayOverlayTexture() { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - gluOrtho2D(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0); + glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0f, 1.0f); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index fd3fc34adb..2287324656 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -128,7 +128,7 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture glPushMatrix(); glLoadIdentity(); - gluOrtho2D(bounds.left(), bounds.right(), bounds.bottom(), bounds.top()); + glOrtho(bounds.left(), bounds.right(), bounds.bottom(), bounds.top(), -1.0f, 1.0f); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); From 979f5f8fc50784bb17dc1208e33f58a3f02ab844 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 12:19:49 -0800 Subject: [PATCH 29/67] fix for coding standard compliance --- libraries/networking/src/AddressManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 57412b645f..f9789ff97e 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -350,7 +350,7 @@ bool AddressManager::handleUsername(const QString& lookupString) { } -void AddressManager::setDomainInfo(const QString &hostname, quint16 port, const QString& domainName) { +void AddressManager::setDomainInfo(const QString& hostname, quint16 port, const QString& domainName) { _currentDomain = domainName.isEmpty() ? hostname : domainName; emit possibleDomainChangeRequired(hostname, port); } From 66b1886b440e810f7400ec186ca7ef4044d3b934 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 12:33:26 -0800 Subject: [PATCH 30/67] don't add the unused assignment type to DS queue --- domain-server/src/DomainServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 73092b694b..cea5bec3ef 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -549,7 +549,9 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { - if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) { + if (!excludedTypes.contains(defaultedType) + && defaultedType != Assignment::UNUSED + && defaultedType != Assignment::AgentType) { // type has not been set from a command line or config file config, use the default // by clearing whatever exists and writing a single default assignment with no payload Assignment* newAssignment = new Assignment(Assignment::CreateCommand, (Assignment::Type) defaultedType); From 046564ec470dc7587ecd680e904eaf9fc40cca0b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 12:35:47 -0800 Subject: [PATCH 31/67] oops double --- interface/src/devices/OculusManager.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 4 ++-- interface/src/ui/RearMirrorTools.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 76a54eb9d8..f59ce639a0 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -582,7 +582,7 @@ void OculusManager::renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]) { glLoadIdentity(); GLCanvas::SharedPointer glCanvas = DependencyManager::get(); - glOrtho(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight(), -1.0f, 1.0f); + glOrtho(0, glCanvas->getDeviceWidth(), 0, glCanvas->getDeviceHeight(), -1.0, 1.0); glDisable(GL_DEPTH_TEST); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 0350726d9c..b2ed9fc77d 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -180,7 +180,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glPushMatrix(); { glLoadIdentity(); - glOrtho(0, glCanvas->width(), glCanvas->height(), 0, -1.0f, 1.0f); + glOrtho(0, glCanvas->width(), glCanvas->height(), 0, -1.0, 1.0); renderAudioMeter(); @@ -224,7 +224,7 @@ void ApplicationOverlay::displayOverlayTexture() { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0f, 1.0f); + glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0, 1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index 2287324656..37f7c6ae23 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -128,7 +128,7 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture glPushMatrix(); glLoadIdentity(); - glOrtho(bounds.left(), bounds.right(), bounds.bottom(), bounds.top(), -1.0f, 1.0f); + glOrtho(bounds.left(), bounds.right(), bounds.bottom(), bounds.top(), -1.0, 1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); From 096b09e8e17d11ffca76611131d24196f8d8dd82 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 19 Dec 2014 12:44:46 -0800 Subject: [PATCH 32/67] Importing fixes from Model branch to the gpu library --- libraries/gpu/src/gpu/Batch.cpp | 36 +++- libraries/gpu/src/gpu/Batch.h | 10 +- libraries/gpu/src/gpu/Context.h | 1 - libraries/gpu/src/gpu/Format.h | 9 +- libraries/gpu/src/gpu/GLBackend.cpp | 50 ++++- libraries/gpu/src/gpu/GLBackend.h | 14 ++ libraries/gpu/src/gpu/Resource.cpp | 40 +++- libraries/gpu/src/gpu/Resource.h | 295 +++++++++++++++++++++++++++- libraries/gpu/src/gpu/Stream.cpp | 4 +- libraries/gpu/src/gpu/Stream.h | 10 +- 10 files changed, 433 insertions(+), 36 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 30e591cc60..5604fa21c7 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -107,6 +107,19 @@ void Batch::setInputFormat(const Stream::FormatPointer& format) { _params.push_back(_streamFormats.cache(format)); } +void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) { + ADD_COMMAND(setInputBuffer); + + _params.push_back(stride); + _params.push_back(offset); + _params.push_back(_buffers.cache(buffer)); + _params.push_back(channel); +} + +void Batch::setInputBuffer(Slot channel, const BufferView& view) { + setInputBuffer(channel, view._buffer, view._offset, Offset(view._stride)); +} + void Batch::setInputStream(Slot startChannel, const BufferStream& stream) { if (stream.getNumBuffers()) { const Buffers& buffers = stream.getBuffers(); @@ -118,15 +131,6 @@ void Batch::setInputStream(Slot startChannel, const BufferStream& stream) { } } -void Batch::setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride) { - ADD_COMMAND(setInputBuffer); - - _params.push_back(stride); - _params.push_back(offset); - _params.push_back(_buffers.cache(buffer)); - _params.push_back(channel); -} - void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset) { ADD_COMMAND(setIndexBuffer); @@ -153,3 +157,17 @@ void Batch::setProjectionTransform(const Transform& proj) { _params.push_back(_transforms.cache(proj)); } +void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { + ADD_COMMAND(setUniformBuffer); + + _params.push_back(size); + _params.push_back(offset); + _params.push_back(_buffers.cache(buffer)); + _params.push_back(slot); +} + +void Batch::setUniformBuffer(uint32 slot, const BufferView& view) { + setUniformBuffer(slot, view._buffer, view._offset, view._size); +} + + diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 601ae63a77..c3a87c8f19 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -72,8 +72,9 @@ public: // IndexBuffer void setInputFormat(const Stream::FormatPointer& format); - void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer void setInputBuffer(Slot channel, const BufferPointer& buffer, Offset offset, Offset stride); + void setInputBuffer(Slot channel, const BufferView& buffer); // not a command, just a shortcut from a BufferView + void setInputStream(Slot startChannel, const BufferStream& stream); // not a command, just unroll into a loop of setInputBuffer void setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset); @@ -87,6 +88,9 @@ public: void setViewTransform(const Transform& view); void setProjectionTransform(const Transform& proj); + // Shader Stage + void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); + void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long @@ -117,6 +121,7 @@ public: void _glUseProgram(GLuint program); void _glUniform1f(GLint location, GLfloat v0); void _glUniform2f(GLint location, GLfloat v0, GLfloat v1); + void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); void _glMatrixMode(GLenum mode); @@ -161,6 +166,8 @@ public: COMMAND_setViewTransform, COMMAND_setProjectionTransform, + COMMAND_setUniformBuffer, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -187,6 +194,7 @@ public: COMMAND_glUseProgram, COMMAND_glUniform1f, COMMAND_glUniform2f, + COMMAND_glUniform4fv, COMMAND_glUniformMatrix4fv, COMMAND_glMatrixMode, diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 3a0fffb4ef..6839f9480a 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -12,7 +12,6 @@ #define hifi_gpu_Context_h #include -#include "GPUConfig.h" #include "Resource.h" diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index d216495b4c..aeeece8a62 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -12,8 +12,6 @@ #define hifi_gpu_Format_h #include -#include "GPUConfig.h" - namespace gpu { @@ -94,7 +92,8 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = { // Semantic of an Element // Provide information on how to use the element enum Semantic { - RGB = 0, + RAW = 0, // used as RAW memory + RGB, RGBA, XYZ, XYZW, @@ -104,6 +103,8 @@ enum Semantic { DIR_XYZ, UV, R8, + INDEX, //used by index buffer of a mesh + PART, // used by part buffer of a mesh NUM_SEMANTICS, }; @@ -119,7 +120,7 @@ public: _type(type) {} Element() : - _semantic(R8), + _semantic(RAW), _dimension(SCALAR), _type(INT8) {} diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 90639929ca..436045e8a3 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -31,6 +31,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setViewTransform), (&::gpu::GLBackend::do_setProjectionTransform), + (&::gpu::GLBackend::do_setUniformBuffer), + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -54,6 +56,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUseProgram), (&::gpu::GLBackend::do_glUniform1f), (&::gpu::GLBackend::do_glUniform2f), + (&::gpu::GLBackend::do_glUniform4fv), (&::gpu::GLBackend::do_glUniformMatrix4fv), (&::gpu::GLBackend::do_glMatrixMode), @@ -171,8 +174,8 @@ void GLBackend::checkGLError() { } } -//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -#define CHECK_GL_ERROR() +#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +//#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); @@ -483,6 +486,25 @@ void GLBackend::updateTransform() { } } +void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { + GLuint slot = batch._params[paramOffset + 3]._uint; + BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); + GLintptr rangeStart = batch._params[paramOffset + 1]._uint; + GLsizeiptr rangeSize = batch._params[paramOffset + 0]._uint; +#if defined(Q_OS_MAC) + GLfloat* data = (GLfloat*) (uniformBuffer->getData() + rangeStart); + glUniform4fv(slot, rangeSize / sizeof(GLfloat[4]), data); +#else + GLuint bo = getBufferID(*uniformBuffer); + glBindBufferRange(GL_UNIFORM_BUFFER, slot, bo, rangeStart, rangeSize); + + // glUniformBufferEXT(_shader._program, slot, bo); + + //glBindBufferBase(GL_UNIFORM_BUFFER, slot, bo); +#endif + CHECK_GL_ERROR(); +} + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -672,7 +694,10 @@ void Batch::_glUseProgram(GLuint program) { DO_IT_NOW(_glUseProgram, 1); } void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { - glUseProgram(batch._params[paramOffset]._uint); + + _shader._program = batch._params[paramOffset]._uint; + glUseProgram(_shader._program); + CHECK_GL_ERROR(); } @@ -708,6 +733,25 @@ void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } +void Batch::_glUniform4fv(GLint location, GLsizei count, const GLfloat* value) { + ADD_COMMAND_GL(glUniform4fv); + + const int VEC4_SIZE = 4 * sizeof(float); + _params.push_back(cacheData(count * VEC4_SIZE, value)); + _params.push_back(count); + _params.push_back(location); + + DO_IT_NOW(_glUniform4fv, 3); +} +void GLBackend::do_glUniform4fv(Batch& batch, uint32 paramOffset) { + glUniform4fv( + batch._params[paramOffset + 2]._int, + batch._params[paramOffset + 1]._uint, + (const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint)); + + CHECK_GL_ERROR(); +} + void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { ADD_COMMAND_GL(glUniformMatrix4fv); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 5a40e9ca36..be7a0a594b 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -122,6 +122,19 @@ protected: _lastMode(GL_TEXTURE) {} } _transform; + // Shader Stage + void do_setUniformBuffer(Batch& batch, uint32 paramOffset); + + void updateShader(); + struct ShaderStageState { + + GLuint _program; + + ShaderStageState() : + _program(0) {} + } _shader; + + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -148,6 +161,7 @@ protected: void do_glUseProgram(Batch& batch, uint32 paramOffset); void do_glUniform1f(Batch& batch, uint32 paramOffset); void do_glUniform2f(Batch& batch, uint32 paramOffset); + void do_glUniform4fv(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); void do_glMatrixMode(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index 3a6e47a7ba..085d97184b 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -67,6 +67,26 @@ Resource::Sysmem::Sysmem(Size size, const Byte* bytes) : } } +Resource::Sysmem::Sysmem(const Sysmem& sysmem) : + _stamp(0), + _size(0), + _data(NULL) +{ + if (sysmem.getSize() > 0) { + _size = allocateMemory(&_data, sysmem.getSize()); + if (_size >= sysmem.getSize()) { + if (sysmem.readData()) { + memcpy(_data, sysmem.readData(), sysmem.getSize()); + } + } + } +} + +Resource::Sysmem& Resource::Sysmem::operator=(const Sysmem& sysmem) { + setData(sysmem.getSize(), sysmem.readData()); + return (*this); +} + Resource::Sysmem::~Sysmem() { deallocateMemory( _data, _size ); _data = NULL; @@ -152,9 +172,25 @@ Resource::Size Resource::Sysmem::append(Size size, const Byte* bytes) { Buffer::Buffer() : Resource(), - _sysmem(NULL), + _sysmem(new Sysmem()), _gpuObject(NULL) { - _sysmem = new Sysmem(); +} + +Buffer::Buffer(Size size, const Byte* bytes) : + Resource(), + _sysmem(new Sysmem(size, bytes)), + _gpuObject(NULL) { +} + +Buffer::Buffer(const Buffer& buf) : + Resource(), + _sysmem(new Sysmem(buf.getSysmem())), + _gpuObject(NULL) { +} + +Buffer& Buffer::operator=(const Buffer& buf) { + (*_sysmem) = buf.getSysmem(); + return (*this); } Buffer::~Buffer() { diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 6247efe675..ec528c230b 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -12,13 +12,15 @@ #define hifi_gpu_Resource_h #include -#include "GPUConfig.h" #include "Format.h" #include #include +#ifdef _DEBUG +#include +#endif namespace gpu { @@ -29,7 +31,7 @@ typedef int Stamp; class Resource { public: typedef unsigned char Byte; - typedef unsigned int Size; + typedef unsigned int Size; static const Size NOT_ALLOCATED = -1; @@ -47,6 +49,8 @@ protected: Sysmem(); Sysmem(Size size, const Byte* bytes); + Sysmem(const Sysmem& sysmem); // deep copy of the sysmem buffer + Sysmem& operator=(const Sysmem& sysmem); // deep copy of the sysmem buffer ~Sysmem(); Size getSize() const { return _size; } @@ -90,9 +94,6 @@ protected: static void deallocateMemory(Byte* memDeallocated, Size size); private: - Sysmem(const Sysmem& sysmem) {} - Sysmem &operator=(const Sysmem& other) {return *this;} - Stamp _stamp; Size _size; Byte* _data; @@ -104,12 +105,15 @@ class Buffer : public Resource { public: Buffer(); - Buffer(const Buffer& buf); + Buffer(Size size, const Byte* bytes); + Buffer(const Buffer& buf); // deep copy of the sysmem buffer + Buffer& operator=(const Buffer& buf); // deep copy of the sysmem buffer ~Buffer(); // The size in bytes of data stored in the buffer Size getSize() const { return getSysmem().getSize(); } const Byte* getData() const { return getSysmem().readData(); } + Byte* editData() { return editSysmem().editData(); } // Resize the buffer // Keep previous data [0 to min(pSize, mSize)] @@ -130,7 +134,7 @@ public: // Access the sysmem object. const Sysmem& getSysmem() const { assert(_sysmem); return (*_sysmem); } - + Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); } protected: @@ -138,8 +142,6 @@ protected: mutable GPUObject* _gpuObject; - Sysmem& editSysmem() { assert(_sysmem); return (*_sysmem); } - // This shouldn't be used by anything else than the Backend class with the proper casting. void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } GPUObject* getGPUObject() const { return _gpuObject; } @@ -149,6 +151,281 @@ protected: typedef QSharedPointer BufferPointer; typedef std::vector< BufferPointer > Buffers; + + +class BufferView { +public: + typedef Resource::Size Size; + typedef int Index; + + BufferPointer _buffer; + Size _offset; + Size _size; + Element _element; + uint16 _stride; + + BufferView() : + _buffer(NULL), + _offset(0), + _size(0), + _element(gpu::SCALAR, gpu::UINT8, gpu::RAW), + _stride(1) + {}; + + BufferView(const Element& element) : + _buffer(NULL), + _offset(0), + _size(0), + _element(element), + _stride(uint16(element.getSize())) + {}; + + // create the BufferView and own the Buffer + BufferView(Buffer* newBuffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : + _buffer(newBuffer), + _offset(0), + _size(newBuffer->getSize()), + _element(element), + _stride(uint16(element.getSize())) + {}; + BufferView(const BufferPointer& buffer, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : + _buffer(buffer), + _offset(0), + _size(buffer->getSize()), + _element(element), + _stride(uint16(element.getSize())) + {}; + BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = Element(gpu::SCALAR, gpu::UINT8, gpu::RAW)) : + _buffer(buffer), + _offset(offset), + _size(size), + _element(element), + _stride(uint16(element.getSize())) + {}; + ~BufferView() {} + BufferView(const BufferView& view) = default; + BufferView& operator=(const BufferView& view) = default; + + Size getNumElements() const { return _size / _element.getSize(); } + + //Template iterator with random access on the buffer sysmem + template + class Iterator : public std::iterator + { + public: + + Iterator(T* ptr = NULL) { _ptr = ptr; } + Iterator(const Iterator& iterator) = default; + ~Iterator() {} + + Iterator& operator=(const Iterator& iterator) = default; + Iterator& operator=(T* ptr) { + _ptr = ptr; + return (*this); + } + + operator bool() const + { + if(_ptr) + return true; + else + return false; + } + + bool operator==(const Iterator& iterator) const { return (_ptr == iterator.getConstPtr()); } + bool operator!=(const Iterator& iterator) const { return (_ptr != iterator.getConstPtr()); } + + Iterator& operator+=(const Index& movement) { + _ptr += movement; + return (*this); + } + Iterator& operator-=(const Index& movement) { + _ptr -= movement; + return (*this); + } + Iterator& operator++() { + ++_ptr; + return (*this); + } + Iterator& operator--() { + --_ptr; + return (*this); + } + Iterator operator++(Index) { + auto temp(*this); + ++_ptr; + return temp; + } + Iterator operator--(Index) { + auto temp(*this); + --_ptr; + return temp; + } + Iterator operator+(const Index& movement) { + auto oldPtr = _ptr; + _ptr += movement; + auto temp(*this); + _ptr = oldPtr; + return temp; + } + Iterator operator-(const Index& movement) { + auto oldPtr = _ptr; + _ptr -= movement; + auto temp(*this); + _ptr = oldPtr; + return temp; + } + + Index operator-(const Iterator& iterator) { return (iterator.getPtr() - this->getPtr())/sizeof(T); } + + T& operator*(){return *_ptr;} + const T& operator*()const{return *_ptr;} + T* operator->(){return _ptr;} + + T* getPtr()const{return _ptr;} + const T* getConstPtr()const{return _ptr;} + + protected: + + T* _ptr; + }; + + template Iterator begin() { return Iterator(&edit(0)); } + template Iterator end() { return Iterator(&edit(getNum())); } + template Iterator cbegin() const { return Iterator(&get(0)); } + template Iterator cend() const { return Iterator(&get(getNum())); } + + // the number of elements of the specified type fitting in the view size + template Index getNum() const { + return Index(_size / sizeof(T)); + } + + template const T& get() const { + #if _DEBUG + if (_buffer.isNull()) { + qDebug() << "Accessing null gpu::buffer!"; + } + if (sizeof(T) > (_buffer->getSize() - _offset)) { + qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset); + } + if (sizeof(T) > _size) { + qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size; + } + #endif + const T* t = (reinterpret_cast (_buffer->getData() + _offset)); + return *(t); + } + + template T& edit() { + #if _DEBUG + if (_buffer.isNull()) { + qDebug() << "Accessing null gpu::buffer!"; + } + if (sizeof(T) > (_buffer->getSize() - _offset)) { + qDebug() << "Accessing buffer in non allocated memory, element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - _offset); + } + if (sizeof(T) > _size) { + qDebug() << "Accessing buffer outside the BufferView range, element size = " << sizeof(T) << " when bufferView size = " << _size; + } + #endif + T* t = (reinterpret_cast (_buffer->editData() + _offset)); + return *(t); + } + + template const T& get(const Index index) const { + Resource::Size elementOffset = index * sizeof(T) + _offset; + #if _DEBUG + if (_buffer.isNull()) { + qDebug() << "Accessing null gpu::buffer!"; + } + if (sizeof(T) > (_buffer->getSize() - elementOffset)) { + qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset); + } + if (index > getNum()) { + qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum(); + } + #endif + return *(reinterpret_cast (_buffer->getData() + elementOffset)); + } + + template T& edit(const Index index) const { + Resource::Size elementOffset = index * sizeof(T) + _offset; + #if _DEBUG + if (_buffer.isNull()) { + qDebug() << "Accessing null gpu::buffer!"; + } + if (sizeof(T) > (_buffer->getSize() - elementOffset)) { + qDebug() << "Accessing buffer in non allocated memory, index = " << index << ", element size = " << sizeof(T) << " available space in buffer at offset is = " << (_buffer->getSize() - elementOffset); + } + if (index > getNum()) { + qDebug() << "Accessing buffer outside the BufferView range, index = " << index << " number elements = " << getNum(); + } + #endif + return *(reinterpret_cast (_buffer->editData() + elementOffset)); + } +}; + + + // TODO: For now TextureView works with Buffer as a place holder for the Texture. + // The overall logic should be about the same except that the Texture will be a real GL Texture under the hood +class TextureView { +public: + typedef Resource::Size Size; + typedef int Index; + + BufferPointer _buffer; + Size _offset; + Size _size; + Element _element; + uint16 _stride; + + TextureView() : + _buffer(NULL), + _offset(0), + _size(0), + _element(gpu::VEC3, gpu::UINT8, gpu::RGB), + _stride(1) + {}; + + TextureView(const Element& element) : + _buffer(NULL), + _offset(0), + _size(0), + _element(element), + _stride(uint16(element.getSize())) + {}; + + // create the BufferView and own the Buffer + TextureView(Buffer* newBuffer, const Element& element) : + _buffer(newBuffer), + _offset(0), + _size(newBuffer->getSize()), + _element(element), + _stride(uint16(element.getSize())) + {}; + TextureView(const BufferPointer& buffer, const Element& element) : + _buffer(buffer), + _offset(0), + _size(buffer->getSize()), + _element(element), + _stride(uint16(element.getSize())) + {}; + TextureView(const BufferPointer& buffer, Size offset, Size size, const Element& element) : + _buffer(buffer), + _offset(offset), + _size(size), + _element(element), + _stride(uint16(element.getSize())) + {}; + ~TextureView() {} + TextureView(const TextureView& view) = default; + TextureView& operator=(const TextureView& view) = default; +}; + }; diff --git a/libraries/gpu/src/gpu/Stream.cpp b/libraries/gpu/src/gpu/Stream.cpp index 099cbde24a..73677f715e 100644 --- a/libraries/gpu/src/gpu/Stream.cpp +++ b/libraries/gpu/src/gpu/Stream.cpp @@ -18,7 +18,7 @@ void Stream::Format::evaluateCache() { _elementTotalSize = 0; for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) { Attribute& attrib = (*it).second; - Channel& channel = _channels[attrib._channel]; + ChannelInfo& channel = _channels[attrib._channel]; channel._slots.push_back(attrib._slot); channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset); channel._netSize += attrib.getSize(); @@ -41,7 +41,7 @@ BufferStream::BufferStream() : BufferStream::~BufferStream() { } -void BufferStream::addBuffer(BufferPointer& buffer, Offset offset, Offset stride) { +void BufferStream::addBuffer(const BufferPointer& buffer, Offset offset, Offset stride) { _buffers.push_back(buffer); _offsets.push_back(offset); _strides.push_back(stride); diff --git a/libraries/gpu/src/gpu/Stream.h b/libraries/gpu/src/gpu/Stream.h index 93abfeeca3..b1aaec665f 100644 --- a/libraries/gpu/src/gpu/Stream.h +++ b/libraries/gpu/src/gpu/Stream.h @@ -12,7 +12,6 @@ #define hifi_gpu_Stream_h #include -#include "GPUConfig.h" #include "Resource.h" #include "Format.h" @@ -83,16 +82,16 @@ public: public: typedef std::map< Slot, Attribute > AttributeMap; - class Channel { + class ChannelInfo { public: std::vector< Slot > _slots; std::vector< Offset > _offsets; Offset _stride; uint32 _netSize; - Channel() : _stride(0), _netSize(0) {} + ChannelInfo() : _stride(0), _netSize(0) {} }; - typedef std::map< Slot, Channel > ChannelMap; + typedef std::map< Slot, ChannelInfo > ChannelMap; Format() : _attributes(), @@ -104,6 +103,7 @@ public: uint8 getNumChannels() const { return _channels.size(); } const ChannelMap& getChannels() const { return _channels; } + const Offset getChannelStride(Slot channel) const { return _channels.at(channel)._stride; } uint32 getElementTotalSize() const { return _elementTotalSize; } @@ -131,7 +131,7 @@ public: BufferStream(); ~BufferStream(); - void addBuffer(BufferPointer& buffer, Offset offset, Offset stride); + void addBuffer(const BufferPointer& buffer, Offset offset, Offset stride); const Buffers& getBuffers() const { return _buffers; } const Offsets& getOffsets() const { return _offsets; } From a7b039fbb9703128a2e560d82f1456afab21fbfa Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 19 Dec 2014 13:28:19 -0800 Subject: [PATCH 33/67] Disabling glDebug --- libraries/gpu/src/gpu/GLBackend.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 436045e8a3..f5f998d0d9 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -174,8 +174,8 @@ void GLBackend::checkGLError() { } } -#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() -//#define CHECK_GL_ERROR() +//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError() +#define CHECK_GL_ERROR() void GLBackend::do_draw(Batch& batch, uint32 paramOffset) { updateInput(); From 1db1914a2efb409d5c1027343e1da4d40ab5b380 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 13:46:33 -0800 Subject: [PATCH 34/67] replace gluProject() with just the math --- interface/src/avatar/Avatar.cpp | 138 ++++++++++++++++---------------- interface/src/avatar/Avatar.h | 1 + 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 39c528d080..4c309b2c8c 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -669,6 +669,49 @@ glm::vec3 Avatar::getDisplayNamePosition() { return namePosition; } +float Avatar::calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD) { + + // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates + // We project a unit vector and check the difference in screen coordinates, to check which is the + // correction scale needed + // save the matrices for later scale correction factor + // The up vector must be relative to the rotation current rotation matrix: + // we set the identity + glm::vec3 testPoint0 = textPosition; + glm::vec3 testPoint1 = textPosition + (Application::getInstance()->getCamera()->getRotation() * IDENTITY_UP); + + double textWindowHeight; + + GLCanvas::SharedPointer glCanvas = DependencyManager::get(); + float windowSizeX = glCanvas->getDeviceWidth(); + float windowSizeY = glCanvas->getDeviceHeight(); + + glm::dmat4 modelViewMatrix; + glm::dmat4 projectionMatrix; + Application::getInstance()->getModelViewMatrix(&modelViewMatrix); + Application::getInstance()->getProjectionMatrix(&projectionMatrix); + + glm::dvec4 p0 = modelViewMatrix * glm::dvec4(testPoint0, 1.0); + p0 = projectionMatrix * p0; + glm::dvec2 result0 = glm::vec2(windowSizeX * (p0.x / p0.w + 1.0f) * 0.5f, windowSizeY * (p0.y / p0.w + 1.0f) * 0.5f); + + glm::dvec4 p1 = modelViewMatrix * glm::dvec4(testPoint1, 1.0); + p1 = projectionMatrix * p1; + glm::vec2 result1 = glm::vec2(windowSizeX * (p1.x / p1.w + 1.0f) * 0.5f, windowSizeY * (p1.y / p1.w + 1.0f) * 0.5f); + textWindowHeight = abs(result1.y - result0.y); + + // need to scale to compensate for the font resolution due to the device + float scaleFactor = QApplication::desktop()->windowHandle()->devicePixelRatio() * + ((textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f); + if (inHMD) { + const float HMDMODE_NAME_SCALE = 0.65f; + scaleFactor *= HMDMODE_NAME_SCALE; + } else { + scaleFactor *= Application::getInstance()->getRenderResolutionScale(); + } + return scaleFactor; +} + void Avatar::renderDisplayName() { if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) { @@ -700,78 +743,39 @@ void Avatar::renderDisplayName() { frontAxis = glm::normalize(glm::vec3(frontAxis.z, 0.0f, -frontAxis.x)); float angle = acos(frontAxis.x) * ((frontAxis.z < 0) ? 1.0f : -1.0f); glRotatef(glm::degrees(angle), 0.0f, 1.0f, 0.0f); - - // We need to compute the scale factor such as the text remains with fixed size respect to window coordinates - // We project a unit vector and check the difference in screen coordinates, to check which is the - // correction scale needed - // save the matrices for later scale correction factor - glm::dmat4 modelViewMatrix; - glm::dmat4 projectionMatrix; - GLint viewportMatrix[4]; - Application::getInstance()->getModelViewMatrix(&modelViewMatrix); - Application::getInstance()->getProjectionMatrix(&projectionMatrix); - glGetIntegerv(GL_VIEWPORT, viewportMatrix); - GLdouble result0[3], result1[3]; - - // The up vector must be relative to the rotation current rotation matrix: - // we set the identity - glm::dvec3 testPoint0 = glm::dvec3(textPosition); - glm::dvec3 testPoint1 = glm::dvec3(textPosition) + glm::dvec3(Application::getInstance()->getCamera()->getRotation() * IDENTITY_UP); - bool success; - success = gluProject(testPoint0.x, testPoint0.y, testPoint0.z, - (GLdouble*)&modelViewMatrix, (GLdouble*)&projectionMatrix, viewportMatrix, - &result0[0], &result0[1], &result0[2]); - success = success && - gluProject(testPoint1.x, testPoint1.y, testPoint1.z, - (GLdouble*)&modelViewMatrix, (GLdouble*)&projectionMatrix, viewportMatrix, - &result1[0], &result1[1], &result1[2]); + float scaleFactor = calculateDisplayNameScaleFactor(textPosition, inHMD); + glScalef(scaleFactor, scaleFactor, 1.0); + + glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis - if (success) { - double textWindowHeight = abs(result1[1] - result0[1]); - // need to scale to compensate for the font resolution due to the device - float scaleFactor = QApplication::desktop()->windowHandle()->devicePixelRatio() * - ((textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f); - if (inHMD) { - const float HMDMODE_NAME_SCALE = 0.65f; - scaleFactor *= HMDMODE_NAME_SCALE; - } else { - scaleFactor *= Application::getInstance()->getRenderResolutionScale(); - } - glScalef(scaleFactor, scaleFactor, 1.0); - - glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis + int text_x = -_displayNameBoundingRect.width() / 2; + int text_y = -_displayNameBoundingRect.height() / 2; - int text_x = -_displayNameBoundingRect.width() / 2; - int text_y = -_displayNameBoundingRect.height() / 2; + // draw a gray background + int left = text_x + _displayNameBoundingRect.x(); + int right = left + _displayNameBoundingRect.width(); + int bottom = text_y + _displayNameBoundingRect.y(); + int top = bottom + _displayNameBoundingRect.height(); + const int border = 8; + bottom -= border; + left -= border; + top += border; + right += border; - // draw a gray background - int left = text_x + _displayNameBoundingRect.x(); - int right = left + _displayNameBoundingRect.width(); - int bottom = text_y + _displayNameBoundingRect.y(); - int top = bottom + _displayNameBoundingRect.height(); - const int border = 8; - bottom -= border; - left -= border; - top += border; - right += border; + // We are drawing coplanar textures with depth: need the polygon offset + glEnable(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); - // We are drawing coplanar textures with depth: need the polygon offset - glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); - - glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA); - renderBevelCornersRect(left, bottom, right - left, top - bottom, 3); - - glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha); - QByteArray ba = _displayName.toLocal8Bit(); - const char* text = ba.data(); - - glDisable(GL_POLYGON_OFFSET_FILL); - textRenderer(DISPLAYNAME)->draw(text_x, text_y, text); - - - } + glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA); + renderBevelCornersRect(left, bottom, right - left, top - bottom, 3); + + glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha); + QByteArray ba = _displayName.toLocal8Bit(); + const char* text = ba.data(); + + glDisable(GL_POLYGON_OFFSET_FILL); + textRenderer(DISPLAYNAME)->draw(text_x, text_y, text); glPopMatrix(); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 88ab3b12ca..d862e042c2 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -230,6 +230,7 @@ protected: float getPelvisFloatingHeight() const; glm::vec3 getDisplayNamePosition(); + float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD); void renderDisplayName(); virtual void renderBody(RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; From 22e2fcf746af7df99a71b2f5caea198d1d63ef1e Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 13:46:42 -0800 Subject: [PATCH 35/67] add some vec2 debugging --- libraries/shared/src/StreamUtils.cpp | 8 ++++++++ libraries/shared/src/StreamUtils.h | 1 + 2 files changed, 9 insertions(+) diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index 85b800efbe..47bb8dd4e4 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -98,6 +98,14 @@ std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule) { #ifndef QT_NO_DEBUG_STREAM #include +QDebug& operator<<(QDebug& dbg, const glm::vec2& v) { + dbg.nospace() << "{type='glm::vec2'" + ", x=" << v.x << + ", y=" << v.y << + "}"; + return dbg; +} + QDebug& operator<<(QDebug& dbg, const glm::vec3& v) { dbg.nospace() << "{type='glm::vec3'" ", x=" << v.x << diff --git a/libraries/shared/src/StreamUtils.h b/libraries/shared/src/StreamUtils.h index 6d00c0e354..d176d68e45 100644 --- a/libraries/shared/src/StreamUtils.h +++ b/libraries/shared/src/StreamUtils.h @@ -49,6 +49,7 @@ std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule); #ifndef QT_NO_DEBUG_STREAM class QDebug; // Add support for writing these to qDebug(). +QDebug& operator<<(QDebug& s, const glm::vec2& v); QDebug& operator<<(QDebug& s, const glm::vec3& v); QDebug& operator<<(QDebug& s, const glm::quat& q); QDebug& operator<<(QDebug& s, const glm::mat4& m); From 2e3a522e73d045d5efa071e8a6ca4417db52dae6 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 13:53:44 -0800 Subject: [PATCH 36/67] remove glut.h from CmakeLists.txt and fix a compiler issue with Hair.cpp --- interface/CMakeLists.txt | 6 +++--- interface/src/Hair.cpp | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a9688a5919..6d0b6a2f07 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -25,15 +25,15 @@ else () endif () if (APPLE) - set(GL_HEADERS "#include \n#include ") + set(GL_HEADERS "#include ") elseif (UNIX) # include the right GL headers for UNIX - set(GL_HEADERS "#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include ") elseif (WIN32) add_definitions(-D_USE_MATH_DEFINES) # apparently needed to get M_PI and other defines from cmath/math.h add_definitions(-DWINDOWS_LEAN_AND_MEAN) # needed to make sure windows doesn't go to crazy with its defines - set(GL_HEADERS "#include \n#include \n#include \n#include ") + set(GL_HEADERS "#include \n#include \n#include ") endif () # set up the external glm library diff --git a/interface/src/Hair.cpp b/interface/src/Hair.cpp index cb664f39ed..6fd326a9b5 100644 --- a/interface/src/Hair.cpp +++ b/interface/src/Hair.cpp @@ -10,6 +10,8 @@ // // Creates single flexible verlet-integrated strands that can be used for hair/fur/grass +#include + #include "Hair.h" #include "Util.h" From 4f478e158f728412006464e0307013d908ad6e4b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 13:59:43 -0800 Subject: [PATCH 37/67] remove includes for glu for APPLE --- interface/src/avatar/Avatar.cpp | 5 ----- interface/src/ui/ApplicationOverlay.cpp | 5 ----- interface/src/ui/RearMirrorTools.cpp | 5 ----- 3 files changed, 15 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index aa94b21d71..39c528d080 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -13,11 +13,6 @@ #include -// TODO: remove calls to gluProject to remove this include -#ifdef __APPLE__ -#include -#endif - #include #include diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f82b44a403..ab85da125c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -11,11 +11,6 @@ #include "InterfaceConfig.h" -// TODO: remove calls to gluProject to remove this include -#ifdef __APPLE__ -#include -#endif - #include #include diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index 2c671ef548..fd3fc34adb 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -11,11 +11,6 @@ #include "InterfaceConfig.h" -// TODO: remove calls to gluProject to remove this include -#ifdef __APPLE__ -#include -#endif - #include #include From 30e2a9c13f13c0e6cd3b13db85f4307b7b3783f4 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Dec 2014 14:18:44 -0800 Subject: [PATCH 38/67] Add notifications.js to defaultScripts --- examples/defaultScripts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index d39fce0186..cdb8e76c65 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -15,3 +15,4 @@ Script.load("hydraMove.js"); Script.load("headMove.js"); Script.load("inspect.js"); Script.load("lobby.js"); +Script.load("notifications.js"); From 7e37aaabde2f7597fdff8ef28b0c66ffd931d1dd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 14:24:04 -0800 Subject: [PATCH 39/67] windows build hack --- interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6d0b6a2f07..ff813343ab 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -232,7 +232,7 @@ else (APPLE) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" wsock32.lib opengl32.lib) + target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" "${NSIGHT_LIBRARIES}" wsock32.lib opengl32.lib Winmm.lib) # try to find the Nsight package and add it to the build if we find it find_package(NSIGHT) From b7165abd5beaa5498024ed098bcbadcec83a12d5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 19 Dec 2014 14:33:45 -0800 Subject: [PATCH 40/67] possible glew warning fix for windows --- libraries/gpu/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index 340adcc9e6..e63495867e 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -19,7 +19,7 @@ elseif (WIN32) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} "${GLEW_LIBRARIES}" opengl32.lib) + target_link_libraries(${TARGET_NAME} opengl32.lib) # need to bubble up the GLEW_INCLUDE_DIRS list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${GLEW_INCLUDE_DIRS}") From 691be3bf7c4e29b596b44ba3c889f4111c306cb0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 14:59:55 -0800 Subject: [PATCH 41/67] add a test to confirm link fail --- libraries/gpu/src/gpu/GLBackend.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 90639929ca..6663e0b169 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -117,7 +117,8 @@ GLBackend::GLBackend() : _input(), _transform() { - + // TEST FOR SANITY + glewInit(); } GLBackend::~GLBackend() { From d7d11955f3d4eafb3b7258ccd7f785752a1ff343 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 15:05:13 -0800 Subject: [PATCH 42/67] Revert "add a test to confirm link fail" This reverts commit 691be3bf7c4e29b596b44ba3c889f4111c306cb0. --- libraries/gpu/src/gpu/GLBackend.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6663e0b169..90639929ca 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -117,8 +117,7 @@ GLBackend::GLBackend() : _input(), _transform() { - // TEST FOR SANITY - glewInit(); + } GLBackend::~GLBackend() { From 2780415b1d4d529d91d8d6382d8cbadd8dbb18d1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 19 Dec 2014 15:07:31 -0800 Subject: [PATCH 43/67] put glew link back into gpu --- libraries/gpu/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/CMakeLists.txt b/libraries/gpu/CMakeLists.txt index b4da0d8b03..7f2b475dd2 100644 --- a/libraries/gpu/CMakeLists.txt +++ b/libraries/gpu/CMakeLists.txt @@ -19,7 +19,7 @@ elseif (WIN32) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) - target_link_libraries(${TARGET_NAME} opengl32.lib) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) # need to bubble up the GLEW_INCLUDE_DIRS list(APPEND ${TARGET_NAME}_DEPENDENCY_INCLUDES "${GLEW_INCLUDE_DIRS}") From 25a78534aae5eae68b241e9419bffdd21f294fe8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 19 Dec 2014 15:52:31 -0800 Subject: [PATCH 44/67] Fix quad vertices for ImageOverlay and TextOverlay --- interface/src/ui/overlays/ImageOverlay.cpp | 13 +++++++++---- interface/src/ui/overlays/TextOverlay.cpp | 13 +++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index f903dfe19c..b14f49737f 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -100,26 +100,31 @@ void ImageOverlay::render(RenderArgs* args) { float w = fromImage.width() / imageWidth; // ?? is this what we want? not sure float h = fromImage.height() / imageHeight; + int left = _bounds.left(); + int right = _bounds.right() + 1; + int top = _bounds.top(); + int bottom = _bounds.bottom() + 1; + glBegin(GL_QUADS); if (_renderImage) { glTexCoord2f(x, 1.0f - y); } - glVertex2f(_bounds.left(), _bounds.top()); + glVertex2f(left, top); if (_renderImage) { glTexCoord2f(x + w, 1.0f - y); } - glVertex2f(_bounds.right(), _bounds.top()); + glVertex2f(right, top); if (_renderImage) { glTexCoord2f(x + w, 1.0f - (y + h)); } - glVertex2f(_bounds.right(), _bounds.bottom()); + glVertex2f(right, bottom); if (_renderImage) { glTexCoord2f(x, 1.0f - (y + h)); } - glVertex2f(_bounds.left(), _bounds.bottom()); + glVertex2f(left, bottom); glEnd(); if (_renderImage) { diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 97d910eb64..03a5c3d846 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -70,11 +70,16 @@ void TextOverlay::render(RenderArgs* args) { glColor4f(backgroundColor.red / MAX_COLOR, backgroundColor.green / MAX_COLOR, backgroundColor.blue / MAX_COLOR, getBackgroundAlpha()); + int left = _bounds.left(); + int right = _bounds.right() + 1; + int top = _bounds.top(); + int bottom = _bounds.bottom() + 1; + glBegin(GL_QUADS); - glVertex2f(_bounds.left(), _bounds.top()); - glVertex2f(_bounds.right(), _bounds.top()); - glVertex2f(_bounds.right(), _bounds.bottom()); - glVertex2f(_bounds.left(), _bounds.bottom()); + glVertex2f(left, top); + glVertex2f(right, top); + glVertex2f(right, bottom); + glVertex2f(left, bottom); glEnd(); // Same font properties as textSize() From 967c6dbc4b93024bddce4bd608b4de0bd5eeacf8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 19 Dec 2014 16:19:06 -0800 Subject: [PATCH 45/67] Add the Model library --- assignment-client/CMakeLists.txt | 2 +- interface/CMakeLists.txt | 2 +- libraries/animation/CMakeLists.txt | 2 +- libraries/avatars/CMakeLists.txt | 4 +- libraries/entities/CMakeLists.txt | 2 +- libraries/fbx/CMakeLists.txt | 2 +- libraries/fbx/src/FBXReader.h | 7 +- libraries/model/CMakeLists.txt | 11 ++ libraries/model/src/model/Geometry.cpp | 141 +++++++++++++++++++++++ libraries/model/src/model/Geometry.h | 151 +++++++++++++++++++++++++ libraries/model/src/model/Material.cpp | 92 +++++++++++++++ libraries/model/src/model/Material.h | 114 +++++++++++++++++++ libraries/script-engine/CMakeLists.txt | 2 +- libraries/shared/src/AABox.cpp | 25 +++- libraries/shared/src/AABox.h | 5 + tests/octree/CMakeLists.txt | 2 +- 16 files changed, 549 insertions(+), 15 deletions(-) create mode 100755 libraries/model/CMakeLists.txt create mode 100755 libraries/model/src/model/Geometry.cpp create mode 100755 libraries/model/src/model/Geometry.h create mode 100755 libraries/model/src/model/Material.cpp create mode 100755 libraries/model/src/model/Material.h diff --git a/assignment-client/CMakeLists.txt b/assignment-client/CMakeLists.txt index 6e31182f0d..9d604cd5dd 100644 --- a/assignment-client/CMakeLists.txt +++ b/assignment-client/CMakeLists.txt @@ -6,7 +6,7 @@ include_glm() # link in the shared libraries link_hifi_libraries( - audio avatars octree voxels fbx entities metavoxels + audio avatars octree voxels gpu model fbx entities metavoxels networking animation shared script-engine embedded-webserver physics ) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a9688a5919..92c0d03add 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -107,7 +107,7 @@ endif() add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM}) # link required hifi libraries -link_hifi_libraries(shared octree voxels gpu fbx metavoxels networking entities avatars audio animation script-engine physics +link_hifi_libraries(shared octree voxels gpu model fbx metavoxels networking entities avatars audio animation script-engine physics render-utils entities-renderer) # find any optional and required libraries diff --git a/libraries/animation/CMakeLists.txt b/libraries/animation/CMakeLists.txt index 3f65c1ab6c..ee80db7567 100644 --- a/libraries/animation/CMakeLists.txt +++ b/libraries/animation/CMakeLists.txt @@ -3,7 +3,7 @@ set(TARGET_NAME animation) # use setup_hifi_library macro to setup our project and link appropriate Qt modules setup_hifi_library(Network Script) -link_hifi_libraries(shared fbx) +link_hifi_libraries(shared gpu model fbx) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() \ No newline at end of file diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index 42b3cf7d3c..4c84c542ef 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -5,8 +5,8 @@ setup_hifi_library(Network Script) include_glm() -link_hifi_libraries(shared octree voxels networking physics) -include_hifi_library_headers(fbx) +link_hifi_libraries(shared octree voxels gpu model fbx networking physics) +include_hifi_library_headers(gpu model fbx) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index e48baa7615..b266050e69 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Network Script) include_glm() -link_hifi_libraries(shared octree fbx networking animation physics) +link_hifi_libraries(shared octree gpu model fbx networking animation physics) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 5a151deb8b..fe460c93b5 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library() include_glm() -link_hifi_libraries(shared networking octree voxels) +link_hifi_libraries(shared gpu model networking octree voxels) find_package(ZLIB REQUIRED) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 736da3a349..3d07d29e7d 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -24,8 +24,10 @@ #include #include -class QIODevice; +#include +#include +class QIODevice; class FBXNode; typedef QList FBXNodeList; @@ -131,6 +133,7 @@ public: FBXTexture emissiveTexture; QString materialID; + model::MaterialPointer _material; }; /// A single mesh (with optional blendshapes) extracted from an FBX document. @@ -159,6 +162,8 @@ public: bool hasSpecularTexture() const; bool hasEmissiveTexture() const; + + model::Mesh _mesh; }; /// A single animation frame extracted from an FBX document. diff --git a/libraries/model/CMakeLists.txt b/libraries/model/CMakeLists.txt new file mode 100755 index 0000000000..d9fd4b67a7 --- /dev/null +++ b/libraries/model/CMakeLists.txt @@ -0,0 +1,11 @@ +set(TARGET_NAME model) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library() + +include_glm() + +link_hifi_libraries(shared gpu) + +# call macro to link our dependencies and bubble them up via a property on our target +link_shared_dependencies() diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp new file mode 100755 index 0000000000..d5d3ba6c07 --- /dev/null +++ b/libraries/model/src/model/Geometry.cpp @@ -0,0 +1,141 @@ +// +// Geometry.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 12/5/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Geometry.h" + +#include + +using namespace model; + +Mesh::Mesh() : + _vertexBuffer(gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)), + _indexBuffer(gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX)), + _partBuffer(gpu::Element(gpu::VEC4, gpu::UINT32, gpu::PART)) { +} + +Mesh::Mesh(const Mesh& mesh) : + _vertexFormat(mesh._vertexFormat), + _vertexBuffer(mesh._vertexBuffer), + _attributeBuffers(mesh._attributeBuffers), + _indexBuffer(mesh._indexBuffer), + _partBuffer(mesh._partBuffer) { +} + +Mesh::~Mesh() { +} + +void Mesh::setVertexBuffer(const BufferView& buffer) { + _vertexBuffer = buffer; + evalVertexFormat(); +} + +void Mesh::addAttribute(Slot slot, const BufferView& buffer) { + _attributeBuffers[slot] = buffer; + evalVertexFormat(); +} + +void Mesh::evalVertexFormat() { + VertexFormat vf; + int channelNum = 0; + if (hasVertexData()) { + vf.setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0); + channelNum++; + } + for (auto attrib : _attributeBuffers) { + vf.setAttribute(attrib.first, channelNum, attrib.second._element, 0); + channelNum++; + } + + _vertexFormat = vf; +} + +void Mesh::setIndexBuffer(const BufferView& buffer) { + _indexBuffer = buffer; +} + +void Mesh::setPartBuffer(const BufferView& buffer) { + _partBuffer = buffer; +} + +const Box Mesh::evalPartBound(int partNum) const { + Box box; + if (partNum < _partBuffer.getNum()) { + const Part& part = _partBuffer.get(partNum); + auto index = _indexBuffer.cbegin(); + index += part._startIndex; + auto endIndex = index; + endIndex += part._numIndices; + auto vertices = &_vertexBuffer.get(part._baseVertex); + for (;index != endIndex; index++) { + // skip primitive restart indices + if ((*index) != PRIMITIVE_RESTART_INDEX) { + box += vertices[(*index)]; + } + } + } + return box; +} + +const Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const { + Box totalBound; + auto part = _partBuffer.cbegin() + partStart; + auto partItEnd = _partBuffer.cbegin() + partEnd; + + for (;part != partItEnd; part++) { + + Box partBound; + auto index = _indexBuffer.cbegin() + (*part)._startIndex; + auto endIndex = index + (*part)._numIndices; + auto vertices = &_vertexBuffer.get((*part)._baseVertex); + for (;index != endIndex; index++) { + // skip primitive restart indices + if ((*index) != PRIMITIVE_RESTART_INDEX) { + partBound += vertices[(*index)]; + } + } + + totalBound += partBound; + } + return totalBound; +} + +const gpu::BufferStream Mesh::makeBufferStream() const { + gpu::BufferStream stream; + + int channelNum = 0; + if (hasVertexData()) { + stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat.getChannelStride(channelNum)); + channelNum++; + } + for (auto attrib : _attributeBuffers) { + BufferView& view = attrib.second; + stream.addBuffer(view._buffer, view._offset, _vertexFormat.getChannelStride(channelNum)); + channelNum++; + } + + return stream; +} + +Geometry::Geometry() { +} + +Geometry::Geometry(const Geometry& geometry): + _mesh(geometry._mesh), + _boxes(geometry._boxes) { +} + +Geometry::~Geometry() { +} + +void Geometry::setMesh(const MeshPointer& mesh) { + _mesh = mesh; +} + diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h new file mode 100755 index 0000000000..8f0625ef69 --- /dev/null +++ b/libraries/model/src/model/Geometry.h @@ -0,0 +1,151 @@ +// +// Geometry.h +// libraries/model/src/model +// +// Created by Sam Gateau on 12/5/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Geometry_h +#define hifi_model_Geometry_h + +#include + +#include "AABox.h" + +#include "gpu/Resource.h" +#include "gpu/Stream.h" + +namespace model { +typedef gpu::BufferView::Index Index; +typedef gpu::BufferView BufferView; +typedef AABox Box; +typedef std::vector< Box > Boxes; + +class Mesh { +public: + const static Index PRIMITIVE_RESTART_INDEX = -1; + + typedef gpu::BufferView BufferView; + typedef std::vector< BufferView > BufferViews; + + typedef gpu::Stream::Slot Slot; + typedef gpu::Stream::Format VertexFormat; + typedef std::map< Slot, BufferView > BufferViewMap; + + typedef glm::vec3 Vec3; + + Mesh(); + Mesh(const Mesh& mesh); + Mesh& operator= (const Mesh& mesh) = default; + virtual ~Mesh(); + + // Vertex buffer + void setVertexBuffer(const BufferView& buffer); + const BufferView& getVertexBuffer() const { return _vertexBuffer; } + uint getNumVertices() const { return _vertexBuffer.getNumElements(); } + bool hasVertexData() const { return !_vertexBuffer._buffer.isNull(); } + + // Attribute Buffers + int getNumAttributes() const { return _attributeBuffers.size(); } + void addAttribute(Slot slot, const BufferView& buffer); + + // Stream format + const VertexFormat& getVertexFormat() const { return _vertexFormat; } + + // Index Buffer + void setIndexBuffer(const BufferView& buffer); + const BufferView& getIndexBuffer() const { return _indexBuffer; } + uint getNumIndices() const { return _indexBuffer.getNumElements(); } + + // Access vertex position value + const Vec3& getPos3(Index index) const { return _vertexBuffer.get(index); } + + enum Topology + { + POINTS = 0, + LINES, + LINE_STRIP, + TRIANGLES, + TRIANGLE_STRIP, + QUADS, + QUAD_STRIP, + + NUM_TOPOLOGIES, + }; + + // Subpart of a mesh, describing the toplogy of the surface + class Part { + public: + Index _startIndex; + Index _numIndices; + Index _baseVertex; + Topology _topology; + + Part() : + _startIndex(0), + _numIndices(0), + _baseVertex(0), + _topology(TRIANGLES) + {} + Part(Index startIndex, Index numIndices, Index baseVertex, Topology topology) : + _startIndex(startIndex), + _numIndices(numIndices), + _baseVertex(baseVertex), + _topology(topology) + {} + }; + + void setPartBuffer(const BufferView& buffer); + const BufferView& getPartBuffer() const { return _partBuffer; } + uint getNumParts() const { return _partBuffer.getNumElements(); } + + // evaluate the bounding box of A part + const Box evalPartBound(int partNum) const; + // evaluate the bounding boxes of the parts in the range [start, end[ and fill the bounds parameter + // the returned box is the bounding box of ALL the evaluated part bounds. + const Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const; + + + // Generate a BufferStream on the mesh vertices and attributes + const gpu::BufferStream makeBufferStream() const; + +protected: + + VertexFormat _vertexFormat; + + BufferView _vertexBuffer; + BufferViewMap _attributeBuffers; + + BufferView _indexBuffer; + + BufferView _partBuffer; + + void evalVertexFormat(); + +}; +typedef QSharedPointer< Mesh > MeshPointer; + + +class Geometry { +public: + + Geometry(); + Geometry(const Geometry& geometry); + ~Geometry(); + + void setMesh(const MeshPointer& mesh); + const MeshPointer& getMesh() const { return _mesh; } + +protected: + + MeshPointer _mesh; + BufferView _boxes; + +}; + +}; + +#endif diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp new file mode 100755 index 0000000000..44e0051386 --- /dev/null +++ b/libraries/model/src/model/Material.cpp @@ -0,0 +1,92 @@ +// +// Material.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 12/10/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Material.h" + +using namespace model; + +Material::Material() : + _flags(0), + _schemaBuffer(), + _textureMap() { + + // only if created from nothing shall we create the Buffer to store the properties + Schema schema; + _schemaBuffer = gpu::BufferView(new gpu::Buffer(sizeof(Schema), (const gpu::Buffer::Byte*) &schema)); + + +} + +Material::Material(const Material& material) : + _flags(material._flags), + _schemaBuffer(material._schemaBuffer), + _textureMap(material._textureMap) { +} + +Material& Material::operator= (const Material& material) { + _flags = (material._flags); + _schemaBuffer = (material._schemaBuffer); + _textureMap = (material._textureMap); + + return (*this); +} + +Material::~Material() { +} + +void Material::setDiffuse(const Color& diffuse) { + if (glm::any(glm::greaterThan(diffuse, Color(0.0f)))) { + _flags.set(DIFFUSE_BIT); + } else { + _flags.reset(DIFFUSE_BIT); + } + _schemaBuffer.edit()._diffuse = diffuse; +} + +void Material::setSpecular(const Color& specular) { + if (glm::any(glm::greaterThan(specular, Color(0.0f)))) { + _flags.set(SPECULAR_BIT); + } else { + _flags.reset(SPECULAR_BIT); + } + _schemaBuffer.edit()._specular = specular; +} + +void Material::setEmissive(const Color& emissive) { + if (glm::any(glm::greaterThan(emissive, Color(0.0f)))) { + _flags.set(EMISSIVE_BIT); + } else { + _flags.reset(EMISSIVE_BIT); + } + _schemaBuffer.edit()._emissive = emissive; +} + +void Material::setShininess(float shininess) { + if (shininess > 0.0f) { + _flags.set(SHININESS_BIT); + } else { + _flags.reset(SHININESS_BIT); + } + _schemaBuffer.edit()._shininess = shininess; +} + +void Material::setOpacity(float opacity) { + if (opacity >= 1.0f) { + _flags.reset(TRANSPARENT_BIT); + } else { + _flags.set(TRANSPARENT_BIT); + } + _schemaBuffer.edit()._opacity = opacity; +} + +void Material::setTextureView(MapChannel channel, const TextureView& view) { + _flags.set(DIFFUSE_MAP_BIT + channel); + _textureMap[channel] = view; +} \ No newline at end of file diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h new file mode 100755 index 0000000000..ec15522658 --- /dev/null +++ b/libraries/model/src/model/Material.h @@ -0,0 +1,114 @@ +// +// Material.h +// libraries/model/src/model +// +// Created by Sam Gateau on 12/10/2014. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Material_h +#define hifi_model_Material_h + +#include +#include + +#include + +#include "gpu/Resource.h" + +namespace model { +typedef gpu::BufferView UniformBufferView; +typedef gpu::TextureView TextureView; + +class Material { +public: + + typedef glm::vec3 Color; + + enum MapChannel { + DIFFUSE_MAP = 0, + SPECULAR_MAP, + SHININESS_MAP, + EMISSIVE_MAP, + OPACITY_MAP, + NORMAL_MAP, + + NUM_MAPS, + }; + typedef std::map TextureMap; + + enum FlagBit { + DIFFUSE_BIT = 0, + SPECULAR_BIT, + SHININESS_BIT, + EMISSIVE_BIT, + TRANSPARENT_BIT, + + DIFFUSE_MAP_BIT, + SPECULAR_MAP_BIT, + SHININESS_MAP_BIT, + EMISSIVE_MAP_BIT, + OPACITY_MAP_BIT, + NORMAL_MAP_BIT, + + NUM_FLAGS, + }; + typedef std::bitset Flags; + + Material(); + Material(const Material& material); + Material& operator= (const Material& material); + virtual ~Material(); + + const Color& getEmissive() const { return _schemaBuffer.get()._emissive; } + const Color& getDiffuse() const { return _schemaBuffer.get()._diffuse; } + const Color& getSpecular() const { return _schemaBuffer.get()._specular; } + float getShininess() const { return _schemaBuffer.get()._shininess; } + float getOpacity() const { return _schemaBuffer.get()._opacity; } + + void setDiffuse(const Color& diffuse); + void setSpecular(const Color& specular); + void setEmissive(const Color& emissive); + void setShininess(float shininess); + void setOpacity(float opacity); + + // Schema to access the attribute values of the material + class Schema { + public: + + Color _diffuse; + float _opacity; + Color _specular; + float _shininess; + Color _emissive; + float _spare0; + + Schema() : + _diffuse(0.5f), + _opacity(1.0f), + _specular(0.03f), + _shininess(0.1f), + _emissive(0.0f) + {} + }; + + const UniformBufferView& getSchemaBuffer() const { return _schemaBuffer; } + + void setTextureView(MapChannel channel, const TextureView& texture); + const TextureMap& getTextureMap() const { return _textureMap; } + + const Schema* getSchema() const { return &_schemaBuffer.get(); } +protected: + + Flags _flags; + UniformBufferView _schemaBuffer; + TextureMap _textureMap; + +}; +typedef QSharedPointer< Material > MaterialPointer; + +}; + +#endif diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 3b3a63549d..d5c5aac39a 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(Gui Network Script Widgets) include_glm() -link_hifi_libraries(shared octree voxels fbx entities animation audio physics) +link_hifi_libraries(shared octree voxels gpu model fbx entities animation audio physics) # call macro to link our dependencies and bubble them up via a property on our target link_shared_dependencies() diff --git a/libraries/shared/src/AABox.cpp b/libraries/shared/src/AABox.cpp index 00e6db7d33..8823071132 100644 --- a/libraries/shared/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -33,7 +33,7 @@ AABox::AABox(const glm::vec3& corner, const glm::vec3& dimensions) : _corner(corner), _scale(dimensions) { }; -AABox::AABox() : _corner(0.0f, 0.0f, 0.0f), _scale(0.0f, 0.0f, 0.0f) { +AABox::AABox() : _corner(std::numeric_limits::infinity()), _scale(0.0f) { }; glm::vec3 AABox::calcCenter() const { @@ -69,7 +69,7 @@ glm::vec3 AABox::getVertex(BoxVertex vertex) const { return _corner + glm::vec3(0, 0, _scale.z); case TOP_RIGHT_FAR: return _corner + glm::vec3(0, _scale.y, _scale.z); - default: //quiet windows warnings + default: //quiet windows warnings case TOP_LEFT_FAR: return _corner + _scale; } @@ -357,7 +357,7 @@ glm::vec3 AABox::getClosestPointOnFace(const glm::vec3& point, BoxFace face) con return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z), glm::vec3(_corner.x + _scale.z, _corner.y + _scale.y, _corner.z)); - default: //quiet windows warnings + default: //quiet windows warnings case MAX_Z_FACE: return glm::clamp(point, glm::vec3(_corner.x, _corner.y, _corner.z + _scale.z), glm::vec3(_corner.x + _scale.x, _corner.y + _scale.y, _corner.z + _scale.z)); @@ -438,7 +438,7 @@ glm::vec4 AABox::getPlane(BoxFace face) const { case MIN_Y_FACE: return glm::vec4(0.0f, -1.0f, 0.0f, _corner.y); case MAX_Y_FACE: return glm::vec4(0.0f, 1.0f, 0.0f, -_corner.y - _scale.y); case MIN_Z_FACE: return glm::vec4(0.0f, 0.0f, -1.0f, _corner.z); - default: //quiet windows warnings + default: //quiet windows warnings case MAX_Z_FACE: return glm::vec4(0.0f, 0.0f, 1.0f, -_corner.z - _scale.z); } } @@ -450,7 +450,7 @@ BoxFace AABox::getOppositeFace(BoxFace face) { case MIN_Y_FACE: return MAX_Y_FACE; case MAX_Y_FACE: return MIN_Y_FACE; case MIN_Z_FACE: return MAX_Z_FACE; - default: //quiet windows warnings + default: //quiet windows warnings case MAX_Z_FACE: return MIN_Z_FACE; } } @@ -470,3 +470,18 @@ AABox AABox::clamp(float min, float max) const { return AABox(clampedCorner, clampedScale); } + +AABox& AABox::operator += (const glm::vec3& point) { + _corner = glm::min(_corner, point); + _scale = glm::max(_scale, point - _corner); + + return (*this); +} + +AABox& AABox::operator += (const AABox& box) { + if (!box.isInvalid()) { + (*this) += box._corner; + _scale = glm::max(_scale, box.calcTopFarLeft() - _corner); + } + return (*this); +} diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index 010a7523c5..d862957642 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -72,6 +72,11 @@ public: AABox clamp(const glm::vec3& min, const glm::vec3& max) const; AABox clamp(float min, float max) const; + AABox& operator += (const glm::vec3& point); + AABox& operator += (const AABox& box); + + bool isInvalid() const { return _corner == glm::vec3(std::numeric_limits::infinity()); } + private: glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; diff --git a/tests/octree/CMakeLists.txt b/tests/octree/CMakeLists.txt index 7139d4edb6..d4ca79fa1c 100644 --- a/tests/octree/CMakeLists.txt +++ b/tests/octree/CMakeLists.txt @@ -5,6 +5,6 @@ setup_hifi_project(Script Network) include_glm() # link in the shared libraries -link_hifi_libraries(shared octree voxels fbx metavoxels networking entities avatars audio animation script-engine physics) +link_hifi_libraries(shared octree voxels gpu model fbx metavoxels networking entities avatars audio animation script-engine physics) link_shared_dependencies() From 9ab6a680e9fa06c43d8ef2b8773fd443931c3cc8 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 11:03:08 -0800 Subject: [PATCH 46/67] fix typo in cmakelists --- libraries/script-engine/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/script-engine/CMakeLists.txt b/libraries/script-engine/CMakeLists.txt index 84aca5d2bb..c153e093cd 100644 --- a/libraries/script-engine/CMakeLists.txt +++ b/libraries/script-engine/CMakeLists.txt @@ -8,4 +8,5 @@ include_glm() link_hifi_libraries(shared octree voxels gpu model fbx entities animation audio physics metavoxels) # call macro to include our dependency includes and bubble them up via a property on our target -gpu model () +include_dependency_includes() + From 979d50f7d82ebe20a977b51fed63439a96d7ab77 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 11:20:04 -0800 Subject: [PATCH 47/67] fixed pointers which were using 0 instead of NULL and syntax in resource.h --- libraries/gpu/src/gpu/Resource.cpp | 8 ++++---- libraries/gpu/src/gpu/Resource.h | 12 +++--------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/Resource.cpp b/libraries/gpu/src/gpu/Resource.cpp index 085d97184b..f59152550b 100644 --- a/libraries/gpu/src/gpu/Resource.cpp +++ b/libraries/gpu/src/gpu/Resource.cpp @@ -95,7 +95,7 @@ Resource::Sysmem::~Sysmem() { Resource::Size Resource::Sysmem::allocate(Size size) { if (size != _size) { - Byte* newData = 0; + Byte* newData = NULL; Size newSize = 0; if (size > 0) { Size allocated = allocateMemory(&newData, size); @@ -116,7 +116,7 @@ Resource::Size Resource::Sysmem::allocate(Size size) { Resource::Size Resource::Sysmem::resize(Size size) { if (size != _size) { - Byte* newData = 0; + Byte* newData = NULL; Size newSize = 0; if (size > 0) { Size allocated = allocateMemory(&newData, size); @@ -196,11 +196,11 @@ Buffer& Buffer::operator=(const Buffer& buf) { Buffer::~Buffer() { if (_sysmem) { delete _sysmem; - _sysmem = 0; + _sysmem = NULL; } if (_gpuObject) { delete _gpuObject; - _gpuObject = 0; + _gpuObject = NULL; } } diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index ec528c230b..2ec616251c 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -82,10 +82,8 @@ protected: inline const Byte* readData() const { return _data; } inline Byte* editData() { _stamp++; return _data; } - template< typename T > - const T* read() const { return reinterpret_cast< T* > ( _data ); } - template< typename T > - T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); } + template< typename T > const T* read() const { return reinterpret_cast< T* > ( _data ); } + template< typename T > T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); } // Access the current version of the sysmem, used to compare if copies are in sync inline Stamp getStamp() const { return _stamp; } @@ -210,11 +208,7 @@ public: //Template iterator with random access on the buffer sysmem template - class Iterator : public std::iterator + class Iterator : public std::iterator { public: From 1ae682ff21df7f209c5e144d3a2927f6bf1b0047 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 11:36:18 -0800 Subject: [PATCH 48/67] fix end line typo --- libraries/model/src/model/Material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 44e0051386..1ce50174e0 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -89,4 +89,4 @@ void Material::setOpacity(float opacity) { void Material::setTextureView(MapChannel channel, const TextureView& view) { _flags.set(DIFFUSE_MAP_BIT + channel); _textureMap[channel] = view; -} \ No newline at end of file +} From 4ee005affa7436aa1b896cee0109969a8112e4cc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 11:51:54 -0800 Subject: [PATCH 49/67] adding scribe tool --- tools/CMakeLists.txt | 1 + tools/scribe/CMakeLists.txt | 5 + tools/scribe/src/TextTemplate.cpp | 1001 +++++++++++++++++++++++++++++ tools/scribe/src/TextTemplate.h | 205 ++++++ tools/scribe/src/main.cpp | 226 +++++++ 5 files changed, 1438 insertions(+) create mode 100755 tools/scribe/CMakeLists.txt create mode 100755 tools/scribe/src/TextTemplate.cpp create mode 100755 tools/scribe/src/TextTemplate.h create mode 100755 tools/scribe/src/main.cpp diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 32a82627a3..a13933ba5e 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(bitstream2json) add_subdirectory(json2bitstream) add_subdirectory(mtc) +add_subdirectory(scribe) diff --git a/tools/scribe/CMakeLists.txt b/tools/scribe/CMakeLists.txt new file mode 100755 index 0000000000..e67354cffa --- /dev/null +++ b/tools/scribe/CMakeLists.txt @@ -0,0 +1,5 @@ +set(TARGET_NAME scribe) +setup_hifi_project() + +# call macro to include our dependency includes and bubble them up via a property on our target +include_dependency_includes() \ No newline at end of file diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp new file mode 100755 index 0000000000..0199f7249e --- /dev/null +++ b/tools/scribe/src/TextTemplate.cpp @@ -0,0 +1,1001 @@ +// +// TextTemplate.cpp +// tools/shaderScribe/src +// +// Created by Sam Gateau on 12/15/2014. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +#include "TextTemplate.h" + +#include +#include +#include +#include + +typedef TextTemplate::Block::Pointer BlockPointer; +typedef TextTemplate::Config::Pointer ConfigPointer; +typedef TextTemplate::Pointer TextTemplatePointer; + +//----------------------------------------------------------------------------- +TextTemplate::Config::Config() : + _includes(), + _funcs(), + _logStream(&std::cout), + _numErrors(0), + _includerCallback(TextTemplate::loadFile) { + _paths.push_back(""); +} + +const TextTemplatePointer TextTemplate::Config::addInclude(const ConfigPointer& config, const char* include) { + if (!config) { + return TextTemplatePointer(); + } + + TextTemplatePointer included = config->findInclude(include); + if (included) { + return included; + } + + // INcluded doest exist yet so let's try to create it + String includeStream; + if (config->_includerCallback(config, include, includeStream)) { + // ok, then create a new Template on the include file with this as lib + included = TextTemplatePointer(new TextTemplate(include, config)); + + std::stringstream src(includeStream); + + int nbErrors = included->parse(src); + if (nbErrors > 0) { + included->logError(included->_root, "File failed to parse, not included"); + return TextTemplatePointer(); + } + config->_includes.insert(Includes::value_type(include, included)); + return included; + } + + return TextTemplatePointer(); +} + +const TextTemplatePointer TextTemplate::Config::findInclude(const char* include) { + Includes::iterator it = _includes.find(String(include)); + if (it != _includes.end()) { + return (*it).second; + } else { + return TextTemplatePointer(); + } +} + +void TextTemplate::Config::addIncludePath(const char* path) { + _paths.push_back(String(path)); +} + +bool TextTemplate::loadFile(const ConfigPointer& config, const char* filename, String& source) { + String s(filename); + String fullfilename; + for (unsigned int i = 0; i < config->_paths.size(); i++) { + fullfilename = config->_paths[i] + s; + { + std::ifstream ifs; + ifs.open(fullfilename.c_str()); + if (ifs.is_open()) { + std::string str((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + source = str; + ifs.close(); + return (source.length() > 0); + } + } + } + + return false; +} + +//----------------------------------------------------------------------------- + +TextTemplate::Funcs::Funcs() : + _funcs() { +} + +TextTemplate::Funcs::~Funcs() { +} + + +const BlockPointer TextTemplate::Funcs::findFunc(const char* func) { + map::iterator it = _funcs.find(String(func)); + if (it != _funcs.end()) { + return (*it).second; + } else { + return BlockPointer(); + } +} + +const BlockPointer TextTemplate::Funcs::addFunc(const char* func, const BlockPointer& funcBlock) { + BlockPointer included = findFunc(func); + if (! included) { + _funcs.insert(map::value_type(func, funcBlock)); + } + return included; +} + +//----------------------------------------------------------------------------- + +void TextTemplate::Block::addNewBlock(const Pointer& parent, const Pointer& block) { + if (parent) { + parent->blocks.push_back(block); + block->parent = parent; + } +} + +const BlockPointer& TextTemplate::Block::getCurrentBlock(const Pointer& block) { + if ((block) && block->command.isBlockEnd()) { + return block->parent; + } else { + return block; + } +} + +//----------------------------------------------------------------------------- + +void TextTemplate::logError(const Block::Pointer& block, const char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + + char buff[256]; + sprintf(buff, fmt, argp); + + _numErrors++; + log() << block->sourceName << " Error >>" << buff << std::endl; + + int level = 1; + displayTree(std::cerr, level); + +} + +bool TextTemplate::grabUntilBeginTag(std::istream* str, std::string& grabbed, Tag::Type& tagType) { + std::stringstream dst; + while (!str->eof()) { + + std::string datatoken; + getline((*str), datatoken, Tag::BEGIN); + dst << datatoken; + + char next = str->peek(); + if (next == Tag::VAR) { + tagType = Tag::VARIABLE; + grabbed = dst.str(); + str->get(); // skip tag char + return true; + } else if (next == Tag::COM) { + tagType = Tag::COMMAND; + grabbed = dst.str(); + str->get(); // skip tag char + return true; + } else if (next == Tag::REM) { + tagType = Tag::REMARK; + grabbed = dst.str(); + str->get(); // skip tag char + return true; + } else { + if (!str->eof()) { + // false positive, just found the Tag::BEGIN without consequence + dst << Tag::BEGIN; + // keep searching + } else { + // end of the file finishing with no tag + tagType = Tag::INVALID; + grabbed = dst.str(); + return true; + } + } + } + + return false; +} + +bool TextTemplate::grabUntilEndTag(std::istream* str, std::string& grabbed, Tag::Type& tagType) { + std::stringstream dst; + + // preend char depends on tag type + char preend = Tag::COM; + if (tagType == Tag::VARIABLE) { + preend = Tag::VAR; + } else if (tagType == Tag::REMARK) { + preend = Tag::REM; + } + + while (!str->eof()) { + // looking for the end of the tag means find the next preEnd + std::string datatoken; + getline((*str), datatoken, preend); + char end = str->peek(); + + dst << datatoken; + + // and if the next char is Tag::END then that's it + if (end == Tag::END) { + grabbed = dst.str(); + str->get(); // eat the Tag::END + return true; + } else { + // false positive, keep on searching + dst << preend; + } + } + grabbed = dst.str(); + return false; +} + +bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::string& tag, Tag::Type& tagType, Tag::Type& nextTagType) { + if (str->eof()) { + return false; + } + + if (!_steppingStarted) { + _steppingStarted = true; + return grabUntilBeginTag(str, grabbed, nextTagType); + } + + // Read from the last opening Tag::BEGIN captured to the next Tag::END + if (grabUntilEndTag(str, tag, tagType)) { + // skip trailing space and new lines only after Command or Remark tag block + if ((tagType == Tag::COMMAND) || (tagType == Tag::REMARK)) { + while (!str->eof()) { + char c = str->peek(); + if ((c== ' ') || (c=='\t') || (c=='\n')) { + str->get(); + } else { + break; + } + } + } + + grabUntilBeginTag(str, grabbed, nextTagType); + /*if (grabbed.empty()) { + grabbed += ' '; + }*/ + } + + return true; //hasElement; +} + +const BlockPointer TextTemplate::processStep(const BlockPointer& block, std::string& grabbed, std::string& tag, Tag::Type& tagType) { + switch (tagType) { + case Tag::INVALID: + block->ostr << grabbed; + return block; + break; + case Tag::VARIABLE: + return processStepVar(block, grabbed, tag); + break; + case Tag::COMMAND: + return processStepCommand(block, grabbed, tag); + break; + case Tag::REMARK: + return processStepRemark(block, grabbed, tag); + break; + } + + logError(block, "Invalid tag"); + return block; +} + +bool TextTemplate::grabFirstToken(String& src, String& token, String& reminder) { + bool goOn = true; + std::string::size_type i = 0; + while (goOn && (i < src.length())) { + char c = src[i]; + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_') || (c == '.') || (c == '[') || (c == ']')) { + token += c; + } else { + if (!token.empty()) { + reminder = src.substr(i); + return true; + } + } + i++; + } + + return (!token.empty()); +} + +bool TextTemplate::convertExpressionToArguments(String& src, std::vector< String >& arguments) { + std::stringstream str(src); + String token; + + while (!str.eof()) { + str >> token; + if (!str.fail()) { + arguments.push_back(token); + } + } + + return true; +} + +bool TextTemplate::convertExpressionToDefArguments(String& src, std::vector< String >& arguments) { + if (src.empty()) { + return false; + } + + std::stringstream argstr(src); + std::stringstream dest; + bool inVar = false; + while (!argstr.eof()) { + // parse the value of a var, try to find a VAR, so look for the pattern BEGIN,VAR ... VAR,END + String token; + char tag; + if (!inVar) { + getline(argstr, token, Tag::BEGIN); + dest << token; + tag = argstr.peek(); + } else { + getline(argstr, token, Tag::END); + dest << token; + tag = token.back(); + } + + if (tag == Tag::VAR) { + if (!inVar) { + // real var coming: + arguments.push_back(dest.str()); + inVar = true; + } else { + // real var over + arguments.push_back(dest.str()); + inVar = false; + } + } else { + if (argstr.eof()) { + arguments.push_back(dest.str()); + } else { + // put back the tag char stolen + dest << (!inVar ? Tag::BEGIN : Tag::END); + } + } + } + + return true; +} + +bool TextTemplate::convertExpressionToFuncArguments(String& src, std::vector< String >& arguments) { + if (src.empty()) { + return false; + } + std::stringstream str_src(src); + String params; + getline(str_src, params, '('); + getline(str_src, params, ')'); + if (params.empty()) { + return false; + } + + std::stringstream str(params); + String token; + int nbTokens = 0; + while (!str.eof()) { + char c = str.peek(); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_') || (c == '.') || (c == Tag::VAR) || (c == '[') || (c == ']')) { + token += c; + } else if (c == ',') { + if (!token.empty()) { + arguments.push_back(token); + nbTokens++; + } + token.clear(); + } + + str.get(); + } + + if (token.size()) { + arguments.push_back(token); + nbTokens++; + } + + return (nbTokens > 0); +} + +const BlockPointer TextTemplate::processStepVar(const BlockPointer& block, String& grabbed, String& tag) { + // then look at the define + String var = tag; + String varName; + String val; + + if (grabFirstToken(var, varName, val)) { + if (!varName.empty()) { + BlockPointer parent = Block::getCurrentBlock(block); + + // Add a new BLock + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::VAR; + + newBlock->command.arguments.push_back(varName); + + if (!val.empty()) { + convertExpressionToFuncArguments(val, newBlock->command.arguments); + } + + Block::addNewBlock(parent, newBlock); + + // dive in the new block + return newBlock; + } + } + + return block; +} + +const BlockPointer TextTemplate::processStepCommand(const BlockPointer& block, String& grabbed, String& tag) { + // Grab the command name + String command = tag; + String commandName; + + if (grabFirstToken(command, commandName, command)) { + if (commandName.compare("def") == 0) { + return processStepDef(block, grabbed, command); + } else if (commandName.compare("if") == 0) { + return processStepCommandIf(block, grabbed, command); + } else if (commandName.compare("endif") == 0) { + return processStepCommandEndIf(block, grabbed, command); + } else if (commandName.compare("else") == 0) { + return processStepCommandElse(block, grabbed, command); + } else if (commandName.compare("elif") == 0) { + return processStepCommandElif(block, grabbed, command); + } else if (commandName.compare("include") == 0) { + return processStepInclude(block, grabbed, command); + } else if (commandName.compare("func") == 0) { + return processStepFunc(block, grabbed, command); + } else if (commandName.compare("endfunc") == 0) { + return processStepEndFunc(block, grabbed, command); + } + } + + return block; +} + +const BlockPointer TextTemplate::processStepDef(const BlockPointer& block, String& grabbed, String& def) { + // then look at the define + String varName; + String val; + + if (!grabFirstToken(def, varName, val)) { + logError(block, "Invalid Var name in a tag"); + return block; + } + + BlockPointer parent = Block::getCurrentBlock(block); + + // Add a new BLock + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::DEF; + newBlock->command.arguments.push_back(varName); + if (! val.empty()) { + // loose first character which should be a white space + val = val.substr(val.find_first_not_of(' ')); + convertExpressionToDefArguments(val, newBlock->command.arguments); + } + + Block::addNewBlock(parent, newBlock); + + // dive in the new block + return newBlock; +} + + +const BlockPointer TextTemplate::processStepCommandIf(const BlockPointer& block, String& grabbed, String& expression) { + BlockPointer parent = Block::getCurrentBlock(block); + + // Add a new BLock depth + BlockPointer newIfBlock = BlockPointer(new Block(_root->sourceName)); + newIfBlock->command.type = Command::IFBLOCK; + + Block::addNewBlock(parent, newIfBlock); + + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::IF; + convertExpressionToArguments(expression, newBlock->command.arguments); + + Block::addNewBlock(newIfBlock, newBlock); + + // dive in the new If branch + return newBlock; +} + +const BlockPointer TextTemplate::processStepCommandEndIf(const BlockPointer& block, String& grabbed, String& expression) { + BlockPointer parent = Block::getCurrentBlock(block); + + // are we in a if block ? + if ((parent->command.type == Command::IF) + || (parent->command.type == Command::ELIF) + || (parent->command.type == Command::ELSE)) { + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::ENDIF; + newBlock->command.arguments.push_back(expression); + + Block::addNewBlock(parent->parent->parent, newBlock); + + return newBlock; + } else { + logError(block, "Invalid block, not in a block"); + return block; + } + + return block; +} + +const BlockPointer TextTemplate::processStepCommandElse(const BlockPointer& block, String& grabbed, String& expression) { + BlockPointer parent = Block::getCurrentBlock(block); + + // are we in a if block ? + if ((parent->command.type == Command::IF) + || (parent->command.type == Command::ELIF)) { + // All good go back to the IfBlock + parent = parent->parent; + + // Add a new BLock depth + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + newBlock->ostr << grabbed; + newBlock->command.type = Command::ELSE; + newBlock->command.arguments.push_back(expression); + + Block::addNewBlock(parent, newBlock); + + // dive in the new block + return newBlock; + + } else if ((block)->command.type == Command::ELSE) { + logError(block, "Invalid block, in a block but after a block"); + return block; + } else { + logError(block, "Invalid block, not in a block"); + return block; + } +} + +const BlockPointer TextTemplate::processStepCommandElif(const BlockPointer& block, String& grabbed, String& expression) { + BlockPointer parent = Block::getCurrentBlock(block); + + // are we in a if block ? + if ((parent->command.type == Command::IF) + || (parent->command.type == Command::ELIF)) { + // All good go back to the IfBlock + parent = parent->parent; + + // Add a new BLock depth + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::ELIF; + convertExpressionToArguments(expression, newBlock->command.arguments); + + Block::addNewBlock(parent, newBlock); + + // dive in the new block + return newBlock; + + } else if (parent->command.type == Command::ELSE) { + logError(block, "Invalid block, in a block but after a block"); + return block; + } else { + logError(block, "Invalid block, not in a block"); + return block; + } +} + +const BlockPointer TextTemplate::processStepRemark(const BlockPointer& block, String& grabbed, String& tag) { + // nothing to do :) + + // no need to think, let's just add the grabbed text + (block->ostr) << grabbed; + + return block; +} + +const BlockPointer TextTemplate::processStepInclude(const BlockPointer& block, String& grabbed, String& include) { + BlockPointer parent = Block::getCurrentBlock(block); + + // Add a new BLock + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::INCLUDE; + convertExpressionToArguments(include, newBlock->command.arguments); + + Block::addNewBlock(parent, newBlock); + + TextTemplatePointer inc = Config::addInclude(_config, newBlock->command.arguments.front().c_str()); + if (!inc) { + logError(newBlock, "Failed to include %s", newBlock->command.arguments.front().c_str()); + } + + // dive in the new block + return newBlock; +} + +const BlockPointer TextTemplate::processStepFunc(const BlockPointer& block, String& grabbed, String& func) { + // then look at the define + String varName; + String var; + + if (!grabFirstToken(func, varName, var)) { + logError(block, "Invalid func name <%s> in a block", func.c_str()); + return block; + } + + + // DOes the func already exists ? + if (_config->_funcs.findFunc(varName.c_str())) { + logError(block, "Declaring a new func named <%s> already exists", func.c_str()); + return block; + } + + BlockPointer parent = Block::getCurrentBlock(block); + + // Add a new BLock + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::FUNC; + newBlock->command.arguments.push_back(varName); + convertExpressionToFuncArguments(var, newBlock->command.arguments); + + _config->_funcs.addFunc(varName.c_str(), newBlock); + + Block::addNewBlock(parent, newBlock); + + // dive in the new block + return newBlock; +} + +const BlockPointer TextTemplate::processStepEndFunc(const BlockPointer& block, String& grabbed, String& tag) { + BlockPointer parent = Block::getCurrentBlock(block); + + // are we in a func block ? + if (parent->command.type == Command::FUNC) { + // Make sure the FUnc has been declared properly + BlockPointer funcBlock = _config->_funcs.findFunc(parent->command.arguments.front().c_str()); + if (funcBlock != parent) { + logError(block, "Mismatching blocks"); + return BlockPointer(); + } + + // Everything is cool , so let's unplugg the FUnc block from this tree and just put the EndFunc block + + BlockPointer newBlock = BlockPointer(new Block(_root->sourceName)); + (newBlock->ostr) << grabbed; + + newBlock->command.type = Command::ENDFUNC; + convertExpressionToArguments(tag, newBlock->command.arguments); + + newBlock->parent = parent->parent; + + parent->parent->blocks.back() = newBlock; + + parent->parent = 0; + + // dive in the new block + return newBlock; + } else { + logError(block, "Invalid block, not in a block"); + return BlockPointer(); + } + + return block; +} + +//----------------------------------------------------------------------------- + +TextTemplate::TextTemplate(const String& name, const ConfigPointer& externalConfig) : + _config(externalConfig), + _root(new Block(name)), + _numErrors(0), + _steppingStarted(false) { +} + +TextTemplate::~TextTemplate() { +} + +int TextTemplate::scribe(std::ostream& dst, std::istream& src, Vars& vars) { + int nbErrors = parse(src); + + if (nbErrors == 0) { + return generate(dst, vars); + } + return nbErrors; +} + +int TextTemplate::generateTree(std::ostream& dst, const BlockPointer& block, Vars& vars) { + BlockPointer newCurrentBlock; + int numPasses = evalBlockGeneration(dst, block, vars, newCurrentBlock); + for (int passNum= 0; passNum < numPasses; passNum++) { + dst << newCurrentBlock->ostr.str(); + + for (auto child : newCurrentBlock->blocks) { + generateTree(dst, child, vars); + } + } + + return _numErrors; +} + +int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& block, Vars& vars, BlockPointer& branch) { + switch (block->command.type) { + case Command::BLOCK: { + branch = block; + return 1; + } + break; + case Command::VAR: { + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it != vars.end()) { + dst << (*it).second; + } else { + BlockPointer funcBlock = _config->_funcs.findFunc(block->command.arguments.front().c_str()); + if (funcBlock) { + // before diving in the func tree, let's modify the vars with the local defs: + int nbParams = std::min(block->command.arguments.size(), funcBlock->command.arguments.size()); + std::vector< String > paramCache; + paramCache.push_back(""); + String val; + for (int i = 1; i < nbParams; i++) { + val = block->command.arguments[i]; + if ((val[0] == Tag::VAR) && (val[val.length()-1] == Tag::VAR)) { + val = val.substr(1, val.length()-2); + Vars::iterator it = vars.find(val); + if (it != vars.end()) { + val = (*it).second; + } + } + + Vars::iterator it = vars.find(funcBlock->command.arguments[i]); + if (it != vars.end()) { + paramCache.push_back((*it).second); + (*it).second = val; + } else { + vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); + paramCache.push_back(""); + } + } + + generateTree(dst, funcBlock, vars); + + for (int i = 1; i < nbParams; i++) { + vars[ funcBlock->command.arguments[i] ] = paramCache[i]; + } + } + } + branch = block; + return 1; + } + break; + case Command::IFBLOCK: { + // ok, go through the branches and pick the first one that goes + for (auto child: block->blocks) { + int numPasses = evalBlockGeneration(dst, child, vars, branch); + if (numPasses > 0) { + return numPasses; + } + } + } + break; + case Command::IF: + case Command::ELIF: { + if (!block->command.arguments.empty()) { + // Just one argument means check for the var beeing defined + if (block->command.arguments.size() == 1) { + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it != vars.end()) { + branch = block; + return 1; + } + } else if (block->command.arguments.size() == 2) { + if (block->command.arguments[0].compare("not") == 0) { + Vars::iterator it = vars.find(block->command.arguments[1]); + if (it == vars.end()) { + branch = block; + return 1; + } + } + } else if (block->command.arguments.size() == 3) { + if (block->command.arguments[1].compare("and") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) && (itR != vars.end())) { + branch = block; + return 1; + } + } else if (block->command.arguments[1].compare("or") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) || (itR != vars.end())) { + branch = block; + return 1; + } + } else if (block->command.arguments[1].compare("==") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + if (itL != vars.end()) { + if ((*itL).second.compare(block->command.arguments[2]) == 0) { + branch = block; + return 1; + } + } + } + } + + } + return 0; + } + break; + case Command::ELSE: { + branch = block; + return 1; + } + break; + case Command::ENDIF: { + branch = block; + return 1; + } + break; + case Command::DEF: { + if (block->command.arguments.size()) { + // THe actual value of the var defined sneeds to be evaluated: + String val; + for (int t = 1; t < block->command.arguments.size(); t++) { + // detect if a param is a var + int len = block->command.arguments[t].length(); + if ((block->command.arguments[t][0] == Tag::VAR) + && (block->command.arguments[t][len-1] == Tag::VAR)) { + String var = block->command.arguments[t].substr(1, len-2); + Vars::iterator it = vars.find(var); + if (it != vars.end()) { + val += (*it).second; + } + } else { + val += block->command.arguments[t]; + } + } + + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it == vars.end()) { + vars.insert(Vars::value_type(block->command.arguments.front(), val)); + } else { + (*it).second = val; + } + + branch = block; + return 1; + } else { + branch = block; + return 0; + } + } + break; + + case Command::INCLUDE: { + TextTemplatePointer include = _config->findInclude(block->command.arguments.front().c_str()); + if (include && !include->_root->blocks.empty()) { + if (&include->_root) { + generateTree(dst, include->_root, vars); + } + } + + branch = block; + return 1; + } + break; + + case Command::FUNC: { + branch = block; + return 1; + } + break; + + case Command::ENDFUNC: { + branch = block; + return 1; + } + break; + + default: { + } + } + + return 0; +} + + +int TextTemplate::parse(std::istream& src) { + _root->command.type = Command::BLOCK; + BlockPointer currentBlock = _root; + _numErrors = 0; + + // First Parse the input file + int nbLoops = 0; + bool goOn = true; + Tag::Type tagType = Tag::INVALID; + Tag::Type nextTagType = Tag::INVALID; + while (goOn) { + std::string data; + std::string tag; + if (stepForward(&src, data, tag, tagType, nextTagType)) { + currentBlock = processStep(currentBlock, data, tag, tagType); + } else { + goOn = false; + } + + tagType = nextTagType; + nbLoops++; + } + + return _numErrors; +} + +int TextTemplate::generate(std::ostream& dst, Vars& vars) { + return generateTree(dst, _root, vars); +} + +void TextTemplate::displayTree(std::ostream& dst, int& level) const { + Block::displayTree(_root, dst, level); +} + +void TextTemplate::Block::displayTree(const BlockPointer& block, std::ostream& dst, int& level) { + String tab(level * 2, ' '); + + const String BLOCK_TYPE_NAMES[] = { + "VAR", + "BLOCK", + "FUNC", + "ENDFUNC", + "IFBLOCK", + "IF", + "ELIF", + "ELSE", + "ENDIF", + "FOR", + "ENDFOR", + "INCLUDE", + "DEF" + }; + + dst << tab << "{ " << BLOCK_TYPE_NAMES[block->command.type] << ":"; + if (!block->command.arguments.empty()) { + for (auto arg: block->command.arguments) { + dst << " " << arg; + } + } + dst << std::endl; + + level++; + for (auto sub: block->blocks) { + displayTree(sub, dst, level); + } + level--; + + dst << tab << "}" << std::endl; +} + +void TextTemplate::Config::displayTree(std::ostream& dst, int& level) const { + String tab(level * 2, ' '); + + level++; + dst << tab << "Includes:" << std::endl; + for (auto inc: _includes) { + dst << tab << tab << inc.first << std::endl; + inc.second->displayTree(dst, level); + } + dst << tab << "Funcs:" << std::endl; + for (auto func: _funcs._funcs) { + dst << tab << tab << func.first << std::endl; + TextTemplate::Block::displayTree( func.second, dst, level); + } + level--; +} diff --git a/tools/scribe/src/TextTemplate.h b/tools/scribe/src/TextTemplate.h new file mode 100755 index 0000000000..54580aed09 --- /dev/null +++ b/tools/scribe/src/TextTemplate.h @@ -0,0 +1,205 @@ + +// +// TextTemplate.cpp +// tools/shaderScribe/src +// +// Created by Sam Gateau on 12/15/2014. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +#ifndef hifi_TEXT_TEMPLATE_H +#define hifi_TEXT_TEMPLATE_H + +#include +#include +#include +#include +#include +#include +#include + +class TextTemplate { +public: + typedef std::shared_ptr< TextTemplate > Pointer; + typedef std::string String; + typedef std::vector< String > StringVector; + typedef std::map< String, String > Vars; + typedef std::map< String, TextTemplate::Pointer > Includes; + + class Tag { + public: + enum Type { + VARIABLE = 0, + COMMAND, + REMARK, + INVALID = -1, + }; + + static const char BEGIN = '<'; + static const char END = '>'; + + static const char VAR = '$'; + static const char COM = '@'; + static const char REM = '!'; + }; + + class Command { + public: + typedef std::vector< Command > vector; + + enum Type { + VAR = 0, + BLOCK, + FUNC, + ENDFUNC, + IFBLOCK, + IF, + ELIF, + ELSE, + ENDIF, + FOR, + ENDFOR, + INCLUDE, + DEF, + }; + + Type type; + std::vector< String > arguments; + + bool isBlockEnd() { + switch (type) { + case ENDFUNC: + case ENDIF: + case ENDFOR: + case INCLUDE: + case DEF: + case VAR: + return true; + default: + return false; + } + } + }; + + class Block { + public: + typedef std::shared_ptr Pointer; + typedef std::vector< Block::Pointer > Vector; + + Block::Pointer parent; + Command command; + Vector blocks; + std::stringstream ostr; + + String sourceName; + + Block(const String& sourceFilename) : + sourceName(sourceFilename) + {} + + static void addNewBlock(const Block::Pointer& parent, const Block::Pointer& block); + static const Block::Pointer& getCurrentBlock(const Block::Pointer& block); + + static void displayTree(const Block::Pointer& block, std::ostream& dst, int& level); + }; + + class Funcs { + public: + typedef std::map< String, Block::Pointer > map; + + Funcs(); + ~Funcs(); + + const Block::Pointer findFunc(const char* func); + const Block::Pointer addFunc(const char* func, const Block::Pointer& root); + + map _funcs; + protected: + }; + + class Config { + public: + typedef std::shared_ptr< Config > Pointer; + typedef bool (*IncluderCallback) (const Config::Pointer& config, const char* filename, String& source); + + Includes _includes; + Funcs _funcs; + std::ostream* _logStream; + int _numErrors; + IncluderCallback _includerCallback; + StringVector _paths; + + Config(); + + static const TextTemplate::Pointer addInclude(const Config::Pointer& config, const char* include); + const TextTemplate::Pointer findInclude(const char* include); + + void addIncludePath(const char* path); + + void displayTree(std::ostream& dst, int& level) const; + }; + + static bool loadFile(const Config::Pointer& config, const char* filename, String& source); + + TextTemplate(const String& name, const Config::Pointer& config = Config::Pointer(new Config())); + ~TextTemplate(); + + // Scibe does all the job of parsing an inout template stream and then gneerating theresulting stream using the vars + int scribe(std::ostream& dst, std::istream& src, Vars& vars); + + int parse(std::istream& src); + int generate(std::ostream& dst, Vars& vars); + + const Config::Pointer config() { return _config; } + + void displayTree(std::ostream& dst, int& level) const; + +protected: + Config::Pointer _config; + Block::Pointer _root; + int _numErrors; + bool _steppingStarted; + + bool grabUntilBeginTag(std::istream* str, String& grabbed, Tag::Type& tagType); + bool grabUntilEndTag(std::istream* str, String& grabbed, Tag::Type& tagType); + + bool stepForward(std::istream* str, String& grabbed, String& tag, Tag::Type& tagType, Tag::Type& nextTagType); + + bool grabFirstToken(String& src, String& token, String& reminder); + bool convertExpressionToArguments(String& src, std::vector< String >& arguments); + bool convertExpressionToDefArguments(String& src, std::vector< String >& arguments); + bool convertExpressionToFuncArguments(String& src, std::vector< String >& arguments); + + // Filter between var, command or comments + const Block::Pointer processStep(const Block::Pointer& block, String& grabbed, String& tag, Tag::Type& tagType); + const Block::Pointer processStepVar(const Block::Pointer& block, String& grabbed, String& tag); + const Block::Pointer processStepCommand(const Block::Pointer& block, String& grabbed, String& tag); + const Block::Pointer processStepRemark(const Block::Pointer& block, String& grabbed, String& tag); + + // Define command + const Block::Pointer processStepDef(const Block::Pointer& block, String& grabbed, String& tag); + + // If commands + const Block::Pointer processStepCommandIf(const Block::Pointer& block, String& grabbed, String& expression); + const Block::Pointer processStepCommandEndIf(const Block::Pointer& block, String& grabbed, String& expression); + const Block::Pointer processStepCommandElif(const Block::Pointer& block, String& grabbed, String& expression); + const Block::Pointer processStepCommandElse(const Block::Pointer& block, String& grabbed, String& expression); + + // Include command + const Block::Pointer processStepInclude(const Block::Pointer& block, String& grabbed, String& tag); + + // Function command + const Block::Pointer processStepFunc(const Block::Pointer& block, String& grabbed, String& tag); + const Block::Pointer processStepEndFunc(const Block::Pointer& block, String& grabbed, String& tag); + + // Generation + int generateTree(std::ostream& dst, const Block::Pointer& block, Vars& vars); + int evalBlockGeneration(std::ostream& dst, const Block::Pointer& block, Vars& vars, Block::Pointer& branch); + + // Errors + std::ostream& log() { return (* _config->_logStream); } + void logError(const Block::Pointer& block, const char* error, ...); +}; + +#endif \ No newline at end of file diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp new file mode 100755 index 0000000000..89e355de68 --- /dev/null +++ b/tools/scribe/src/main.cpp @@ -0,0 +1,226 @@ +// +// main.cpp +// tools/shaderScribe/src +// +// Created by Sam Gateau on 12/15/2014. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + + +#include "TextTemplate.h" + +#include +#include +#include + +using namespace std; + +int main (int argc, char** argv) { + // process the command line arguments + std::vector< std::string > inputs; + + std::string srcFilename; + std::string destFilename; + std::string targetName; + TextTemplate::Vars vars; + + std::string lastVarName; + bool listVars = false; + bool showParseTree = false; + bool makeCplusplus = false; + + TextTemplate::Config::Pointer config(new TextTemplate::Config()); + + enum Mode { + READY = 0, + GRAB_OUTPUT, + GRAB_VAR_NAME, + GRAB_VAR_VALUE, + GRAB_INCLUDE_PATH, + GRAB_TARGET_NAME, + EXIT, + } mode = READY; + for (int ii = 1; (mode != EXIT) && (ii < argc); ii++) { + inputs.push_back(argv[ii]); + + switch (mode) { + case READY: { + if (inputs.back() == "-o") { + mode = GRAB_OUTPUT; + } else if (inputs.back() == "-tn") { + mode = GRAB_TARGET_NAME; + } else if (inputs.back() == "-D") { + mode = GRAB_VAR_NAME; + } else if (inputs.back() == "-I") { + mode = GRAB_INCLUDE_PATH; + } else if (inputs.back() == "-listvars") { + listVars = true; + mode = READY; + } else if (inputs.back() == "-showParseTree") { + showParseTree = true; + mode = READY; + } else if (inputs.back() == "-c++") { + makeCplusplus = true; + mode = READY; + } else { + // just grabbed the source filename, stop parameter parsing + srcFilename = inputs.back(); + mode = EXIT; + } + } + break; + + case GRAB_OUTPUT: { + destFilename = inputs.back(); + mode = READY; + } + break; + + case GRAB_TARGET_NAME: { + targetName = inputs.back(); + mode = READY; + } + break; + + case GRAB_VAR_NAME: { + // grab first the name of the var + lastVarName = inputs.back(); + mode = GRAB_VAR_VALUE; + } + break; + case GRAB_VAR_VALUE: { + // and then the value + vars.insert(TextTemplate::Vars::value_type(lastVarName, inputs.back())); + + mode = READY; + } + break; + + case GRAB_INCLUDE_PATH: { + config->addIncludePath(inputs.back().c_str()); + mode = READY; + } + break; + + case EXIT: { + // THis shouldn't happen + } + break; + } + } + + if (srcFilename.empty()) { + cerr << "Usage: shaderScribe [OPTION]... inputFilename" << endl; + cerr << "Where options include:" << endl; + cerr << " -o filename: Send output to filename rather than standard output." << endl; + cerr << " -tn targetName: Set the targetName used, if not defined use the output filename 'name' and if not defined use the inputFilename 'name'" << endl; + cerr << " -I include_directory: Declare a directory to be added to the includes search pool." << endl; + cerr << " -D varname varvalue: Declare a var used to generate the output file." << endl; + cerr << " varname and varvalue must be made of alpha numerical characters with no spaces." << endl; + cerr << " -listvars : Will list the vars name and value in the standard output." << endl; + cerr << " -showParseTree : Draw the tree obtained while parsing the source" << endl; + cerr << " -c++ : Generate a c++ header file containing the output file stream stored as a char[] variable" << endl; + return 0; + } + + // Define targetName: if none, get destFilenmae, if none get srcFilename + if (targetName.empty()) { + if (destFilename.empty()) { + targetName = srcFilename; + } else { + targetName = destFilename; + } + } + // no clean it to have just a descent c var name + if (!targetName.empty()) + { + // trim anything before '/' or '\' + targetName = targetName.substr(targetName.find_last_of('/') + 1); + targetName = targetName.substr(targetName.find_last_of('\\') + 1); + + // trim anything after '.' + targetName = targetName.substr(0, targetName.find_first_of('.')); + } + + // Add built in vars + time_t endTime = chrono::system_clock::to_time_t(chrono::system_clock::now()); + std::string endTimStr(ctime(&endTime)); + vars["_SCRIBE_DATE"] = endTimStr.substr(0, endTimStr.length() - 1); + + // List vars? + if (listVars) { + cerr << "Vars:" << endl; + for (auto v : vars) { + cerr << " " << v.first << " = " << v.second << endl; + } + } + + // Open up source + std::fstream srcStream; + srcStream.open(srcFilename, std::fstream::in); + if (!srcStream.is_open()) { + cerr << "Failed to open source file <" << srcFilename << ">" << endl; + return 0; + } + + + TextTemplate::Pointer scribe(new TextTemplate(srcFilename, config)); + + // ready to parse and generate + std::ostringstream destStringStream; + int numErrors = scribe->scribe(destStringStream, srcStream, vars); + if (numErrors) { + cerr << "Scribe " << srcFilename << "> failed: " << numErrors << " errors." << endl; + return 0; + }; + + + if (showParseTree) { + int level = 1; + cerr << "Config trees:" << std::endl; + config->displayTree(cerr, level); + + cerr << srcFilename << " tree:" << std::endl; + scribe->displayTree(cerr, level); + } + + std::ostringstream targetStringStream; + if (makeCplusplus) { + targetStringStream << "// File generated by Scribe " << vars["_SCRIBE_DATE"] << std::endl; + + targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; + targetStringStream << "#define scribe_" << targetName << "_h" << std::endl << std::endl; + + targetStringStream << "const char " << targetName << "[] = {\n\""; + + std::stringstream destStringStreamAgain(destStringStream.str()); + while (!destStringStreamAgain.eof()) { + std::string line; + std::getline(destStringStreamAgain, line); + targetStringStream << line << " \\n\\\n"; + } + targetStringStream << "\"};" << std::endl << std::endl; + + targetStringStream << "#endif" << std::endl; + } else { + targetStringStream << destStringStream.str(); + } + + // Destination stream + if (!destFilename.empty()) { + std::fstream destFileStream; + destFileStream.open(destFilename, std::fstream::out); + if (!destFileStream.is_open()) { + cerr << "Scribe output file " << destFilename << "> failed to open." << endl; + return 0; + } + + destFileStream << targetStringStream.str(); + } else { + cerr << targetStringStream.str(); + } + + return 0; +} From bc836413005e6aa93dd6fcf9491f013f718b7d65 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 14:05:09 -0800 Subject: [PATCH 50/67] add comments to Transform.h --- libraries/shared/src/Transform.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 4adeccb46f..e08f00c0ac 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -63,20 +63,20 @@ public: void setIdentity(); const Vec3& getTranslation() const; - void setTranslation(const Vec3& translation); - void preTranslate(const Vec3& translation); - void postTranslate(const Vec3& translation); + void setTranslation(const Vec3& translation); // [new this] = [translation] * [this.rotation] * [this.scale] + void preTranslate(const Vec3& translation); // [new this] = [translation] * [this] + void postTranslate(const Vec3& translation); // [new this] = [this] * [translation] equivalent to glTranslate const Quat& getRotation() const; - void setRotation(const Quat& rotation); - void preRotate(const Quat& rotation); - void postRotate(const Quat& rotation); + void setRotation(const Quat& rotation); // [new this] = [this.translation] * [rotation] * [this.scale] + void preRotate(const Quat& rotation); // [new this] = [rotation] * [this] + void postRotate(const Quat& rotation); // [new this] = [this] * [rotation] equivalent to glRotate const Vec3& getScale() const; void setScale(float scale); - void setScale(const Vec3& scale); - void postScale(float scale); - void postScale(const Vec3& scale); + void setScale(const Vec3& scale); // [new this] = [this.translation] * [this.rotation] * [scale] + void postScale(float scale); // [new this] = [this] * [scale] equivalent to glScale + void postScale(const Vec3& scale); // [new this] = [this] * [scale] equivalent to glScale bool isIdentity() const { return (_flags & ~Flags(FLAG_CACHE_INVALID_BITSET)).none(); } bool isTranslating() const { return _flags[FLAG_TRANSLATION]; } From 6b88eaceb568dd88705bb01a028bc7eedbf3ff80 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 15:44:46 -0800 Subject: [PATCH 51/67] FIx typos --- libraries/model/src/model/Geometry.h | 3 +-- tools/scribe/src/TextTemplate.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 8f0625ef69..0beaa20a83 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -63,8 +63,7 @@ public: // Access vertex position value const Vec3& getPos3(Index index) const { return _vertexBuffer.get(index); } - enum Topology - { + enum Topology { POINTS = 0, LINES, LINE_STRIP, diff --git a/tools/scribe/src/TextTemplate.h b/tools/scribe/src/TextTemplate.h index 54580aed09..0a61ae454a 100755 --- a/tools/scribe/src/TextTemplate.h +++ b/tools/scribe/src/TextTemplate.h @@ -202,4 +202,4 @@ protected: void logError(const Block::Pointer& block, const char* error, ...); }; -#endif \ No newline at end of file +#endif From e16da55b1b156150b8d245363d5d2afde78ac544 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 22 Dec 2014 16:02:58 -0800 Subject: [PATCH 52/67] cleaning scribe main and checking naming --- tools/scribe/src/main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index 89e355de68..e71b21f32b 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -55,7 +55,7 @@ int main (int argc, char** argv) { mode = GRAB_VAR_NAME; } else if (inputs.back() == "-I") { mode = GRAB_INCLUDE_PATH; - } else if (inputs.back() == "-listvars") { + } else if (inputs.back() == "-listVars") { listVars = true; mode = READY; } else if (inputs.back() == "-showParseTree") { @@ -115,11 +115,11 @@ int main (int argc, char** argv) { cerr << "Usage: shaderScribe [OPTION]... inputFilename" << endl; cerr << "Where options include:" << endl; cerr << " -o filename: Send output to filename rather than standard output." << endl; - cerr << " -tn targetName: Set the targetName used, if not defined use the output filename 'name' and if not defined use the inputFilename 'name'" << endl; + cerr << " -t targetName: Set the targetName used, if not defined use the output filename 'name' and if not defined use the inputFilename 'name'" << endl; cerr << " -I include_directory: Declare a directory to be added to the includes search pool." << endl; cerr << " -D varname varvalue: Declare a var used to generate the output file." << endl; cerr << " varname and varvalue must be made of alpha numerical characters with no spaces." << endl; - cerr << " -listvars : Will list the vars name and value in the standard output." << endl; + cerr << " -listVars : Will list the vars name and value in the standard output." << endl; cerr << " -showParseTree : Draw the tree obtained while parsing the source" << endl; cerr << " -c++ : Generate a c++ header file containing the output file stream stored as a char[] variable" << endl; return 0; From 55370477dbcaa9098c0bb1fbccf01bd4e59da615 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 22 Dec 2014 16:40:19 -0800 Subject: [PATCH 53/67] Remove Application dependency --- interface/src/ui/ModelsBrowser.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp index a39d9b9a19..8c1d90d8b5 100644 --- a/interface/src/ui/ModelsBrowser.cpp +++ b/interface/src/ui/ModelsBrowser.cpp @@ -12,16 +12,19 @@ #include #include #include +#include #include +#include #include +#include +#include +#include #include -#include +#include #include #include -#include "Application.h" - #include "ModelsBrowser.h" const char* MODEL_TYPE_NAMES[] = { "entities", "heads", "skeletons", "attachments" }; From 17ed92cf7ea81c651e531b3cbb867811853a588b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Dec 2014 10:11:08 -0800 Subject: [PATCH 54/67] fix runaway backup bug --- libraries/octree/src/OctreePersistThread.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index c9dcf82099..d9ebea0c2b 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -189,6 +189,9 @@ void OctreePersistThread::backup() { quint64 intervalToBackup = _backupInterval * MSECS_TO_USECS; if (sinceLastBackup > intervalToBackup) { + qDebug() << "Time since last backup [" << sinceLastBackup << "] exceeds backup interval [" + << intervalToBackup << "] doing backup now..."; + struct tm* localTime = localtime(&_lastPersistTime); QString backupFileName; @@ -213,6 +216,8 @@ void OctreePersistThread::backup() { } else { qDebug() << "ERROR in backing up persist file..."; } + + _lastBackup = now; } } } From e105ba61e871b4fb49bacaad3fb022937d906c9f Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Tue, 23 Dec 2014 11:01:25 -0800 Subject: [PATCH 55/67] Fix for model uploading to work Fix for model uploading to work. The deleted elements were causing an error when trying to upload models. --- examples/libraries/modelUploader.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/examples/libraries/modelUploader.js b/examples/libraries/modelUploader.js index d83fc8c16d..7f575a54ef 100644 --- a/examples/libraries/modelUploader.js +++ b/examples/libraries/modelUploader.js @@ -274,19 +274,11 @@ modelUploader = (function () { } } - if (view.string(0, 18) === "Kaydara FBX Binary") { - previousNodeFilename = ""; - - index = 27; - while (index < view.byteLength - 39 && !EOF) { - parseBinaryFBX(); - } - - } else { + readTextFBX(); - } + } function readModel() { From 72cced12a6794e798971c6c138079ea6bf546eed Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 23 Dec 2014 11:30:32 -0800 Subject: [PATCH 56/67] guards for NULL collisions, possible fix to fountain crash --- libraries/entities/src/EntityCollisionSystem.cpp | 7 +++++++ libraries/entities/src/EntityTreeElement.cpp | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityCollisionSystem.cpp b/libraries/entities/src/EntityCollisionSystem.cpp index 7669f73c7d..f0ffbefb46 100644 --- a/libraries/entities/src/EntityCollisionSystem.cpp +++ b/libraries/entities/src/EntityCollisionSystem.cpp @@ -144,6 +144,13 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) { penetration = collision->_penetration; entityB = static_cast(collision->_extraData); + // The collision _extraData should be a valid entity, but if for some reason + // it's NULL then continue with a warning. + if (!entityB) { + qDebug() << "UNEXPECTED - we have a collision with missing _extraData. Something went wrong down below!"; + continue; // skip this loop pass if the entity is NULL + } + // don't collide entities with unknown IDs, if (!entityB->isKnownID()) { continue; // skip this loop pass if the entity has an unknown ID diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 05928990d1..55693b6ff9 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -585,8 +585,12 @@ bool EntityTreeElement::findShapeCollisions(const Shape* shape, CollisionList& c if (shape != otherCollisionShape && !ignoreForCollisions) { if (ShapeCollider::collideShapes(shape, otherCollisionShape, collisions)) { CollisionInfo* lastCollision = collisions.getLastCollision(); - lastCollision->_extraData = entity; - atLeastOneCollision = true; + if (lastCollision) { + lastCollision->_extraData = entity; + atLeastOneCollision = true; + } else { + qDebug() << "UNEXPECTED - ShapeCollider::collideShapes() returned true, but no lastCollision."; + } } } ++entityItr; From 879c3e2fd078c844585e170cb566acd641a5bd47 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Dec 2014 12:30:00 -0800 Subject: [PATCH 57/67] Add entity model upload --- interface/src/Application.cpp | 4 + interface/src/Application.h | 1 + interface/src/Menu.cpp | 10 +- interface/src/Menu.h | 1 + interface/src/ModelUploader.cpp | 182 +++++++++++++++++--------------- interface/src/ModelUploader.h | 2 +- 6 files changed, 109 insertions(+), 91 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bc6c119fe9..67821e5f7f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4202,6 +4202,10 @@ void Application::uploadAttachment() { uploadModel(ATTACHMENT_MODEL); } +void Application::uploadEntity() { + uploadModel(ENTITY_MODEL); +} + void Application::openUrl(const QUrl& url) { if (!url.isEmpty()) { if (url.scheme() == HIFI_URL_SCHEME) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 041e5e6b5b..c08e7359ab 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -374,6 +374,7 @@ public slots: void uploadHead(); void uploadSkeleton(); void uploadAttachment(); + void uploadEntity(); void openUrl(const QUrl& url); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f0c2a687a4..2147dd9220 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -189,10 +189,14 @@ Menu::Menu() : SLOT(toggleAddressBar())); addDisabledActionAndSeparator(fileMenu, "Upload Avatar Model"); - addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, Application::getInstance(), SLOT(uploadHead())); - addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0, Application::getInstance(), SLOT(uploadSkeleton())); + addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadHead, 0, + Application::getInstance(), SLOT(uploadHead())); + addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadSkeleton, 0, + Application::getInstance(), SLOT(uploadSkeleton())); addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadAttachment, 0, - Application::getInstance(), SLOT(uploadAttachment())); + Application::getInstance(), SLOT(uploadAttachment())); + addActionToQMenuAndActionHash(fileMenu, MenuOption::UploadEntity, 0, + Application::getInstance(), SLOT(uploadEntity())); addDisabledActionAndSeparator(fileMenu, "Settings"); addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings())); addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings())); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 77936e7ac4..27e57983af 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -482,6 +482,7 @@ namespace MenuOption { const QString TransmitterDrive = "Transmitter Drive"; const QString TurnWithHead = "Turn using Head"; const QString UploadAttachment = "Upload Attachment Model"; + const QString UploadEntity = "Upload Entity Model"; const QString UploadHead = "Upload Head Model"; const QString UploadSkeleton = "Upload Skeleton Model"; const QString UserInterface = "User Interface"; diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 29d1596809..c400e25246 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -55,8 +55,9 @@ static const QString MODEL_URL = "/api/v1/models"; static const QString SETTING_NAME = "LastModelUploadLocation"; -static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB -static const int MAX_TEXTURE_SIZE = 1024; +static const int BYTES_PER_MEGABYTES = 1024 * 1024; +static const unsigned long MAX_SIZE = 50 * 1024 * BYTES_PER_MEGABYTES; // 50 GB (Virtually remove limit) +static const int MAX_TEXTURE_SIZE = 4096; static const int TIMEOUT = 1000; static const int MAX_CHECK = 30; @@ -590,9 +591,9 @@ bool ModelUploader::addPart(const QFile& file, const QByteArray& contents, const if (_totalSize > MAX_SIZE) { QMessageBox::warning(NULL, QString("ModelUploader::zip()"), - QString("Model too big, over %1 Bytes.").arg(MAX_SIZE), + QString("Model too big, over %1 MB.").arg(MAX_SIZE / BYTES_PER_MEGABYTES), QMessageBox::Ok); - qDebug() << "[Warning] " << QString("Model too big, over %1 Bytes.").arg(MAX_SIZE); + qDebug() << "[Warning] " << QString("Model too big, over %1 MB.").arg(MAX_SIZE / BYTES_PER_MEGABYTES); return false; } qDebug() << "Current model size: " << _totalSize; @@ -613,8 +614,8 @@ ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariant _modelType(modelType), _originalMapping(originalMapping), _basePath(basePath), - _geometry(geometry) { - + _geometry(geometry) +{ setWindowTitle("Set Model Properties"); QFormLayout* form = new QFormLayout(); @@ -629,33 +630,35 @@ ModelPropertiesDialog::ModelPropertiesDialog(ModelType modelType, const QVariant _scale->setMaximum(FLT_MAX); _scale->setSingleStep(0.01); - if (_modelType == ATTACHMENT_MODEL) { - QHBoxLayout* translation = new QHBoxLayout(); - form->addRow("Translation:", translation); - translation->addWidget(_translationX = createTranslationBox()); - translation->addWidget(_translationY = createTranslationBox()); - translation->addWidget(_translationZ = createTranslationBox()); - form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox()); - form->addRow("Pivot Joint:", _pivotJoint = createJointBox()); - connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint())); - _pivotAboutCenter->setChecked(true); - - } else { - form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox()); - form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); - form->addRow("Neck Joint:", _neckJoint = createJointBox()); - } - if (_modelType == SKELETON_MODEL) { - form->addRow("Root Joint:", _rootJoint = createJointBox()); - form->addRow("Lean Joint:", _leanJoint = createJointBox()); - form->addRow("Head Joint:", _headJoint = createJointBox()); - form->addRow("Left Hand Joint:", _leftHandJoint = createJointBox()); - form->addRow("Right Hand Joint:", _rightHandJoint = createJointBox()); - - form->addRow("Free Joints:", _freeJoints = new QVBoxLayout()); - QPushButton* newFreeJoint = new QPushButton("New Free Joint"); - _freeJoints->addWidget(newFreeJoint); - connect(newFreeJoint, SIGNAL(clicked(bool)), SLOT(createNewFreeJoint())); + if (_modelType != ENTITY_MODEL) { + if (_modelType == ATTACHMENT_MODEL) { + QHBoxLayout* translation = new QHBoxLayout(); + form->addRow("Translation:", translation); + translation->addWidget(_translationX = createTranslationBox()); + translation->addWidget(_translationY = createTranslationBox()); + translation->addWidget(_translationZ = createTranslationBox()); + form->addRow("Pivot About Center:", _pivotAboutCenter = new QCheckBox()); + form->addRow("Pivot Joint:", _pivotJoint = createJointBox()); + connect(_pivotAboutCenter, SIGNAL(toggled(bool)), SLOT(updatePivotJoint())); + _pivotAboutCenter->setChecked(true); + + } else { + form->addRow("Left Eye Joint:", _leftEyeJoint = createJointBox()); + form->addRow("Right Eye Joint:", _rightEyeJoint = createJointBox()); + form->addRow("Neck Joint:", _neckJoint = createJointBox()); + } + if (_modelType == SKELETON_MODEL) { + form->addRow("Root Joint:", _rootJoint = createJointBox()); + form->addRow("Lean Joint:", _leanJoint = createJointBox()); + form->addRow("Head Joint:", _headJoint = createJointBox()); + form->addRow("Left Hand Joint:", _leftHandJoint = createJointBox()); + form->addRow("Right Hand Joint:", _rightHandJoint = createJointBox()); + + form->addRow("Free Joints:", _freeJoints = new QVBoxLayout()); + QPushButton* newFreeJoint = new QPushButton("New Free Joint"); + _freeJoints->addWidget(newFreeJoint); + connect(newFreeJoint, SIGNAL(clicked(bool)), SLOT(createNewFreeJoint())); + } } QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | @@ -683,38 +686,40 @@ QVariantHash ModelPropertiesDialog::getMapping() const { } mapping.insert(JOINT_INDEX_FIELD, jointIndices); - QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); - if (_modelType == ATTACHMENT_MODEL) { - glm::vec3 pivot; - if (_pivotAboutCenter->isChecked()) { - pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f; - - } else if (_pivotJoint->currentIndex() != 0) { - pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform); + if (_modelType != ENTITY_MODEL) { + QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); + if (_modelType == ATTACHMENT_MODEL) { + glm::vec3 pivot; + if (_pivotAboutCenter->isChecked()) { + pivot = (_geometry.meshExtents.minimum + _geometry.meshExtents.maximum) * 0.5f; + + } else if (_pivotJoint->currentIndex() != 0) { + pivot = extractTranslation(_geometry.joints.at(_pivotJoint->currentIndex() - 1).transform); + } + mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value()); + mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value()); + mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value()); + + } else { + insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText()); + insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText()); + insertJointMapping(joints, "jointNeck", _neckJoint->currentText()); } - mapping.insert(TRANSLATION_X_FIELD, -pivot.x * _scale->value() + _translationX->value()); - mapping.insert(TRANSLATION_Y_FIELD, -pivot.y * _scale->value() + _translationY->value()); - mapping.insert(TRANSLATION_Z_FIELD, -pivot.z * _scale->value() + _translationZ->value()); - - } else { - insertJointMapping(joints, "jointEyeLeft", _leftEyeJoint->currentText()); - insertJointMapping(joints, "jointEyeRight", _rightEyeJoint->currentText()); - insertJointMapping(joints, "jointNeck", _neckJoint->currentText()); - } - if (_modelType == SKELETON_MODEL) { - insertJointMapping(joints, "jointRoot", _rootJoint->currentText()); - insertJointMapping(joints, "jointLean", _leanJoint->currentText()); - insertJointMapping(joints, "jointHead", _headJoint->currentText()); - insertJointMapping(joints, "jointLeftHand", _leftHandJoint->currentText()); - insertJointMapping(joints, "jointRightHand", _rightHandJoint->currentText()); - - mapping.remove(FREE_JOINT_FIELD); - for (int i = 0; i < _freeJoints->count() - 1; i++) { - QComboBox* box = static_cast(_freeJoints->itemAt(i)->widget()->layout()->itemAt(0)->widget()); - mapping.insertMulti(FREE_JOINT_FIELD, box->currentText()); + if (_modelType == SKELETON_MODEL) { + insertJointMapping(joints, "jointRoot", _rootJoint->currentText()); + insertJointMapping(joints, "jointLean", _leanJoint->currentText()); + insertJointMapping(joints, "jointHead", _headJoint->currentText()); + insertJointMapping(joints, "jointLeftHand", _leftHandJoint->currentText()); + insertJointMapping(joints, "jointRightHand", _rightHandJoint->currentText()); + + mapping.remove(FREE_JOINT_FIELD); + for (int i = 0; i < _freeJoints->count() - 1; i++) { + QComboBox* box = static_cast(_freeJoints->itemAt(i)->widget()->layout()->itemAt(0)->widget()); + mapping.insertMulti(FREE_JOINT_FIELD, box->currentText()); + } } + mapping.insert(JOINT_FIELD, joints); } - mapping.insert(JOINT_FIELD, joints); return mapping; } @@ -729,32 +734,35 @@ void ModelPropertiesDialog::reset() { _scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble()); QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash(); - if (_modelType == ATTACHMENT_MODEL) { - _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble()); - _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble()); - _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble()); - _pivotAboutCenter->setChecked(true); - _pivotJoint->setCurrentIndex(0); - - } else { - setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString()); - setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString()); - setJointText(_neckJoint, jointHash.value("jointNeck").toString()); - } - if (_modelType == SKELETON_MODEL) { - setJointText(_rootJoint, jointHash.value("jointRoot").toString()); - setJointText(_leanJoint, jointHash.value("jointLean").toString()); - setJointText(_headJoint, jointHash.value("jointHead").toString()); - setJointText(_leftHandJoint, jointHash.value("jointLeftHand").toString()); - setJointText(_rightHandJoint, jointHash.value("jointRightHand").toString()); - - while (_freeJoints->count() > 1) { - delete _freeJoints->itemAt(0)->widget(); + + if (_modelType != ENTITY_MODEL) { + if (_modelType == ATTACHMENT_MODEL) { + _translationX->setValue(_originalMapping.value(TRANSLATION_X_FIELD).toDouble()); + _translationY->setValue(_originalMapping.value(TRANSLATION_Y_FIELD).toDouble()); + _translationZ->setValue(_originalMapping.value(TRANSLATION_Z_FIELD).toDouble()); + _pivotAboutCenter->setChecked(true); + _pivotJoint->setCurrentIndex(0); + + } else { + setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString()); + setJointText(_rightEyeJoint, jointHash.value("jointEyeRight").toString()); + setJointText(_neckJoint, jointHash.value("jointNeck").toString()); } - foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) { - QString jointName = joint.toString(); - if (_geometry.jointIndices.contains(jointName)) { - createNewFreeJoint(jointName); + if (_modelType == SKELETON_MODEL) { + setJointText(_rootJoint, jointHash.value("jointRoot").toString()); + setJointText(_leanJoint, jointHash.value("jointLean").toString()); + setJointText(_headJoint, jointHash.value("jointHead").toString()); + setJointText(_leftHandJoint, jointHash.value("jointLeftHand").toString()); + setJointText(_rightHandJoint, jointHash.value("jointRightHand").toString()); + + while (_freeJoints->count() > 1) { + delete _freeJoints->itemAt(0)->widget(); + } + foreach (const QVariant& joint, _originalMapping.values(FREE_JOINT_FIELD)) { + QString jointName = joint.toString(); + if (_geometry.jointIndices.contains(jointName)) { + createNewFreeJoint(jointName); + } } } } diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h index 7d8ad2b526..af347e36bd 100644 --- a/interface/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -53,7 +53,7 @@ private: QSet _textureFilenames; int _lodCount; int _texturesCount; - int _totalSize; + unsigned long _totalSize; ModelType _modelType; bool _readyToSend; From 0a66b23efa2fd66c9f1a9a69b3b70a43b3c3a8bd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 23 Dec 2014 13:33:19 -0800 Subject: [PATCH 58/67] remove current address from address bar dialog --- interface/src/ui/AddressBarDialog.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 75049f9ed4..5f55aa5210 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -116,9 +116,8 @@ void AddressBarDialog::setupUI() { void AddressBarDialog::showEvent(QShowEvent* event) { _goButton->setIcon(QIcon(PathUtils::resourcesPath() + ADDRESSBAR_GO_BUTTON_ICON)); - _addressLineEdit->setText(AddressManager::getInstance().currentAddress().toString()); + _addressLineEdit->setText(QString()); _addressLineEdit->setFocus(); - _addressLineEdit->selectAll(); FramelessDialog::showEvent(event); } From f317b54017cb299479376be8125854c167980dcd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Dec 2014 13:35:01 -0800 Subject: [PATCH 59/67] Broke down ModelUploader::zip() --- interface/src/ModelUploader.cpp | 170 ++++++++++++++++---------------- interface/src/ModelUploader.h | 2 +- 2 files changed, 88 insertions(+), 84 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index c400e25246..687fae4c54 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -149,6 +149,91 @@ bool ModelUploader::zip() { FBXGeometry geometry = readFBX(fbxContents, QVariantHash()); // make sure we have some basic mappings + populateBasicMapping(mapping, filename, geometry); + + // open the dialog to configure the rest + ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry); + if (properties.exec() == QDialog::Rejected) { + return false; + } + mapping = properties.getMapping(); + + QByteArray nameField = mapping.value(NAME_FIELD).toByteArray(); + QString urlBase; + if (!nameField.isEmpty()) { + QHttpPart textPart; + textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"model_name\""); + textPart.setBody(nameField); + _dataMultiPart->append(textPart); + urlBase = S3_URL + "/models/" + MODEL_TYPE_NAMES[_modelType] + "/" + nameField; + _url = urlBase + ".fst"; + + } else { + QMessageBox::warning(NULL, + QString("ModelUploader::zip()"), + QString("Model name is missing in the .fst file."), + QMessageBox::Ok); + qDebug() << "[Warning] " << QString("Model name is missing in the .fst file."); + return false; + } + + QByteArray texdirField = mapping.value(TEXDIR_FIELD).toByteArray(); + QString texDir; + _textureBase = urlBase + "/textures/"; + if (!texdirField.isEmpty()) { + texDir = basePath + "/" + texdirField; + QFileInfo texInfo(texDir); + if (!texInfo.exists() || !texInfo.isDir()) { + QMessageBox::warning(NULL, + QString("ModelUploader::zip()"), + QString("Texture directory could not be found."), + QMessageBox::Ok); + qDebug() << "[Warning] " << QString("Texture directory could not be found."); + return false; + } + } + + QVariantHash lodField = mapping.value(LOD_FIELD).toHash(); + for (QVariantHash::const_iterator it = lodField.constBegin(); it != lodField.constEnd(); it++) { + QFileInfo lod(basePath + "/" + it.key()); + if (!lod.exists() || !lod.isFile()) { // Check existence + QMessageBox::warning(NULL, + QString("ModelUploader::zip()"), + QString("LOD file %1 could not be found.").arg(lod.fileName()), + QMessageBox::Ok); + qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(lod.fileName()); + } + // Compress and copy + if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) { + return false; + } + } + + // Write out, compress and copy the fst + if (!addPart(*fst, writeMapping(mapping), QString("fst"))) { + return false; + } + + // Compress and copy the fbx + if (!addPart(fbx, fbxContents, "fbx")) { + return false; + } + + if (!addTextures(texDir, geometry)) { + return false; + } + + QHttpPart textPart; + textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" + " name=\"model_category\""); + textPart.setBody(MODEL_TYPE_NAMES[_modelType]); + _dataMultiPart->append(textPart); + + _readyToSend = true; + return true; +} + +void ModelUploader::populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry) { if (!mapping.contains(NAME_FIELD)) { mapping.insert(NAME_FIELD, QFileInfo(filename).baseName()); } @@ -163,11 +248,11 @@ bool ModelUploader::zip() { QVariantHash joints = mapping.value(JOINT_FIELD).toHash(); if (!joints.contains("jointEyeLeft")) { joints.insert("jointEyeLeft", geometry.jointIndices.contains("jointEyeLeft") ? "jointEyeLeft" : - (geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye")); + (geometry.jointIndices.contains("EyeLeft") ? "EyeLeft" : "LeftEye")); } if (!joints.contains("jointEyeRight")) { joints.insert("jointEyeRight", geometry.jointIndices.contains("jointEyeRight") ? "jointEyeRight" : - geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye"); + geometry.jointIndices.contains("EyeRight") ? "EyeRight" : "RightEye"); } if (!joints.contains("jointNeck")) { joints.insert("jointNeck", geometry.jointIndices.contains("jointNeck") ? "jointNeck" : "Neck"); @@ -251,87 +336,6 @@ bool ModelUploader::zip() { blendshapes.insertMulti("Sneer", QVariantList() << "Squint_Right" << 0.5); mapping.insert(BLENDSHAPE_FIELD, blendshapes); } - - // open the dialog to configure the rest - ModelPropertiesDialog properties(_modelType, mapping, basePath, geometry); - if (properties.exec() == QDialog::Rejected) { - return false; - } - mapping = properties.getMapping(); - - QByteArray nameField = mapping.value(NAME_FIELD).toByteArray(); - QString urlBase; - if (!nameField.isEmpty()) { - QHttpPart textPart; - textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"model_name\""); - textPart.setBody(nameField); - _dataMultiPart->append(textPart); - urlBase = S3_URL + "/models/" + MODEL_TYPE_NAMES[_modelType] + "/" + nameField; - _url = urlBase + ".fst"; - - } else { - QMessageBox::warning(NULL, - QString("ModelUploader::zip()"), - QString("Model name is missing in the .fst file."), - QMessageBox::Ok); - qDebug() << "[Warning] " << QString("Model name is missing in the .fst file."); - return false; - } - - QByteArray texdirField = mapping.value(TEXDIR_FIELD).toByteArray(); - QString texDir; - _textureBase = urlBase + "/textures/"; - if (!texdirField.isEmpty()) { - texDir = basePath + "/" + texdirField; - QFileInfo texInfo(texDir); - if (!texInfo.exists() || !texInfo.isDir()) { - QMessageBox::warning(NULL, - QString("ModelUploader::zip()"), - QString("Texture directory could not be found."), - QMessageBox::Ok); - qDebug() << "[Warning] " << QString("Texture directory could not be found."); - return false; - } - } - - QVariantHash lodField = mapping.value(LOD_FIELD).toHash(); - for (QVariantHash::const_iterator it = lodField.constBegin(); it != lodField.constEnd(); it++) { - QFileInfo lod(basePath + "/" + it.key()); - if (!lod.exists() || !lod.isFile()) { // Check existence - QMessageBox::warning(NULL, - QString("ModelUploader::zip()"), - QString("LOD file %1 could not be found.").arg(lod.fileName()), - QMessageBox::Ok); - qDebug() << "[Warning] " << QString("FBX file %1 could not be found.").arg(lod.fileName()); - } - // Compress and copy - if (!addPart(lod.filePath(), QString("lod%1").arg(++_lodCount))) { - return false; - } - } - - // Write out, compress and copy the fst - if (!addPart(*fst, writeMapping(mapping), QString("fst"))) { - return false; - } - - // Compress and copy the fbx - if (!addPart(fbx, fbxContents, "fbx")) { - return false; - } - - if (!addTextures(texDir, geometry)) { - return false; - } - - QHttpPart textPart; - textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" - " name=\"model_category\""); - textPart.setBody(MODEL_TYPE_NAMES[_modelType]); - _dataMultiPart->append(textPart); - - _readyToSend = true; - return true; } void ModelUploader::send() { diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h index af347e36bd..7013d33106 100644 --- a/interface/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -65,7 +65,7 @@ private: QDialog* _progressDialog; QProgressBar* _progressBar; - + void populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry); bool zip(); bool addTextures(const QString& texdir, const FBXGeometry& geometry); bool addPart(const QString& path, const QString& name, bool isTexture = false); From da636ca918b65d50eb41c2b45e6cd71924e514e4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Dec 2014 14:00:23 -0800 Subject: [PATCH 60/67] ModelUploader only has static methods accessible --- interface/src/Application.cpp | 18 ++++-------------- interface/src/Application.h | 2 -- interface/src/ModelUploader.cpp | 26 ++++++++++++++++++++++++++ interface/src/ModelUploader.h | 25 +++++++++++++++---------- 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 67821e5f7f..6ddf116acd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3626,16 +3626,6 @@ void Application::setMenuShortcutsEnabled(bool enabled) { setShortcutsEnabled(_window->menuBar(), enabled); } -void Application::uploadModel(ModelType modelType) { - ModelUploader* uploader = new ModelUploader(modelType); - QThread* thread = new QThread(); - thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit())); - thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater())); - uploader->connect(thread, SIGNAL(started()), SLOT(send())); - - thread->start(); -} - void Application::updateWindowTitle(){ QString buildVersion = " (build " + applicationVersion() + ")"; @@ -4191,19 +4181,19 @@ void Application::toggleRunningScriptsWidget() { } void Application::uploadHead() { - uploadModel(HEAD_MODEL); + ModelUploader::uploadHead(); } void Application::uploadSkeleton() { - uploadModel(SKELETON_MODEL); + ModelUploader::uploadSkeleton(); } void Application::uploadAttachment() { - uploadModel(ATTACHMENT_MODEL); + ModelUploader::uploadAttachment(); } void Application::uploadEntity() { - uploadModel(ENTITY_MODEL); + ModelUploader::uploadEntity(); } void Application::openUrl(const QUrl& url) { diff --git a/interface/src/Application.h b/interface/src/Application.h index c08e7359ab..a3c3d51d59 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -460,8 +460,6 @@ private: void setMenuShortcutsEnabled(bool enabled); - void uploadModel(ModelType modelType); - static void attachNewHeadToNode(Node *newNode); static void* networkReceive(void* args); // network receive thread diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 687fae4c54..29d82d3b69 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -64,6 +64,32 @@ static const int MAX_CHECK = 30; static const int QCOMPRESS_HEADER_POSITION = 0; static const int QCOMPRESS_HEADER_SIZE = 4; +void ModelUploader::uploadModel(ModelType modelType) { + ModelUploader* uploader = new ModelUploader(modelType); + QThread* thread = new QThread(); + thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit())); + thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater())); + uploader->connect(thread, SIGNAL(started()), SLOT(send())); + + thread->start(); +} + +void ModelUploader::uploadHead() { + uploadModel(HEAD_MODEL); +} + +void ModelUploader::uploadSkeleton() { + uploadModel(SKELETON_MODEL); +} + +void ModelUploader::uploadAttachment() { + uploadModel(ATTACHMENT_MODEL); +} + +void ModelUploader::uploadEntity() { + uploadModel(ENTITY_MODEL); +} + ModelUploader::ModelUploader(ModelType modelType) : _lodCount(-1), _texturesCount(-1), diff --git a/interface/src/ModelUploader.h b/interface/src/ModelUploader.h index 7013d33106..eafb07c4b0 100644 --- a/interface/src/ModelUploader.h +++ b/interface/src/ModelUploader.h @@ -33,13 +33,15 @@ class ModelUploader : public QObject { Q_OBJECT public: - ModelUploader(ModelType type); - ~ModelUploader(); + static void uploadModel(ModelType modelType); -public slots: - void send(); + static void uploadHead(); + static void uploadSkeleton(); + static void uploadAttachment(); + static void uploadEntity(); private slots: + void send(); void checkJSON(QNetworkReply& requestReply); void uploadUpdate(qint64 bytesSent, qint64 bytesTotal); void uploadSuccess(QNetworkReply& requestReply); @@ -48,6 +50,15 @@ private slots: void processCheck(); private: + ModelUploader(ModelType type); + ~ModelUploader(); + + void populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry); + bool zip(); + bool addTextures(const QString& texdir, const FBXGeometry& geometry); + bool addPart(const QString& path, const QString& name, bool isTexture = false); + bool addPart(const QFile& file, const QByteArray& contents, const QString& name, bool isTexture = false); + QString _url; QString _textureBase; QSet _textureFilenames; @@ -64,12 +75,6 @@ private: QDialog* _progressDialog; QProgressBar* _progressBar; - - void populateBasicMapping(QVariantHash& mapping, QString filename, FBXGeometry geometry); - bool zip(); - bool addTextures(const QString& texdir, const FBXGeometry& geometry); - bool addPart(const QString& path, const QString& name, bool isTexture = false); - bool addPart(const QFile& file, const QByteArray& contents, const QString& name, bool isTexture = false); }; /// A dialog that allows customization of various model properties. From 59387be856f14e072227a69bb3f1e1afc3165ee4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:20:12 -0800 Subject: [PATCH 61/67] Fixing typo and syntax --- tools/scribe/src/TextTemplate.cpp | 67 +++++++++++++------------------ 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index 0199f7249e..e4bc8fcf6d 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -59,9 +59,9 @@ const TextTemplatePointer TextTemplate::Config::addInclude(const ConfigPointer& } const TextTemplatePointer TextTemplate::Config::findInclude(const char* include) { - Includes::iterator it = _includes.find(String(include)); - if (it != _includes.end()) { - return (*it).second; + Includes::iterator includeIt = _includes.find(String(include)); + if (includeIt != _includes.end()) { + return (*includeIt).second; } else { return TextTemplatePointer(); } @@ -76,23 +76,19 @@ bool TextTemplate::loadFile(const ConfigPointer& config, const char* filename, S String fullfilename; for (unsigned int i = 0; i < config->_paths.size(); i++) { fullfilename = config->_paths[i] + s; - { - std::ifstream ifs; - ifs.open(fullfilename.c_str()); - if (ifs.is_open()) { - std::string str((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); - source = str; - ifs.close(); - return (source.length() > 0); - } + std::ifstream ifs; + ifs.open(fullfilename.c_str()); + if (ifs.is_open()) { + std::string str((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + source = str; + ifs.close(); + return (source.length() > 0); } } return false; } -//----------------------------------------------------------------------------- - TextTemplate::Funcs::Funcs() : _funcs() { } @@ -118,8 +114,6 @@ const BlockPointer TextTemplate::Funcs::addFunc(const char* func, const BlockPoi return included; } -//----------------------------------------------------------------------------- - void TextTemplate::Block::addNewBlock(const Pointer& parent, const Pointer& block) { if (parent) { parent->blocks.push_back(block); @@ -128,15 +122,13 @@ void TextTemplate::Block::addNewBlock(const Pointer& parent, const Pointer& bloc } const BlockPointer& TextTemplate::Block::getCurrentBlock(const Pointer& block) { - if ((block) && block->command.isBlockEnd()) { + if (block && block->command.isBlockEnd()) { return block->parent; } else { return block; } } -//----------------------------------------------------------------------------- - void TextTemplate::logError(const Block::Pointer& block, const char* fmt, ...) { va_list argp; va_start(argp, fmt); @@ -196,21 +188,21 @@ bool TextTemplate::grabUntilBeginTag(std::istream* str, std::string& grabbed, Ta bool TextTemplate::grabUntilEndTag(std::istream* str, std::string& grabbed, Tag::Type& tagType) { std::stringstream dst; - // preend char depends on tag type - char preend = Tag::COM; + // preEnd char depends on tag type + char preEnd = Tag::COM; if (tagType == Tag::VARIABLE) { - preend = Tag::VAR; + preEnd = Tag::VAR; } else if (tagType == Tag::REMARK) { - preend = Tag::REM; + preEnd = Tag::REM; } while (!str->eof()) { // looking for the end of the tag means find the next preEnd - std::string datatoken; - getline((*str), datatoken, preend); + std::string dataToken; + getline((*str), dataToken, preEnd); char end = str->peek(); - dst << datatoken; + dst << dataToken; // and if the next char is Tag::END then that's it if (end == Tag::END) { @@ -219,14 +211,15 @@ bool TextTemplate::grabUntilEndTag(std::istream* str, std::string& grabbed, Tag: return true; } else { // false positive, keep on searching - dst << preend; + dst << preEnd; } } grabbed = dst.str(); return false; } -bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::string& tag, Tag::Type& tagType, Tag::Type& nextTagType) { +bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::string& tag, Tag::Type& tagType, + Tag::Type& nextTagType) { if (str->eof()) { return false; } @@ -242,7 +235,7 @@ bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::str if ((tagType == Tag::COMMAND) || (tagType == Tag::REMARK)) { while (!str->eof()) { char c = str->peek(); - if ((c== ' ') || (c=='\t') || (c=='\n')) { + if ((c == ' ') || (c == '\t') || (c == '\n')) { str->get(); } else { break; @@ -251,15 +244,13 @@ bool TextTemplate::stepForward(std::istream* str, std::string& grabbed, std::str } grabUntilBeginTag(str, grabbed, nextTagType); - /*if (grabbed.empty()) { - grabbed += ' '; - }*/ } return true; //hasElement; } -const BlockPointer TextTemplate::processStep(const BlockPointer& block, std::string& grabbed, std::string& tag, Tag::Type& tagType) { +const BlockPointer TextTemplate::processStep(const BlockPointer& block, std::string& grabbed, std::string& tag, + Tag::Type& tagType) { switch (tagType) { case Tag::INVALID: block->ostr << grabbed; @@ -362,10 +353,10 @@ bool TextTemplate::convertExpressionToFuncArguments(String& src, std::vector< St if (src.empty()) { return false; } - std::stringstream str_src(src); + std::stringstream streamSrc(src); String params; - getline(str_src, params, '('); - getline(str_src, params, ')'); + getline(streamSrc, params, '('); + getline(streamSrc, params, ')'); if (params.empty()) { return false; } @@ -474,7 +465,7 @@ const BlockPointer TextTemplate::processStepDef(const BlockPointer& block, Strin newBlock->command.type = Command::DEF; newBlock->command.arguments.push_back(varName); - if (! val.empty()) { + if (!val.empty()) { // loose first character which should be a white space val = val.substr(val.find_first_not_of(' ')); convertExpressionToDefArguments(val, newBlock->command.arguments); @@ -692,8 +683,6 @@ const BlockPointer TextTemplate::processStepEndFunc(const BlockPointer& block, S return block; } -//----------------------------------------------------------------------------- - TextTemplate::TextTemplate(const String& name, const ConfigPointer& externalConfig) : _config(externalConfig), _root(new Block(name)), From 4bdc0d718dda45b0cd31a1e6c7d955bcd164f152 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:29:26 -0800 Subject: [PATCH 62/67] Fixing typo and syntax --- tools/scribe/src/TextTemplate.cpp | 291 +++++++++++++++--------------- 1 file changed, 145 insertions(+), 146 deletions(-) diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index e4bc8fcf6d..6508a9787b 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -72,10 +72,10 @@ void TextTemplate::Config::addIncludePath(const char* path) { } bool TextTemplate::loadFile(const ConfigPointer& config, const char* filename, String& source) { - String s(filename); + String sourceFile(filename); String fullfilename; for (unsigned int i = 0; i < config->_paths.size(); i++) { - fullfilename = config->_paths[i] + s; + fullfilename = config->_paths[i] + sourceFile; std::ifstream ifs; ifs.open(fullfilename.c_str()); if (ifs.is_open()) { @@ -622,7 +622,6 @@ const BlockPointer TextTemplate::processStepFunc(const BlockPointer& block, Stri return block; } - // DOes the func already exists ? if (_config->_funcs.findFunc(varName.c_str())) { logError(block, "Declaring a new func named <%s> already exists", func.c_str()); @@ -719,183 +718,183 @@ int TextTemplate::generateTree(std::ostream& dst, const BlockPointer& block, Var int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& block, Vars& vars, BlockPointer& branch) { switch (block->command.type) { case Command::BLOCK: { - branch = block; - return 1; - } - break; + branch = block; + return 1; + } + break; case Command::VAR: { - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it != vars.end()) { - dst << (*it).second; - } else { - BlockPointer funcBlock = _config->_funcs.findFunc(block->command.arguments.front().c_str()); - if (funcBlock) { - // before diving in the func tree, let's modify the vars with the local defs: - int nbParams = std::min(block->command.arguments.size(), funcBlock->command.arguments.size()); - std::vector< String > paramCache; - paramCache.push_back(""); - String val; - for (int i = 1; i < nbParams; i++) { - val = block->command.arguments[i]; - if ((val[0] == Tag::VAR) && (val[val.length()-1] == Tag::VAR)) { - val = val.substr(1, val.length()-2); - Vars::iterator it = vars.find(val); - if (it != vars.end()) { - val = (*it).second; - } - } - - Vars::iterator it = vars.find(funcBlock->command.arguments[i]); + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it != vars.end()) { + dst << (*it).second; + } else { + BlockPointer funcBlock = _config->_funcs.findFunc(block->command.arguments.front().c_str()); + if (funcBlock) { + // before diving in the func tree, let's modify the vars with the local defs: + int nbParams = std::min(block->command.arguments.size(), funcBlock->command.arguments.size()); + std::vector< String > paramCache; + paramCache.push_back(""); + String val; + for (int i = 1; i < nbParams; i++) { + val = block->command.arguments[i]; + if ((val[0] == Tag::VAR) && (val[val.length()-1] == Tag::VAR)) { + val = val.substr(1, val.length()-2); + Vars::iterator it = vars.find(val); if (it != vars.end()) { - paramCache.push_back((*it).second); - (*it).second = val; - } else { - vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); - paramCache.push_back(""); + val = (*it).second; } } - generateTree(dst, funcBlock, vars); - - for (int i = 1; i < nbParams; i++) { - vars[ funcBlock->command.arguments[i] ] = paramCache[i]; + Vars::iterator it = vars.find(funcBlock->command.arguments[i]); + if (it != vars.end()) { + paramCache.push_back((*it).second); + (*it).second = val; + } else { + vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); + paramCache.push_back(""); } } - } - branch = block; - return 1; - } - break; - case Command::IFBLOCK: { - // ok, go through the branches and pick the first one that goes - for (auto child: block->blocks) { - int numPasses = evalBlockGeneration(dst, child, vars, branch); - if (numPasses > 0) { - return numPasses; + + generateTree(dst, funcBlock, vars); + + for (int i = 1; i < nbParams; i++) { + vars[ funcBlock->command.arguments[i] ] = paramCache[i]; } } } - break; + branch = block; + return 1; + } + break; + case Command::IFBLOCK: { + // ok, go through the branches and pick the first one that goes + for (auto child: block->blocks) { + int numPasses = evalBlockGeneration(dst, child, vars, branch); + if (numPasses > 0) { + return numPasses; + } + } + } + break; case Command::IF: case Command::ELIF: { - if (!block->command.arguments.empty()) { - // Just one argument means check for the var beeing defined - if (block->command.arguments.size() == 1) { - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it != vars.end()) { + if (!block->command.arguments.empty()) { + // Just one argument means check for the var beeing defined + if (block->command.arguments.size() == 1) { + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it != vars.end()) { + branch = block; + return 1; + } + } else if (block->command.arguments.size() == 2) { + if (block->command.arguments[0].compare("not") == 0) { + Vars::iterator it = vars.find(block->command.arguments[1]); + if (it == vars.end()) { branch = block; return 1; } - } else if (block->command.arguments.size() == 2) { - if (block->command.arguments[0].compare("not") == 0) { - Vars::iterator it = vars.find(block->command.arguments[1]); - if (it == vars.end()) { - branch = block; - return 1; - } + } + } else if (block->command.arguments.size() == 3) { + if (block->command.arguments[1].compare("and") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) && (itR != vars.end())) { + branch = block; + return 1; } - } else if (block->command.arguments.size() == 3) { - if (block->command.arguments[1].compare("and") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - Vars::iterator itR = vars.find(block->command.arguments[2]); - if ((itL != vars.end()) && (itR != vars.end())) { + } else if (block->command.arguments[1].compare("or") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) || (itR != vars.end())) { + branch = block; + return 1; + } + } else if (block->command.arguments[1].compare("==") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + if (itL != vars.end()) { + if ((*itL).second.compare(block->command.arguments[2]) == 0) { branch = block; return 1; } - } else if (block->command.arguments[1].compare("or") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - Vars::iterator itR = vars.find(block->command.arguments[2]); - if ((itL != vars.end()) || (itR != vars.end())) { - branch = block; - return 1; - } - } else if (block->command.arguments[1].compare("==") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - if (itL != vars.end()) { - if ((*itL).second.compare(block->command.arguments[2]) == 0) { - branch = block; - return 1; - } - } } } - } + + } + return 0; + } + break; + case Command::ELSE: { + branch = block; + return 1; + } + break; + case Command::ENDIF: { + branch = block; + return 1; + } + break; + case Command::DEF: { + if (block->command.arguments.size()) { + // THe actual value of the var defined sneeds to be evaluated: + String val; + for (int t = 1; t < block->command.arguments.size(); t++) { + // detect if a param is a var + int len = block->command.arguments[t].length(); + if ((block->command.arguments[t][0] == Tag::VAR) + && (block->command.arguments[t][len-1] == Tag::VAR)) { + String var = block->command.arguments[t].substr(1, len-2); + Vars::iterator it = vars.find(var); + if (it != vars.end()) { + val += (*it).second; + } + } else { + val += block->command.arguments[t]; + } + } + + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it == vars.end()) { + vars.insert(Vars::value_type(block->command.arguments.front(), val)); + } else { + (*it).second = val; + } + + branch = block; + return 1; + } else { + branch = block; return 0; } - break; - case Command::ELSE: { - branch = block; - return 1; - } - break; - case Command::ENDIF: { - branch = block; - return 1; - } - break; - case Command::DEF: { - if (block->command.arguments.size()) { - // THe actual value of the var defined sneeds to be evaluated: - String val; - for (int t = 1; t < block->command.arguments.size(); t++) { - // detect if a param is a var - int len = block->command.arguments[t].length(); - if ((block->command.arguments[t][0] == Tag::VAR) - && (block->command.arguments[t][len-1] == Tag::VAR)) { - String var = block->command.arguments[t].substr(1, len-2); - Vars::iterator it = vars.find(var); - if (it != vars.end()) { - val += (*it).second; - } - } else { - val += block->command.arguments[t]; - } - } - - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it == vars.end()) { - vars.insert(Vars::value_type(block->command.arguments.front(), val)); - } else { - (*it).second = val; - } - - branch = block; - return 1; - } else { - branch = block; - return 0; - } - } - break; + } + break; case Command::INCLUDE: { - TextTemplatePointer include = _config->findInclude(block->command.arguments.front().c_str()); - if (include && !include->_root->blocks.empty()) { - if (&include->_root) { - generateTree(dst, include->_root, vars); - } + TextTemplatePointer include = _config->findInclude(block->command.arguments.front().c_str()); + if (include && !include->_root->blocks.empty()) { + if (&include->_root) { + generateTree(dst, include->_root, vars); } - - branch = block; - return 1; } - break; + + branch = block; + return 1; + } + break; case Command::FUNC: { - branch = block; - return 1; - } - break; + branch = block; + return 1; + } + break; case Command::ENDFUNC: { - branch = block; - return 1; - } - break; + branch = block; + return 1; + } + break; default: { - } + } } return 0; From 0578a54ea044c0fa941ce42910c30a9821918931 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:41:05 -0800 Subject: [PATCH 63/67] Fixing typo and syntax --- tools/scribe/src/TextTemplate.cpp | 306 +++++++++++++++--------------- tools/scribe/src/TextTemplate.h | 3 +- 2 files changed, 154 insertions(+), 155 deletions(-) diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index 6508a9787b..7c92fe33fa 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -717,184 +717,184 @@ int TextTemplate::generateTree(std::ostream& dst, const BlockPointer& block, Var int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& block, Vars& vars, BlockPointer& branch) { switch (block->command.type) { - case Command::BLOCK: { - branch = block; - return 1; - } - break; - case Command::VAR: { - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it != vars.end()) { - dst << (*it).second; - } else { - BlockPointer funcBlock = _config->_funcs.findFunc(block->command.arguments.front().c_str()); - if (funcBlock) { - // before diving in the func tree, let's modify the vars with the local defs: - int nbParams = std::min(block->command.arguments.size(), funcBlock->command.arguments.size()); - std::vector< String > paramCache; - paramCache.push_back(""); - String val; - for (int i = 1; i < nbParams; i++) { - val = block->command.arguments[i]; - if ((val[0] == Tag::VAR) && (val[val.length()-1] == Tag::VAR)) { - val = val.substr(1, val.length()-2); - Vars::iterator it = vars.find(val); + case Command::BLOCK: { + branch = block; + return 1; + } + break; + case Command::VAR: { + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it != vars.end()) { + dst << (*it).second; + } else { + BlockPointer funcBlock = _config->_funcs.findFunc(block->command.arguments.front().c_str()); + if (funcBlock) { + // before diving in the func tree, let's modify the vars with the local defs: + int nbParams = std::min(block->command.arguments.size(), funcBlock->command.arguments.size()); + std::vector< String > paramCache; + paramCache.push_back(""); + String val; + for (int i = 1; i < nbParams; i++) { + val = block->command.arguments[i]; + if ((val[0] == Tag::VAR) && (val[val.length()-1] == Tag::VAR)) { + val = val.substr(1, val.length()-2); + Vars::iterator it = vars.find(val); + if (it != vars.end()) { + val = (*it).second; + } + } + + Vars::iterator it = vars.find(funcBlock->command.arguments[i]); if (it != vars.end()) { - val = (*it).second; + paramCache.push_back((*it).second); + (*it).second = val; + } else { + vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); + paramCache.push_back(""); } } - Vars::iterator it = vars.find(funcBlock->command.arguments[i]); + generateTree(dst, funcBlock, vars); + + for (int i = 1; i < nbParams; i++) { + vars[ funcBlock->command.arguments[i] ] = paramCache[i]; + } + } + } + branch = block; + return 1; + } + break; + case Command::IFBLOCK: { + // ok, go through the branches and pick the first one that goes + for (auto child: block->blocks) { + int numPasses = evalBlockGeneration(dst, child, vars, branch); + if (numPasses > 0) { + return numPasses; + } + } + } + break; + case Command::IF: + case Command::ELIF: { + if (!block->command.arguments.empty()) { + // Just one argument means check for the var beeing defined + if (block->command.arguments.size() == 1) { + Vars::iterator it = vars.find(block->command.arguments.front()); if (it != vars.end()) { - paramCache.push_back((*it).second); - (*it).second = val; - } else { - vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); - paramCache.push_back(""); - } - } - - generateTree(dst, funcBlock, vars); - - for (int i = 1; i < nbParams; i++) { - vars[ funcBlock->command.arguments[i] ] = paramCache[i]; - } - } - } - branch = block; - return 1; - } - break; - case Command::IFBLOCK: { - // ok, go through the branches and pick the first one that goes - for (auto child: block->blocks) { - int numPasses = evalBlockGeneration(dst, child, vars, branch); - if (numPasses > 0) { - return numPasses; - } - } - } - break; - case Command::IF: - case Command::ELIF: { - if (!block->command.arguments.empty()) { - // Just one argument means check for the var beeing defined - if (block->command.arguments.size() == 1) { - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it != vars.end()) { - branch = block; - return 1; - } - } else if (block->command.arguments.size() == 2) { - if (block->command.arguments[0].compare("not") == 0) { - Vars::iterator it = vars.find(block->command.arguments[1]); - if (it == vars.end()) { branch = block; return 1; } - } - } else if (block->command.arguments.size() == 3) { - if (block->command.arguments[1].compare("and") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - Vars::iterator itR = vars.find(block->command.arguments[2]); - if ((itL != vars.end()) && (itR != vars.end())) { - branch = block; - return 1; - } - } else if (block->command.arguments[1].compare("or") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - Vars::iterator itR = vars.find(block->command.arguments[2]); - if ((itL != vars.end()) || (itR != vars.end())) { - branch = block; - return 1; - } - } else if (block->command.arguments[1].compare("==") == 0) { - Vars::iterator itL = vars.find(block->command.arguments[0]); - if (itL != vars.end()) { - if ((*itL).second.compare(block->command.arguments[2]) == 0) { + } else if (block->command.arguments.size() == 2) { + if (block->command.arguments[0].compare("not") == 0) { + Vars::iterator it = vars.find(block->command.arguments[1]); + if (it == vars.end()) { branch = block; return 1; } } - } - } - - } - return 0; - } - break; - case Command::ELSE: { - branch = block; - return 1; - } - break; - case Command::ENDIF: { - branch = block; - return 1; - } - break; - case Command::DEF: { - if (block->command.arguments.size()) { - // THe actual value of the var defined sneeds to be evaluated: - String val; - for (int t = 1; t < block->command.arguments.size(); t++) { - // detect if a param is a var - int len = block->command.arguments[t].length(); - if ((block->command.arguments[t][0] == Tag::VAR) - && (block->command.arguments[t][len-1] == Tag::VAR)) { - String var = block->command.arguments[t].substr(1, len-2); - Vars::iterator it = vars.find(var); - if (it != vars.end()) { - val += (*it).second; + } else if (block->command.arguments.size() == 3) { + if (block->command.arguments[1].compare("and") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) && (itR != vars.end())) { + branch = block; + return 1; + } + } else if (block->command.arguments[1].compare("or") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + Vars::iterator itR = vars.find(block->command.arguments[2]); + if ((itL != vars.end()) || (itR != vars.end())) { + branch = block; + return 1; + } + } else if (block->command.arguments[1].compare("==") == 0) { + Vars::iterator itL = vars.find(block->command.arguments[0]); + if (itL != vars.end()) { + if ((*itL).second.compare(block->command.arguments[2]) == 0) { + branch = block; + return 1; + } + } } - } else { - val += block->command.arguments[t]; } - } - Vars::iterator it = vars.find(block->command.arguments.front()); - if (it == vars.end()) { - vars.insert(Vars::value_type(block->command.arguments.front(), val)); + } + return 0; + } + break; + case Command::ELSE: { + branch = block; + return 1; + } + break; + case Command::ENDIF: { + branch = block; + return 1; + } + break; + case Command::DEF: { + if (block->command.arguments.size()) { + // THe actual value of the var defined sneeds to be evaluated: + String val; + for (int t = 1; t < block->command.arguments.size(); t++) { + // detect if a param is a var + int len = block->command.arguments[t].length(); + if ((block->command.arguments[t][0] == Tag::VAR) + && (block->command.arguments[t][len-1] == Tag::VAR)) { + String var = block->command.arguments[t].substr(1, len-2); + Vars::iterator it = vars.find(var); + if (it != vars.end()) { + val += (*it).second; + } + } else { + val += block->command.arguments[t]; + } + } + + Vars::iterator it = vars.find(block->command.arguments.front()); + if (it == vars.end()) { + vars.insert(Vars::value_type(block->command.arguments.front(), val)); + } else { + (*it).second = val; + } + + branch = block; + return 1; } else { - (*it).second = val; + branch = block; + return 0; + } + } + break; + + case Command::INCLUDE: { + TextTemplatePointer include = _config->findInclude(block->command.arguments.front().c_str()); + if (include && !include->_root->blocks.empty()) { + if (&include->_root) { + generateTree(dst, include->_root, vars); + } } branch = block; return 1; - } else { + } + break; + + case Command::FUNC: { branch = block; - return 0; + return 1; } - } - break; + break; - case Command::INCLUDE: { - TextTemplatePointer include = _config->findInclude(block->command.arguments.front().c_str()); - if (include && !include->_root->blocks.empty()) { - if (&include->_root) { - generateTree(dst, include->_root, vars); - } + case Command::ENDFUNC: { + branch = block; + return 1; } + break; - branch = block; - return 1; - } - break; - - case Command::FUNC: { - branch = block; - return 1; - } - break; - - case Command::ENDFUNC: { - branch = block; - return 1; - } - break; - - default: { - } + default: { + } } return 0; diff --git a/tools/scribe/src/TextTemplate.h b/tools/scribe/src/TextTemplate.h index 0a61ae454a..30a17bc1c9 100755 --- a/tools/scribe/src/TextTemplate.h +++ b/tools/scribe/src/TextTemplate.h @@ -95,8 +95,7 @@ public: String sourceName; Block(const String& sourceFilename) : - sourceName(sourceFilename) - {} + sourceName(sourceFilename) {} static void addNewBlock(const Block::Pointer& parent, const Block::Pointer& block); static const Block::Pointer& getCurrentBlock(const Block::Pointer& block); From 522ca55ed8f74ff3a0580e97390a35f272bf0eab Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:41:49 -0800 Subject: [PATCH 64/67] Fixing typo and syntax --- tools/scribe/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index e71b21f32b..e69d927941 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -42,6 +42,7 @@ int main (int argc, char** argv) { GRAB_TARGET_NAME, EXIT, } mode = READY; + for (int ii = 1; (mode != EXIT) && (ii < argc); ii++) { inputs.push_back(argv[ii]); From 4004831377c13f76c2db832a825b57aaeba39f32 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:46:58 -0800 Subject: [PATCH 65/67] Fixing typo and syntax --- tools/scribe/src/main.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index e69d927941..55f23f8c55 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -29,7 +29,7 @@ int main (int argc, char** argv) { std::string lastVarName; bool listVars = false; bool showParseTree = false; - bool makeCplusplus = false; + bool makeCPlusPlus = false; TextTemplate::Config::Pointer config(new TextTemplate::Config()); @@ -63,7 +63,7 @@ int main (int argc, char** argv) { showParseTree = true; mode = READY; } else if (inputs.back() == "-c++") { - makeCplusplus = true; + makeCPlusPlus = true; mode = READY; } else { // just grabbed the source filename, stop parameter parsing @@ -135,8 +135,7 @@ int main (int argc, char** argv) { } } // no clean it to have just a descent c var name - if (!targetName.empty()) - { + if (!targetName.empty()) { // trim anything before '/' or '\' targetName = targetName.substr(targetName.find_last_of('/') + 1); targetName = targetName.substr(targetName.find_last_of('\\') + 1); @@ -166,7 +165,6 @@ int main (int argc, char** argv) { return 0; } - TextTemplate::Pointer scribe(new TextTemplate(srcFilename, config)); // ready to parse and generate @@ -188,7 +186,7 @@ int main (int argc, char** argv) { } std::ostringstream targetStringStream; - if (makeCplusplus) { + if (makeCPlusPlus) { targetStringStream << "// File generated by Scribe " << vars["_SCRIBE_DATE"] << std::endl; targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; From 249e6d02f8aaae95237540efc9c7629029108f8c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 23 Dec 2014 14:49:06 -0800 Subject: [PATCH 66/67] Fixing typo and syntax --- tools/scribe/src/TextTemplate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index 7c92fe33fa..5d10e55e3f 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -841,8 +841,8 @@ int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& blo // detect if a param is a var int len = block->command.arguments[t].length(); if ((block->command.arguments[t][0] == Tag::VAR) - && (block->command.arguments[t][len-1] == Tag::VAR)) { - String var = block->command.arguments[t].substr(1, len-2); + && (block->command.arguments[t][len - 1] == Tag::VAR)) { + String var = block->command.arguments[t].substr(1, len - 2); Vars::iterator it = vars.find(var); if (it != vars.end()) { val += (*it).second; From 2a54ef01ef2b50d4745206cd4f24be2ea41da3f7 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 23 Dec 2014 15:06:22 -0800 Subject: [PATCH 67/67] Set texture limit back to 1024 --- interface/src/ModelUploader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index 29d82d3b69..e702d9db76 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -57,7 +57,7 @@ static const QString SETTING_NAME = "LastModelUploadLocation"; static const int BYTES_PER_MEGABYTES = 1024 * 1024; static const unsigned long MAX_SIZE = 50 * 1024 * BYTES_PER_MEGABYTES; // 50 GB (Virtually remove limit) -static const int MAX_TEXTURE_SIZE = 4096; +static const int MAX_TEXTURE_SIZE = 1024; static const int TIMEOUT = 1000; static const int MAX_CHECK = 30;