Merge branch 'master' into linux-actions-builds

This commit is contained in:
Simon Walton 2019-11-22 18:02:48 -08:00 committed by GitHub
commit 30f3525932
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 173 additions and 134 deletions

View file

@ -72,23 +72,6 @@ env:
#STABLE_BUILD=0 #STABLE_BUILD=0
jobs: jobs:
unlabel:
runs-on: ubuntu-latest
if: github.event.action == 'labeled'
steps:
- name: Install python modules
run: pip install PyGithub
- uses: actions/checkout@v1
with:
submodules: true
fetch-depth: 1
- name: Remove Trigger Labels
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_TOKEN: ${{ secrets.github_ci_token }}
LABEL_PREFIX: rebuild
run: python "$GITHUB_WORKSPACE/tools/ci-scripts/remove-labels.py"
build_client_mac: build_client_mac:
runs-on: macOS-latest runs-on: macOS-latest
if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-mac' || github.event.label.name == 'rebuild' if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-mac' || github.event.label.name == 'rebuild'
@ -113,14 +96,6 @@ jobs:
- name: Build Installer - name: Build Installer
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target package run: cmake --build . --config $BUILD_TYPE --target package
- name: Upload Artifact
working-directory: ${{runner.workspace}}/build
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_TOKEN: ${{ secrets.github_ci_token }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
ARTIFACT_PATTERN: HighFidelity-Beta-Interface-PR${{ github.event.number }}-*.dmg
run: python3 "$GITHUB_WORKSPACE/tools/ci-scripts/upload.py"
build_full_mac: build_full_mac:
runs-on: macOS-latest runs-on: macOS-latest
@ -154,14 +129,6 @@ jobs:
- name: Build Installer - name: Build Installer
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target package run: cmake --build . --config $BUILD_TYPE --target package
- name: Upload Artifact
working-directory: ${{runner.workspace}}/build
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_TOKEN: ${{ secrets.github_ci_token }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
ARTIFACT_PATTERN: HighFidelity-Beta-PR${{ github.event.number }}-*.dmg
run: python3 "$GITHUB_WORKSPACE/tools/ci-scripts/upload.py"
build_client_win32: build_client_win32:
runs-on: windows-latest runs-on: windows-latest
@ -191,15 +158,6 @@ jobs:
shell: bash shell: bash
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target package run: cmake --build . --config $BUILD_TYPE --target package
- name: Upload Artifact
shell: bash
working-directory: ${{runner.workspace}}/build
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_TOKEN: ${{ secrets.github_ci_token }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
ARTIFACT_PATTERN: HighFidelity-Beta-Interface-PR${{ github.event.number }}-*.exe
run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload.py"
build_full_win32: build_full_win32:
runs-on: windows-latest runs-on: windows-latest
@ -237,15 +195,6 @@ jobs:
shell: bash shell: bash
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: cmake --build . --config $BUILD_TYPE --target package run: cmake --build . --config $BUILD_TYPE --target package
- name: Upload Artifact
shell: bash
working-directory: ${{runner.workspace}}/build
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
GITHUB_TOKEN: ${{ secrets.github_ci_token }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.aws_secret_access_key }}
ARTIFACT_PATTERN: HighFidelity-Beta-PR${{ github.event.number }}-*.exe
run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload.py"
build_full_linux: build_full_linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-win' || github.event.label.name == 'rebuild' if: github.event.action != 'labeled' || github.event.label.name == 'rebuild-win' || github.event.label.name == 'rebuild'
@ -280,5 +229,3 @@ jobs:
shell: bash shell: bash
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: docker save -o ${{runner.workspace}}/build/hifi_docker_image.tar $DOCKER_IMAGE_NAME run: docker save -o ${{runner.workspace}}/build/hifi_docker_image.tar $DOCKER_IMAGE_NAME

View file

@ -9,6 +9,8 @@
- [git](https://git-scm.com/downloads): >= 1.6 - [git](https://git-scm.com/downloads): >= 1.6
- [cmake](https://cmake.org/download/): 3.9 - [cmake](https://cmake.org/download/): 3.9
- [Python](https://www.python.org/downloads/): 3.6 or higher - [Python](https://www.python.org/downloads/): 3.6 or higher
- [Node.JS](https://nodejs.org/en/): >= 12.13.1 LTS
- Used to build the Screen Sharing executable.
### CMake External Project Dependencies ### CMake External Project Dependencies

View file

@ -57,9 +57,12 @@ else()
include("${CMAKE_BINARY_DIR}/qt.cmake") include("${CMAKE_BINARY_DIR}/qt.cmake")
endif() endif()
option(VCPKG_APPLOCAL_DEPS OFF)
project(hifi) project(hifi)
include("cmake/init.cmake") include("cmake/init.cmake")
include("cmake/compiler.cmake") include("cmake/compiler.cmake")
option(VCPKG_APPLOCAL_DEPS OFF)
add_paths_to_fixup_libs(${VCPKG_INSTALL_ROOT}/bin) add_paths_to_fixup_libs(${VCPKG_INSTALL_ROOT}/bin)
add_paths_to_fixup_libs(${VCPKG_INSTALL_ROOT}/debug/bin) add_paths_to_fixup_libs(${VCPKG_INSTALL_ROOT}/debug/bin)

View file

@ -2,10 +2,7 @@ High Fidelity (hifi) is an early-stage technology lab experimenting with Virtual
This repository contains the source to many of the components in our This repository contains the source to many of the components in our
alpha-stage virtual world. The project embraces distributed development. alpha-stage virtual world. The project embraces distributed development.
If you'd like to help, we'll pay you -- find out more at [Worklist.net](https://worklist.net). If you find a small bug and have a fix, pull requests are welcome.
If you find a small bug and have a fix, pull requests are welcome. If you'd
like to get paid for your work, make sure you report the bug via a job on
[Worklist.net](https://worklist.net).
We're hiring! We're looking for skilled developers; We're hiring! We're looking for skilled developers;
send your resume to hiring@highfidelity.com send your resume to hiring@highfidelity.com

Binary file not shown.

View file

@ -159,6 +159,9 @@ void AudioClient::checkDevices() {
auto inputDevices = getAvailableDevices(QAudio::AudioInput, hmdInputName); auto inputDevices = getAvailableDevices(QAudio::AudioInput, hmdInputName);
auto outputDevices = getAvailableDevices(QAudio::AudioOutput, hmdOutputName); auto outputDevices = getAvailableDevices(QAudio::AudioOutput, hmdOutputName);
static const QMetaMethod devicesChangedSig= QMetaMethod::fromSignal(&AudioClient::devicesChanged);
//only emit once the scripting interface has connected to the signal
if (isSignalConnected(devicesChangedSig)) {
Lock lock(_deviceMutex); Lock lock(_deviceMutex);
if (inputDevices != _inputDevices) { if (inputDevices != _inputDevices) {
_inputDevices.swap(inputDevices); _inputDevices.swap(inputDevices);
@ -169,6 +172,7 @@ void AudioClient::checkDevices() {
_outputDevices.swap(outputDevices); _outputDevices.swap(outputDevices);
emit devicesChanged(QAudio::AudioOutput, _outputDevices); emit devicesChanged(QAudio::AudioOutput, _outputDevices);
} }
}
} }
HifiAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const { HifiAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {

View file

@ -242,7 +242,10 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) {
QUrl lookupUrl = lookupUrlIn; QUrl lookupUrl = lookupUrlIn;
if (!lookupUrl.host().isEmpty() && !lookupUrl.path().isEmpty()) {
// Assignment clients ping for empty url until assigned. Don't spam.
qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString(); qCDebug(networking) << "Trying to go to URL" << lookupUrl.toString();
}
if (lookupUrl.scheme().isEmpty() && !lookupUrl.path().startsWith("/")) { if (lookupUrl.scheme().isEmpty() && !lookupUrl.path().startsWith("/")) {
// 'urls' without schemes are taken as domain names, as opposed to // 'urls' without schemes are taken as domain names, as opposed to
@ -263,8 +266,8 @@ bool AddressManager::handleUrl(const QUrl& lookupUrlIn, LookupTrigger trigger) {
if (lookupUrl.scheme() == URL_SCHEME_HIFI) { if (lookupUrl.scheme() == URL_SCHEME_HIFI) {
if (lookupUrl.host().isEmpty()) { if (lookupUrl.host().isEmpty()) {
// this was in the form hifi:/somewhere or hifi:somewhere. Fix it by making it hifi://somewhere // this was in the form hifi:/somewhere or hifi:somewhere. Fix it by making it hifi://somewhere
static const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/?", Qt::CaseInsensitive); static const QRegExp HIFI_SCHEME_REGEX = QRegExp(URL_SCHEME_HIFI + ":\\/?($|\\w+)", Qt::CaseInsensitive);
lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_HIFI + "://")); lookupUrl = QUrl(lookupUrl.toString().replace(HIFI_SCHEME_REGEX, URL_SCHEME_HIFI + "://\\1"));
} }
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::LookupAddress); DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::LookupAddress);

View file

@ -981,7 +981,9 @@ bool Model::addToScene(const render::ScenePointer& scene,
render::Transaction& transaction, render::Transaction& transaction,
render::Item::Status::Getters& statusGetters, render::Item::Status::Getters& statusGetters,
BlendShapeOperator modelBlendshapeOperator) { BlendShapeOperator modelBlendshapeOperator) {
if (!_addedToScene && isLoaded()) { if (!_addedToScene && isLoaded()) {
updateGeometry();
updateClusterMatrices(); updateClusterMatrices();
if (_modelMeshRenderItems.empty()) { if (_modelMeshRenderItems.empty()) {
createRenderItemSet(); createRenderItemSet();

View file

@ -12,7 +12,7 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#if defined(Q_OS_WIN) || defined(Q_OS_LINUX) #if defined(Q_OS_WIN)
// Enable event queue debugging // Enable event queue debugging
#define DEBUG_EVENT_QUEUE #define DEBUG_EVENT_QUEUE
#endif #endif

View file

@ -9,11 +9,11 @@
(function() { (function() {
var ZoomStatus = { var ZoomStatus = {
"zoomingIn" : 0, "zoomingIn" : 0, // The camera is moving towards the selected entity
"zoomingOut" : 1, "zoomingOut" : 1, // The camera is moving away from the selected entity
"zoomedIn" : 2, "zoomedIn" : 2, // The camera is locked looking at the selected entity
"zoomedOut" : 4, "zoomedOut" : 4, // The camera is on its initial position and mode
"consumed" : 5 "consumed" : 5 // The zooming loop has been completed
} }
var FocusType = { var FocusType = {
@ -42,32 +42,36 @@
// acceleration until halfway, then deceleration // acceleration until halfway, then deceleration
easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t } easeInOutQuint: function (t) { return t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }
}; };
// Class that manages the zoom effect
var ZoomData = function(type, lookAt, focusNormal, focusDimensions, velocity, maxDuration) { var ZoomData = function(type, lookAt, focusNormal, focusDimensions, velocity, maxDuration) {
var self = this; var self = this;
this.focusType = type; this.focusType = type;
this.lookAt = lookAt; this.lookAt = lookAt; // Look at 3d point in world coordinates
this.focusDimensions = focusDimensions; this.focusDimensions = focusDimensions; // 2d dimensions of the bounding box projection approximation of the selected entity
this.focusNormal = focusNormal; this.focusNormal = focusNormal; // The normal vector provided by the ray intersection used to initialize the zoom
this.velocity = velocity; this.velocity = velocity; // Max velocity of the camera zoom effect
this.maxDuration = maxDuration; this.maxDuration = maxDuration; // Max duration of the camera zoom effect
this.initialPos = Camera.getPosition(); this.initialPos = Camera.getPosition();
this.initialRot = Camera.getOrientation(); this.initialRot = Camera.getOrientation();
this.interpolatedPos = this.initialPos; this.interpolatedPos = this.initialPos;
this.interpolatedRot = this.initialRot; this.interpolatedRot = this.initialRot;
this.initialMode = Camera.mode; this.initialMode = Camera.mode;
this.initialOffset = Vec3.distance(self.initialPos, MyAvatar.getDefaultEyePosition()); this.initialOffset = Vec3.distance(self.initialPos, MyAvatar.getDefaultEyePosition()); // Save the offset distance from the camera to the avatar eyes (boom)
this.finalPos = Vec3.ZERO; this.finalPos = Vec3.ZERO;
this.finalRot = Quat.IDENTITY; this.finalRot = Quat.IDENTITY;
this.direction = Vec3.ZERO; this.direction = Vec3.ZERO; // Direction vector for the camera path
this.distance = Vec3.ZERO; this.distance = Vec3.ZERO; // Total distance that the camera needs to cover to zoom in along the path
this.totalTime = 0.0; this.totalTime = 0.0; // Total time needed to cover the zoom path
this.elapsedTime = 0.0; this.elapsedTime = 0.0;
this.maxZoomInAmount = 0.6;
this.maxZoomOutAmount = 0.2; var MAX_ZOOM_IN_AMOUNT = 0.6; // Maximum percentage of camera proximity to the selected entity from the look at point
var MAX_ZOOM_OUT_AMOUNT = 0.2; // Maximum percentage of camera remoteness to the selected entity from the look at point
this.maxZoomInAmount = MAX_ZOOM_IN_AMOUNT;
this.maxZoomOutAmount = MAX_ZOOM_OUT_AMOUNT;
this.currentZoomAmount = 0.0; this.currentZoomAmount = 0.0;
this.zoomPanOffset = {x: 0.5 * Window.innerWidth, y: 0.5 * Window.innerHeight}; this.zoomPanOffset = {x: 0.5 * Window.innerWidth, y: 0.5 * Window.innerHeight};
@ -76,14 +80,17 @@
this.status = ZoomStatus.zoomedOut; this.status = ZoomStatus.zoomedOut;
var OWN_CAMERA_CHANGE_MAX_FRAMES = 30; var OWN_CAMERA_CHANGE_MAX_FRAMES = 30;
this.ownCameraChangeElapseTime = 0.0; this.ownCameraChangeElapseTime = 0.0; // Variables used to track if the camera mode change is triggered by this script
this.ownCameraChange = false; this.ownCameraChange = false; // or by user input, since the later needs to abort the zoom loop
// Function called when the user release the mouse while panning the camera when using the secondary zoom
this.applyZoomPan = function() { this.applyZoomPan = function() {
self.zoomPanOffset.x += self.zoomPanDelta.x; self.zoomPanOffset.x += self.zoomPanDelta.x;
self.zoomPanOffset.y += self.zoomPanDelta.y; self.zoomPanOffset.y += self.zoomPanDelta.y;
} }
// Function called when the user moves the mouse while panning the camera when using the secondary zoom
this.setZoomPanDelta = function(x, y) { this.setZoomPanDelta = function(x, y) {
self.zoomPanDelta.x = x; self.zoomPanDelta.x = x;
self.zoomPanDelta.y = y; self.zoomPanDelta.y = y;
@ -96,6 +103,7 @@
self.updateSuperPan(totalX, totalY); self.updateSuperPan(totalX, totalY);
} }
// This function computes the correct distance to the selected entity so it ends up fitted on the screen
this.getFocusDistance = function(zoomDims) { this.getFocusDistance = function(zoomDims) {
var objAspect = zoomDims.x / zoomDims.y; var objAspect = zoomDims.x / zoomDims.y;
var camAspect = Camera.frustum.aspectRatio; var camAspect = Camera.frustum.aspectRatio;
@ -110,9 +118,13 @@
return (0.5 * m) / Math.tan(0.5 * fov); return (0.5 * m) / Math.tan(0.5 * fov);
} }
this.finalPos = Vec3.sum(this.lookAt, Vec3.multiply(this.getFocusDistance(this.focusDimensions), this.focusNormal)); // This function computes the final camera position and rotation
this.finalRot = Quat.lookAtSimple(this.finalPos, this.lookAt); this.computeFinalForm = function() {
self.finalPos = Vec3.sum(self.lookAt, Vec3.multiply(self.getFocusDistance(self.focusDimensions), self.focusNormal));
self.finalRot = Quat.lookAtSimple(self.finalPos, self.lookAt);
}
// Function that computes the time and path information for the camera zoom in
this.computeRouteIn = function() { this.computeRouteIn = function() {
var railVector = Vec3.subtract(self.finalPos, self.initialPos); var railVector = Vec3.subtract(self.finalPos, self.initialPos);
self.direction = Vec3.normalize(railVector); self.direction = Vec3.normalize(railVector);
@ -121,6 +133,9 @@
self.totalTime = self.totalTime > self.maxDuration ? self.maxDuration : self.totalTime; self.totalTime = self.totalTime > self.maxDuration ? self.maxDuration : self.totalTime;
} }
// Function that computes the time and path information for the camera zoom out
// Since the camera orientation and position gets reset when changing camera modes,
// the camera path while zooming out is different from the path zooming in.
this.computeRouteOut = function() { this.computeRouteOut = function() {
self.finalPos = Camera.getPosition(); self.finalPos = Camera.getPosition();
var camOffset = Vec3.ZERO; var camOffset = Vec3.ZERO;
@ -137,6 +152,7 @@
self.computeRouteIn(); self.computeRouteIn();
} }
// This function initiate the camera zoom in
this.initZoomIn = function() { this.initZoomIn = function() {
if (self.status === ZoomStatus.zoomedOut) { if (self.status === ZoomStatus.zoomedOut) {
self.computeRouteIn(); self.computeRouteIn();
@ -146,6 +162,7 @@
} }
} }
// This function initiate the camera zoom in
this.initZoomOut = function() { this.initZoomOut = function() {
if (self.status === ZoomStatus.zoomedIn) { if (self.status === ZoomStatus.zoomedIn) {
self.computeRouteOut(); self.computeRouteOut();
@ -155,10 +172,12 @@
} }
} }
// This function checks if the zoom loop needs update
this.needsUpdate = function() { this.needsUpdate = function() {
return self.status === ZoomStatus.zoomingIn || self.status === ZoomStatus.zoomingOut; return self.status === ZoomStatus.zoomingIn || self.status === ZoomStatus.zoomingOut;
} }
// This function connects to the update signal only when zoom in or zoom out is needed
this.updateZoom = function(deltaTime) { this.updateZoom = function(deltaTime) {
if (self.ownCameraChange) { if (self.ownCameraChange) {
self.ownCameraChange = self.ownCameraChangeElapseTime < OWN_CAMERA_CHANGE_MAX_FRAMES * deltaTime; self.ownCameraChange = self.ownCameraChangeElapseTime < OWN_CAMERA_CHANGE_MAX_FRAMES * deltaTime;
@ -194,11 +213,14 @@
} }
} }
// This function recomputes the camera distance to the selected item in order to fit it on the screen
this.resetZoomAspect = function() { this.resetZoomAspect = function() {
self.computeFinalForm();
self.computeRouteIn(); self.computeRouteIn();
Camera.setPosition(self.finalPos); Camera.setPosition(self.finalPos);
} }
// This function updates the secondary zoom distance to the selected entity according to the mouse wheel event
this.updateSuperZoom = function(delta) { this.updateSuperZoom = function(delta) {
var ZOOM_STEP = 0.1; var ZOOM_STEP = 0.1;
self.currentZoomAmount = self.currentZoomAmount + (delta < 0.0 ? -1 : 1) * ZOOM_STEP; self.currentZoomAmount = self.currentZoomAmount + (delta < 0.0 ? -1 : 1) * ZOOM_STEP;
@ -206,6 +228,7 @@
self.updateSuperPan(self.zoomPanOffset.x, self.zoomPanOffset.y); self.updateSuperPan(self.zoomPanOffset.x, self.zoomPanOffset.y);
} }
// This function updates the secondary zoom panning according to the mouse move event
this.updateSuperPan = function(x, y) { this.updateSuperPan = function(x, y) {
var zoomOffset = Vec3.multiply(self.currentZoomAmount, Vec3.subtract(self.lookAt, self.finalPos)); var zoomOffset = Vec3.multiply(self.currentZoomAmount, Vec3.subtract(self.lookAt, self.finalPos));
var xRatio = 0.5 - x / Window.innerWidth; var xRatio = 0.5 - x / Window.innerWidth;
@ -220,28 +243,34 @@
Camera.setPosition(Vec3.sum(self.finalPos, zoomOffset)); Camera.setPosition(Vec3.sum(self.finalPos, zoomOffset));
} }
// This function aborts the zoom loop when the user changes the camera mode
this.abort = function() { this.abort = function() {
self.changeCameraMode(self.initialMode); self.changeCameraMode(self.initialMode);
} }
// This function changes the camera mode
this.changeCameraMode = function(mode) { this.changeCameraMode = function(mode) {
self.ownCameraChange = true; self.ownCameraChange = true;
self.ownCameraChangeElapseTime = 0.0; self.ownCameraChangeElapseTime = 0.0;
Camera.mode = mode; Camera.mode = mode;
} }
this.computeFinalForm();
} }
// Class that manages the mouse events and computes the 3d structure data of the selected entity or avatar
var ZoomOnAnything = function() { var ZoomOnAnything = function() {
var self = this; var self = this;
this.zoomEntityID; this.zoomEntityData; // The selected entity's data
this.zoomEntityData;
this.zoomCameraPos; this.zoomCameraPos;
var ZOOM_MAX_VELOCITY = 15.0; // meters per second var ZOOM_MAX_VELOCITY = 15.0; // meters per second
var ZOOM_MAX_DURATION = 1.0; var ZOOM_MAX_DURATION = 1.0; // seconds
this.zoomDelta = {x: 0.0, y: 0.0}; this.zoomDelta = {x: 0.0, y: 0.0}; // mouse move delta while panning
this.isPanning = false; this.isPanning = false;
this.screenPointRef = {x: 0.0, y: 0.0}; this.screenPointRef = {x: 0.0, y: 0.0}; // Screen pixels reference used to compute the zoomDelta
this.connected = false;
// This function estimates the projection axis and the dimensions along that axis of the selected entity
this.getEntityDimsFromNormal = function(dims, rot, normal) { this.getEntityDimsFromNormal = function(dims, rot, normal) {
var zoomXNormal = Vec3.multiplyQbyV(rot, Vec3.UNIT_X); var zoomXNormal = Vec3.multiplyQbyV(rot, Vec3.UNIT_X);
var zoomYNormal = Vec3.multiplyQbyV(rot, Vec3.UNIT_Y); var zoomYNormal = Vec3.multiplyQbyV(rot, Vec3.UNIT_Y);
@ -257,6 +286,7 @@
return affinities[0]; return affinities[0];
} }
// This function estimates the appropriate focus point when the selected entity is an avatar
this.getAvatarFocusPoint = function(avatar) { this.getAvatarFocusPoint = function(avatar) {
var rEyeIndex = avatar.getJointIndex("RightEye"); var rEyeIndex = avatar.getJointIndex("RightEye");
var lEyeIndex = avatar.getJointIndex("LeftEye"); var lEyeIndex = avatar.getJointIndex("LeftEye");
@ -288,8 +318,9 @@
return Vec3.multiply(1.0/count, focusPoint); return Vec3.multiply(1.0/count, focusPoint);
} }
// This function sets the data needed to zoom in on an avatar
this.getZoomDataFromAvatar = function(avatarID, skinToBoneDist, zoomVelocity, maxDuration) { this.getZoomDataFromAvatar = function(avatarID, skinToBoneDist, zoomVelocity, maxDuration) {
var headDiam = 2.0 * skinToBoneDist; var headDiam = 2.0 * skinToBoneDist; // Head diameter is estimated based on the distance to the bone
headDiam = headDiam < 0.5 ? 0.5 : headDiam; headDiam = headDiam < 0.5 ? 0.5 : headDiam;
var avatar = AvatarList.getAvatar(avatarID); var avatar = AvatarList.getAvatar(avatarID);
var focusPoint = self.getAvatarFocusPoint(avatar); var focusPoint = self.getAvatarFocusPoint(avatar);
@ -299,6 +330,7 @@
return zoomData; return zoomData;
} }
// This function sets the data needed to zoom in on an entity
this.getZoomDataFromEntity = function(intersection, objectProps, zoomVelocity, maxDuration) { this.getZoomDataFromEntity = function(intersection, objectProps, zoomVelocity, maxDuration) {
var position = objectProps.position; var position = objectProps.position;
var dimensions = objectProps.dimensions; var dimensions = objectProps.dimensions;
@ -312,40 +344,61 @@
return zoomData; return zoomData;
} }
// This function initiate the zoom loop on the selected entity
this.zoomOnEntity = function(intersection, objectProps) { this.zoomOnEntity = function(intersection, objectProps) {
self.zoomEntityData = self.getZoomDataFromEntity(intersection, objectProps, ZOOM_MAX_VELOCITY, ZOOM_MAX_DURATION); self.zoomEntityData = self.getZoomDataFromEntity(intersection, objectProps, ZOOM_MAX_VELOCITY, ZOOM_MAX_DURATION);
self.zoomEntityData.initZoomIn(); self.zoomEntityData.initZoomIn();
} }
// This function initiates the zoom loop on the selected avatar
this.zoomOnAvatar = function(avatarID, skinToBoneDist) { this.zoomOnAvatar = function(avatarID, skinToBoneDist) {
self.zoomEntityData = self.getZoomDataFromAvatar(avatarID, skinToBoneDist, ZOOM_MAX_VELOCITY, ZOOM_MAX_DURATION); self.zoomEntityData = self.getZoomDataFromAvatar(avatarID, skinToBoneDist, ZOOM_MAX_VELOCITY, ZOOM_MAX_DURATION);
self.zoomEntityData.initZoomIn(); self.zoomEntityData.initZoomIn();
} }
// This function connects to the Script.update signal
this.connect = function() {
self.connected = true;
Script.update.connect(self.updateZoom);
}
// This function disconnects to the Script.update signal
this.disconnect = function() {
self.connected = false;
Script.update.disconnect(self.updateZoom);
}
// This function get connected to the Script.update signal
this.updateZoom = function(deltaTime) { this.updateZoom = function(deltaTime) {
if (self.zoomEntityData && self.zoomEntityData.needsUpdate()) { if (self.zoomEntityData) {
if (self.zoomEntityData.needsUpdate()) {
self.zoomEntityData.updateZoom(deltaTime); self.zoomEntityData.updateZoom(deltaTime);
if (self.zoomEntityData.status === ZoomStatus.consumed) { if (self.zoomEntityData.status === ZoomStatus.consumed) {
self.disconnect();
self.zoomEntityData = undefined; self.zoomEntityData = undefined;
} }
} else {
self.disconnect();
}
} else if (self.connected) {
self.disconnect();
} }
} }
// This function listen to the mouse double click that evaluates the selected entity and the intersection data that initiates the zoom loop
this.mouseDoublePressEvent = function(event) { this.mouseDoublePressEvent = function(event) {
if (event.isLeftButton) { if (event.isLeftButton) {
self.connect();
if (!self.zoomEntityData) { if (!self.zoomEntityData) {
var pickRay = Camera.computePickRay(event.x, event.y); var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = AvatarManager.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, [], [MyAvatar.sessionUUID], false); var intersection = AvatarManager.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, [], [MyAvatar.sessionUUID], false);
zoomingAtAvatarID = intersection.intersects ? intersection.avatarID : undefined; if (!intersection.intersects) {
if (!zoomingAtAvatarID) {
intersection = Entities.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, true); intersection = Entities.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, true);
self.zoomEntityID = intersection.entityID;
var entityProps = Entities.getEntityProperties(intersection.entityID); var entityProps = Entities.getEntityProperties(intersection.entityID);
if (entityProps.type === "Shape") { if (entityProps.type === "Shape") {
var FIND_SHAPES_DISTANCE = 10.0; var FIND_SHAPES_DISTANCE = 10.0;
var shapes = Entities.findEntitiesByType("Shape", intersection.intersection, FIND_SHAPES_DISTANCE); var shapes = Entities.findEntitiesByType("Shape", intersection.intersection, FIND_SHAPES_DISTANCE);
intersection = Entities.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, true, [], shapes); intersection = Entities.findRayIntersection({origin: pickRay.origin, direction: pickRay.direction}, true, [], shapes);
self.zoomEntityID = intersection.entityID;
entityProps = Entities.getEntityProperties(intersection.entityID); entityProps = Entities.getEntityProperties(intersection.entityID);
} }
if (!entityProps.dimensions) { if (!entityProps.dimensions) {
@ -353,9 +406,9 @@
} }
self.zoomOnEntity(intersection, entityProps); self.zoomOnEntity(intersection, entityProps);
} else { } else {
var avatar = AvatarList.getAvatar(zoomingAtAvatarID); var avatar = AvatarList.getAvatar(intersection.avatarID);
var skinToBoneDist = Vec3.distance(intersection.intersection, avatar.getJointPosition(intersection.jointIndex)); var skinToBoneDist = Vec3.distance(intersection.intersection, avatar.getJointPosition(intersection.jointIndex));
self.zoomOnAvatar(zoomingAtAvatarID, skinToBoneDist); self.zoomOnAvatar(intersection.avatarID, skinToBoneDist);
} }
} else if (!self.zoomEntityData.needsUpdate()){ } else if (!self.zoomEntityData.needsUpdate()){
self.zoomEntityData.initZoomOut(); self.zoomEntityData.initZoomOut();
@ -363,6 +416,7 @@
} }
} }
// This function listen to the mouse press event to initiate panning while on secondary zoom
this.mousePressEvent = function(event) { this.mousePressEvent = function(event) {
if (event.isRightButton) { if (event.isRightButton) {
self.isPanning = true; self.isPanning = true;
@ -370,6 +424,7 @@
} }
} }
// This function listen to the mouse release event to apply the pan delta while on secondary zoom
this.mouseReleaseEvent = function(event) { this.mouseReleaseEvent = function(event) {
if (event.isRightButton) { if (event.isRightButton) {
if (self.zoomEntityData) { if (self.zoomEntityData) {
@ -380,6 +435,7 @@
} }
} }
// This function listen to the mouse move event to modify the pan delta coordenates while on secondary zoom
this.mouseMoveEvent = function(event) { this.mouseMoveEvent = function(event) {
if (event.isRightButton) { if (event.isRightButton) {
if (self.isPanning && self.zoomEntityData) { if (self.isPanning && self.zoomEntityData) {
@ -388,41 +444,66 @@
} }
} }
// This function listen to the mouse wheel event to modify the ammount of secondary zoom
this.mouseWheel = function(event) { this.mouseWheel = function(event) {
if (self.zoomEntityData) { if (self.zoomEntityData) {
self.zoomEntityData.updateSuperZoom(event.delta); self.zoomEntityData.updateSuperZoom(event.delta);
} }
} }
// This function aborts the zoom loop
this.abort = function() { this.abort = function() {
self.zoomEntityData.abort(); self.zoomEntityData.abort();
self.zoomEntityData = undefined; self.zoomEntityData = undefined;
if (self.connected) {
self.disconnect();
}
}
// This function refits the selected entity on the screen when the screen dimensions change
this.geometryChanged = function() {
if (self.zoomEntityData !== undefined){
self.zoomEntityData.resetZoomAspect();
}
}
// This function aborts the zoom loop if the camera mode is set by the user
this.modeUpdated = function(mode) {
if (self.zoomEntityData && !self.zoomEntityData.ownCameraChange) {
self.abort();
}
}
// This function initiate the connections
this.init = function() {
// Connect signals
Window.geometryChanged.connect(self.geometryChanged);
Camera.modeUpdated.connect(self.modeUpdated);
Controller.mousePressEvent.connect(self.mousePressEvent);
Controller.mouseDoublePressEvent.connect(self.mouseDoublePressEvent);
Controller.mouseMoveEvent.connect(self.mouseMoveEvent);
Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent);
Controller.wheelEvent.connect(self.mouseWheel);
}
// This function finish the connections
this.scriptEnding = function() {
// Disconnect on exit
Window.geometryChanged.disconnect(self.geometryChanged);
Camera.modeUpdated.disconnect(self.modeUpdated);
Controller.mousePressEvent.disconnect(self.mousePressEvent);
Controller.mouseDoublePressEvent.disconnect(self.mouseDoublePressEvent);
Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent);
Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent);
Controller.wheelEvent.disconnect(self.mouseWheel);
if (self.zoomEntityData) {
self.abort();
}
} }
} }
var zoomOE = new ZoomOnAnything(); var zoomOE = new ZoomOnAnything();
zoomOE.init();
Script.scriptEnding.connect(zoomOE.scriptEnding);
Window.geometryChanged.connect(function() {
if (zoomOE.zoomEntityData){
zoomOE.zoomEntityData.resetZoomAspect();
}
});
Camera.modeUpdated.connect(function(mode) {
if (zoomOE.zoomEntityData && !zoomOE.zoomEntityData.ownCameraChange) {
zoomOE.abort();
}
});
Controller.mousePressEvent.connect(zoomOE.mousePressEvent);
Controller.mouseDoublePressEvent.connect(zoomOE.mouseDoublePressEvent);
Controller.mouseMoveEvent.connect(zoomOE.mouseMoveEvent);
Controller.mouseReleaseEvent.connect(zoomOE.mouseReleaseEvent);
Controller.wheelEvent.connect(zoomOE.mouseWheel);
Script.update.connect(zoomOE.updateZoom);
Script.scriptEnding.connect(function() {
if (zoomOE.zoomEntityData) {
zoomOE.abort();
}
});
})(); })();

View file

@ -50,7 +50,7 @@ var OVERLAY_DATA_HMD = {
}; };
var AWAY_INTRO = { var AWAY_INTRO = {
url: "https://hifi-content.s3.amazonaws.com/doug/animation/fbx/afk_texting.fbx", url: "qrc:///avatar/animations/afk_texting.fbx",
playbackRate: 30.0, playbackRate: 30.0,
loopFlag: true, loopFlag: true,
startFrame: 1.0, startFrame: 1.0,

View file

@ -93,7 +93,7 @@ if (WIN32)
set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF") set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG "/OPT:NOREF /OPT:NOICF")
endif() endif()
link_hifi_libraries(entities-renderer platform) link_hifi_libraries(entities-renderer platform physics)
# perform standard include and linking for found externals # perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) foreach(EXTERNAL ${OPTIONAL_EXTERNALS})