mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 14:33:31 +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.
|
||||
|
||||
###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
|
||||
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_TBB "Get Threading Building Blocks 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_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)
|
||||
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(
|
||||
${EXTERNAL_NAME}
|
||||
URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip
|
||||
URL_MD5 4fbde7759f604aaa68b9c40d628cc34a
|
||||
URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip
|
||||
URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_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
|
||||
}
|
||||
var isGrabbing = false;
|
||||
var isGrabbingPaddle = false;
|
||||
var grabbedEntity = null;
|
||||
var prevMouse = {};
|
||||
var prevMouse = {x: 0, y: 0};
|
||||
var deltaMouse = {
|
||||
z: 0
|
||||
}
|
||||
|
||||
var MAX_GRAB_DISTANCE = 100;
|
||||
var TABLE_SEARCH_RANGE = 10;
|
||||
var entityProps;
|
||||
var moveUpDown = false;
|
||||
var CLOSE_ENOUGH = 0.001;
|
||||
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 ANGULAR_DAMPING_RATE = 0.40;
|
||||
var SCREEN_TO_METERS = 0.001;
|
||||
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
|
||||
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 grabOffset;
|
||||
var originalGravity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
var shouldRotate = false;
|
||||
var dQ, theta, axisAngle, dT;
|
||||
var dQ, dT;
|
||||
var angularVelocity = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
@ -94,6 +101,34 @@ function nearLinePoint(targetPosition) {
|
|||
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) {
|
||||
if (!event.isLeftButton) {
|
||||
|
@ -103,23 +138,35 @@ function mousePressEvent(event) {
|
|||
prevMouse.y = event.y;
|
||||
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||
if (!intersection.intersects) {
|
||||
var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking
|
||||
if (!pickResults.intersects) {
|
||||
return;
|
||||
}
|
||||
if (intersection.properties.collisionsWillMove) {
|
||||
grabbedEntity = intersection.entityID;
|
||||
if (pickResults.properties.collisionsWillMove) {
|
||||
grabbedEntity = pickResults.entityID;
|
||||
var props = Entities.getEntityProperties(grabbedEntity)
|
||||
isGrabbing = true;
|
||||
originalGravity = props.gravity;
|
||||
targetPosition = props.position;
|
||||
var objectPosition = 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;
|
||||
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
|
||||
// we'll try to maintain this height during the rest of this grab
|
||||
grabHeight = currentPosition.y;
|
||||
initialVerticalGrabPosition = currentPosition;
|
||||
|
||||
Entities.editEntity(grabbedEntity, {
|
||||
gravity: {
|
||||
|
@ -194,7 +241,6 @@ function mouseReleaseEvent() {
|
|||
}
|
||||
}
|
||||
|
||||
// new mouseMoveEvent
|
||||
function mouseMoveEvent(event) {
|
||||
if (isGrabbing) {
|
||||
// see if something added/restored gravity
|
||||
|
@ -204,71 +250,78 @@ function mouseMoveEvent(event) {
|
|||
}
|
||||
|
||||
if (shouldRotate) {
|
||||
targetPosition = currentPosition;
|
||||
deltaMouse.x = event.x - prevMouse.x;
|
||||
if (!moveUpDown) {
|
||||
deltaMouse.z = event.y - prevMouse.y;
|
||||
deltaMouse.y = 0;
|
||||
} else {
|
||||
deltaMouse.y = (event.y - prevMouse.y) * -1;
|
||||
deltaMouse.z = 0;
|
||||
}
|
||||
deltaMouse.z = event.y - prevMouse.y;
|
||||
deltaMouse.y = 0;
|
||||
|
||||
var transformedDeltaMouse = {
|
||||
x: deltaMouse.z,
|
||||
y: deltaMouse.x,
|
||||
z: deltaMouse.y
|
||||
};
|
||||
transformedDeltaMouse = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), transformedDeltaMouse);
|
||||
dQ = Quat.fromVec3Degrees(transformedDeltaMouse);
|
||||
theta = 2 * Math.acos(dQ.w);
|
||||
axisAngle = Quat.axis(dQ);
|
||||
angularVelocity = Vec3.multiply((theta / dT), axisAngle);
|
||||
var theta = 2 * Math.acos(dQ.w);
|
||||
var axis = Quat.axis(dQ);
|
||||
angularVelocity = Vec3.multiply((theta / ANGULAR_SPRING_TIMESCALE), axis);
|
||||
} else {
|
||||
var relativePosition = Vec3.subtract(currentPosition, Camera.getPosition());
|
||||
if (relativePosition.y < 0) {
|
||||
// grabee is below camera, so movement is valid
|
||||
// compute intersectionPoint where mouse ray hits grabee's current x-z plane
|
||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||
var mousePosition = pickRay.direction;
|
||||
var length = relativePosition.y / mousePosition.y;
|
||||
mousePosition = Vec3.multiply(mousePosition, length);
|
||||
mousePosition = Vec3.sum(Camera.getPosition(), mousePosition);
|
||||
if (moveUpDown) {
|
||||
targetPosition = forwardPickRayIntersection(currentPosition, event.x, event.y);
|
||||
grabHeight = targetPosition.y;
|
||||
} else {
|
||||
var pointOnPlane = xzPickRayIntersetion(currentPosition, event.x, event.y);
|
||||
pointOnPlane = Vec3.subtract(pointOnPlane, grabOffset);
|
||||
|
||||
// translate mousePosition into local-frame
|
||||
mousePosition = Vec3.subtract(mousePosition, tablePosition);
|
||||
if (isGrabbingPaddle) {
|
||||
// translate pointOnPlane into local-frame
|
||||
pointOnPlane = Vec3.subtract(pointOnPlane, tablePosition);
|
||||
|
||||
// clamp local mousePosition to table field
|
||||
if (mousePosition.x > fieldMaxOffset.x) {
|
||||
mousePosition.x = fieldMaxOffset.x;
|
||||
} else if (mousePosition.x < fieldMinOffset.x) {
|
||||
mousePosition.x = fieldMinOffset.x;
|
||||
// clamp local pointOnPlane to table field
|
||||
if (pointOnPlane.x > fieldMaxOffset.x) {
|
||||
pointOnPlane.x = fieldMaxOffset.x;
|
||||
} else if (pointOnPlane.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) {
|
||||
mousePosition.z = fieldMaxOffset.z;
|
||||
} else if (mousePosition.z < fieldMinOffset.z) {
|
||||
mousePosition.z = fieldMinOffset.z;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// clamp to grabHeight
|
||||
pointOnPlane.y = grabHeight;
|
||||
targetPosition = pointOnPlane;
|
||||
initialVerticalGrabPosition = targetPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,57 +350,32 @@ function keyPressEvent(event) {
|
|||
function update(deltaTime) {
|
||||
dT = deltaTime;
|
||||
if (isGrabbing) {
|
||||
|
||||
entityProps = Entities.getEntityProperties(grabbedEntity);
|
||||
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) {
|
||||
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
|
||||
Entities.editEntity(grabbedEntity, { angularVelocity: angularVelocity, });
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,8 +36,6 @@ var angularVelocity = {
|
|||
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_COLOR = {
|
||||
|
@ -90,10 +88,6 @@ function mousePressEvent(event) {
|
|||
gravity: {x: 0, y: 0, z: 0}
|
||||
});
|
||||
|
||||
Audio.playSound(grabSound, {
|
||||
position: props.position,
|
||||
volume: 0.4
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,11 +129,6 @@ function mouseReleaseEvent() {
|
|||
});
|
||||
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 QtQuick 2.3
|
||||
import QtQuick.Controls 1.2
|
||||
import "controls"
|
||||
import "styles"
|
||||
|
||||
Dialog {
|
||||
Item {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
title: "Go to..."
|
||||
|
||||
objectName: "AddressBarDialog"
|
||||
contentImplicitWidth: addressBarDialog.implicitWidth
|
||||
contentImplicitHeight: addressBarDialog.implicitHeight
|
||||
destroyOnCloseButton: false
|
||||
|
||||
property int animationDuration: hifi.effects.fadeInDuration
|
||||
property bool destroyOnInvisible: false
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
reset();
|
||||
}
|
||||
implicitWidth: addressBarDialog.implicitWidth
|
||||
implicitHeight: addressBarDialog.implicitHeight
|
||||
|
||||
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: {
|
||||
opacity = enabled ? 1.0 : 0.0
|
||||
if (enabled) {
|
||||
addressLine.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
onParentChanged: {
|
||||
if (enabled && visible) {
|
||||
addressLine.forceActiveFocus();
|
||||
|
||||
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) {
|
||||
reset()
|
||||
|
||||
// Some dialogs should be destroyed when they become invisible.
|
||||
if (destroyOnInvisible) {
|
||||
destroy()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function reset() {
|
||||
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() {
|
||||
|
@ -95,8 +149,22 @@ Dialog {
|
|||
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.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.
|
||||
*/
|
||||
enabled: false
|
||||
scale: 0.0
|
||||
opacity: 1.0
|
||||
|
||||
// The offscreen UI will enable an object, rather than manipulating it's
|
||||
// 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
|
||||
// modify the visibility
|
||||
onEnabledChanged: {
|
||||
scale = enabled ? 1.0 : 0.0
|
||||
opacity = enabled ? 1.0 : 0.0
|
||||
}
|
||||
|
||||
// The actual animator
|
||||
Behavior on scale {
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.InOutBounce
|
||||
duration: animationDuration
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
|
||||
// Once we're scaled to 0, disable the dialog's visibility
|
||||
onScaleChanged: {
|
||||
visible = (scale != 0.0);
|
||||
// Once we're transparent, disable the dialog's visibility
|
||||
onOpacityChanged: {
|
||||
visible = (opacity != 0.0);
|
||||
}
|
||||
|
||||
// Some dialogs should be destroyed when they become invisible,
|
||||
|
|
|
@ -56,6 +56,6 @@ Item {
|
|||
|
||||
QtObject {
|
||||
id: effects
|
||||
readonly property int fadeInDuration: 400
|
||||
readonly property int fadeInDuration: 300
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,40 +55,41 @@
|
|||
#include <QMessageBox>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <AccountManager.h>
|
||||
#include <AddressManager.h>
|
||||
#include <AmbientOcclusionEffect.h>
|
||||
#include <AudioInjector.h>
|
||||
#include <DeferredLightingEffect.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <EntityScriptingInterface.h>
|
||||
#include <ErrorDialog.h>
|
||||
#include <GlowEffect.h>
|
||||
#include <HFActionEvent.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <VrMenu.h>
|
||||
#include <InfoView.h>
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <MessageDialog.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <NetworkAccessManager.h>
|
||||
#include <NetworkingConstants.h>
|
||||
#include <ObjectMotionState.h>
|
||||
#include <OctalCode.h>
|
||||
#include <OctreeSceneStats.h>
|
||||
#include <ObjectMotionState.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <PathUtils.h>
|
||||
#include <PerfStat.h>
|
||||
#include <PhysicsEngine.h>
|
||||
#include <ProgramObject.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <SceneScriptingInterface.h>
|
||||
#include <ScriptCache.h>
|
||||
#include <SettingHandle.h>
|
||||
#include <SoundCache.h>
|
||||
#include <TextRenderer.h>
|
||||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
#include <MessageDialog.h>
|
||||
#include <InfoView.h>
|
||||
#include <SceneScriptingInterface.h>
|
||||
#include <VrMenu.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AudioClient.h"
|
||||
|
@ -807,6 +808,7 @@ void Application::initializeGL() {
|
|||
|
||||
void Application::initializeUi() {
|
||||
AddressBarDialog::registerType();
|
||||
ErrorDialog::registerType();
|
||||
LoginDialog::registerType();
|
||||
MessageDialog::registerType();
|
||||
VrMenu::registerType();
|
||||
|
@ -3105,21 +3107,27 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
|
||||
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
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
|
||||
Glower glower(renderArgs);
|
||||
|
||||
const int BILLBOARD_SIZE = 64;
|
||||
// TODO: Pass a RenderArgs to renderAvatarBillboard
|
||||
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
|
||||
BILLBOARD_SIZE, BILLBOARD_SIZE),
|
||||
true);
|
||||
|
||||
|
||||
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
|
||||
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);
|
||||
|
||||
|
||||
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();
|
||||
PROFILE_RANGE(__FUNCTION__);
|
||||
PerformanceTimer perfTimer("display");
|
||||
|
@ -3481,7 +3489,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
|
||||
}
|
||||
|
||||
{
|
||||
if (!billboard) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
|
||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||
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
|
||||
glPushMatrix();
|
||||
displaySide(renderArgs, _mirrorCamera, true);
|
||||
displaySide(renderArgs, _mirrorCamera, true, billboard);
|
||||
glPopMatrix();
|
||||
|
||||
if (!billboard) {
|
||||
|
|
|
@ -271,7 +271,7 @@ public:
|
|||
|
||||
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
|
||||
/// the view matrix translation.
|
||||
|
|
|
@ -36,12 +36,10 @@ void AddressBarDialog::loadAddress(const QString& address) {
|
|||
}
|
||||
|
||||
void AddressBarDialog::displayAddressOfflineMessage() {
|
||||
OffscreenUi::information("Address offline",
|
||||
"That user or place is currently offline.");
|
||||
OffscreenUi::error("That user or place is currently offline");
|
||||
}
|
||||
|
||||
void AddressBarDialog::displayAddressNotFoundMessage() {
|
||||
OffscreenUi::information("Address not found",
|
||||
"There is no address information for that user or place.");
|
||||
OffscreenUi::error("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 glm::vec3 position = collision.contactPoint;
|
||||
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);
|
||||
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
|
||||
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.
|
||||
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;
|
||||
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
|
||||
|
||||
|
@ -1225,7 +1225,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
|
|||
return;
|
||||
}
|
||||
// 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)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <DeferredLightingEffect.h>
|
||||
#include <Model.h>
|
||||
#include <PerfStat.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
#include "EntityTreeRenderer.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
|
@ -136,27 +137,67 @@ bool RenderableModelEntityItem::readyToAddToScene(RenderArgs* renderArgs) {
|
|||
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,
|
||||
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) {
|
||||
return _model->addToScene(scene, pendingChanges);
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myMetaItem);
|
||||
if (_model) {
|
||||
_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) {
|
||||
PerformanceTimer perfTimer("RMEIrender");
|
||||
assert(getType() == EntityTypes::Model);
|
||||
|
||||
bool drawAsModel = hasModel();
|
||||
|
||||
glm::vec3 position = getPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
|
||||
|
@ -168,8 +209,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
highlightSimulationOwnership = (getSimulatorID() == myNodeID);
|
||||
}
|
||||
|
||||
bool didDraw = false;
|
||||
if (drawAsModel && !highlightSimulationOwnership) {
|
||||
if (hasModel()) {
|
||||
remapTextures();
|
||||
{
|
||||
float alpha = getLocalRenderAlpha();
|
||||
|
@ -212,27 +252,14 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
_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);
|
||||
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,8 @@ private:
|
|||
QStringList _originalTextures;
|
||||
bool _originalTexturesRead;
|
||||
QVector<QVector<glm::vec3>> _points;
|
||||
|
||||
render::ItemID _myMetaItem;
|
||||
};
|
||||
|
||||
#endif // hifi_RenderableModelEntityItem_h
|
||||
|
|
|
@ -480,17 +480,21 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
bytesRead += encodedUpdateDelta.size();
|
||||
|
||||
// Newer bitstreams will have a last simulated and a last updated value
|
||||
quint64 lastSimulatedFromBufferAdjusted = now;
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
|
||||
// last simulated is stored as ByteCountCoded delta from lastEdited
|
||||
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
|
||||
quint64 simulatedDelta = simulatedDeltaCoder;
|
||||
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
|
||||
qCDebug(entities) << " _lastSimulated:" << debugTime(_lastSimulated, now);
|
||||
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
|
||||
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
|
||||
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
|
||||
#endif
|
||||
}
|
||||
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.
|
||||
const float MIN_TIME_SKIP = 0.0f;
|
||||
const float MAX_TIME_SKIP = 1.0f; // in seconds
|
||||
float skipTimeForward = glm::clamp((float)(now - _lastSimulated) / (float)(USECS_PER_SECOND),
|
||||
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
||||
float skipTimeForward = glm::clamp((float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND),
|
||||
MIN_TIME_SKIP, MAX_TIME_SKIP);
|
||||
if (skipTimeForward > 0.0f) {
|
||||
#ifdef WANT_DEBUG
|
||||
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.
|
||||
simulateKinematicMotion(skipTimeForward, false);
|
||||
}
|
||||
_lastSimulated = now;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
if (overwriteLocalData && _simulatorID == myNodeID && !_simulatorID.isNull()) {
|
||||
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
|
||||
// rather than accept the values in the packet
|
||||
setPosition(savePosition);
|
||||
setRotation(saveRotation);
|
||||
_velocity = saveVelocity;
|
||||
_angularVelocity = saveAngularVelocity;
|
||||
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
|
||||
if (overwriteLocalData) {
|
||||
if (_simulatorID == myNodeID && !_simulatorID.isNull()) {
|
||||
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
|
||||
// rather than accept the values in the packet
|
||||
setPosition(savePosition);
|
||||
setRotation(saveRotation);
|
||||
_velocity = saveVelocity;
|
||||
_angularVelocity = saveAngularVelocity;
|
||||
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
|
||||
} else {
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
|
@ -919,6 +926,21 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
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 somethingChanged = false;
|
||||
|
||||
|
|
|
@ -366,6 +366,8 @@ public:
|
|||
|
||||
quint64 getLastEditedFromRemote() { return _lastEditedFromRemote; }
|
||||
|
||||
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
|
||||
|
||||
protected:
|
||||
|
||||
static bool _sendPhysicsUpdates;
|
||||
|
|
|
@ -1156,4 +1156,7 @@ AABox EntityItemProperties::getAABox() const {
|
|||
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; }
|
||||
|
||||
bool hasTerseUpdateChanges() const;
|
||||
|
||||
private:
|
||||
QUuid _id;
|
||||
bool _idSet;
|
||||
|
@ -215,6 +217,7 @@ private:
|
|||
QStringList _textureNames;
|
||||
glm::vec3 _naturalDimensions;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(EntityItemProperties);
|
||||
QScriptValue EntityItemPropertiesToScriptValue(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;
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
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);
|
||||
return id;
|
||||
}
|
||||
|
|
|
@ -505,9 +505,13 @@ void NodeList::pingPunchForDomainServer() {
|
|||
} else {
|
||||
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
|
||||
qCDebug(networking) << "No ping replies received from domain-server with ID"
|
||||
<< uuidStringWithoutCurlyBraces(_domainHandler.getICEClientID()) << "-" << "re-sending ICE query.";
|
||||
|
||||
_domainHandler.getICEPeer().softReset();
|
||||
handleICEConnectionToDomainServer();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,14 +27,17 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
ViewFrustum::ViewFrustum() {
|
||||
}
|
||||
|
||||
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
|
||||
_orientation = orientationAsQuaternion;
|
||||
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
|
||||
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 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.
|
||||
|
|
|
@ -36,11 +36,9 @@ const float DEFAULT_FAR_CLIP = (float)TREE_SCALE;
|
|||
|
||||
class ViewFrustum {
|
||||
public:
|
||||
ViewFrustum();
|
||||
|
||||
// setters for camera attributes
|
||||
void setPosition(const glm::vec3& p) { _position = p; }
|
||||
void setOrientation(const glm::quat& orientationAsQuaternion);
|
||||
void setPosition(const glm::vec3& position);
|
||||
void setOrientation(const glm::quat& orientation);
|
||||
|
||||
// getters for camera attributes
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
|
@ -54,7 +52,8 @@ public:
|
|||
void getFocalLength(float focalLength) { _focalLength = focalLength; }
|
||||
|
||||
// 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 getHeight() const { return _height; }
|
||||
float getFieldOfView() const { return _fieldOfView; }
|
||||
|
@ -120,6 +119,7 @@ private:
|
|||
// camera location/orientation attributes
|
||||
glm::vec3 _position; // the position in world-frame
|
||||
glm::quat _orientation;
|
||||
glm::mat4 _view;
|
||||
|
||||
// Lens attributes
|
||||
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 <QOpenGLDebugLogger>
|
||||
|
||||
OffscreenGlCanvas::OffscreenGlCanvas() {
|
||||
}
|
||||
|
@ -27,16 +28,35 @@ void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) {
|
|||
format.setMajorVersion(4);
|
||||
format.setMinorVersion(1);
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
|
||||
#ifdef DEBUG
|
||||
format.setOption(QSurfaceFormat::DebugContext);
|
||||
#endif
|
||||
_context.setFormat(format);
|
||||
}
|
||||
_context.create();
|
||||
|
||||
_offscreenSurface.setFormat(_context.format());
|
||||
_offscreenSurface.create();
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -15,16 +15,24 @@
|
|||
#include <QOpenGLContext>
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
class QOpenGLDebugLogger;
|
||||
|
||||
class OffscreenGlCanvas : public QObject {
|
||||
public:
|
||||
OffscreenGlCanvas();
|
||||
void create(QOpenGLContext* sharedContext = nullptr);
|
||||
bool makeCurrent();
|
||||
void doneCurrent();
|
||||
QOpenGLContext* getContext() {
|
||||
return &_context;
|
||||
}
|
||||
|
||||
protected:
|
||||
QOpenGLContext _context;
|
||||
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 <QGLWidget>
|
||||
#include <QtQml>
|
||||
#include "ErrorDialog.h"
|
||||
#include "MessageDialog.h"
|
||||
|
||||
|
||||
|
@ -130,6 +131,15 @@ void OffscreenUi::critical(const QString& title, const QString& text,
|
|||
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) {};
|
||||
|
||||
|
|
|
@ -115,6 +115,8 @@ public:
|
|||
static void critical(const QString& title, const QString& text,
|
||||
ButtonCallback callback = NO_OP_CALLBACK,
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||
|
||||
static void error(const QString& text); // Interim dialog in new style
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue