diff --git a/BUILD.md b/BUILD.md index d6e1603f37..e1d920b8df 100644 --- a/BUILD.md +++ b/BUILD.md @@ -96,12 +96,13 @@ Currently building on Windows has been tested using the following compilers: #####Windows SDK 7.1 -Whichever version of Visual Studio you use, you will need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). +If using Visual Studio 2010, or using Visual Studio 2013 but building as a Visual Studio 2010 project, you need [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279). NOTE: If using Visual Studio C++ 2010 Express, you need to follow a specific install order. See below before installing the Windows SDK. -######Windows 8.1 -You may have already downloaded the Windows 8 SDK (e.g. if you have previously installed Visual Studio 2013). If so, change CMAKE_PREFIX_PATH in %HIFI_DIR%\CMakeLists.txt to point to the Windows 8 SDK binaries. The default path is `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86` +######Windows SDK 8.1 + +If using Visual Studio 2013 and building as a Visual Studio 2013 project you need the Windows 8 SDK which you should already have as part of installing Visual Studio 2013. You should be able to see it at `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`. #####Visual Studio C++ 2010 Express @@ -123,9 +124,11 @@ Some of the build instructions will ask you to start a Visual Studio Command Pro #####Visual Studio 2013 -This product must be purchased separately. +You can use the Community or Professional editions of Visual Studio 2013. -Visual Studio 2013 doesn't have a shortcut to start a Visual Studio Command Prompt. Instead, start a regular command prompt and then run: +You can start a Visual Studio 2013 command prompt using the shortcut provided in the Visual Studio Tools folder installed as part of Visual Studio 2013. + +Or you can start a regular command prompt and then run: "%VS120COMNTOOLS%\vsvars32.bat" @@ -146,6 +149,8 @@ Once Qt is installed, you need to manually configure the following: * Make sure the Qt runtime DLLs are loadable. You must do this before you attempt to build because some tools for the build depend on Qt. E.g., add to the PATH: `Qt\5.2.0\msvc2010_opengl\bin\`. * Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.2.0\msvc2010_opengl` directory. +If building as a Visual Studio 2013 project, download and configure the msvc2013 version of Qt instead. + ####External Libraries CMake will need to know where the headers and libraries for required external dependencies are. diff --git a/cmake/modules/FindLibOVR.cmake b/cmake/modules/FindLibOVR.cmake index a1d75add3f..6ffb3ed309 100644 --- a/cmake/modules/FindLibOVR.cmake +++ b/cmake/modules/FindLibOVR.cmake @@ -48,8 +48,13 @@ elseif (UNIX) select_library_configurations(XINERAMA) elseif (WIN32) - find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) - find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + if (MSVC10) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2010 HINTS ${LIBOVR_SEARCH_DIRS}) + elseif (MSVC12) + find_library(LIBOVR_LIBRARY_DEBUG NAMES libovrd PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + find_library(LIBOVR_LIBRARY_RELEASE NAMES libovr PATH_SUFFIXES Lib/Win32/VS2013 HINTS ${LIBOVR_SEARCH_DIRS}) + endif () find_package(ATL) endif () diff --git a/examples/html/gridControls.html b/examples/html/gridControls.html index 241fa2406c..d95c9545e4 100644 --- a/examples/html/gridControls.html +++ b/examples/html/gridControls.html @@ -6,7 +6,7 @@ var gridColor = { red: 0, green: 0, blue: 0 }; var gridColors = [ { red: 0, green: 0, blue: 0 }, - { red: 128, green: 128, blue: 128 }, + { red: 255, green: 255, blue: 255 }, { red: 255, green: 0, blue: 0 }, { red: 0, green: 255, blue: 0}, { red: 0, green: 0, blue: 255 }, diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 236cecab18..46715839c3 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -245,10 +245,12 @@ function handleGrabBehavior(deltaTime) { } // Update for joysticks and move button +var THRUST_DEAD_ZONE = 0.1; +var ROTATE_DEAD_ZONE = 0.1; function flyWithHydra(deltaTime) { var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); - if (thrustJoystickPosition.x != 0 || thrustJoystickPosition.y != 0) { + if (Math.abs(thrustJoystickPosition.x) > THRUST_DEAD_ZONE || Math.abs(thrustJoystickPosition.y) > THRUST_DEAD_ZONE) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); } @@ -270,7 +272,7 @@ function flyWithHydra(deltaTime) { // View Controller var viewJoystickPosition = Controller.getJoystickPosition(VIEW_CONTROLLER); - if (viewJoystickPosition.x != 0 || viewJoystickPosition.y != 0) { + if (Math.abs(viewJoystickPosition.x) > ROTATE_DEAD_ZONE || Math.abs(viewJoystickPosition.y) > ROTATE_DEAD_ZONE) { // change the body yaw based on our x controller var orientation = MyAvatar.orientation; diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 813bf015d1..1a43231f6f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -200,6 +200,13 @@ SelectionManager = (function() { return that; })(); +// Normalize degrees to be in the range (-180, 180] +function normalizeDegrees(degrees) { + while (degrees > 180) degrees -= 360; + while (degrees <= -180) degrees += 360; + return degrees; +} + SelectionDisplay = (function () { var that = {}; @@ -207,6 +214,12 @@ SelectionDisplay = (function () { var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075; + // These are multipliers for sizing the rotation degrees display while rotating an entity + var ROTATION_DISPLAY_DISTANCE_MULTIPLIER = 1.2; + var ROTATION_DISPLAY_SIZE_X_MULTIPLIER = 0.5; + var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18; + var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.17; + var showExtendedStretchHandles = false; var spaceMode = SPACE_LOCAL; @@ -306,7 +319,7 @@ SelectionDisplay = (function () { var highlightBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, - color: { red: 180, green: 180, blue: 180}, + color: { red: 90, green: 90, blue: 90}, alpha: 1, solid: false, visible: false, @@ -318,7 +331,7 @@ SelectionDisplay = (function () { var selectionBox = Overlays.addOverlay("cube", { position: { x:0, y: 0, z: 0}, size: 1, - color: { red: 180, green: 180, blue: 180}, + color: { red: 60, green: 60, blue: 60}, alpha: 1, solid: false, visible: false, @@ -326,6 +339,24 @@ SelectionDisplay = (function () { lineWidth: 1.0, }); + var rotationDegreesDisplay = Overlays.addOverlay("text3d", { + position: { x:0, y: 0, z: 0}, + text: "", + color: { red: 0, green: 0, blue: 0}, + backgroundColor: { red: 255, green: 255, blue: 255 }, + alpha: 0.7, + visible: false, + isFacingAvatar: true, + drawInFront: true, + ignoreRayIntersection: true, + dimensions: { x: 0, y: 0 }, + lineHeight: 0.0, + topMargin: 0, + rightMargin: 0, + bottomMargin: 0, + leftMargin: 0, + }); + var grabberMoveUp = Overlays.addOverlay("billboard", { url: HIFI_PUBLIC_BUCKET + "images/up-arrow.png", position: { x:0, y: 0, z: 0}, @@ -585,6 +616,7 @@ SelectionDisplay = (function () { rotateOverlayCurrent, rotateZeroOverlay, rotateCurrentOverlay, + rotationDegreesDisplay, xRailOverlay, yRailOverlay, zRailOverlay, @@ -848,8 +880,8 @@ SelectionDisplay = (function () { } else { yawHandleRotation = Quat.fromVec3Degrees({ x: 270, y: 270, z: 0 }); - rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); pitchHandleRotation = Quat.fromVec3Degrees({ x: 180, y: 270, z: 0 }); + rollHandleRotation = Quat.fromVec3Degrees({ x: 0, y: 0, z: 180 }); yawNormal = { x: 0, y: 1, z: 0 }; rollNormal = { x: 0, y: 0, z: 1 }; @@ -1292,7 +1324,11 @@ SelectionDisplay = (function () { var vec3Mult = function(v1, v2) { return { x: v1.x * v2.x, y: v1.y * v2.y, z: v1.z * v2.z }; } - var makeStretchTool = function(stretchMode, direction, pivot) { + // stretchMode - name of mode + // direction - direction to stretch in + // pivot - point to use as a pivot + // offset - the position of the overlay tool relative to the selections center position + var makeStretchTool = function(stretchMode, direction, pivot, offset) { var signs = { x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0), y: direction.y < 0 ? -1 : (direction.y > 0 ? 1 : 0), @@ -1313,6 +1349,7 @@ SelectionDisplay = (function () { var initialDimensions = null; var initialIntersection = null; var initialProperties = null; + var pickRayPosition = null; var rotation = null; var onBegin = function(event) { @@ -1321,13 +1358,22 @@ SelectionDisplay = (function () { rotation = spaceMode == SPACE_LOCAL ? properties.rotation : Quat.fromPitchYawRollDegrees(0, 0, 0); if (spaceMode == SPACE_LOCAL) { + rotation = SelectionManager.localRotation; initialPosition = SelectionManager.localPosition; initialDimensions = SelectionManager.localDimensions; } else { + rotation = SelectionManager.worldRotation; initialPosition = SelectionManager.worldPosition; initialDimensions = SelectionManager.worldDimensions; } + var scaledOffset = { + x: initialDimensions.x * offset.x * 0.5, + y: initialDimensions.y * offset.y * 0.5, + z: initialDimensions.z * offset.z * 0.5, + }; + pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffset)); + if (numDimensions == 1 && mask.x) { var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 }); start = Vec3.sum(start, properties.position); @@ -1381,7 +1427,7 @@ SelectionDisplay = (function () { planeNormal = Vec3.multiplyQbyV(rotation, planeNormal); var pickRay = Camera.computePickRay(event.x, event.y); lastPick = rayPlaneIntersection(pickRay, - initialPosition, + pickRayPosition, planeNormal); // Overlays.editOverlay(normalLine, { @@ -1416,7 +1462,7 @@ SelectionDisplay = (function () { var pickRay = Camera.computePickRay(event.x, event.y); newPick = rayPlaneIntersection(pickRay, - initialPosition, + pickRayPosition, planeNormal); var vector = Vec3.subtract(newPick, lastPick); @@ -1491,44 +1537,64 @@ SelectionDisplay = (function () { }; }; - function addStretchTool(overlay, mode, pivot, direction) { + function addStretchTool(overlay, mode, pivot, direction, offset) { if (!pivot) { pivot = Vec3.multiply(-1, direction); pivot.y = direction.y; } - var tool = makeStretchTool(mode, direction, pivot); + var tool = makeStretchTool(mode, direction, pivot, offset); addGrabberTool(overlay, tool); } - addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); - addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); - addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); - addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); - addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); - addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); + addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); + addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); + addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); + addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); - addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}); - addStretchTool(grabberRBF, "STRETCH_RBF", null, {x: -1, y: 0, z: -1}); - addStretchTool(grabberLTN, "STRETCH_LTN", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberRTN, "STRETCH_RTN", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberLTF, "STRETCH_LTF", null, {x: 1, y: 0, z: -1}); - addStretchTool(grabberRTF, "STRETCH_RTF", null, {x: -1, y: 0, z: -1}); + addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 }); + addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 }); + addStretchTool(grabberLBF, "STRETCH_LBF", null, {x: 1, y: 0, z: -1}, { x: -1, y: -1, z: 1 }); + addStretchTool(grabberRBF, "STRETCH_RBF", null, {x: -1, y: 0, z: -1}, { x: 1, y: -1, z: 1 }); + addStretchTool(grabberLTN, "STRETCH_LTN", null, {x: 1, y: 0, z: 1}, { x: -1, y: 1, z: -1 }); + addStretchTool(grabberRTN, "STRETCH_RTN", null, {x: -1, y: 0, z: 1}, { x: 1, y: 1, z: -1 }); + addStretchTool(grabberLTF, "STRETCH_LTF", null, {x: 1, y: 0, z: -1}, { x: -1, y: 1, z: 1 }); + addStretchTool(grabberRTF, "STRETCH_RTF", null, {x: -1, y: 0, z: -1}, { x: 1, y: 1, z: 1 }); - addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {x: 1, y: 1, z: 0}); - addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}); - addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}); - addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}); - addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: -1, y: 0, z: 0}); - addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: 1, y: 0, z: 0}); - addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: 0, z: -1}); - addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: 0, z: 1}); - addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}); - addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}); - addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}); - addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}); + addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {x: 1, y: 1, z: 0}, { x: 1, y: 1, z: 0 }); + addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {x: -1, y: 1, z: 0}, { x: -1, y: 1, z: 0 }); + addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {x: 0, y: 1, z: -1}, { x: 0, y: 1, z: -1 }); + addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {x: 0, y: 1, z: 1}, { x: 0, y: 1, z: 1 }); + addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {x: -1, y: 0, z: 0}, { x: 1, y: -1, z: 0 }); + addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {x: 1, y: 0, z: 0}, { x: -1, y: -1, z: 0 }); + addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {x: 0, y: 0, z: -1}, { x: 0, y: -1, z: -1 }); + addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {x: 0, y: 0, z: 1}, { x: 0, y: -1, z: 1 }); + addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {x: -1, y: 0, z: 1}, { x: 1, y: 0, z: -1 }); + addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {x: 1, y: 0, z: 1}, { x: -1, y: 0, z: -1 }); + addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {x: -1, y: 0, z: -1}, { x: 1, y: 0, z: 1 }); + addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {x: 1, y: 0, z: -1}, { x: -1, y: 0, z: 1 }); + + function updateRotationDegreesOverlay(angleFromZero, handleRotation, centerPosition) { + var angle = angleFromZero * (Math.PI / 180); + var position = { + x: Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + y: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER, + z: 0, + }; + position = Vec3.multiplyQbyV(handleRotation, position); + position = Vec3.sum(centerPosition, position); + Overlays.editOverlay(rotationDegreesDisplay, { + position: position, + dimensions: { + x: innerRadius * ROTATION_DISPLAY_SIZE_X_MULTIPLIER, + y: innerRadius * ROTATION_DISPLAY_SIZE_Y_MULTIPLIER + }, + lineHeight: innerRadius * ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER, + text: normalizeDegrees(angleFromZero), + }); + } var initialPosition = SelectionManager.worldPosition; addGrabberTool(yawHandle, { @@ -1570,11 +1636,18 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + }); + + updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1605,12 +1678,9 @@ SelectionDisplay = (function () { 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 snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1632,7 +1702,9 @@ SelectionDisplay = (function () { rotation: Quat.multiply(yawChange, initialProperties.rotation), }); } - + + updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; @@ -1701,11 +1773,18 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + }); + + updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1736,11 +1815,9 @@ SelectionDisplay = (function () { var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } + var snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1764,6 +1841,8 @@ SelectionDisplay = (function () { }); } + updateRotationDegreesOverlay(angleFromZero, pitchHandleRotation, pitchCenter); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; @@ -1831,11 +1910,18 @@ SelectionDisplay = (function () { endAt: 0, innerRadius: 0.9, }); + + Overlays.editOverlay(rotationDegreesDisplay, { + visible: true, + }); + + updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter); }, onEnd: function(event, reason) { Overlays.editOverlay(rotateOverlayInner, { visible: false }); Overlays.editOverlay(rotateOverlayOuter, { visible: false }); Overlays.editOverlay(rotateOverlayCurrent, { visible: false }); + Overlays.editOverlay(rotationDegreesDisplay, { visible: false }); pushCommandForSelections(); }, @@ -1866,11 +1952,9 @@ SelectionDisplay = (function () { var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); - var snapToInner = false; - if (distanceFromCenter < innerRadius) { - angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle; - snapToInner = true; - } + var snapToInner = distanceFromCenter < innerRadius; + var snapAngle = snapToInner ? innerSnapAngle : 1.0; + angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle; // for debugging if (debug) { @@ -1893,6 +1977,8 @@ SelectionDisplay = (function () { }); } + updateRotationDegreesOverlay(angleFromZero, rollHandleRotation, rollCenter); + // update the rotation display accordingly... var startAtCurrent = 0; var endAtCurrent = angleFromZero; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 31b73274fc..9561115478 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1574,7 +1574,9 @@ void Application::setFullscreen(bool fullscreen) { } _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); - _window->show(); + if (!_aboutToQuit) { + _window->show(); + } } void Application::setEnable3DTVMode(bool enable3DTVMode) { @@ -4013,26 +4015,23 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return _scriptEnginesHash[scriptURLString]; } - ScriptEngine* scriptEngine; - if (scriptFilename.isNull()) { - scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); - } else { - // start the script on a new thread... - scriptEngine = new ScriptEngine(scriptUrl, &_controllerScriptingInterface); - - if (!scriptEngine->hasScript()) { - qDebug() << "Application::loadScript(), script failed to load..."; - QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load."); - return NULL; - } - - _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine); - _runningScriptsWidget->setRunningScripts(getRunningScripts()); - UserActivityLogger::getInstance().loadedScript(scriptURLString); - } + ScriptEngine* scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); scriptEngine->setUserLoaded(isUserLoaded); - registerScriptEngineWithApplicationServices(scriptEngine); + if (scriptFilename.isNull()) { + // this had better be the script editor (we should de-couple so somebody who thinks they are loading a script + // doesn't just get an empty script engine) + + // we can complete setup now since there isn't a script we have to load + registerScriptEngineWithApplicationServices(scriptEngine); + } else { + // connect to the appropriate signals of this script engine + connect(scriptEngine, &ScriptEngine::scriptLoaded, this, &Application::handleScriptEngineLoaded); + connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &Application::handleScriptLoadError); + + // get the script engine object to load the script at the designated script URL + scriptEngine->loadURL(scriptUrl); + } // restore the main window's active state if (activateMainWindow && !loadScriptFromEditor) { @@ -4043,6 +4042,22 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser return scriptEngine; } +void Application::handleScriptEngineLoaded(const QUrl& scriptURL) { + ScriptEngine* scriptEngine = qobject_cast(sender()); + + _scriptEnginesHash.insertMulti(scriptURL.toString(), scriptEngine); + _runningScriptsWidget->setRunningScripts(getRunningScripts()); + UserActivityLogger::getInstance().loadedScript(scriptURL.toString()); + + // register our application services and set it off on its own thread + registerScriptEngineWithApplicationServices(scriptEngine); +} + +void Application::handleScriptLoadError(const QUrl& scriptURL) { + qDebug() << "Application::loadScript(), script failed to load..."; + QMessageBox::warning(getWindow(), "Error Loading Script", scriptURL.toString() + " failed to load."); +} + void Application::scriptFinished(const QString& scriptName) { const QString& scriptURLString = QUrl(scriptName).toString(); QHash::iterator it = _scriptEnginesHash.find(scriptURLString); diff --git a/interface/src/Application.h b/interface/src/Application.h index 9f2cdbd520..caaebea876 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -393,6 +393,9 @@ private slots: void timer(); void idle(); void aboutToQuit(); + + void handleScriptEngineLoaded(const QUrl& scriptURL); + void handleScriptLoadError(const QUrl& scriptURL); void connectedToDomain(const QString& hostname); diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index e2517613df..e523d7e608 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -841,6 +841,8 @@ void GeometryReader::run() { grabLightmaps = false; } else if (_url.path().toLower().endsWith("apt8_reboot.fbx")) { lightmapLevel = 4.0f; + } else if (_url.path().toLower().endsWith("palaceoforinthilian4.fbx")) { + lightmapLevel = 3.5f; } fbxgeo = readFBX(_reply->readAll(), _mapping, grabLightmaps, lightmapLevel); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 1307672ad1..305119a019 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -571,8 +571,6 @@ void ApplicationOverlay::renderControllerPointers() { static quint64 pressedTime[NUMBER_OF_MAGNIFIERS] = { 0ULL, 0ULL, 0ULL }; static bool isPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; static bool stateWhenPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool triggerPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; - static bool bumperPressed[NUMBER_OF_MAGNIFIERS] = { false, false, false }; const HandData* handData = Application::getInstance()->getAvatar()->getHandData(); @@ -613,30 +611,6 @@ void ApplicationOverlay::renderControllerPointers() { } } - //Check for UI active toggle - if (palmData->getTrigger() == 1.0f) { - if (!triggerPressed[index]) { - if (bumperPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - triggerPressed[index] = true; - } - } else { - triggerPressed[index] = false; - } - if ((controllerButtons & BUTTON_FWD)) { - if (!bumperPressed[index]) { - if (triggerPressed[index]) { - Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface, - !Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)); - } - bumperPressed[index] = true; - } - } else { - bumperPressed[index] = false; - } - //if we have the oculus, we should make the cursor smaller since it will be //magnified if (OculusManager::isConnected()) { diff --git a/interface/src/ui/ToolWindow.cpp b/interface/src/ui/ToolWindow.cpp index de88d75b3d..da1d2c68f4 100644 --- a/interface/src/ui/ToolWindow.cpp +++ b/interface/src/ui/ToolWindow.cpp @@ -21,6 +21,7 @@ ToolWindow::ToolWindow(QWidget* parent) : _hasShown(false), _lastGeometry() { + setDockOptions(QMainWindow::ForceTabbedDocks); Application::getInstance()->installEventFilter(this); } @@ -99,8 +100,17 @@ void ToolWindow::onChildVisibilityUpdated(bool visible) { } void ToolWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget* dockWidget) { + QList dockWidgets = findChildren(); + QMainWindow::addDockWidget(area, dockWidget); + // We want to force tabbing, so retabify all of our widgets. + QDockWidget* lastDockWidget = dockWidget; + foreach (QDockWidget* nextDockWidget, dockWidgets) { + tabifyDockWidget(lastDockWidget, nextDockWidget); + lastDockWidget = nextDockWidget; + } + connect(dockWidget, &QDockWidget::visibilityChanged, this, &ToolWindow::onChildVisibilityUpdated); } diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e6002d7c10..6cef69d23f 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -100,71 +100,6 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam { } -ScriptEngine::ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface) : - _scriptContents(), - _isFinished(false), - _isRunning(false), - _isInitialized(false), - _isAvatar(false), - _avatarIdentityTimer(NULL), - _avatarBillboardTimer(NULL), - _timerFunctionMap(), - _isListeningToAudioStream(false), - _avatarSound(NULL), - _numAvatarSoundSentBytes(0), - _controllerScriptingInterface(controllerScriptingInterface), - _avatarData(NULL), - _scriptName(), - _fileNameString(), - _quatLibrary(), - _vec3Library(), - _uuidLibrary(), - _animationCache(this), - _isUserLoaded(false), - _arrayBufferClass(new ArrayBufferClass(this)) -{ - QString scriptURLString = scriptURL.toString(); - _fileNameString = scriptURLString; - - QUrl url(scriptURL); - - // if the scheme length is one or lower, maybe they typed in a file, let's try - const int WINDOWS_DRIVE_LETTER_SIZE = 1; - if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { - url = QUrl::fromLocalFile(scriptURLString); - } - - // ok, let's see if it's valid... and if so, load it - if (url.isValid()) { - if (url.scheme() == "file") { - QString fileName = url.toLocalFile(); - QFile scriptFile(fileName); - if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { - qDebug() << "Loading file:" << fileName; - QTextStream in(&scriptFile); - _scriptContents = in.readAll(); - } else { - qDebug() << "ERROR Loading file:" << fileName; - emit errorMessage("ERROR Loading file:" + fileName); - } - } else { - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); - qDebug() << "Downloading script at" << url; - QEventLoop loop; - QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - loop.exec(); - if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { - _scriptContents = reply->readAll(); - } else { - qDebug() << "ERROR Loading file:" << url.toString(); - emit errorMessage("ERROR Loading file:" + url.toString()); - } - } - } -} - void ScriptEngine::setIsAvatar(bool isAvatar) { _isAvatar = isAvatar; @@ -217,6 +152,56 @@ bool ScriptEngine::setScriptContents(const QString& scriptContents, const QStrin return true; } +void ScriptEngine::loadURL(const QUrl& scriptURL) { + if (_isRunning) { + return; + } + + QString scriptURLString = scriptURL.toString(); + _fileNameString = scriptURLString; + + QUrl url(scriptURL); + + // if the scheme length is one or lower, maybe they typed in a file, let's try + const int WINDOWS_DRIVE_LETTER_SIZE = 1; + if (url.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { + url = QUrl::fromLocalFile(scriptURLString); + } + + // ok, let's see if it's valid... and if so, load it + if (url.isValid()) { + if (url.scheme() == "file") { + QString fileName = url.toLocalFile(); + QFile scriptFile(fileName); + if (scriptFile.open(QFile::ReadOnly | QFile::Text)) { + qDebug() << "Loading file:" << fileName; + QTextStream in(&scriptFile); + _scriptContents = in.readAll(); + emit scriptLoaded(url); + } else { + qDebug() << "ERROR Loading file:" << fileName; + emit errorLoadingScript(url); + } + } else { + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url)); + connect(reply, &QNetworkReply::finished, this, &ScriptEngine::handleScriptDownload); + } + } +} + +void ScriptEngine::handleScriptDownload() { + QNetworkReply* reply = qobject_cast(sender()); + + if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 200) { + _scriptContents = reply->readAll(); + emit scriptLoaded(reply->url()); + } else { + qDebug() << "ERROR Loading file:" << reply->url().toString(); + emit errorLoadingScript(reply->url()); + } +} + Q_SCRIPT_DECLARE_QMETAOBJECT(LocalVoxels, QString) void ScriptEngine::init() { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index bb279b8887..4b6b3e48ab 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -40,9 +40,6 @@ const unsigned int SCRIPT_DATA_CALLBACK_USECS = floor(((1.0 / 60.0f) * 1000 * 10 class ScriptEngine : public QScriptEngine { Q_OBJECT public: - ScriptEngine(const QUrl& scriptURL, - AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); - ScriptEngine(const QString& scriptContents = NO_SCRIPT, const QString& fileNameString = QString(""), AbstractControllerScriptingInterface* controllerScriptingInterface = NULL); @@ -94,6 +91,7 @@ public: bool isUserLoaded() const { return _isUserLoaded; } public slots: + void loadURL(const QUrl& scriptURL); void stop(); QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); @@ -109,6 +107,8 @@ public slots: void nodeKilled(SharedNodePointer node); signals: + void scriptLoaded(const QUrl& scriptURL); + void errorLoadingScript(const QUrl& scriptURL); void update(float deltaTime); void scriptEnding(); void finished(const QString& fileNameString); @@ -155,6 +155,8 @@ private: ArrayBufferClass* _arrayBufferClass; QHash _outgoingScriptAudioSequenceNumbers; +private slots: + void handleScriptDownload(); }; #endif // hifi_ScriptEngine_h