mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 17:35:45 +02:00
Merge branch 'team-teaching' of https://github.com/highfidelity/hifi into punk
This commit is contained in:
commit
cd7914ad9d
45 changed files with 1310 additions and 396 deletions
15
BUILD_WIN.md
15
BUILD_WIN.md
|
@ -75,21 +75,6 @@ To prevent these problems, install OpenSSL yourself. Download the following bina
|
||||||
|
|
||||||
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
|
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
|
||||||
|
|
||||||
###vhacd
|
|
||||||
Download it directly from https://github.com/virneo/v-hacd
|
|
||||||
|
|
||||||
To build it run the following commands
|
|
||||||
1. cd src\
|
|
||||||
2. mkdir build
|
|
||||||
3. cd build
|
|
||||||
4. cmake ..
|
|
||||||
|
|
||||||
Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug.
|
|
||||||
|
|
||||||
This will create an output folder with include and lib directory inside it.
|
|
||||||
|
|
||||||
Either copy the contents of output folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory.
|
|
||||||
|
|
||||||
###Build High Fidelity using Visual Studio
|
###Build High Fidelity using Visual Studio
|
||||||
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.
|
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.
|
||||||
|
|
||||||
|
|
|
@ -178,9 +178,13 @@ option(GET_GVERB "Get Gverb library automatically as external project" 1)
|
||||||
option(GET_SOXR "Get Soxr library automatically as external project" 1)
|
option(GET_SOXR "Get Soxr library automatically as external project" 1)
|
||||||
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
|
||||||
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
|
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
|
||||||
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
|
||||||
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
|
||||||
option(GET_POLYVOX "Get polyvox library automatically as external project" 1)
|
option(GET_POLYVOX "Get polyvox library automatically as external project" 1)
|
||||||
|
option(GET_OPENVR "Get OpenVR library automatically as external project" 1)
|
||||||
|
option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1)
|
||||||
|
option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1)
|
||||||
|
|
||||||
|
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
option(GET_GLEW "Get GLEW library automatically as external project" 1)
|
option(GET_GLEW "Get GLEW library automatically as external project" 1)
|
||||||
|
|
18
cmake/externals/boostconfig/CMakeLists.txt
vendored
Normal file
18
cmake/externals/boostconfig/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
set(EXTERNAL_NAME boostconfig)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://github.com/boostorg/config/archive/boost-1.58.0.zip
|
||||||
|
URL_MD5 42fa673bae2b7645a22736445e80eb8d
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)
|
||||||
|
|
18
cmake/externals/oglplus/CMakeLists.txt
vendored
Normal file
18
cmake/externals/oglplus/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
set(EXTERNAL_NAME oglplus)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip
|
||||||
|
URL_MD5 bb55038c36c660d2b6c7be380414fa60
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include ${SOURCE_DIR}/implement CACHE TYPE INTERNAL)
|
||||||
|
|
4
cmake/externals/openvr/CMakeLists.txt
vendored
4
cmake/externals/openvr/CMakeLists.txt
vendored
|
@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip
|
URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip
|
||||||
URL_MD5 4fbde7759f604aaa68b9c40d628cc34a
|
URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND ""
|
||||||
|
|
24
cmake/modules/FindBoostConfig.cmake
Normal file
24
cmake/modules/FindBoostConfig.cmake
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# Try to find BOOSTCONFIG include path.
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# BOOSTCONFIG_INCLUDE_DIRS
|
||||||
|
#
|
||||||
|
# Created by Bradley Austin Davis on 2015/05/22
|
||||||
|
# Copyright 2015 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
|
||||||
|
#
|
||||||
|
|
||||||
|
# setup hints for BOOSTCONFIG search
|
||||||
|
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||||
|
hifi_library_search_hints("BOOSTCONFIG")
|
||||||
|
|
||||||
|
# locate header
|
||||||
|
find_path(BOOSTCONFIG_INCLUDE_DIRS "boost/config.hpp" HINTS ${BOOSTCONFIG_SEARCH_DIRS})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(BOOSTCONFIG DEFAULT_MSG BOOSTCONFIG_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
mark_as_advanced(BOOSTCONFIG_INCLUDE_DIRS BOOSTCONFIG_SEARCH_DIRS)
|
24
cmake/modules/FindOGLPLUS.cmake
Normal file
24
cmake/modules/FindOGLPLUS.cmake
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# Try to find OGLPLUS include path.
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# OGLPLUS_INCLUDE_DIRS
|
||||||
|
#
|
||||||
|
# Created by Bradley Austin Davis on 2015/05/22
|
||||||
|
# Copyright 2015 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
|
||||||
|
#
|
||||||
|
|
||||||
|
# setup hints for OGLPLUS search
|
||||||
|
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||||
|
hifi_library_search_hints("oglplus")
|
||||||
|
|
||||||
|
# locate header
|
||||||
|
find_path(OGLPLUS_INCLUDE_DIRS "oglplus/fwd.hpp" HINTS ${OGLPLUS_SEARCH_DIRS})
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(OGLPLUS DEFAULT_MSG OGLPLUS_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
mark_as_advanced(OGLPLUS_INCLUDE_DIRS OGLPLUS_SEARCH_DIRS)
|
247
examples/example/brownianFun.js
Normal file
247
examples/example/brownianFun.js
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||||
|
var SOUND_PATH = HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/";
|
||||||
|
var soundURLS = ["67LCollision01.wav", "67LCollision02.wav", "airhockey_hit1.wav"];
|
||||||
|
var FLOOR_SIZE = 10;
|
||||||
|
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(FLOOR_SIZE * 1.5, Quat.getFront(Camera.getOrientation())));
|
||||||
|
var WALL_WIDTH = .1;
|
||||||
|
var FLOOR_HEIGHT_OFFSET = -2;
|
||||||
|
var WALL_HEIGHT = FLOOR_SIZE / 4;
|
||||||
|
var BALL_DROP_HEIGHT = center.y + WALL_HEIGHT;
|
||||||
|
var NUM_BALLS = 50;
|
||||||
|
var BALL_RADIUS = 1;
|
||||||
|
var BROWNIAN_INTERVAL_TIME = 16;
|
||||||
|
var BROWNIAN_FORCE_RANGE = 5;
|
||||||
|
var SPAWN_TIME = 50;
|
||||||
|
var spawnCount = 0;
|
||||||
|
|
||||||
|
var brownianMotionActivated = false;
|
||||||
|
var buttonOffColor = {
|
||||||
|
red: 250,
|
||||||
|
green: 10,
|
||||||
|
blue: 10
|
||||||
|
};
|
||||||
|
var buttonOnColor = {
|
||||||
|
red: 10,
|
||||||
|
green: 200,
|
||||||
|
blue: 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var bounds = {
|
||||||
|
xMin: center.x - FLOOR_SIZE / 2,
|
||||||
|
xMax: center.x + FLOOR_SIZE / 2,
|
||||||
|
zMin: center.z - FLOOR_SIZE / 2,
|
||||||
|
zMax: center.z + FLOOR_SIZE / 2
|
||||||
|
};
|
||||||
|
var balls = [];
|
||||||
|
|
||||||
|
var screenSize = Controller.getViewportDimensions();
|
||||||
|
var BUTTON_SIZE = 32;
|
||||||
|
var PADDING = 3;
|
||||||
|
|
||||||
|
var brownianButton = Overlays.addOverlay("image", {
|
||||||
|
x: screenSize.x / 2 - BUTTON_SIZE,
|
||||||
|
y: screenSize.y - (BUTTON_SIZE + PADDING),
|
||||||
|
width: BUTTON_SIZE,
|
||||||
|
height: BUTTON_SIZE,
|
||||||
|
imageURL: HIFI_PUBLIC_BUCKET + "images/blocks.png",
|
||||||
|
color: buttonOffColor,
|
||||||
|
alpha: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var floor = Entities.addEntity({
|
||||||
|
type: 'Box',
|
||||||
|
position: Vec3.sum(center, {
|
||||||
|
x: 0,
|
||||||
|
y: FLOOR_HEIGHT_OFFSET,
|
||||||
|
z: 0
|
||||||
|
}),
|
||||||
|
dimensions: {
|
||||||
|
x: FLOOR_SIZE,
|
||||||
|
y: WALL_WIDTH,
|
||||||
|
z: FLOOR_SIZE
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 100,
|
||||||
|
green: 100,
|
||||||
|
blue: 100
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var rightWall = Entities.addEntity({
|
||||||
|
type: 'Box',
|
||||||
|
position: Vec3.sum(center, {
|
||||||
|
x: FLOOR_SIZE / 2,
|
||||||
|
y: FLOOR_HEIGHT_OFFSET / 2,
|
||||||
|
z: 0
|
||||||
|
}),
|
||||||
|
dimensions: {
|
||||||
|
x: WALL_WIDTH,
|
||||||
|
y: WALL_HEIGHT,
|
||||||
|
z: FLOOR_SIZE
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 120,
|
||||||
|
green: 100,
|
||||||
|
blue: 120
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var leftWall = Entities.addEntity({
|
||||||
|
type: 'Box',
|
||||||
|
position: Vec3.sum(center, {
|
||||||
|
x: -FLOOR_SIZE / 2,
|
||||||
|
y: FLOOR_HEIGHT_OFFSET / 2,
|
||||||
|
z: 0
|
||||||
|
}),
|
||||||
|
dimensions: {
|
||||||
|
x: WALL_WIDTH,
|
||||||
|
y: WALL_HEIGHT,
|
||||||
|
z: FLOOR_SIZE
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 120,
|
||||||
|
green: 100,
|
||||||
|
blue: 120
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var backWall = Entities.addEntity({
|
||||||
|
type: 'Box',
|
||||||
|
position: Vec3.sum(center, {
|
||||||
|
x: 0,
|
||||||
|
y: FLOOR_HEIGHT_OFFSET / 2,
|
||||||
|
z: -FLOOR_SIZE / 2,
|
||||||
|
}),
|
||||||
|
dimensions: {
|
||||||
|
x: FLOOR_SIZE,
|
||||||
|
y: WALL_HEIGHT,
|
||||||
|
z: WALL_WIDTH
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 120,
|
||||||
|
green: 100,
|
||||||
|
blue: 120
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var frontWall = Entities.addEntity({
|
||||||
|
type: 'Box',
|
||||||
|
position: Vec3.sum(center, {
|
||||||
|
x: 0,
|
||||||
|
y: FLOOR_HEIGHT_OFFSET / 2,
|
||||||
|
z: FLOOR_SIZE / 2,
|
||||||
|
}),
|
||||||
|
dimensions: {
|
||||||
|
x: FLOOR_SIZE,
|
||||||
|
y: WALL_HEIGHT,
|
||||||
|
z: WALL_WIDTH
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 120,
|
||||||
|
green: 100,
|
||||||
|
blue: 120
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var spawnInterval = Script.setInterval(spawnBalls, SPAWN_TIME);
|
||||||
|
|
||||||
|
function spawnBalls() {
|
||||||
|
balls.push(Entities.addEntity({
|
||||||
|
type: "Sphere",
|
||||||
|
shapeType: "sphere",
|
||||||
|
position: {
|
||||||
|
x: randFloat(bounds.xMin, bounds.xMax),
|
||||||
|
y: BALL_DROP_HEIGHT,
|
||||||
|
z: randFloat(bounds.zMin, bounds.zMax)
|
||||||
|
},
|
||||||
|
dimensions: {
|
||||||
|
x: BALL_RADIUS,
|
||||||
|
y: BALL_RADIUS,
|
||||||
|
z: BALL_RADIUS
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: randFloat(100, 150),
|
||||||
|
green: randFloat(20, 80),
|
||||||
|
blue: randFloat(10, 180)
|
||||||
|
},
|
||||||
|
ignoreCollisions: false,
|
||||||
|
collisionsWillMove: true,
|
||||||
|
gravity: {
|
||||||
|
x: 0,
|
||||||
|
y: -9.9,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
velocity: {
|
||||||
|
x: 0,
|
||||||
|
y: -.25,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
collisionSoundURL: SOUND_PATH + soundURLS[randInt(0, soundURLS.length - 1)]
|
||||||
|
}));
|
||||||
|
spawnCount++;
|
||||||
|
if (spawnCount === NUM_BALLS) {
|
||||||
|
Script.clearInterval(spawnInterval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
var clickedOverlay = Overlays.getOverlayAtPoint({
|
||||||
|
x: event.x,
|
||||||
|
y: event.y
|
||||||
|
});
|
||||||
|
if (clickedOverlay == brownianButton) {
|
||||||
|
brownianMotionActivated = !brownianMotionActivated;
|
||||||
|
if (brownianMotionActivated) {
|
||||||
|
brownianInterval = Script.setInterval(bumpBalls, BROWNIAN_INTERVAL_TIME);
|
||||||
|
Overlays.editOverlay(brownianButton, {
|
||||||
|
color: buttonOnColor
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Script.clearInterval(brownianInterval);
|
||||||
|
Overlays.editOverlay(brownianButton, {
|
||||||
|
color: buttonOffColor
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bumpBalls() {
|
||||||
|
balls.forEach(function(ball) {
|
||||||
|
var props = Entities.getEntityProperties(ball);
|
||||||
|
var newVelocity = Vec3.sum(props.velocity, {
|
||||||
|
x: (Math.random() - 0.5) * BROWNIAN_FORCE_RANGE,
|
||||||
|
y: 0,
|
||||||
|
z: (Math.random() - 0.5) * BROWNIAN_FORCE_RANGE
|
||||||
|
});
|
||||||
|
Entities.editEntity(ball, {
|
||||||
|
velocity: newVelocity
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
Entities.deleteEntity(floor);
|
||||||
|
Entities.deleteEntity(rightWall);
|
||||||
|
Entities.deleteEntity(leftWall);
|
||||||
|
Entities.deleteEntity(backWall);
|
||||||
|
Entities.deleteEntity(frontWall);
|
||||||
|
balls.forEach(function(ball) {
|
||||||
|
Entities.deleteEntity(ball);
|
||||||
|
});
|
||||||
|
Overlays.deleteOverlay(brownianButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
function randFloat(low, high) {
|
||||||
|
return Math.floor(low + Math.random() * (high - low));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function randInt(low, high) {
|
||||||
|
return Math.floor(randFloat(low, high));
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
|
@ -29,31 +29,38 @@ var tablePosition = {
|
||||||
z: 0
|
z: 0
|
||||||
}
|
}
|
||||||
var isGrabbing = false;
|
var isGrabbing = false;
|
||||||
|
var isGrabbingPaddle = false;
|
||||||
var grabbedEntity = null;
|
var grabbedEntity = null;
|
||||||
var prevMouse = {};
|
var prevMouse = {x: 0, y: 0};
|
||||||
var deltaMouse = {
|
var deltaMouse = {
|
||||||
z: 0
|
z: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var MAX_GRAB_DISTANCE = 100;
|
||||||
var TABLE_SEARCH_RANGE = 10;
|
var TABLE_SEARCH_RANGE = 10;
|
||||||
var entityProps;
|
var entityProps;
|
||||||
var moveUpDown = false;
|
var moveUpDown = false;
|
||||||
var CLOSE_ENOUGH = 0.001;
|
var CLOSE_ENOUGH = 0.001;
|
||||||
var FULL_STRENGTH = 1.0;
|
var FULL_STRENGTH = 1.0;
|
||||||
var SPRING_RATE = 1.5;
|
var SPRING_TIMESCALE = 0.05;
|
||||||
|
var ANGULAR_SPRING_TIMESCALE = 0.03;
|
||||||
var DAMPING_RATE = 0.80;
|
var DAMPING_RATE = 0.80;
|
||||||
var ANGULAR_DAMPING_RATE = 0.40;
|
var ANGULAR_DAMPING_RATE = 0.40;
|
||||||
var SCREEN_TO_METERS = 0.001;
|
var SCREEN_TO_METERS = 0.001;
|
||||||
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
|
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
|
||||||
var grabHeight;
|
var grabHeight;
|
||||||
|
var initialVerticalGrabPosition;
|
||||||
|
var MAX_VERTICAL_ANGLE = Math.PI / 3;
|
||||||
|
var MIN_VERTICAL_ANGLE = - MAX_VERTICAL_ANGLE;
|
||||||
var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition;
|
var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition;
|
||||||
|
var grabOffset;
|
||||||
var originalGravity = {
|
var originalGravity = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
};
|
};
|
||||||
var shouldRotate = false;
|
var shouldRotate = false;
|
||||||
var dQ, theta, axisAngle, dT;
|
var dQ, dT;
|
||||||
var angularVelocity = {
|
var angularVelocity = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
|
@ -94,6 +101,34 @@ function nearLinePoint(targetPosition) {
|
||||||
return Vec3.sum(handPosition, along);
|
return Vec3.sum(handPosition, along);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function xzPickRayIntersetion(pointOnPlane, mouseX, mouseY) {
|
||||||
|
var relativePoint = Vec3.subtract(pointOnPlane, Camera.getPosition());
|
||||||
|
var pickRay = Camera.computePickRay(mouseX, mouseY);
|
||||||
|
if (Math.abs(pickRay.direction.y) > 0.001) {
|
||||||
|
var distance = relativePoint.y / pickRay.direction.y;
|
||||||
|
if (distance < 0.001) {
|
||||||
|
return pointOnPlane;
|
||||||
|
}
|
||||||
|
var pickInersection = Vec3.multiply(pickRay.direction, distance);
|
||||||
|
pickInersection = Vec3.sum(Camera.getPosition(), pickInersection);
|
||||||
|
return pickInersection;
|
||||||
|
}
|
||||||
|
// point and line are more-or-less co-planar: compute closest approach of pickRay and pointOnPlane
|
||||||
|
var distance = Vec3.dot(relativePoint, pickRay.direction);
|
||||||
|
var pickInersection = Vec3.multiply(pickRay.direction, distance);
|
||||||
|
return pickInersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
function forwardPickRayIntersection(pointOnPlane, mouseX, mouseY) {
|
||||||
|
var relativePoint = Vec3.subtract(pointOnPlane, Camera.getPosition());
|
||||||
|
var pickRay = Camera.computePickRay(mouseX, mouseY);
|
||||||
|
var planeNormal = Quat.getFront(Camera.getOrientation());
|
||||||
|
var distance = Vec3.dot(planeNormal, relativePoint);
|
||||||
|
var rayDistance = Vec3.dot(planeNormal, pickRay.direction);
|
||||||
|
var pickIntersection = Vec3.multiply(pickRay.direction, distance / rayDistance);
|
||||||
|
pickIntersection = Vec3.sum(pickIntersection, Camera.getPosition())
|
||||||
|
return pickIntersection;
|
||||||
|
}
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
if (!event.isLeftButton) {
|
if (!event.isLeftButton) {
|
||||||
|
@ -103,23 +138,35 @@ function mousePressEvent(event) {
|
||||||
prevMouse.y = event.y;
|
prevMouse.y = event.y;
|
||||||
|
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||||
if (!intersection.intersects) {
|
if (!pickResults.intersects) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (intersection.properties.collisionsWillMove) {
|
if (pickResults.properties.collisionsWillMove) {
|
||||||
grabbedEntity = intersection.entityID;
|
grabbedEntity = pickResults.entityID;
|
||||||
var props = Entities.getEntityProperties(grabbedEntity)
|
var props = Entities.getEntityProperties(grabbedEntity)
|
||||||
isGrabbing = true;
|
|
||||||
originalGravity = props.gravity;
|
originalGravity = props.gravity;
|
||||||
targetPosition = props.position;
|
var objectPosition = props.position;
|
||||||
currentPosition = props.position;
|
currentPosition = props.position;
|
||||||
|
if (Vec3.distance(currentPosition, Camera.getPosition()) > MAX_GRAB_DISTANCE) {
|
||||||
|
// don't allow grabs of things far away
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isGrabbing = true;
|
||||||
|
isGrabbingPaddle = (props.name == "air-hockey-paddle-23j4h1jh82jsjfw91jf232n2k");
|
||||||
|
|
||||||
currentVelocity = props.velocity;
|
currentVelocity = props.velocity;
|
||||||
updateDropLine(targetPosition);
|
updateDropLine(objectPosition);
|
||||||
|
|
||||||
|
var pointOnPlane = xzPickRayIntersetion(objectPosition, event.x, event.y);
|
||||||
|
grabOffset = Vec3.subtract(pointOnPlane, objectPosition);
|
||||||
|
targetPosition = objectPosition;
|
||||||
|
|
||||||
// remember the height of the object when first grabbed
|
// remember the height of the object when first grabbed
|
||||||
// we'll try to maintain this height during the rest of this grab
|
// we'll try to maintain this height during the rest of this grab
|
||||||
grabHeight = currentPosition.y;
|
grabHeight = currentPosition.y;
|
||||||
|
initialVerticalGrabPosition = currentPosition;
|
||||||
|
|
||||||
Entities.editEntity(grabbedEntity, {
|
Entities.editEntity(grabbedEntity, {
|
||||||
gravity: {
|
gravity: {
|
||||||
|
@ -194,7 +241,6 @@ function mouseReleaseEvent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// new mouseMoveEvent
|
|
||||||
function mouseMoveEvent(event) {
|
function mouseMoveEvent(event) {
|
||||||
if (isGrabbing) {
|
if (isGrabbing) {
|
||||||
// see if something added/restored gravity
|
// see if something added/restored gravity
|
||||||
|
@ -204,71 +250,78 @@ function mouseMoveEvent(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldRotate) {
|
if (shouldRotate) {
|
||||||
|
targetPosition = currentPosition;
|
||||||
deltaMouse.x = event.x - prevMouse.x;
|
deltaMouse.x = event.x - prevMouse.x;
|
||||||
if (!moveUpDown) {
|
deltaMouse.z = event.y - prevMouse.y;
|
||||||
deltaMouse.z = event.y - prevMouse.y;
|
deltaMouse.y = 0;
|
||||||
deltaMouse.y = 0;
|
|
||||||
} else {
|
|
||||||
deltaMouse.y = (event.y - prevMouse.y) * -1;
|
|
||||||
deltaMouse.z = 0;
|
|
||||||
}
|
|
||||||
var transformedDeltaMouse = {
|
var transformedDeltaMouse = {
|
||||||
x: deltaMouse.z,
|
x: deltaMouse.z,
|
||||||
y: deltaMouse.x,
|
y: deltaMouse.x,
|
||||||
z: deltaMouse.y
|
z: deltaMouse.y
|
||||||
};
|
};
|
||||||
transformedDeltaMouse = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), transformedDeltaMouse);
|
|
||||||
dQ = Quat.fromVec3Degrees(transformedDeltaMouse);
|
dQ = Quat.fromVec3Degrees(transformedDeltaMouse);
|
||||||
theta = 2 * Math.acos(dQ.w);
|
var theta = 2 * Math.acos(dQ.w);
|
||||||
axisAngle = Quat.axis(dQ);
|
var axis = Quat.axis(dQ);
|
||||||
angularVelocity = Vec3.multiply((theta / dT), axisAngle);
|
angularVelocity = Vec3.multiply((theta / ANGULAR_SPRING_TIMESCALE), axis);
|
||||||
} else {
|
} else {
|
||||||
var relativePosition = Vec3.subtract(currentPosition, Camera.getPosition());
|
if (moveUpDown) {
|
||||||
if (relativePosition.y < 0) {
|
targetPosition = forwardPickRayIntersection(currentPosition, event.x, event.y);
|
||||||
// grabee is below camera, so movement is valid
|
grabHeight = targetPosition.y;
|
||||||
// compute intersectionPoint where mouse ray hits grabee's current x-z plane
|
} else {
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pointOnPlane = xzPickRayIntersetion(currentPosition, event.x, event.y);
|
||||||
var mousePosition = pickRay.direction;
|
pointOnPlane = Vec3.subtract(pointOnPlane, grabOffset);
|
||||||
var length = relativePosition.y / mousePosition.y;
|
|
||||||
mousePosition = Vec3.multiply(mousePosition, length);
|
|
||||||
mousePosition = Vec3.sum(Camera.getPosition(), mousePosition);
|
|
||||||
|
|
||||||
// translate mousePosition into local-frame
|
if (isGrabbingPaddle) {
|
||||||
mousePosition = Vec3.subtract(mousePosition, tablePosition);
|
// translate pointOnPlane into local-frame
|
||||||
|
pointOnPlane = Vec3.subtract(pointOnPlane, tablePosition);
|
||||||
|
|
||||||
// clamp local mousePosition to table field
|
// clamp local pointOnPlane to table field
|
||||||
if (mousePosition.x > fieldMaxOffset.x) {
|
if (pointOnPlane.x > fieldMaxOffset.x) {
|
||||||
mousePosition.x = fieldMaxOffset.x;
|
pointOnPlane.x = fieldMaxOffset.x;
|
||||||
} else if (mousePosition.x < fieldMinOffset.x) {
|
} else if (pointOnPlane.x < fieldMinOffset.x) {
|
||||||
mousePosition.x = fieldMinOffset.x;
|
pointOnPlane.x = fieldMinOffset.x;
|
||||||
|
}
|
||||||
|
if (pointOnPlane.z > fieldMaxOffset.z) {
|
||||||
|
pointOnPlane.z = fieldMaxOffset.z;
|
||||||
|
} else if (pointOnPlane.z < fieldMinOffset.z) {
|
||||||
|
pointOnPlane.z = fieldMinOffset.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clamp to rotated square (for cut corners)
|
||||||
|
var rotation = Quat.angleAxis(45, { x:0, y:1, z:0 });
|
||||||
|
pointOnPlane = Vec3.multiplyQbyV(rotation, pointOnPlane);
|
||||||
|
if (pointOnPlane.x > halfCornerBoxWidth) {
|
||||||
|
pointOnPlane.x = halfCornerBoxWidth;
|
||||||
|
} else if (pointOnPlane.x < -halfCornerBoxWidth) {
|
||||||
|
pointOnPlane.x = -halfCornerBoxWidth;
|
||||||
|
}
|
||||||
|
if (pointOnPlane.z > halfCornerBoxWidth) {
|
||||||
|
pointOnPlane.z = halfCornerBoxWidth;
|
||||||
|
} else if (pointOnPlane.z < -halfCornerBoxWidth) {
|
||||||
|
pointOnPlane.z = -halfCornerBoxWidth;
|
||||||
|
}
|
||||||
|
// rotate back into local frame
|
||||||
|
rotation.y = -rotation.y;
|
||||||
|
pointOnPlane = Vec3.multiplyQbyV(rotation, pointOnPlane);
|
||||||
|
|
||||||
|
// translate into world-frame
|
||||||
|
pointOnPlane = Vec3.sum(tablePosition, pointOnPlane);
|
||||||
|
} else {
|
||||||
|
// we're grabbing a non-paddle object
|
||||||
|
|
||||||
|
// clamp distance
|
||||||
|
var relativePosition = Vec3.subtract(pointOnPlane, Camera.getPosition());
|
||||||
|
var length = Vec3.length(relativePosition);
|
||||||
|
if (length > MAX_GRAB_DISTANCE) {
|
||||||
|
relativePosition = Vec3.multiply(relativePosition, MAX_GRAB_DISTANCE / length);
|
||||||
|
pointOnPlane = Vec3.sum(relativePosition, Camera.getPosition());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mousePosition.z > fieldMaxOffset.z) {
|
// clamp to grabHeight
|
||||||
mousePosition.z = fieldMaxOffset.z;
|
pointOnPlane.y = grabHeight;
|
||||||
} else if (mousePosition.z < fieldMinOffset.z) {
|
targetPosition = pointOnPlane;
|
||||||
mousePosition.z = fieldMinOffset.z;
|
initialVerticalGrabPosition = targetPosition;
|
||||||
}
|
|
||||||
|
|
||||||
// clamp to rotated square (for cut corners)
|
|
||||||
var rotation = Quat.angleAxis(45, { x:0, y:1, z:0 });
|
|
||||||
mousePosition = Vec3.multiplyQbyV(rotation, mousePosition);
|
|
||||||
if (mousePosition.x > halfCornerBoxWidth) {
|
|
||||||
mousePosition.x = halfCornerBoxWidth;
|
|
||||||
} else if (mousePosition.x < -halfCornerBoxWidth) {
|
|
||||||
mousePosition.x = -halfCornerBoxWidth;
|
|
||||||
}
|
|
||||||
if (mousePosition.z > halfCornerBoxWidth) {
|
|
||||||
mousePosition.z = halfCornerBoxWidth;
|
|
||||||
} else if (mousePosition.z < -halfCornerBoxWidth) {
|
|
||||||
mousePosition.z = -halfCornerBoxWidth;
|
|
||||||
}
|
|
||||||
// rotate back into local frame
|
|
||||||
rotation.y = -rotation.y;
|
|
||||||
mousePosition = Vec3.multiplyQbyV(rotation, mousePosition);
|
|
||||||
// translate into world-frame
|
|
||||||
mousePosition = Vec3.sum(tablePosition, mousePosition);
|
|
||||||
|
|
||||||
mousePosition.y = grabHeight;
|
|
||||||
targetPosition = mousePosition;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,57 +350,32 @@ function keyPressEvent(event) {
|
||||||
function update(deltaTime) {
|
function update(deltaTime) {
|
||||||
dT = deltaTime;
|
dT = deltaTime;
|
||||||
if (isGrabbing) {
|
if (isGrabbing) {
|
||||||
|
|
||||||
entityProps = Entities.getEntityProperties(grabbedEntity);
|
entityProps = Entities.getEntityProperties(grabbedEntity);
|
||||||
currentPosition = entityProps.position;
|
currentPosition = entityProps.position;
|
||||||
currentVelocity = entityProps.velocity;
|
|
||||||
currentRotation = entityProps.rotation;
|
|
||||||
|
|
||||||
var dPosition = Vec3.subtract(targetPosition, currentPosition);
|
|
||||||
|
|
||||||
distanceToTarget = Vec3.length(dPosition);
|
|
||||||
if (distanceToTarget > CLOSE_ENOUGH) {
|
|
||||||
// compute current velocity in the direction we want to move
|
|
||||||
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
|
|
||||||
velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), velocityTowardTarget);
|
|
||||||
// compute the speed we would like to be going toward the target position
|
|
||||||
|
|
||||||
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
|
|
||||||
// compute how much we want to add to the existing velocity
|
|
||||||
addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget);
|
|
||||||
// If target is too far, roll off the force as inverse square of distance
|
|
||||||
if (distanceToTarget / cameraEntityDistance > FULL_STRENGTH) {
|
|
||||||
addedVelocity = Vec3.multiply(addedVelocity, Math.pow(FULL_STRENGTH / distanceToTarget, 2.0));
|
|
||||||
}
|
|
||||||
newVelocity = Vec3.sum(currentVelocity, addedVelocity);
|
|
||||||
// Add Damping
|
|
||||||
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
|
|
||||||
// Update entity
|
|
||||||
} else {
|
|
||||||
newVelocity = {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (shouldRotate) {
|
if (shouldRotate) {
|
||||||
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
|
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
|
||||||
|
Entities.editEntity(grabbedEntity, { angularVelocity: angularVelocity, });
|
||||||
} else {
|
} else {
|
||||||
angularVelocity = entityProps.angularVelocity;
|
var dPosition = Vec3.subtract(targetPosition, currentPosition);
|
||||||
|
var delta = Vec3.length(dPosition);
|
||||||
|
if (delta > CLOSE_ENOUGH) {
|
||||||
|
var MAX_POSITION_DELTA = 0.50;
|
||||||
|
if (delta > MAX_POSITION_DELTA) {
|
||||||
|
dPosition = Vec3.multiply(dPosition, MAX_POSITION_DELTA / delta);
|
||||||
|
}
|
||||||
|
// desired speed is proportional to displacement by the inverse of timescale
|
||||||
|
// (for critically damped motion)
|
||||||
|
newVelocity = Vec3.multiply(dPosition, 1.0 / SPRING_TIMESCALE);
|
||||||
|
} else {
|
||||||
|
newVelocity = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Entities.editEntity(grabbedEntity, { velocity: newVelocity, });
|
||||||
}
|
}
|
||||||
|
|
||||||
// enforce that grabee's rotation is only about y-axis while being grabbed
|
|
||||||
currentRotation.x = 0;
|
|
||||||
currentRotation.z = 0;
|
|
||||||
currentRotation.y = Math.sqrt(1.0 - currentRotation.w * currentRotation.w);
|
|
||||||
// Hrm... slamming the currentRotation doesn't seem to work
|
|
||||||
|
|
||||||
Entities.editEntity(grabbedEntity, {
|
|
||||||
position: currentPosition,
|
|
||||||
rotation: currentRotation,
|
|
||||||
velocity: newVelocity,
|
|
||||||
angularVelocity: angularVelocity
|
|
||||||
});
|
|
||||||
updateDropLine(targetPosition);
|
updateDropLine(targetPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,6 @@ var angularVelocity = {
|
||||||
z: 0
|
z: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
|
|
||||||
var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
|
|
||||||
|
|
||||||
var DROP_DISTANCE = 5.0;
|
var DROP_DISTANCE = 5.0;
|
||||||
var DROP_COLOR = {
|
var DROP_COLOR = {
|
||||||
|
@ -90,10 +88,6 @@ function mousePressEvent(event) {
|
||||||
gravity: {x: 0, y: 0, z: 0}
|
gravity: {x: 0, y: 0, z: 0}
|
||||||
});
|
});
|
||||||
|
|
||||||
Audio.playSound(grabSound, {
|
|
||||||
position: props.position,
|
|
||||||
volume: 0.4
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,11 +129,6 @@ function mouseReleaseEvent() {
|
||||||
});
|
});
|
||||||
targetPosition = null;
|
targetPosition = null;
|
||||||
|
|
||||||
Audio.playSound(grabSound, {
|
|
||||||
position: entityProps.position,
|
|
||||||
volume: 0.25
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
interface/resources/images/address-bar-error-close.svg
Normal file
50
interface/resources/images/address-bar-error-close.svg
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="pomodoro"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
viewBox="-7.125 -7.328 100 100"
|
||||||
|
enable-background="new -7.125 -7.328 100 91.57"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="address-bar-error-close.svg"><metadata
|
||||||
|
id="metadata4143"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs4141" /><sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1840"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
id="namedview4139"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="4.8487496"
|
||||||
|
inkscape:cx="50"
|
||||||
|
inkscape:cy="37.53545"
|
||||||
|
inkscape:window-x="72"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="pomodoro" /><path
|
||||||
|
d="m 42.8705,-2.3280001 c -24.8688,0 -44.9955,20.1618001 -44.9955,45.0045001 0,24.8733 20.1267,44.9955 44.9955,44.9955 24.8427,0 45.0045,-20.1222 45.0045,-44.9955 0,-24.8427 -20.1618,-45.0045001 -45.0045,-45.0045001 z M 67.1066,57.126 57.329,66.9036 42.6293,52.221 27.9422,66.9036 18.1511,57.126 32.8247,42.4443 18.1511,27.7482 27.9422,17.9796 42.6284,32.6487 57.3281,17.9796 67.1057,27.7482 52.424,42.4434 67.1066,57.126 Z"
|
||||||
|
id="path4137"
|
||||||
|
inkscape:connector-curvature="0" /><path
|
||||||
|
style="fill:#787878;fill-opacity:1;stroke:none;stroke-opacity:1"
|
||||||
|
d="M 38.400102,87.62655 C 28.705316,86.39839 21.084707,83.18102 13.982682,77.31765 5.5185024,70.329714 -0.09877759,60.244376 -1.7904936,48.998291 -2.1921426,46.328239 -2.2434696,39.677941 -1.8825126,37.07572 0.23131941,21.836625 9.4778634,8.9272213 23.005945,2.3281243 c 9.805646,-4.783264 20.444414,-5.902737 30.964952,-3.25830896 7.357662,1.849413 14.403738,5.75570696 19.976698,11.07495366 7.36697,7.031569 12.03213,16.084669 13.58981,26.37208 0.45133,2.980701 0.44981,9.518147 -0.003,12.481442 -0.72914,4.772737 -2.08456,9.199896 -4.04575,13.214497 -2.40852,4.930297 -4.94684,8.502038 -8.75077,12.313422 -6.78153,6.79482 -14.822805,10.95587 -24.504932,12.68035 -1.787127,0.3183 -3.134188,0.40875 -6.708441,0.45045 -2.459762,0.0287 -4.765789,0.0149 -5.124505,-0.0304 z m -3.02899,-27.869116 7.314939,-7.311007 7.360877,7.35692 7.360872,7.356917 4.983865,-4.982378 4.98386,-4.982378 -7.359111,-7.358686 -7.359105,-7.358687 7.359105,-7.358687 7.359111,-7.358686 -4.98387,-4.982383 -4.983864,-4.982384 -7.407456,7.393329 -7.407456,7.393328 -7.360652,-7.342464 -7.36065,-7.342467 -4.922357,4.916384 -4.922356,4.916381 7.300528,7.417269 7.300528,7.417267 -7.362706,7.362244 -7.362709,7.362244 4.890918,4.889465 c 2.690008,2.689205 4.974582,4.889463 5.076835,4.889463 0.102254,0 3.477639,-3.289951 7.500854,-7.311004 z"
|
||||||
|
id="path4145"
|
||||||
|
inkscape:connector-curvature="0" /></svg>
|
After Width: | Height: | Size: 3.4 KiB |
3
interface/resources/images/address-bar-error-icon.svg
Normal file
3
interface/resources/images/address-bar-error-icon.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="100px" height="100px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve">
|
||||||
|
<path fill="#000000" d="M50.291,0.07c-18.706,0-33.871,15.165-33.871,33.87c0,0.401,0.013,0.81,0.03,1.221 c0.127,3.558,0.798,6.976,1.939,10.173c7.226,23.752,31.901,54.736,31.901,54.736s24.674-30.982,31.901-54.734 c1.143-3.197,1.812-6.617,1.939-10.175c0.02-0.411,0.031-0.819,0.031-1.221C84.162,15.235,68.998,0.07,50.291,0.07z M51.013,58.386 c-2.479,0-4.664-2.126-4.664-4.664c0-2.479,2.184-4.723,4.664-4.723s4.724,2.243,4.724,4.723 C55.736,56.26,53.551,58.386,51.013,58.386z M50.481,45.811c-1.062-6.376-2.479-12.634-3.601-19.01 c-0.236-1.357-0.295-2.302-0.295-3.66c0-2.716,1.299-5.667,4.428-5.667c3.483,0,4.428,3.011,4.428,6.021 c0,1.181-0.059,2.538-0.295,3.66c-1.181,6.199-2.302,12.457-3.483,18.655H50.481z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 954 B |
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 49 49" enable-background="new 0 0 49 49" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path fill="#333" d="M49,46c0,1.7-1.3,3-3,3H3c-1.7,0-3-1.3-3-3V3c0-1.7,1.3-3,3-3h43c1.7,0,3,1.3,3,3V46z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g id="Your_Icon_11_">
|
|
||||||
<g>
|
|
||||||
<polygon fill="#E7EEEE" points="23.6,19.9 15.1,19.9 15.1,27.8 23.6,27.8 23.6,33.8 33,23.9 23.6,14 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 759 B |
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 49 49" enable-background="new 0 0 49 49" xml:space="preserve">
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path fill="#0E7077" d="M49,46c0,1.7-1.3,3-3,3H3c-1.7,0-3-1.3-3-3V3c0-1.7,1.3-3,3-3h43c1.7,0,3,1.3,3,3V46z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g id="Your_Icon_11_">
|
|
||||||
<g>
|
|
||||||
<polygon fill="#E7EEEE" points="23.6,19.9 15.1,19.9 15.1,27.8 23.6,27.8 23.6,33.8 33,23.9 23.6,14 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 762 B |
72
interface/resources/images/address-bar.svg
Normal file
72
interface/resources/images/address-bar.svg
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
width="1440"
|
||||||
|
height="200"
|
||||||
|
data-icon="map-marker"
|
||||||
|
data-container-transform="translate(24)"
|
||||||
|
viewBox="0 0 1440 200"
|
||||||
|
id="svg4136"
|
||||||
|
inkscape:version="0.91 r13725"
|
||||||
|
sodipodi:docname="address-bar.svg">
|
||||||
|
<metadata
|
||||||
|
id="metadata4144">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs4142" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1840"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
id="namedview4140"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.8671875"
|
||||||
|
inkscape:cx="707.02439"
|
||||||
|
inkscape:cy="52.468468"
|
||||||
|
inkscape:window-x="72"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg4136" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ededed;fill-opacity:1;stroke:none;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
id="rect4141"
|
||||||
|
width="1280"
|
||||||
|
height="140"
|
||||||
|
x="160"
|
||||||
|
y="30"
|
||||||
|
rx="16.025024"
|
||||||
|
ry="17.019567" />
|
||||||
|
<circle
|
||||||
|
style="fill:#b8b8b8;fill-opacity:1;stroke:none;stroke-opacity:1"
|
||||||
|
id="path4146"
|
||||||
|
cx="100"
|
||||||
|
cy="100"
|
||||||
|
r="100" />
|
||||||
|
<path
|
||||||
|
d="m 100,36.000005 c -22.1,0 -40,17.9 -40,39.999995 0,30 40,88 40,88 0,0 40,-58 40,-88 0,-22.099995 -17.9,-39.999995 -40,-39.999995 z m 0,22 c 9.9,0 18,8.099995 18,17.999995 0,9.9 -8.1,18 -18,18 -9.9,0 -18,-8.1 -18,-18 0,-9.9 8.1,-17.999995 18,-17.999995 z"
|
||||||
|
id="path4138"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
|
@ -1,91 +1,145 @@
|
||||||
|
//
|
||||||
|
// AddressBarDialog.qml
|
||||||
|
//
|
||||||
|
// Created by Austin Davis on 2015/04/14
|
||||||
|
// Copyright 2015 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
|
||||||
|
//
|
||||||
|
|
||||||
import Hifi 1.0
|
import Hifi 1.0
|
||||||
import QtQuick 2.3
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
import "controls"
|
import "controls"
|
||||||
import "styles"
|
import "styles"
|
||||||
|
|
||||||
Dialog {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
HifiConstants { id: hifi }
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
title: "Go to..."
|
|
||||||
objectName: "AddressBarDialog"
|
objectName: "AddressBarDialog"
|
||||||
contentImplicitWidth: addressBarDialog.implicitWidth
|
|
||||||
contentImplicitHeight: addressBarDialog.implicitHeight
|
|
||||||
destroyOnCloseButton: false
|
|
||||||
|
|
||||||
|
property int animationDuration: hifi.effects.fadeInDuration
|
||||||
|
property bool destroyOnInvisible: false
|
||||||
|
|
||||||
onVisibleChanged: {
|
implicitWidth: addressBarDialog.implicitWidth
|
||||||
if (!visible) {
|
implicitHeight: addressBarDialog.implicitHeight
|
||||||
reset();
|
|
||||||
}
|
x: parent ? parent.width / 2 - width / 2 : 0
|
||||||
|
y: parent ? parent.height / 2 - height / 2 : 0
|
||||||
|
property int maximumX: parent ? parent.width - width : 0
|
||||||
|
property int maximumY: parent ? parent.height - height : 0
|
||||||
|
|
||||||
|
AddressBarDialog {
|
||||||
|
id: addressBarDialog
|
||||||
|
|
||||||
|
implicitWidth: backgroundImage.width
|
||||||
|
implicitHeight: backgroundImage.height
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: backgroundImage
|
||||||
|
|
||||||
|
source: "../images/address-bar.svg"
|
||||||
|
width: 576
|
||||||
|
height: 80
|
||||||
|
property int inputAreaHeight: 56 // Height of the background's input area
|
||||||
|
property int inputAreaStep: (height - inputAreaHeight) / 2
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
id: addressLine
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
leftMargin: parent.height + hifi.layout.spacing * 2
|
||||||
|
rightMargin: hifi.layout.spacing * 2
|
||||||
|
topMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||||
|
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
font.pointSize: 15
|
||||||
|
helperText: "Go to: place, @user, /path, network address"
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
event.accepted = true // Generates erroneous error in program log, "ReferenceError: event is not defined".
|
||||||
|
addressBarDialog.loadAddress(addressLine.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
// Drag the icon
|
||||||
|
width: parent.height
|
||||||
|
height: parent.height
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
drag {
|
||||||
|
target: root
|
||||||
|
minimumX: -parent.inputAreaStep
|
||||||
|
minimumY: -parent.inputAreaStep
|
||||||
|
maximumX: root.parent ? root.maximumX : 0
|
||||||
|
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
// Drag the input rectangle
|
||||||
|
width: parent.width - parent.height
|
||||||
|
height: parent.inputAreaHeight
|
||||||
|
x: parent.height
|
||||||
|
y: parent.inputAreaStep
|
||||||
|
drag {
|
||||||
|
target: root
|
||||||
|
minimumX: -parent.inputAreaStep
|
||||||
|
minimumY: -parent.inputAreaStep
|
||||||
|
maximumX: root.parent ? root.maximumX : 0
|
||||||
|
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions.
|
||||||
|
// Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property
|
||||||
|
// that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the
|
||||||
|
// visibility.
|
||||||
|
enabled: false
|
||||||
|
opacity: 0.0
|
||||||
|
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
|
opacity = enabled ? 1.0 : 0.0
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
addressLine.forceActiveFocus();
|
addressLine.forceActiveFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onParentChanged: {
|
|
||||||
if (enabled && visible) {
|
Behavior on opacity {
|
||||||
addressLine.forceActiveFocus();
|
// Animate opacity.
|
||||||
|
NumberAnimation {
|
||||||
|
duration: animationDuration
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onOpacityChanged: {
|
||||||
|
// Once we're transparent, disable the dialog's visibility.
|
||||||
|
visible = (opacity != 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
reset()
|
||||||
|
|
||||||
|
// Some dialogs should be destroyed when they become invisible.
|
||||||
|
if (destroyOnInvisible) {
|
||||||
|
destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
addressLine.text = ""
|
addressLine.text = ""
|
||||||
goButton.source = "../images/address-bar-submit.svg"
|
|
||||||
}
|
|
||||||
|
|
||||||
AddressBarDialog {
|
|
||||||
id: addressBarDialog
|
|
||||||
// The client area
|
|
||||||
x: root.clientX
|
|
||||||
y: root.clientY
|
|
||||||
implicitWidth: 512
|
|
||||||
implicitHeight: border.height + hifi.layout.spacing * 4
|
|
||||||
|
|
||||||
|
|
||||||
Border {
|
|
||||||
id: border
|
|
||||||
height: 64
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: hifi.layout.spacing * 2
|
|
||||||
anchors.right: goButton.left
|
|
||||||
anchors.rightMargin: hifi.layout.spacing
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
TextInput {
|
|
||||||
id: addressLine
|
|
||||||
anchors.fill: parent
|
|
||||||
helperText: "domain, location, @user, /x,y,z"
|
|
||||||
anchors.margins: hifi.layout.spacing
|
|
||||||
onAccepted: {
|
|
||||||
event.accepted
|
|
||||||
addressBarDialog.loadAddress(addressLine.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: goButton
|
|
||||||
width: 32
|
|
||||||
height: 32
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: hifi.layout.spacing * 2
|
|
||||||
source: "../images/address-bar-submit.svg"
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
parent.source = "../images/address-bar-submit-active.svg"
|
|
||||||
addressBarDialog.loadAddress(addressLine.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onEscapePressed: {
|
|
||||||
enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleOrGo() {
|
function toggleOrGo() {
|
||||||
|
@ -95,8 +149,22 @@ Dialog {
|
||||||
addressBarDialog.loadAddress(addressLine.text)
|
addressBarDialog.loadAddress(addressLine.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: {
|
||||||
|
switch(event.key) {
|
||||||
|
case Qt.Key_W:
|
||||||
|
if (event.modifiers == Qt.ControlModifier) {
|
||||||
|
event.accepted = true
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Keys.onReturnPressed: toggleOrGo()
|
Keys.onReturnPressed: toggleOrGo()
|
||||||
Keys.onEnterPressed: toggleOrGo()
|
Keys.onEnterPressed: toggleOrGo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
152
interface/resources/qml/ErrorDialog.qml
Normal file
152
interface/resources/qml/ErrorDialog.qml
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
//
|
||||||
|
// ErrorDialog.qml
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 30 May 2015
|
||||||
|
// Copyright 2015 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
|
||||||
|
//
|
||||||
|
|
||||||
|
import Hifi 1.0 as Hifi
|
||||||
|
import QtQuick 2.3
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import "controls"
|
||||||
|
import "styles"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
|
property int animationDuration: hifi.effects.fadeInDuration
|
||||||
|
property bool destroyOnInvisible: true
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
onParentChanged: {
|
||||||
|
if (visible && enabled) {
|
||||||
|
forceActiveFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitWidth: content.implicitWidth
|
||||||
|
implicitHeight: content.implicitHeight
|
||||||
|
|
||||||
|
x: parent ? parent.width / 2 - width / 2 : 0
|
||||||
|
y: parent ? parent.height / 2 - height / 2 : 0
|
||||||
|
|
||||||
|
Hifi.ErrorDialog {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
implicitWidth: box.width
|
||||||
|
implicitHeight: icon.height + hifi.layout.spacing * 2
|
||||||
|
|
||||||
|
Border {
|
||||||
|
id: box
|
||||||
|
|
||||||
|
width: 512
|
||||||
|
color: "#ebebeb"
|
||||||
|
radius: 2
|
||||||
|
border.width: 1
|
||||||
|
border.color: "#000000"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: icon
|
||||||
|
|
||||||
|
source: "../images/address-bar-error-icon.svg"
|
||||||
|
width: 40
|
||||||
|
height: 40
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: hifi.layout.spacing
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: messageText
|
||||||
|
|
||||||
|
font.pointSize: 10
|
||||||
|
font.weight: Font.Bold
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
text: content.text
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: "../images/address-bar-error-close.svg"
|
||||||
|
width: 20
|
||||||
|
height: 20
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: hifi.layout.spacing * 2
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
content.accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions.
|
||||||
|
// Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property
|
||||||
|
// that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the
|
||||||
|
// visibility.
|
||||||
|
enabled: false
|
||||||
|
opacity: 0.0
|
||||||
|
|
||||||
|
onEnabledChanged: {
|
||||||
|
opacity = enabled ? 1.0 : 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
// Animate opacity.
|
||||||
|
NumberAnimation {
|
||||||
|
duration: animationDuration
|
||||||
|
easing.type: Easing.OutCubic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpacityChanged: {
|
||||||
|
// Once we're transparent, disable the dialog's visibility.
|
||||||
|
visible = (opacity != 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (!visible) {
|
||||||
|
// Some dialogs should be destroyed when they become invisible.
|
||||||
|
if (destroyOnInvisible) {
|
||||||
|
destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: {
|
||||||
|
if (event.modifiers === Qt.ControlModifier)
|
||||||
|
switch (event.key) {
|
||||||
|
case Qt.Key_W:
|
||||||
|
event.accepted = true
|
||||||
|
content.accept()
|
||||||
|
break
|
||||||
|
} else switch (event.key) {
|
||||||
|
case Qt.Key_Escape:
|
||||||
|
case Qt.Key_Back:
|
||||||
|
case Qt.Key_Enter:
|
||||||
|
case Qt.Key_Return:
|
||||||
|
event.accepted = true
|
||||||
|
content.accept()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ DialogBase {
|
||||||
* Support for animating the dialog in and out.
|
* Support for animating the dialog in and out.
|
||||||
*/
|
*/
|
||||||
enabled: false
|
enabled: false
|
||||||
scale: 0.0
|
opacity: 1.0
|
||||||
|
|
||||||
// The offscreen UI will enable an object, rather than manipulating it's
|
// The offscreen UI will enable an object, rather than manipulating it's
|
||||||
// visibility, so that we can do animations in both directions. Because
|
// visibility, so that we can do animations in both directions. Because
|
||||||
|
@ -40,20 +40,20 @@ DialogBase {
|
||||||
// opacity, and then when the target animation value is reached, we can
|
// opacity, and then when the target animation value is reached, we can
|
||||||
// modify the visibility
|
// modify the visibility
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
scale = enabled ? 1.0 : 0.0
|
opacity = enabled ? 1.0 : 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual animator
|
// The actual animator
|
||||||
Behavior on scale {
|
Behavior on opacity {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
duration: root.animationDuration
|
duration: animationDuration
|
||||||
easing.type: Easing.InOutBounce
|
easing.type: Easing.OutCubic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once we're scaled to 0, disable the dialog's visibility
|
// Once we're transparent, disable the dialog's visibility
|
||||||
onScaleChanged: {
|
onOpacityChanged: {
|
||||||
visible = (scale != 0.0);
|
visible = (opacity != 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some dialogs should be destroyed when they become invisible,
|
// Some dialogs should be destroyed when they become invisible,
|
||||||
|
|
|
@ -56,6 +56,6 @@ Item {
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: effects
|
id: effects
|
||||||
readonly property int fadeInDuration: 400
|
readonly property int fadeInDuration: 300
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,40 +55,41 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include <AddressManager.h>
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
#include <AddressManager.h>
|
||||||
#include <AmbientOcclusionEffect.h>
|
#include <AmbientOcclusionEffect.h>
|
||||||
#include <AudioInjector.h>
|
#include <AudioInjector.h>
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <EntityScriptingInterface.h>
|
#include <EntityScriptingInterface.h>
|
||||||
|
#include <ErrorDialog.h>
|
||||||
#include <GlowEffect.h>
|
#include <GlowEffect.h>
|
||||||
#include <HFActionEvent.h>
|
#include <HFActionEvent.h>
|
||||||
#include <HFBackEvent.h>
|
#include <HFBackEvent.h>
|
||||||
#include <VrMenu.h>
|
#include <InfoView.h>
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
#include <MainWindow.h>
|
#include <MainWindow.h>
|
||||||
|
#include <MessageDialog.h>
|
||||||
#include <ModelEntityItem.h>
|
#include <ModelEntityItem.h>
|
||||||
#include <NetworkAccessManager.h>
|
#include <NetworkAccessManager.h>
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
|
#include <ObjectMotionState.h>
|
||||||
#include <OctalCode.h>
|
#include <OctalCode.h>
|
||||||
#include <OctreeSceneStats.h>
|
#include <OctreeSceneStats.h>
|
||||||
#include <ObjectMotionState.h>
|
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <PhysicsEngine.h>
|
#include <PhysicsEngine.h>
|
||||||
#include <ProgramObject.h>
|
#include <ProgramObject.h>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
|
#include <SceneScriptingInterface.h>
|
||||||
#include <ScriptCache.h>
|
#include <ScriptCache.h>
|
||||||
#include <SettingHandle.h>
|
#include <SettingHandle.h>
|
||||||
#include <SoundCache.h>
|
#include <SoundCache.h>
|
||||||
#include <TextRenderer.h>
|
#include <TextRenderer.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
#include <MessageDialog.h>
|
#include <VrMenu.h>
|
||||||
#include <InfoView.h>
|
|
||||||
#include <SceneScriptingInterface.h>
|
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "AudioClient.h"
|
#include "AudioClient.h"
|
||||||
|
@ -807,6 +808,7 @@ void Application::initializeGL() {
|
||||||
|
|
||||||
void Application::initializeUi() {
|
void Application::initializeUi() {
|
||||||
AddressBarDialog::registerType();
|
AddressBarDialog::registerType();
|
||||||
|
ErrorDialog::registerType();
|
||||||
LoginDialog::registerType();
|
LoginDialog::registerType();
|
||||||
MessageDialog::registerType();
|
MessageDialog::registerType();
|
||||||
VrMenu::registerType();
|
VrMenu::registerType();
|
||||||
|
@ -3105,21 +3107,27 @@ PickRay Application::computePickRay(float x, float y) const {
|
||||||
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
|
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
|
||||||
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||||
|
|
||||||
|
// clear the alpha channel so the background is transparent
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||||
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
||||||
|
|
||||||
// the "glow" here causes an alpha of one
|
// the "glow" here causes an alpha of one
|
||||||
Glower glower(renderArgs);
|
Glower glower(renderArgs);
|
||||||
|
|
||||||
const int BILLBOARD_SIZE = 64;
|
const int BILLBOARD_SIZE = 64;
|
||||||
// TODO: Pass a RenderArgs to renderAvatarBillboard
|
// TODO: Pass a RenderArgs to renderAvatarBillboard
|
||||||
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
||||||
BILLBOARD_SIZE, BILLBOARD_SIZE),
|
BILLBOARD_SIZE, BILLBOARD_SIZE),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||||
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3301,7 +3309,7 @@ namespace render {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
|
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) {
|
||||||
activeRenderingThread = QThread::currentThread();
|
activeRenderingThread = QThread::currentThread();
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
PerformanceTimer perfTimer("display");
|
PerformanceTimer perfTimer("display");
|
||||||
|
@ -3481,7 +3489,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (!billboard) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
||||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
|
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
|
||||||
|
@ -3673,7 +3681,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
|
||||||
|
|
||||||
// render rear mirror view
|
// render rear mirror view
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
displaySide(renderArgs, _mirrorCamera, true);
|
displaySide(renderArgs, _mirrorCamera, true, billboard);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
if (!billboard) {
|
if (!billboard) {
|
||||||
|
|
|
@ -271,7 +271,7 @@ public:
|
||||||
|
|
||||||
QImage renderAvatarBillboard(RenderArgs* renderArgs);
|
QImage renderAvatarBillboard(RenderArgs* renderArgs);
|
||||||
|
|
||||||
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false);
|
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false, bool billboard = false);
|
||||||
|
|
||||||
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
|
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
|
||||||
/// the view matrix translation.
|
/// the view matrix translation.
|
||||||
|
|
|
@ -36,12 +36,10 @@ void AddressBarDialog::loadAddress(const QString& address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressBarDialog::displayAddressOfflineMessage() {
|
void AddressBarDialog::displayAddressOfflineMessage() {
|
||||||
OffscreenUi::information("Address offline",
|
OffscreenUi::error("That user or place is currently offline");
|
||||||
"That user or place is currently offline.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressBarDialog::displayAddressNotFoundMessage() {
|
void AddressBarDialog::displayAddressNotFoundMessage() {
|
||||||
OffscreenUi::information("Address not found",
|
OffscreenUi::error("There is no address information for that user or place");
|
||||||
"There is no address information for that user or place.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1178,7 +1178,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
||||||
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
|
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
|
||||||
const glm::vec3 position = collision.contactPoint;
|
const glm::vec3 position = collision.contactPoint;
|
||||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f;
|
const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f;
|
||||||
const float COLLISION_MINIMUM_VOLUME = 0.001f;
|
const float COLLISION_MINIMUM_VOLUME = 0.005f;
|
||||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||||
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
||||||
return;
|
return;
|
||||||
|
@ -1194,7 +1194,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
|
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
|
||||||
const float COLLISION_SOUND_COMPRESSION_RANGE = 0.7f;
|
const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes.
|
||||||
float volume = energyFactorOfFull;
|
float volume = energyFactorOfFull;
|
||||||
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
||||||
|
|
||||||
|
@ -1225,7 +1225,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Don't respond to small continuous contacts.
|
// Don't respond to small continuous contacts.
|
||||||
const float COLLISION_MINUMUM_PENETRATION = 0.005f;
|
const float COLLISION_MINUMUM_PENETRATION = 0.002f;
|
||||||
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
|
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
#include <Model.h>
|
#include <Model.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
#include <render/Scene.h>
|
||||||
|
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
@ -136,27 +137,67 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) {
|
||||||
return ready;
|
return ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RenderableModelEntityItemMeta {
|
||||||
|
public:
|
||||||
|
RenderableModelEntityItemMeta(EntityItemPointer entity) : entity(entity){ }
|
||||||
|
typedef render::Payload<RenderableModelEntityItemMeta> Payload;
|
||||||
|
typedef Payload::DataPointer Pointer;
|
||||||
|
|
||||||
|
EntityItemPointer entity;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace render {
|
||||||
|
template <> const ItemKey payloadGetKey(const RenderableModelEntityItemMeta::Pointer& payload) {
|
||||||
|
return ItemKey::Builder::opaqueShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> const Item::Bound payloadGetBound(const RenderableModelEntityItemMeta::Pointer& payload) {
|
||||||
|
if (payload && payload->entity) {
|
||||||
|
return payload->entity->getAABox();
|
||||||
|
}
|
||||||
|
return render::Item::Bound();
|
||||||
|
}
|
||||||
|
template <> void payloadRender(const RenderableModelEntityItemMeta::Pointer& payload, RenderArgs* args) {
|
||||||
|
if (args) {
|
||||||
|
args->_elementsTouched++;
|
||||||
|
if (payload && payload->entity) {
|
||||||
|
payload->entity->render(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
render::PendingChanges& pendingChanges) {
|
render::PendingChanges& pendingChanges) {
|
||||||
|
_myMetaItem = scene->allocateID();
|
||||||
|
|
||||||
|
auto renderData = RenderableModelEntityItemMeta::Pointer(new RenderableModelEntityItemMeta(self));
|
||||||
|
auto renderPayload = render::PayloadPointer(new RenderableModelEntityItemMeta::Payload(renderData));
|
||||||
|
|
||||||
|
pendingChanges.resetItem(_myMetaItem, renderPayload);
|
||||||
|
|
||||||
if (_model) {
|
if (_model) {
|
||||||
return _model->addToScene(scene, pendingChanges);
|
return _model->addToScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
render::PendingChanges& pendingChanges) {
|
render::PendingChanges& pendingChanges) {
|
||||||
|
pendingChanges.removeItem(_myMetaItem);
|
||||||
if (_model) {
|
if (_model) {
|
||||||
_model->removeFromScene(scene, pendingChanges);
|
_model->removeFromScene(scene, pendingChanges);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles
|
||||||
|
// the per frame simulation/update that might be required if the models properties changed.
|
||||||
void RenderableModelEntityItem::render(RenderArgs* args) {
|
void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RMEIrender");
|
PerformanceTimer perfTimer("RMEIrender");
|
||||||
assert(getType() == EntityTypes::Model);
|
assert(getType() == EntityTypes::Model);
|
||||||
|
|
||||||
bool drawAsModel = hasModel();
|
|
||||||
|
|
||||||
glm::vec3 position = getPosition();
|
glm::vec3 position = getPosition();
|
||||||
glm::vec3 dimensions = getDimensions();
|
glm::vec3 dimensions = getDimensions();
|
||||||
|
|
||||||
|
@ -168,8 +209,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
highlightSimulationOwnership = (getSimulatorID() == myNodeID);
|
highlightSimulationOwnership = (getSimulatorID() == myNodeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool didDraw = false;
|
if (hasModel()) {
|
||||||
if (drawAsModel && !highlightSimulationOwnership) {
|
|
||||||
remapTextures();
|
remapTextures();
|
||||||
{
|
{
|
||||||
float alpha = getLocalRenderAlpha();
|
float alpha = getLocalRenderAlpha();
|
||||||
|
@ -212,27 +252,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
_needsInitialSimulation = false;
|
_needsInitialSimulation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_model->isActive()) {
|
|
||||||
// TODO: this is the majority of model render time. And rendering of a cube model vs the basic Box render
|
|
||||||
// is significantly more expensive. Is there a way to call this that doesn't cost us as much?
|
|
||||||
PerformanceTimer perfTimer("model->render");
|
|
||||||
// filter out if not needed to render
|
|
||||||
if (args && (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE)) {
|
|
||||||
if (movingOrAnimating) {
|
|
||||||
_model->renderInScene(alpha, args);
|
|
||||||
didDraw = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_model->renderInScene(alpha, args);
|
|
||||||
didDraw = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!didDraw) {
|
if (highlightSimulationOwnership) {
|
||||||
|
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
|
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@ private:
|
||||||
QStringList _originalTextures;
|
QStringList _originalTextures;
|
||||||
bool _originalTexturesRead;
|
bool _originalTexturesRead;
|
||||||
QVector<QVector<glm::vec3>> _points;
|
QVector<QVector<glm::vec3>> _points;
|
||||||
|
|
||||||
|
render::ItemID _myMetaItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RenderableModelEntityItem_h
|
#endif // hifi_RenderableModelEntityItem_h
|
||||||
|
|
|
@ -480,17 +480,21 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
bytesRead += encodedUpdateDelta.size();
|
bytesRead += encodedUpdateDelta.size();
|
||||||
|
|
||||||
// Newer bitstreams will have a last simulated and a last updated value
|
// Newer bitstreams will have a last simulated and a last updated value
|
||||||
|
quint64 lastSimulatedFromBufferAdjusted = now;
|
||||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
||||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||||
quint64 simulatedDelta = simulatedDeltaCoder;
|
quint64 simulatedDelta = simulatedDeltaCoder;
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
lastSimulatedFromBufferAdjusted = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
|
||||||
|
if (lastSimulatedFromBufferAdjusted > now) {
|
||||||
|
lastSimulatedFromBufferAdjusted = now;
|
||||||
|
}
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entities) << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
|
||||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||||
|
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
|
||||||
|
@ -606,8 +610,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
// use our simulation helper routine to get a best estimate of where the entity should be.
|
// use our simulation helper routine to get a best estimate of where the entity should be.
|
||||||
const float MIN_TIME_SKIP = 0.0f;
|
const float MIN_TIME_SKIP = 0.0f;
|
||||||
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
||||||
float skipTimeForward = glm::clamp((float)(now - _lastSimulated) / (float)(USECS_PER_SECOND),
|
float skipTimeForward = glm::clamp((float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND),
|
||||||
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
||||||
if (skipTimeForward > 0.0f) {
|
if (skipTimeForward > 0.0f) {
|
||||||
#ifdef WANT_DEBUG
|
#ifdef WANT_DEBUG
|
||||||
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
|
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
|
||||||
|
@ -617,19 +621,22 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
// we don't want the side effect of flag setting.
|
// we don't want the side effect of flag setting.
|
||||||
simulateKinematicMotion(skipTimeForward, false);
|
simulateKinematicMotion(skipTimeForward, false);
|
||||||
}
|
}
|
||||||
_lastSimulated = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||||
if (overwriteLocalData && _simulatorID == myNodeID && !_simulatorID.isNull()) {
|
if (overwriteLocalData) {
|
||||||
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
|
if (_simulatorID == myNodeID && !_simulatorID.isNull()) {
|
||||||
// rather than accept the values in the packet
|
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
|
||||||
setPosition(savePosition);
|
// rather than accept the values in the packet
|
||||||
setRotation(saveRotation);
|
setPosition(savePosition);
|
||||||
_velocity = saveVelocity;
|
setRotation(saveRotation);
|
||||||
_angularVelocity = saveAngularVelocity;
|
_velocity = saveVelocity;
|
||||||
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
|
_angularVelocity = saveAngularVelocity;
|
||||||
|
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
|
||||||
|
} else {
|
||||||
|
_lastSimulated = now;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
|
@ -919,6 +926,21 @@ EntityItemProperties EntityItem::getProperties() const {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const {
|
||||||
|
// a TerseUpdate includes the transform and its derivatives
|
||||||
|
properties._position = getPosition();
|
||||||
|
properties._velocity = _velocity;
|
||||||
|
properties._rotation = getRotation();
|
||||||
|
properties._angularVelocity = _angularVelocity;
|
||||||
|
properties._acceleration = _acceleration;
|
||||||
|
|
||||||
|
properties._positionChanged = true;
|
||||||
|
properties._velocityChanged = true;
|
||||||
|
properties._rotationChanged = true;
|
||||||
|
properties._angularVelocityChanged = true;
|
||||||
|
properties._accelerationChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||||
bool somethingChanged = false;
|
bool somethingChanged = false;
|
||||||
|
|
||||||
|
|
|
@ -366,6 +366,8 @@ public:
|
||||||
|
|
||||||
quint64 getLastEditedFromRemote() { return _lastEditedFromRemote; }
|
quint64 getLastEditedFromRemote() { return _lastEditedFromRemote; }
|
||||||
|
|
||||||
|
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static bool _sendPhysicsUpdates;
|
static bool _sendPhysicsUpdates;
|
||||||
|
|
|
@ -1156,4 +1156,7 @@ AABox EntityItemProperties::getAABox() const {
|
||||||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityItemProperties::hasTerseUpdateChanges() const {
|
||||||
|
// a TerseUpdate includes the transform and its derivatives
|
||||||
|
return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged;
|
||||||
|
}
|
||||||
|
|
|
@ -195,6 +195,8 @@ public:
|
||||||
|
|
||||||
void setVoxelDataDirty() { _voxelDataChanged = true; }
|
void setVoxelDataDirty() { _voxelDataChanged = true; }
|
||||||
|
|
||||||
|
bool hasTerseUpdateChanges() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid _id;
|
QUuid _id;
|
||||||
bool _idSet;
|
bool _idSet;
|
||||||
|
@ -215,6 +217,7 @@ private:
|
||||||
QStringList _textureNames;
|
QStringList _textureNames;
|
||||||
glm::vec3 _naturalDimensions;
|
glm::vec3 _naturalDimensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(EntityItemProperties);
|
Q_DECLARE_METATYPE(EntityItemProperties);
|
||||||
QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
||||||
QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
|
||||||
|
|
|
@ -146,7 +146,17 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
||||||
EntityItemProperties modifiedProperties = properties;
|
EntityItemProperties modifiedProperties = properties;
|
||||||
entity->setLastBroadcast(usecTimestampNow());
|
entity->setLastBroadcast(usecTimestampNow());
|
||||||
modifiedProperties.setType(entity->getType());
|
modifiedProperties.setType(entity->getType());
|
||||||
bidForSimulationOwnership(modifiedProperties);
|
if (modifiedProperties.hasTerseUpdateChanges()) {
|
||||||
|
// we make a bid for (or assert) our simulation ownership
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
|
modifiedProperties.setSimulatorID(myNodeID);
|
||||||
|
|
||||||
|
if (entity->getSimulatorID() == myNodeID) {
|
||||||
|
// we think we already own simulation, so make sure we send ALL TerseUpdate properties
|
||||||
|
entity->getAllTerseUpdateProperties(modifiedProperties);
|
||||||
|
}
|
||||||
|
}
|
||||||
queueEntityMessage(PacketTypeEntityEdit, entityID, modifiedProperties);
|
queueEntityMessage(PacketTypeEntityEdit, entityID, modifiedProperties);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,9 +505,13 @@ void NodeList::pingPunchForDomainServer() {
|
||||||
} else {
|
} else {
|
||||||
if (_domainHandler.getICEPeer().getConnectionAttempts() % NUM_DOMAIN_SERVER_PINGS_BEFORE_RESET == 0) {
|
if (_domainHandler.getICEPeer().getConnectionAttempts() % NUM_DOMAIN_SERVER_PINGS_BEFORE_RESET == 0) {
|
||||||
// if we have then nullify the domain handler's network peer and send a fresh ICE heartbeat
|
// if we have then nullify the domain handler's network peer and send a fresh ICE heartbeat
|
||||||
|
qCDebug(networking) << "No ping replies received from domain-server with ID"
|
||||||
|
<< uuidStringWithoutCurlyBraces(_domainHandler.getICEClientID()) << "-" << "re-sending ICE query.";
|
||||||
|
|
||||||
_domainHandler.getICEPeer().softReset();
|
_domainHandler.getICEPeer().softReset();
|
||||||
handleICEConnectionToDomainServer();
|
handleICEConnectionToDomainServer();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,17 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
ViewFrustum::ViewFrustum() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
||||||
_orientation = orientationAsQuaternion;
|
_orientation = orientationAsQuaternion;
|
||||||
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
|
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
|
||||||
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f));
|
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f));
|
||||||
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
|
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
|
||||||
|
_view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewFrustum::setPosition(const glm::vec3& position) {
|
||||||
|
_position = position;
|
||||||
|
_view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order cooresponds to the order defined in the BoxVertex enum.
|
// Order cooresponds to the order defined in the BoxVertex enum.
|
||||||
|
|
|
@ -36,11 +36,9 @@ const float DEFAULT_FAR_CLIP = (float)TREE_SCALE;
|
||||||
|
|
||||||
class ViewFrustum {
|
class ViewFrustum {
|
||||||
public:
|
public:
|
||||||
ViewFrustum();
|
|
||||||
|
|
||||||
// setters for camera attributes
|
// setters for camera attributes
|
||||||
void setPosition(const glm::vec3& p) { _position = p; }
|
void setPosition(const glm::vec3& position);
|
||||||
void setOrientation(const glm::quat& orientationAsQuaternion);
|
void setOrientation(const glm::quat& orientation);
|
||||||
|
|
||||||
// getters for camera attributes
|
// getters for camera attributes
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
|
@ -54,7 +52,8 @@ public:
|
||||||
void getFocalLength(float focalLength) { _focalLength = focalLength; }
|
void getFocalLength(float focalLength) { _focalLength = focalLength; }
|
||||||
|
|
||||||
// getters for lens attributes
|
// getters for lens attributes
|
||||||
const glm::mat4 getProjection() const { return _projection; };
|
const glm::mat4& getProjection() const { return _projection; }
|
||||||
|
const glm::mat4& getView() const { return _view; }
|
||||||
float getWidth() const { return _width; }
|
float getWidth() const { return _width; }
|
||||||
float getHeight() const { return _height; }
|
float getHeight() const { return _height; }
|
||||||
float getFieldOfView() const { return _fieldOfView; }
|
float getFieldOfView() const { return _fieldOfView; }
|
||||||
|
@ -120,6 +119,7 @@ private:
|
||||||
// camera location/orientation attributes
|
// camera location/orientation attributes
|
||||||
glm::vec3 _position; // the position in world-frame
|
glm::vec3 _position; // the position in world-frame
|
||||||
glm::quat _orientation;
|
glm::quat _orientation;
|
||||||
|
glm::mat4 _view;
|
||||||
|
|
||||||
// Lens attributes
|
// Lens attributes
|
||||||
glm::mat4 _projection;
|
glm::mat4 _projection;
|
||||||
|
|
66
libraries/render-utils/src/GlWindow.cpp
Normal file
66
libraries/render-utils/src/GlWindow.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/05/21
|
||||||
|
// 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 "GlWindow.h"
|
||||||
|
|
||||||
|
#include <QOpenGLContext>
|
||||||
|
#include <QOpenGLDebugLogger>
|
||||||
|
#include <GLHelpers.h>
|
||||||
|
|
||||||
|
GlWindow::GlWindow(QOpenGLContext* shareContext) : GlWindow(getDefaultOpenGlSurfaceFormat(), shareContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext) {
|
||||||
|
setSurfaceType(QSurface::OpenGLSurface);
|
||||||
|
setFormat(format);
|
||||||
|
_context = new QOpenGLContext;
|
||||||
|
_context->setFormat(format);
|
||||||
|
if (shareContext) {
|
||||||
|
_context->setShareContext(shareContext);
|
||||||
|
}
|
||||||
|
_context->create();
|
||||||
|
}
|
||||||
|
|
||||||
|
GlWindow::~GlWindow() {
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (_logger) {
|
||||||
|
makeCurrent();
|
||||||
|
delete _logger;
|
||||||
|
_logger = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_context->doneCurrent();
|
||||||
|
_context->deleteLater();
|
||||||
|
_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlWindow::makeCurrent() {
|
||||||
|
_context->makeCurrent(this);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!_logger) {
|
||||||
|
_logger = new QOpenGLDebugLogger(this);
|
||||||
|
if (_logger->initialize()) {
|
||||||
|
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
|
||||||
|
qDebug() << message;
|
||||||
|
});
|
||||||
|
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);
|
||||||
|
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlWindow::doneCurrent() {
|
||||||
|
_context->doneCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlWindow::swapBuffers() {
|
||||||
|
_context->swapBuffers(this);
|
||||||
|
}
|
||||||
|
|
33
libraries/render-utils/src/GlWindow.h
Normal file
33
libraries/render-utils/src/GlWindow.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/05/21
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef hifi_GlWindow_h
|
||||||
|
#define hifi_GlWindow_h
|
||||||
|
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
class QOpenGLContext;
|
||||||
|
class QOpenGLDebugLogger;
|
||||||
|
|
||||||
|
class GlWindow : public QWindow {
|
||||||
|
public:
|
||||||
|
GlWindow(QOpenGLContext* shareContext = nullptr);
|
||||||
|
GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext = nullptr);
|
||||||
|
virtual ~GlWindow();
|
||||||
|
void makeCurrent();
|
||||||
|
void doneCurrent();
|
||||||
|
void swapBuffers();
|
||||||
|
private:
|
||||||
|
QOpenGLContext* _context{ nullptr };
|
||||||
|
#ifdef DEBUG
|
||||||
|
QOpenGLDebugLogger* _logger{ nullptr };
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "OffscreenGlCanvas.h"
|
#include "OffscreenGlCanvas.h"
|
||||||
|
#include <QOpenGLDebugLogger>
|
||||||
|
|
||||||
OffscreenGlCanvas::OffscreenGlCanvas() {
|
OffscreenGlCanvas::OffscreenGlCanvas() {
|
||||||
}
|
}
|
||||||
|
@ -27,16 +28,35 @@ void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) {
|
||||||
format.setMajorVersion(4);
|
format.setMajorVersion(4);
|
||||||
format.setMinorVersion(1);
|
format.setMinorVersion(1);
|
||||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
||||||
|
#ifdef DEBUG
|
||||||
|
format.setOption(QSurfaceFormat::DebugContext);
|
||||||
|
#endif
|
||||||
_context.setFormat(format);
|
_context.setFormat(format);
|
||||||
}
|
}
|
||||||
_context.create();
|
_context.create();
|
||||||
|
|
||||||
_offscreenSurface.setFormat(_context.format());
|
_offscreenSurface.setFormat(_context.format());
|
||||||
_offscreenSurface.create();
|
_offscreenSurface.create();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OffscreenGlCanvas::makeCurrent() {
|
bool OffscreenGlCanvas::makeCurrent() {
|
||||||
return _context.makeCurrent(&_offscreenSurface);
|
bool result = _context.makeCurrent(&_offscreenSurface);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (result && !_logger) {
|
||||||
|
_logger = new QOpenGLDebugLogger(this);
|
||||||
|
if (_logger->initialize()) {
|
||||||
|
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
|
||||||
|
qDebug() << message;
|
||||||
|
});
|
||||||
|
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);
|
||||||
|
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenGlCanvas::doneCurrent() {
|
void OffscreenGlCanvas::doneCurrent() {
|
||||||
|
|
|
@ -15,16 +15,24 @@
|
||||||
#include <QOpenGLContext>
|
#include <QOpenGLContext>
|
||||||
#include <QOffscreenSurface>
|
#include <QOffscreenSurface>
|
||||||
|
|
||||||
|
class QOpenGLDebugLogger;
|
||||||
|
|
||||||
class OffscreenGlCanvas : public QObject {
|
class OffscreenGlCanvas : public QObject {
|
||||||
public:
|
public:
|
||||||
OffscreenGlCanvas();
|
OffscreenGlCanvas();
|
||||||
void create(QOpenGLContext* sharedContext = nullptr);
|
void create(QOpenGLContext* sharedContext = nullptr);
|
||||||
bool makeCurrent();
|
bool makeCurrent();
|
||||||
void doneCurrent();
|
void doneCurrent();
|
||||||
|
QOpenGLContext* getContext() {
|
||||||
|
return &_context;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QOpenGLContext _context;
|
QOpenGLContext _context;
|
||||||
QOffscreenSurface _offscreenSurface;
|
QOffscreenSurface _offscreenSurface;
|
||||||
|
#ifdef DEBUG
|
||||||
|
QOpenGLDebugLogger* _logger{ nullptr };
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
//
|
|
||||||
// OffscreenGlCanvas.cpp
|
|
||||||
// interface/src/renderer
|
|
||||||
//
|
|
||||||
// Created by Bradley Austin Davis on 2014/04/09.
|
|
||||||
// Copyright 2015 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 "OffscreenGlContext.h"
|
|
||||||
|
|
||||||
OffscreenGlContext::OffscreenGlContext() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void OffscreenGlContext::create(QOpenGLContext * sharedContext) {
|
|
||||||
QSurfaceFormat format;
|
|
||||||
format.setDepthBufferSize(16);
|
|
||||||
format.setStencilBufferSize(8);
|
|
||||||
format.setMajorVersion(4);
|
|
||||||
format.setMinorVersion(1);
|
|
||||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
|
||||||
|
|
||||||
_context.setFormat(format);
|
|
||||||
if (nullptr != sharedContext) {
|
|
||||||
_context.setShareContext(sharedContext);
|
|
||||||
}
|
|
||||||
_context.create();
|
|
||||||
|
|
||||||
_offscreenSurface.setFormat(_context.format());
|
|
||||||
_offscreenSurface.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OffscreenGlContext::makeCurrent() {
|
|
||||||
return _context.makeCurrent(&_offscreenSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OffscreenGlContext::doneCurrent() {
|
|
||||||
_context.doneCurrent();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
//
|
|
||||||
// OffscreenGlCanvas.h
|
|
||||||
// interface/src/renderer
|
|
||||||
//
|
|
||||||
// Created by Bradley Austin Davis on 2014/04/09.
|
|
||||||
// Copyright 2015 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
|
|
||||||
//
|
|
||||||
#pragma once
|
|
||||||
#ifndef hifi_OffscreenGlContext_h
|
|
||||||
#define hifi_OffscreenGlContext_h
|
|
||||||
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QOffscreenSurface>
|
|
||||||
|
|
||||||
class OffscreenGlContext : public QObject {
|
|
||||||
public:
|
|
||||||
OffscreenGlContext();
|
|
||||||
void create(QOpenGLContext * sharedContext = nullptr);
|
|
||||||
bool makeCurrent();
|
|
||||||
void doneCurrent();
|
|
||||||
QOpenGLContext * getContext() {
|
|
||||||
return &_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QOpenGLContext _context;
|
|
||||||
QOffscreenSurface _offscreenSurface;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_OffscreenGlCanvas_h
|
|
16
libraries/shared/src/GLHelpers.cpp
Normal file
16
libraries/shared/src/GLHelpers.cpp
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#include "GLHelpers.h"
|
||||||
|
|
||||||
|
|
||||||
|
QSurfaceFormat getDefaultOpenGlSurfaceFormat() {
|
||||||
|
QSurfaceFormat format;
|
||||||
|
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
|
||||||
|
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
|
||||||
|
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
|
||||||
|
format.setVersion(4, 1);
|
||||||
|
#ifdef DEBUG
|
||||||
|
format.setOption(QSurfaceFormat::DebugContext);
|
||||||
|
#endif
|
||||||
|
// FIXME move to core as soon as possible
|
||||||
|
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
||||||
|
return format;
|
||||||
|
}
|
23
libraries/shared/src/GLHelpers.h
Normal file
23
libraries/shared/src/GLHelpers.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis 2015/05/29
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef hifi_GLHelpers_h
|
||||||
|
#define hifi_GLHelpers_h
|
||||||
|
|
||||||
|
#include <QSurfaceFormat>
|
||||||
|
|
||||||
|
// 16 bits of depth precision
|
||||||
|
#define DEFAULT_GL_DEPTH_BUFFER_BITS 16
|
||||||
|
// 8 bits of stencil buffer (typically you really only need 1 bit for functionality
|
||||||
|
// but GL implementations usually just come with buffer sizes in multiples of 8)
|
||||||
|
#define DEFAULT_GL_STENCIL_BUFFER_BITS 8
|
||||||
|
|
||||||
|
QSurfaceFormat getDefaultOpenGlSurfaceFormat();
|
||||||
|
|
||||||
|
#endif
|
38
libraries/ui/src/ErrorDialog.cpp
Normal file
38
libraries/ui/src/ErrorDialog.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// ErrorDialog.cpp
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 30 May 2015
|
||||||
|
// Copyright 2015 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 "ErrorDialog.h"
|
||||||
|
|
||||||
|
HIFI_QML_DEF(ErrorDialog)
|
||||||
|
|
||||||
|
ErrorDialog::ErrorDialog(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorDialog::~ErrorDialog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ErrorDialog::text() const {
|
||||||
|
return _text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorDialog::setVisible(bool v) {
|
||||||
|
OffscreenQmlDialog::setVisible(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorDialog::setText(const QString& arg) {
|
||||||
|
if (arg != _text) {
|
||||||
|
_text = arg;
|
||||||
|
emit textChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ErrorDialog::accept() {
|
||||||
|
OffscreenQmlDialog::accept();
|
||||||
|
}
|
46
libraries/ui/src/ErrorDialog.h
Normal file
46
libraries/ui/src/ErrorDialog.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// ErrorDialog.h
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 30 May 2015
|
||||||
|
// Copyright 2015 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef hifi_ErrorDialog_h
|
||||||
|
#define hifi_ErrorDialog_h
|
||||||
|
|
||||||
|
#include "OffscreenQmlDialog.h"
|
||||||
|
|
||||||
|
class ErrorDialog : public OffscreenQmlDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
HIFI_QML_DECL
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
ErrorDialog(QQuickItem* parent = 0);
|
||||||
|
virtual ~ErrorDialog();
|
||||||
|
|
||||||
|
QString text() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
virtual void setVisible(bool v);
|
||||||
|
void setText(const QString& arg);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void textChanged();
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
virtual void accept();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _text;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_ErrorDialog_h
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QOpenGLDebugLogger>
|
#include <QOpenGLDebugLogger>
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <QtQml>
|
#include <QtQml>
|
||||||
|
#include "ErrorDialog.h"
|
||||||
#include "MessageDialog.h"
|
#include "MessageDialog.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,6 +131,15 @@ void OffscreenUi::critical(const QString& title, const QString& text,
|
||||||
static_cast<QMessageBox::Icon>(MessageDialog::Critical), buttons);
|
static_cast<QMessageBox::Icon>(MessageDialog::Critical), buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OffscreenUi::error(const QString& text) {
|
||||||
|
ErrorDialog* pDialog{ nullptr };
|
||||||
|
ErrorDialog::show([&](QQmlContext* ctx, QObject* item) {
|
||||||
|
pDialog = item->findChild<ErrorDialog*>();
|
||||||
|
pDialog->setText(text);
|
||||||
|
});
|
||||||
|
pDialog->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {};
|
OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {};
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,8 @@ public:
|
||||||
static void critical(const QString& title, const QString& text,
|
static void critical(const QString& title, const QString& text,
|
||||||
ButtonCallback callback = NO_OP_CALLBACK,
|
ButtonCallback callback = NO_OP_CALLBACK,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||||
|
|
||||||
|
static void error(const QString& text); // Interim dialog in new style
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue