mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into black-bis
This commit is contained in:
commit
d31b2c474b
51 changed files with 887 additions and 588 deletions
24
docs/LICENSE_highlight.js.txt
Normal file
24
docs/LICENSE_highlight.js.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
Copyright (c) 2006, Ivan Sagalaev
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are
|
||||
permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
of conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
* Neither the name of highlight.js nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
docs/LICENSE_markdeep.txt
Normal file
23
docs/LICENSE_markdeep.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Copyright 2015-2017, Morgan McGuire
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
280
docs/interface/raypick/pick-parenting.md.html
Normal file
280
docs/interface/raypick/pick-parenting.md.html
Normal file
|
@ -0,0 +1,280 @@
|
|||
<meta charset="utf-8">
|
||||
**Pick Parenting**
|
||||
|
||||
# What is a pick?
|
||||
|
||||
A pick calculates spatial information about the world on on the client.
|
||||
Picks are immutable to allow efficient use by scripts. There are currently four types of picks:
|
||||
|
||||
- Ray pick - Finds the first intersected object along a straight path
|
||||
- Parabola pick - Finds the first intersected object along a parabolic path
|
||||
- Stylus pick - Finds the distance between a point and the XZ planes of a list of whitelisted objects
|
||||
- Collision pick - Uses a volume to check for collisions in the physics engine
|
||||
|
||||
With the exception of collision picks, all picks use the visible appearance of the object to check for collisions.
|
||||
|
||||
# What is parenting?
|
||||
|
||||
Parenting allows an object's position, orientation, and scale (where applicable) to be calculated to another object. This collection of state defines the transform of the object.
|
||||
|
||||
Pick parenting allows the pick's transform to be calculated relative to another object, without creating a new pick.
|
||||
|
||||
# What can be parented to what?
|
||||
|
||||
This object... | | Entity | My Avatar | 3D Overlay | Pick^1 | Pointer^1
|
||||
---------------------|----------------|--------|-----------|------------|--------|-----------
|
||||
Can be parented to...| Entity | yes | yes | yes | yes | yes
|
||||
| My Avatar | yes | no | yes | yes | yes
|
||||
| Other Avatar | yes | yes | yes | yes | yes
|
||||
| 3D Overlay | yes | yes | yes | yes | yes
|
||||
| Pick | no | no | no | yes | yes
|
||||
| Pointer | no | no | no | no | no
|
||||
| The Mouse | no | no | no | yes | yes
|
||||
|
||||
- ^1 Excluding stylus, which can only be parented to My Avatar's hands for now
|
||||
|
||||
# How pick parenting works
|
||||
|
||||
This section describes what happens when picks are parented to things.
|
||||
Since pointers use picks to calculate their results, the rules below
|
||||
also apply when pointers are parented to things.
|
||||
|
||||
## Parent transform exposed
|
||||
|
||||
The way a pick is moved/rescaled depends on its parent. In particular,
|
||||
parenting to a pick actually parents to the pick's result, which
|
||||
has no notion of scale. A pick can also be transformed relative to
|
||||
a joint on a model, such as an avatar's hand.
|
||||
|
||||
Parent type: | Entity/Avatar | 3D Overlay | Pick
|
||||
--------------------------|-----------------|--------------|--------
|
||||
Has position | yes | yes | yes
|
||||
Has orientation | yes | yes | no
|
||||
Has scale | yes | yes | no
|
||||
Can have joints | yes | no | no
|
||||
|
||||
## Entity or overlay parent
|
||||
|
||||
Parenting a pick to an entity or overlay works similarly to
|
||||
parenting entities to other things. However, unlike entities,
|
||||
picks with scale will rescale their dimensions when
|
||||
their parent rescales.
|
||||
|
||||
************************************************************************
|
||||
* May have a joint, otherwise parent to the parent's origin *
|
||||
* | *
|
||||
* scale ^ +--+------+ ^ --+ orientation *
|
||||
* determined / / | /| |orientation \ offset *
|
||||
* from / / v / | | v *
|
||||
* dimensions / / o /..|...................... ^ *
|
||||
* +-> +---------+ | ------------. . / *
|
||||
* | | | / position +----> */ <----+ *
|
||||
* | | | / offset child *
|
||||
* | | |/ ^ transform*
|
||||
* v +---------+ / <---+ *
|
||||
* . +-> dimensions *
|
||||
* . . . . . . . . . . . . . . | relative *
|
||||
* . . . v to parent *
|
||||
************************************************************************
|
||||
|
||||
!!! WARNING
|
||||
Skew is not supported for collision picks. Scaling a parent entity or
|
||||
overlay non-uniformly can lead to inaccurate shapes for the child
|
||||
collision pick.
|
||||
|
||||
## Avatar parent
|
||||
|
||||
A pick parented to an avatar behaves like a wearable. It will maintain
|
||||
its position relative to some point on the avatar's body. If the pick
|
||||
has scale (currently only collision picks), then the pick will rescale
|
||||
when the avatar rescales.
|
||||
|
||||
****************************************************************
|
||||
* Avatar .---. hand ^ -. *
|
||||
* | | | joint / | *
|
||||
* '-----> | | \ /orientation | *
|
||||
* '-+-' +-> o | *
|
||||
* | / ^ position |relative *
|
||||
* +---------' +----- |avatar *
|
||||
* | |scale *
|
||||
* | if not a joint, |factor *
|
||||
* | parent to the |(default: 1) *
|
||||
* | avatar's origin | *
|
||||
* |\ | |uniform scale *
|
||||
* | \ | | ^ *
|
||||
* | \ | | +-> *
|
||||
* | o \ <-+ -' v *
|
||||
****************************************************************
|
||||
|
||||
***************************************************************
|
||||
* orientation offset *
|
||||
* <-----+ *
|
||||
* ^ \ *
|
||||
* \ *
|
||||
* \ child *
|
||||
* Avatar .---. hand .......... * <-- transform *
|
||||
* | | | joint . ^ | *
|
||||
* '-----> | | \ . / v *
|
||||
* '-+-' +-> o ---------+ ^ *
|
||||
* | / position +-> scale *
|
||||
* +---------' offset v relative *
|
||||
* | to avatar *
|
||||
***************************************************************
|
||||
|
||||
## Pick parent
|
||||
|
||||
Picks can also be parented to other picks.
|
||||
When this is done, the child pick is actually parented to
|
||||
the parent pick's result, not the pick itself.
|
||||
|
||||
A pick parented to another pick will have its position changed,
|
||||
but not its orientation or scale.
|
||||
|
||||
### Ray pick parent
|
||||
|
||||
**********************************
|
||||
* position *
|
||||
* o *
|
||||
* \ \ orientation *
|
||||
* \ \ *
|
||||
* \ v . . . . *
|
||||
* \ . *
|
||||
* \ . result transform *
|
||||
* * <-- no scale *
|
||||
* . no orientation *
|
||||
* . *
|
||||
**********************************
|
||||
|
||||
### Parabola pick parent
|
||||
|
||||
**************************************************************
|
||||
* .------. acceleration *
|
||||
* + + | ^ *
|
||||
* speed x ^ / \ . | | *
|
||||
* orientation / / \ . v | *
|
||||
* / / * y axis to rotate *
|
||||
* | . ^ acceleration with *
|
||||
* o . | *
|
||||
* position result transform *
|
||||
* no scale *
|
||||
* no orientation *
|
||||
**************************************************************
|
||||
|
||||
### Stylus pick parent
|
||||
|
||||
********************************************
|
||||
* *
|
||||
* *
|
||||
* . *
|
||||
* . *
|
||||
* . *
|
||||
* .---. avatar * *
|
||||
* | | hand / ^. *
|
||||
* | | \ / \ . *
|
||||
* '-+-' +-> o \ *
|
||||
* | / result transform *
|
||||
* +---------' no scale *
|
||||
* | no orientation *
|
||||
********************************************
|
||||
|
||||
### Collision pick parent
|
||||
|
||||
********************************************
|
||||
* *
|
||||
* .---. *
|
||||
* | | <-- collision pick *
|
||||
* | | *
|
||||
* | *<-+--- result transform at *
|
||||
* | | collision pick position *
|
||||
* | | no scale *
|
||||
* . . . '---' . . no orientation *
|
||||
* *
|
||||
********************************************
|
||||
|
||||
# Effect of scale on picks
|
||||
|
||||
Scale affects the position and shape of picks, which in turn affects the pick result.
|
||||
Scale currently does not affect the max distance of a pick.
|
||||
|
||||
## Ray and stylus pick scaling
|
||||
|
||||
Rescaling the parent of a ray pick or stylus pick can result in a translation of the pick.
|
||||
|
||||
***************************************
|
||||
* before after *
|
||||
* *
|
||||
* pick *
|
||||
* pick +--------------+ ^ *
|
||||
* ^ | |/ *
|
||||
* +-----+/ | o *
|
||||
* | o | | *
|
||||
* | | | | *
|
||||
* +-----+ | | *
|
||||
* parent | | *
|
||||
* +--------------+ *
|
||||
* parent *
|
||||
* *
|
||||
***************************************
|
||||
|
||||
## Parabola pick scaling
|
||||
|
||||
***************************************************************************
|
||||
* before after after *
|
||||
* (scaleWithParent (scaleWithParent *
|
||||
* is false) is true) *
|
||||
* *
|
||||
* .----. *
|
||||
* + + *
|
||||
* .--. / \ *
|
||||
* + + / \ *
|
||||
* .--. / \ / \ *
|
||||
* + + /pick \ /pick \ *
|
||||
* / \ +-------o +-------o *
|
||||
* /pick \ | | | | *
|
||||
* +---o | | | | *
|
||||
* | | | | | | *
|
||||
* +---+ +-------+ +-------+ *
|
||||
* parent parent parent *
|
||||
***************************************************************************
|
||||
|
||||
## Collision pick scaling
|
||||
|
||||
Collision picks use the full transform of their parent (position, orientation, and scale/dimensions).
|
||||
When first created, a collision pick's transform is defined in world space.
|
||||
As the parent rescales, the collision pick rescales proportionally.
|
||||
|
||||
The collision pick's threshold also rescales. The change is proportional to the largest
|
||||
dimension of the parent. So, if the largest dimension of the parent was 3.0 and is now 6.0,
|
||||
the threshold doubles.
|
||||
|
||||
**************************************************************************************
|
||||
* *
|
||||
* before after after *
|
||||
* (scaleWithParent (scaleWithParent *
|
||||
* is false) is true) *
|
||||
* *
|
||||
* pick *
|
||||
* +------------+ *
|
||||
* | | *
|
||||
* pick | ........ | *
|
||||
* +-----+ | . . | *
|
||||
* |.....| | . . | *
|
||||
* |. .| theshold | . . | *
|
||||
* pick |.....|___ | | . . | *
|
||||
* +-----+ +-----+--- <-+ | ........ +___ *
|
||||
* |.....| | | theshold *
|
||||
* |. .| theshold +------------+--- *
|
||||
* |.....|___ | *
|
||||
* +-----+--- <-+ *
|
||||
* +----------+ +----------+ *
|
||||
* +---+ / \ / \ *
|
||||
* +-----+ +--------------+ +--------------+ *
|
||||
* parent parent parent *
|
||||
* *
|
||||
**************************************************************************************
|
||||
|
||||
|
||||
|
||||
<style class="fallback">body{visibility:hidden}</style><script>markdeepOptions={tocStyle:'medium'};</script>
|
||||
<link rel="stylesheet" href="../../markdeep_apidoc.css?">
|
||||
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="../../markdeep.min.js"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
|
7
docs/markdeep.min.js
vendored
Normal file
7
docs/markdeep.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
170
docs/markdeep_apidoc.css
Normal file
170
docs/markdeep_apidoc.css
Normal file
|
@ -0,0 +1,170 @@
|
|||
/* Custom stylesheet for API documentation by Aras Pranckevičius, http://aras-p.info/
|
||||
and tweaked by Morgan McGuire.
|
||||
Licensed as public domain or BSD 2-clause, whichever is more convenient for you.
|
||||
Originally from https://github.com/aras-p/markdeep-docs-style */
|
||||
body {
|
||||
max-width: 50em;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
text-align: left;
|
||||
margin: 1.5em;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
/* if screen is wide enough, put table of contents on the right side */
|
||||
@media screen and (min-width: 64em) {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC {
|
||||
max-width: 20em;
|
||||
left: 54em;
|
||||
display:block;
|
||||
position: fixed;
|
||||
top:0;
|
||||
bottom:0;
|
||||
overflow-y:scroll;
|
||||
margin-top:0;
|
||||
margin-bottom:0;
|
||||
padding-top:1em;
|
||||
}
|
||||
}
|
||||
|
||||
/* for narrow screens or print, hide table of contents */
|
||||
@media screen and (max-width: 64em) {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
|
||||
}
|
||||
|
||||
@media print {
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC { display: none; }
|
||||
body { max-width: 100%; }
|
||||
}
|
||||
|
||||
/* reset heading/link fonts to that of body */
|
||||
.md a,
|
||||
.md div.title, contents, .md .tocHeader,
|
||||
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6,
|
||||
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4, .md .nonumberh5, .md .nonumberh6,
|
||||
.md .shortTOC, .md .mediumTOC, .md .longTOC {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.md div.title {
|
||||
margin: 0.4em 0 0 0;
|
||||
padding: 0;
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
.md div.subtitle {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
/* faint border below headings */
|
||||
.md h1, .md h2, .md h3, .md h4,
|
||||
.md .nonumberh1, .md .nonumberh2, .md .nonumberh3, .md .nonumberh4 {
|
||||
border-bottom: 1px solid rgba(0,0,0,.1);
|
||||
}
|
||||
/* heading font styles */
|
||||
.md h1, .md .nonumberh1, .md div.title {
|
||||
font-size: 150%;
|
||||
font-weight: 600;
|
||||
color: rgba(0,0,0,.7);
|
||||
}
|
||||
.md h2, .md .nonumberh2 {
|
||||
font-size: 120%;
|
||||
font-weight: 400;
|
||||
color: rgba(0,0,0,.9);
|
||||
}
|
||||
.md h3, .md .nonumberh3 {
|
||||
font-size: 110%;
|
||||
font-weight: 400;
|
||||
color: rgba(0,0,0,.7);
|
||||
}
|
||||
/* no numbering of headings */
|
||||
.md h1:before, .md h2:before, .md h3:before, .md h4:before { content: none; }
|
||||
|
||||
/* link styling */
|
||||
.md a:link, .md a:visited {
|
||||
color: #3f51b5;
|
||||
}
|
||||
|
||||
/* inline and block code */
|
||||
.md code, .md pre.listing {
|
||||
background-color: rgba(0,0,0,.05);
|
||||
padding: 0.1em 0.2em;
|
||||
border-radius: 0.15em;
|
||||
}
|
||||
.md pre.listing code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* table of contents styling; make all 3 forms of it look the same */
|
||||
.md .longTOC, .md .mediumTOC, .md .shortTOC {
|
||||
font-size: inherit;
|
||||
line-height: 120%;
|
||||
margin: 1em 0;
|
||||
padding: .4rem;
|
||||
border-left: .1rem solid #3f51b5;
|
||||
}
|
||||
|
||||
.md .tocHeader {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.md .tocNumber {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1 {
|
||||
font-weight: inherit;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.md .longTOC p, .md .mediumTOC p, .md .shortTOC p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.md .longTOC center, .md .mediumTOC center, .md .shortTOC center, .md .tocHeader {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.md .longTOC b, .md .mediumTOC b, .md .shortTOC b {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.md .longTOC center b, .md .mediumTOC center b, .md .shortTOC center b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.md .longTOC a, .md .mediumTOC a, .md .shortTOC a {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.md .longTOC .level1, .md .mediumTOC .level1, .md .shortTOC .level1,
|
||||
.md .longTOC .level2, .md .mediumTOC .level2, .md .shortTOC .level2,
|
||||
.md .longTOC .level3, .md .mediumTOC .level3, .md .shortTOC .level3 {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* tables; use fainter colors than regular markdeep style */
|
||||
.md table.table {
|
||||
font-size: 90%;
|
||||
}
|
||||
.md table.table th {
|
||||
border: none;
|
||||
background-color: #ccc;
|
||||
color: rgba(0,0,0,.6);
|
||||
}
|
||||
.md table.table tr, .md table.table td {
|
||||
border-color: #eee;
|
||||
}
|
||||
.md table.table tr:nth-child(even) {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
|
@ -100,6 +100,25 @@ Rectangle {
|
|||
wearablesModel.setProperty(wearableIndex, 'properties', wearableModelItemProperties);
|
||||
}
|
||||
|
||||
function entityHasAvatarJoints(entityID) {
|
||||
var hasAvatarJoint = false;
|
||||
|
||||
var props = Entities.getEntityProperties(entityID);
|
||||
var avatarJointsCount = MyAvatar.getJointNames().length;
|
||||
if (props && avatarJointsCount >= 0 ) {
|
||||
var entityJointNames = Entities.getJointNames(entityID);
|
||||
for (var index = 0; index < entityJointNames.length; index++) {
|
||||
var avatarJointIndex = MyAvatar.getJointIndex(entityJointNames[index]);
|
||||
if (avatarJointIndex >= 0) {
|
||||
hasAvatarJoint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasAvatarJoint;
|
||||
}
|
||||
|
||||
function getCurrentWearable() {
|
||||
return wearablesCombobox.currentIndex !== -1 ? wearablesCombobox.model.get(wearablesCombobox.currentIndex) : null;
|
||||
}
|
||||
|
@ -109,6 +128,7 @@ Rectangle {
|
|||
var wearable = wearablesCombobox.model.get(i);
|
||||
if (wearable.id === entityID) {
|
||||
wearablesCombobox.currentIndex = i;
|
||||
softWearableTimer.restart();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +138,7 @@ Rectangle {
|
|||
visible = false;
|
||||
adjustWearablesClosed(status, avatarName);
|
||||
}
|
||||
|
||||
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
|
@ -130,6 +151,20 @@ Rectangle {
|
|||
hoverEnabled: true;
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: softWearableTimer
|
||||
interval: 1000
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
var currentWearable = getCurrentWearable();
|
||||
var soft = currentWearable ? currentWearable.relayParentJoints : false;
|
||||
var softEnabled = currentWearable ? entityHasAvatarJoints(currentWearable.id) : false;
|
||||
isSoft.set(soft);
|
||||
isSoft.enabled = softEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 12
|
||||
|
@ -247,13 +282,13 @@ Rectangle {
|
|||
var rotation = currentWearable ? currentWearable.localRotationAngles : { x : 0, y : 0, z : 0 };
|
||||
var scale = currentWearable ? currentWearable.dimensions.x / currentWearable.naturalDimensions.x : 1.0;
|
||||
var joint = currentWearable ? currentWearable.parentJointIndex : -1;
|
||||
var soft = currentWearable ? currentWearable.relayParentJoints : false;
|
||||
softWearableTimer.restart();
|
||||
|
||||
positionVector.set(position);
|
||||
rotationVector.set(rotation);
|
||||
scalespinner.set(scale);
|
||||
jointsCombobox.set(joint);
|
||||
isSoft.set(soft);
|
||||
|
||||
|
||||
if (currentWearable) {
|
||||
wearableSelected(currentWearable.id);
|
||||
|
|
|
@ -215,7 +215,8 @@
|
|||
#include <raypick/LaserPointerScriptingInterface.h>
|
||||
#include <raypick/PickScriptingInterface.h>
|
||||
#include <raypick/PointerScriptingInterface.h>
|
||||
#include <raypick/MouseRayPick.h>
|
||||
#include <raypick/RayPick.h>
|
||||
#include <raypick/MouseTransformNode.h>
|
||||
|
||||
#include <FadeEffect.h>
|
||||
|
||||
|
@ -2286,8 +2287,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
});
|
||||
|
||||
// Setup the mouse ray pick and related operators
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
|
||||
PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
|
||||
{
|
||||
auto mouseRayPick = std::make_shared<RayPick>(Vectors::ZERO, Vectors::UP, PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true);
|
||||
mouseRayPick->parentTransform = std::make_shared<MouseTransformNode>();
|
||||
mouseRayPick->setJointState(PickQuery::JOINT_STATE_MOUSE);
|
||||
auto mouseRayPickID = DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, mouseRayPick);
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(mouseRayPickID);
|
||||
}
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([](unsigned int rayPickID) {
|
||||
RayToEntityIntersectionResult entityResult;
|
||||
entityResult.intersects = false;
|
||||
|
|
|
@ -275,7 +275,11 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
if (inView && avatar->hasNewJointData()) {
|
||||
numAvatarsUpdated++;
|
||||
}
|
||||
avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
|
||||
auto transitStatus = avatar->_transit.update(deltaTime, avatar->_globalPosition, _transitConfig);
|
||||
if (avatar->getIsNewAvatar() && (transitStatus == AvatarTransit::Status::START_TRANSIT || transitStatus == AvatarTransit::Status::ABORT_TRANSIT)) {
|
||||
avatar->_transit.reset();
|
||||
avatar->setIsNewAvatar(false);
|
||||
}
|
||||
avatar->simulate(deltaTime, inView);
|
||||
avatar->updateRenderItem(renderTransaction);
|
||||
avatar->updateSpaceProxy(workloadTransaction);
|
||||
|
|
|
@ -345,9 +345,9 @@ void CollisionPick::computeShapeInfo(const CollisionRegion& pick, ShapeInfo& sha
|
|||
}
|
||||
}
|
||||
|
||||
CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) :
|
||||
Pick(filter, maxDistance, enabled),
|
||||
_mathPick(collisionRegion),
|
||||
CollisionPick::CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, bool scaleWithParent, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine) :
|
||||
Pick(collisionRegion, filter, maxDistance, enabled),
|
||||
_scaleWithParent(scaleWithParent),
|
||||
_physicsEngine(physicsEngine) {
|
||||
if (collisionRegion.shouldComputeShapeInfo()) {
|
||||
_cachedResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(collisionRegion.modelURL);
|
||||
|
@ -361,9 +361,15 @@ CollisionRegion CollisionPick::getMathematicalPick() const {
|
|||
if (parentTransform) {
|
||||
Transform parentTransformValue = parentTransform->getTransform();
|
||||
mathPick.transform = parentTransformValue.worldTransform(mathPick.transform);
|
||||
glm::vec3 scale = parentTransformValue.getScale();
|
||||
float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z);
|
||||
mathPick.threshold *= largestDimension;
|
||||
|
||||
if (_scaleWithParent) {
|
||||
glm::vec3 scale = parentTransformValue.getScale();
|
||||
float largestDimension = glm::max(glm::max(scale.x, scale.y), scale.z);
|
||||
mathPick.threshold *= largestDimension;
|
||||
} else {
|
||||
// We need to undo parent scaling after-the-fact because the parent's scale was needed to calculate this mathPick's position
|
||||
mathPick.transform.setScale(_mathPick.transform.getScale());
|
||||
}
|
||||
}
|
||||
return mathPick;
|
||||
}
|
||||
|
@ -424,5 +430,7 @@ PickResultPointer CollisionPick::getHUDIntersection(const CollisionRegion& pick)
|
|||
}
|
||||
|
||||
Transform CollisionPick::getResultTransform() const {
|
||||
return Transform(getMathematicalPick().transform);
|
||||
Transform transform;
|
||||
transform.setTranslation(_mathPick.transform.getTranslation());
|
||||
return transform;
|
||||
}
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
class CollisionPick : public Pick<CollisionRegion> {
|
||||
public:
|
||||
CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine);
|
||||
CollisionPick(const PickFilter& filter, float maxDistance, bool enabled, bool scaleWithParent, CollisionRegion collisionRegion, PhysicsEnginePointer physicsEngine);
|
||||
|
||||
CollisionRegion getMathematicalPick() const override;
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override {
|
||||
|
@ -67,7 +67,8 @@ protected:
|
|||
void computeShapeInfoDimensionsOnly(const CollisionRegion& pick, ShapeInfo& shapeInfo, QSharedPointer<GeometryResource> resource);
|
||||
void filterIntersections(std::vector<ContactTestResult>& intersections) const;
|
||||
|
||||
CollisionRegion _mathPick;
|
||||
bool _scaleWithParent;
|
||||
|
||||
PhysicsEnginePointer _physicsEngine;
|
||||
QSharedPointer<GeometryResource> _cachedResource;
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 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 "JointParabolaPick.h"
|
||||
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
JointParabolaPick::JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
|
||||
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, PickFilter& filter, float maxDistance, bool enabled) :
|
||||
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
|
||||
_jointName(jointName),
|
||||
_posOffset(posOffset),
|
||||
_dirOffset(dirOffset)
|
||||
{
|
||||
}
|
||||
|
||||
PickParabola JointParabolaPick::getMathematicalPick() const {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
|
||||
bool useAvatarHead = _jointName == "Avatar";
|
||||
const int INVALID_JOINT = -1;
|
||||
if (jointIndex != INVALID_JOINT || useAvatarHead) {
|
||||
glm::vec3 jointPos = useAvatarHead ? myAvatar->getHeadPosition() : myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex);
|
||||
glm::quat jointRot = useAvatarHead ? myAvatar->getHeadOrientation() : myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex);
|
||||
glm::vec3 avatarPos = myAvatar->getWorldPosition();
|
||||
glm::quat avatarRot = myAvatar->getWorldOrientation();
|
||||
|
||||
glm::vec3 pos = useAvatarHead ? jointPos : avatarPos + (avatarRot * jointPos);
|
||||
glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot;
|
||||
|
||||
// Apply offset
|
||||
pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset));
|
||||
glm::vec3 dir = glm::normalize(rot * glm::normalize(_dirOffset));
|
||||
|
||||
return PickParabola(pos, getSpeed() * dir, getAcceleration());
|
||||
}
|
||||
|
||||
return PickParabola();
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_JointParabolaPick_h
|
||||
#define hifi_JointParabolaPick_h
|
||||
|
||||
#include "ParabolaPick.h"
|
||||
|
||||
class JointParabolaPick : public ParabolaPick {
|
||||
|
||||
public:
|
||||
JointParabolaPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset,
|
||||
float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
|
||||
PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickParabola getMathematicalPick() const override;
|
||||
|
||||
bool isLeftHand() const override { return (_jointName == "_CONTROLLER_LEFTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); }
|
||||
bool isRightHand() const override { return (_jointName == "_CONTROLLER_RIGHTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"); }
|
||||
|
||||
private:
|
||||
std::string _jointName;
|
||||
glm::vec3 _posOffset;
|
||||
glm::vec3 _dirOffset;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_JointParabolaPick_h
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// JointRayPick.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 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 "JointRayPick.h"
|
||||
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
RayPick(filter, maxDistance, enabled),
|
||||
_jointName(jointName),
|
||||
_posOffset(posOffset),
|
||||
_dirOffset(dirOffset)
|
||||
{
|
||||
}
|
||||
|
||||
PickRay JointRayPick::getMathematicalPick() const {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
|
||||
bool useAvatarHead = _jointName == "Avatar";
|
||||
const int INVALID_JOINT = -1;
|
||||
if (jointIndex != INVALID_JOINT || useAvatarHead) {
|
||||
glm::vec3 jointPos = useAvatarHead ? myAvatar->getHeadPosition() : myAvatar->getAbsoluteJointTranslationInObjectFrame(jointIndex);
|
||||
glm::quat jointRot = useAvatarHead ? myAvatar->getHeadOrientation() : myAvatar->getAbsoluteJointRotationInObjectFrame(jointIndex);
|
||||
glm::vec3 avatarPos = myAvatar->getWorldPosition();
|
||||
glm::quat avatarRot = myAvatar->getWorldOrientation();
|
||||
|
||||
glm::vec3 pos = useAvatarHead ? jointPos : avatarPos + (avatarRot * jointPos);
|
||||
glm::quat rot = useAvatarHead ? jointRot * glm::angleAxis(-PI / 2.0f, Vectors::RIGHT) : avatarRot * jointRot;
|
||||
|
||||
// Apply offset
|
||||
pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset));
|
||||
glm::vec3 dir = glm::normalize(rot * glm::normalize(_dirOffset));
|
||||
|
||||
return PickRay(pos, dir);
|
||||
}
|
||||
|
||||
return PickRay();
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// JointRayPick.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_JointRayPick_h
|
||||
#define hifi_JointRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
|
||||
class JointRayPick : public RayPick {
|
||||
|
||||
public:
|
||||
JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickRay getMathematicalPick() const override;
|
||||
|
||||
bool isLeftHand() const override { return (_jointName == "_CONTROLLER_LEFTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); }
|
||||
bool isRightHand() const override { return (_jointName == "_CONTROLLER_RIGHTHAND") || (_jointName == "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND"); }
|
||||
|
||||
private:
|
||||
std::string _jointName;
|
||||
glm::vec3 _posOffset;
|
||||
glm::vec3 _dirOffset;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_JointRayPick_h
|
|
@ -14,13 +14,14 @@
|
|||
#include "avatar/AvatarManager.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include "PickManager.h"
|
||||
#include "RayPick.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
|
||||
const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalTime, bool centerEndY, bool lockEnd,
|
||||
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled) :
|
||||
bool distanceScaleEnd, bool scaleWithParent, bool enabled) :
|
||||
PathPointer(PickQuery::Ray, rayProps, renderStates, defaultRenderStates, hover, triggers, faceAvatar, followNormal, followNormalTime,
|
||||
centerEndY, lockEnd, distanceScaleEnd, scaleWithAvatar, enabled)
|
||||
centerEndY, lockEnd, distanceScaleEnd, scaleWithParent, enabled)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -146,9 +147,9 @@ void LaserPointer::RenderState::disable() {
|
|||
}
|
||||
}
|
||||
|
||||
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
|
||||
StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
|
||||
QVariant endVariant = vec3toVariant(end);
|
||||
if (!getPathID().isNull()) {
|
||||
QVariantMap pathProps;
|
||||
|
@ -156,9 +157,7 @@ void LaserPointer::RenderState::update(const glm::vec3& origin, const glm::vec3&
|
|||
pathProps.insert("end", endVariant);
|
||||
pathProps.insert("visible", true);
|
||||
pathProps.insert("ignoreRayIntersection", doesPathIgnoreRays());
|
||||
if (scaleWithAvatar) {
|
||||
pathProps.insert("lineWidth", getLineWidth() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale());
|
||||
}
|
||||
pathProps.insert("lineWidth", getLineWidth() * parentScale);
|
||||
qApp->getOverlays().editOverlay(getPathID(), pathProps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,12 @@ public:
|
|||
const OverlayID& getPathID() const { return _pathID; }
|
||||
const bool& doesPathIgnoreRays() const { return _pathIgnoreRays; }
|
||||
|
||||
void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; }
|
||||
const float& getLineWidth() const { return _lineWidth; }
|
||||
void setLineWidth(float width) { _lineWidth = width; }
|
||||
float getLineWidth() const { return _lineWidth; }
|
||||
|
||||
void cleanup() override;
|
||||
void disable() override;
|
||||
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
|
||||
|
||||
private:
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
};
|
||||
|
||||
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover, const PointerTriggers& triggers,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool scaleWithAvatar, bool enabled);
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool scaleWithParent, bool enabled);
|
||||
|
||||
QVariantMap toVariantMap() const override;
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 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 "MouseParabolaPick.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "display-plugins/CompositorHelper.h"
|
||||
|
||||
MouseParabolaPick::MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
|
||||
bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled)
|
||||
{
|
||||
}
|
||||
|
||||
PickParabola MouseParabolaPick::getMathematicalPick() const {
|
||||
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
|
||||
if (position.isValid()) {
|
||||
QVariantMap posMap = position.toMap();
|
||||
PickRay pickRay = qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat());
|
||||
return PickParabola(pickRay.origin, getSpeed() * pickRay.direction, getAcceleration());
|
||||
}
|
||||
|
||||
return PickParabola();
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_MouseParabolaPick_h
|
||||
#define hifi_MouseParabolaPick_h
|
||||
|
||||
#include "ParabolaPick.h"
|
||||
|
||||
class MouseParabolaPick : public ParabolaPick {
|
||||
|
||||
public:
|
||||
MouseParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar,
|
||||
const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickParabola getMathematicalPick() const override;
|
||||
|
||||
bool isMouse() const override { return true; }
|
||||
};
|
||||
|
||||
#endif // hifi_MouseParabolaPick_h
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// MouseRayPick.cpp
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/19/2017
|
||||
// Copyright 2017 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 "MouseRayPick.h"
|
||||
|
||||
#include "Application.h"
|
||||
#include "display-plugins/CompositorHelper.h"
|
||||
|
||||
MouseRayPick::MouseRayPick(const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
RayPick(filter, maxDistance, enabled)
|
||||
{
|
||||
}
|
||||
|
||||
PickRay MouseRayPick::getMathematicalPick() const {
|
||||
QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition();
|
||||
if (position.isValid()) {
|
||||
QVariantMap posMap = position.toMap();
|
||||
return qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat());
|
||||
}
|
||||
|
||||
return PickRay();
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// MouseRayPick.h
|
||||
// interface/src/raypick
|
||||
//
|
||||
// Created by Sam Gondelman 7/19/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_MouseRayPick_h
|
||||
#define hifi_MouseRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
|
||||
class MouseRayPick : public RayPick {
|
||||
|
||||
public:
|
||||
MouseRayPick(const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickRay getMathematicalPick() const override;
|
||||
|
||||
bool isMouse() const override { return true; }
|
||||
};
|
||||
|
||||
#endif // hifi_MouseRayPick_h
|
|
@ -15,6 +15,46 @@
|
|||
#include "DependencyManager.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
ParabolaPick::ParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool rotateAccelerationWithParent, bool scaleWithParent, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
Pick(PickParabola(position, speed * direction, accelerationAxis), filter, maxDistance, enabled),
|
||||
_rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
|
||||
_rotateAccelerationWithParent(rotateAccelerationWithParent),
|
||||
_scaleWithParent(scaleWithParent),
|
||||
_speed(speed) {
|
||||
}
|
||||
|
||||
PickParabola ParabolaPick::getMathematicalPick() const {
|
||||
if (!parentTransform) {
|
||||
PickParabola mathPick = _mathPick;
|
||||
if (_rotateAccelerationWithAvatar) {
|
||||
mathPick.acceleration = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * mathPick.acceleration;
|
||||
}
|
||||
return mathPick;
|
||||
}
|
||||
|
||||
Transform currentParentTransform = parentTransform->getTransform();
|
||||
|
||||
glm::vec3 position = currentParentTransform.transform(_mathPick.origin);
|
||||
glm::vec3 velocity = _mathPick.velocity;
|
||||
if (_scaleWithParent) {
|
||||
velocity = currentParentTransform.transformDirection(velocity);
|
||||
} else {
|
||||
glm::vec3 transformedVelocity = currentParentTransform.transformDirection(velocity);
|
||||
velocity = glm::normalize(transformedVelocity) * _speed;
|
||||
}
|
||||
glm::vec3 acceleration = _mathPick.acceleration;
|
||||
if (_scaleWithParent) {
|
||||
acceleration *= currentParentTransform.getScale();
|
||||
}
|
||||
if (_rotateAccelerationWithAvatar) {
|
||||
acceleration = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * acceleration;
|
||||
} else if (_rotateAccelerationWithParent) {
|
||||
acceleration = currentParentTransform.getRotation() * acceleration;
|
||||
}
|
||||
|
||||
return PickParabola(position, velocity, acceleration);
|
||||
}
|
||||
|
||||
PickResultPointer ParabolaPick::getEntityIntersection(const PickParabola& pick) {
|
||||
if (glm::length2(pick.acceleration) > EPSILON && glm::length2(pick.velocity) > EPSILON) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
|
@ -60,18 +100,6 @@ PickResultPointer ParabolaPick::getHUDIntersection(const PickParabola& pick) {
|
|||
return std::make_shared<ParabolaPickResult>(pick.toVariantMap());
|
||||
}
|
||||
|
||||
float ParabolaPick::getSpeed() const {
|
||||
return (_scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() * _speed : _speed);
|
||||
}
|
||||
|
||||
glm::vec3 ParabolaPick::getAcceleration() const {
|
||||
float scale = (_scaleWithAvatar ? DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() : 1.0f);
|
||||
if (_rotateAccelerationWithAvatar) {
|
||||
return scale * (DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * _accelerationAxis);
|
||||
}
|
||||
return scale * _accelerationAxis;
|
||||
}
|
||||
|
||||
Transform ParabolaPick::getResultTransform() const {
|
||||
PickResultPointer result = getPrevPickResult();
|
||||
if (!result) {
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
class ParabolaPick : public Pick<PickParabola> {
|
||||
|
||||
public:
|
||||
ParabolaPick(float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar, bool scaleWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
Pick(filter, maxDistance, enabled), _speed(speed), _accelerationAxis(accelerationAxis), _rotateAccelerationWithAvatar(rotateAccelerationWithAvatar),
|
||||
_scaleWithAvatar(scaleWithAvatar) {}
|
||||
ParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& acceleration, bool rotateAccelerationWithAvatar, bool rotateAccelerationWithParent, bool scaleWithParent, const PickFilter& filter, float maxDistance, bool enabled);
|
||||
|
||||
PickParabola getMathematicalPick() const override;
|
||||
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<ParabolaPickResult>(pickVariant); }
|
||||
PickResultPointer getEntityIntersection(const PickParabola& pick) override;
|
||||
|
@ -86,13 +86,11 @@ public:
|
|||
Transform getResultTransform() const override;
|
||||
|
||||
protected:
|
||||
float _speed;
|
||||
glm::vec3 _accelerationAxis;
|
||||
bool _rotateAccelerationWithAvatar;
|
||||
bool _scaleWithAvatar;
|
||||
|
||||
float getSpeed() const;
|
||||
glm::vec3 getAcceleration() const;
|
||||
bool _rotateAccelerationWithParent;
|
||||
bool _scaleWithParent;
|
||||
// Cached magnitude of _mathPick.velocity
|
||||
float _speed;
|
||||
};
|
||||
|
||||
#endif // hifi_ParabolaPick_h
|
||||
|
|
|
@ -204,9 +204,9 @@ void ParabolaPointer::RenderState::editParabola(const glm::vec3& color, float al
|
|||
}
|
||||
}
|
||||
|
||||
void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||
StartEndRenderState::update(origin, end, surfaceNormal, scaleWithAvatar, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
|
||||
StartEndRenderState::update(origin, end, surfaceNormal, parentScale, distanceScaleEnd, centerEndY, faceAvatar, followNormal, followNormalStrength, distance, pickResult);
|
||||
auto parabolaPickResult = std::static_pointer_cast<ParabolaPickResult>(pickResult);
|
||||
if (parabolaPickResult && render::Item::isValidID(_pathID)) {
|
||||
render::Transaction transaction;
|
||||
|
@ -216,7 +216,7 @@ void ParabolaPointer::RenderState::update(const glm::vec3& origin, const glm::ve
|
|||
glm::vec3 velocity = parabola.velocity;
|
||||
glm::vec3 acceleration = parabola.acceleration;
|
||||
float parabolicDistance = distance > 0.0f ? distance : parabolaPickResult->parabolicDistance;
|
||||
float width = scaleWithAvatar ? getPathWidth() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale() : getPathWidth();
|
||||
float width = getPathWidth() * parentScale;
|
||||
transaction.updateItem<ParabolaRenderItem>(_pathID, [origin, velocity, acceleration, parabolicDistance, width](ParabolaRenderItem& item) {
|
||||
item.setVisible(true);
|
||||
item.setOrigin(origin);
|
||||
|
|
|
@ -79,7 +79,7 @@ public:
|
|||
};
|
||||
|
||||
RenderState() {}
|
||||
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float pathWidth,
|
||||
RenderState(const OverlayID& startID, const OverlayID& endID, const glm::vec3& pathColor, float pathAlpha, float parentScale,
|
||||
bool isVisibleInSecondaryCamera, bool drawInFront, bool pathEnabled);
|
||||
|
||||
void setPathWidth(float width) { _pathWidth = width; }
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
|
||||
void cleanup() override;
|
||||
void disable() override;
|
||||
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) override;
|
||||
|
||||
void editParabola(const glm::vec3& color, float alpha, float width, bool isVisibleInSecondaryCamera, bool drawInFront, bool enabled);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
bool hover, const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd,
|
||||
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled) :
|
||||
bool distanceScaleEnd, bool scaleWithParent, bool enabled) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createPick(type, rayProps), enabled, hover),
|
||||
_renderStates(renderStates),
|
||||
_defaultRenderStates(defaultRenderStates),
|
||||
|
@ -28,7 +28,7 @@ PathPointer::PathPointer(PickQuery::PickType type, const QVariant& rayProps, con
|
|||
_centerEndY(centerEndY),
|
||||
_lockEnd(lockEnd),
|
||||
_distanceScaleEnd(distanceScaleEnd),
|
||||
_scaleWithAvatar(scaleWithAvatar)
|
||||
_scaleWithParent(scaleWithParent)
|
||||
{
|
||||
for (auto& state : _renderStates) {
|
||||
if (!enabled || state.first != _currentRenderState) {
|
||||
|
@ -146,12 +146,18 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
|
|||
IntersectionType type = getPickedObjectType(pickResult);
|
||||
auto renderState = _renderStates.find(_currentRenderState);
|
||||
auto defaultRenderState = _defaultRenderStates.find(_currentRenderState);
|
||||
float parentScale = 1.0f;
|
||||
if (_enabled && _scaleWithParent) {
|
||||
glm::vec3 dimensions = DependencyManager::get<PickManager>()->getParentTransform(_pickUID).getScale();
|
||||
parentScale = glm::max(glm::max(dimensions.x, dimensions.y), dimensions.z);
|
||||
}
|
||||
|
||||
if (_enabled && !_currentRenderState.empty() && renderState != _renderStates.end() &&
|
||||
(type != IntersectionType::NONE || _pathLength > 0.0f)) {
|
||||
glm::vec3 origin = getPickOrigin(pickResult);
|
||||
glm::vec3 end = getPickEnd(pickResult, _pathLength);
|
||||
glm::vec3 surfaceNormal = getPickedObjectNormal(pickResult);
|
||||
renderState->second->update(origin, end, surfaceNormal, _scaleWithAvatar, _distanceScaleEnd, _centerEndY, _faceAvatar,
|
||||
renderState->second->update(origin, end, surfaceNormal, parentScale, _distanceScaleEnd, _centerEndY, _faceAvatar,
|
||||
_followNormal, _followNormalStrength, _pathLength, pickResult);
|
||||
if (defaultRenderState != _defaultRenderStates.end() && defaultRenderState->second.second->isEnabled()) {
|
||||
defaultRenderState->second.second->disable();
|
||||
|
@ -162,7 +168,7 @@ void PathPointer::updateVisuals(const PickResultPointer& pickResult) {
|
|||
}
|
||||
glm::vec3 origin = getPickOrigin(pickResult);
|
||||
glm::vec3 end = getPickEnd(pickResult, defaultRenderState->second.first);
|
||||
defaultRenderState->second.second->update(origin, end, Vectors::UP, _scaleWithAvatar, _distanceScaleEnd, _centerEndY,
|
||||
defaultRenderState->second.second->update(origin, end, Vectors::UP, parentScale, _distanceScaleEnd, _centerEndY,
|
||||
_faceAvatar, _followNormal, _followNormalStrength, defaultRenderState->second.first, pickResult);
|
||||
} else if (!_currentRenderState.empty()) {
|
||||
if (renderState != _renderStates.end() && renderState->second->isEnabled()) {
|
||||
|
@ -281,15 +287,13 @@ void StartEndRenderState::disable() {
|
|||
_enabled = false;
|
||||
}
|
||||
|
||||
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult) {
|
||||
if (!getStartID().isNull()) {
|
||||
QVariantMap startProps;
|
||||
startProps.insert("position", vec3toVariant(origin));
|
||||
startProps.insert("visible", true);
|
||||
if (scaleWithAvatar) {
|
||||
startProps.insert("dimensions", vec3toVariant(getStartDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale()));
|
||||
}
|
||||
startProps.insert("dimensions", vec3toVariant(getStartDim() * parentScale));
|
||||
startProps.insert("ignoreRayIntersection", doesStartIgnoreRays());
|
||||
qApp->getOverlays().editOverlay(getStartID(), startProps);
|
||||
}
|
||||
|
@ -300,8 +304,8 @@ void StartEndRenderState::update(const glm::vec3& origin, const glm::vec3& end,
|
|||
if (distanceScaleEnd) {
|
||||
dim = getEndDim() * glm::distance(origin, end);
|
||||
endProps.insert("dimensions", vec3toVariant(dim));
|
||||
} else if (scaleWithAvatar) {
|
||||
dim = getEndDim() * DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
} else {
|
||||
dim = getEndDim() * parentScale;
|
||||
endProps.insert("dimensions", vec3toVariant(dim));
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
|
||||
virtual void cleanup();
|
||||
virtual void disable();
|
||||
virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, bool scaleWithAvatar, bool distanceScaleEnd, bool centerEndY,
|
||||
virtual void update(const glm::vec3& origin, const glm::vec3& end, const glm::vec3& surfaceNormal, float parentScale, bool distanceScaleEnd, bool centerEndY,
|
||||
bool faceAvatar, bool followNormal, float followNormalStrength, float distance, const PickResultPointer& pickResult);
|
||||
|
||||
bool isEnabled() const { return _enabled; }
|
||||
|
@ -74,7 +74,7 @@ class PathPointer : public Pointer {
|
|||
public:
|
||||
PathPointer(PickQuery::PickType type, const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
bool hover, const PointerTriggers& triggers, bool faceAvatar, bool followNormal, float followNormalStrength, bool centerEndY, bool lockEnd,
|
||||
bool distanceScaleEnd, bool scaleWithAvatar, bool enabled);
|
||||
bool distanceScaleEnd, bool scaleWithParent, bool enabled);
|
||||
virtual ~PathPointer();
|
||||
|
||||
void setRenderState(const std::string& state) override;
|
||||
|
@ -98,7 +98,7 @@ protected:
|
|||
bool _centerEndY;
|
||||
bool _lockEnd;
|
||||
bool _distanceScaleEnd;
|
||||
bool _scaleWithAvatar;
|
||||
bool _scaleWithParent;
|
||||
LockEndObject _lockEndObject;
|
||||
|
||||
struct TriggerState {
|
||||
|
|
|
@ -14,13 +14,9 @@
|
|||
#include "Application.h"
|
||||
#include <PickManager.h>
|
||||
|
||||
#include "StaticRayPick.h"
|
||||
#include "JointRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
#include "RayPick.h"
|
||||
#include "StylusPick.h"
|
||||
#include "StaticParabolaPick.h"
|
||||
#include "JointParabolaPick.h"
|
||||
#include "MouseParabolaPick.h"
|
||||
#include "ParabolaPick.h"
|
||||
#include "CollisionPick.h"
|
||||
|
||||
#include "SpatialParentFinder.h"
|
||||
|
@ -56,9 +52,9 @@ unsigned int PickScriptingInterface::createPick(const PickQuery::PickType type,
|
|||
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
|
||||
* @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
|
||||
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
|
||||
* @property {string} [joint] Only for Joint or Mouse Ray Picks. If "Mouse", it will create a Ray Pick that follows the system mouse, in desktop or HMD.
|
||||
* If "Avatar", it will create a Joint Ray Pick that follows your avatar's head. Otherwise, it will create a Joint Ray Pick that follows the given joint, if it
|
||||
* exists on your current avatar.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Ray Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
|
||||
* @property {Vec3} [dirOffset=Vec3.UP] Only for Joint Ray Picks. A local joint direction offset. x = upward, y = forward, z = lateral
|
||||
* @property {Vec3} [position] Only for Static Ray Picks. The world-space origin of the ray.
|
||||
|
@ -82,38 +78,29 @@ unsigned int PickScriptingInterface::createRayPick(const QVariant& properties) {
|
|||
maxDistance = propMap["maxDistance"].toFloat();
|
||||
}
|
||||
|
||||
if (propMap["joint"].isValid()) {
|
||||
std::string jointName = propMap["joint"].toString().toStdString();
|
||||
|
||||
if (jointName != "Mouse") {
|
||||
// x = upward, y = forward, z = lateral
|
||||
glm::vec3 posOffset = Vectors::ZERO;
|
||||
if (propMap["posOffset"].isValid()) {
|
||||
posOffset = vec3FromVariant(propMap["posOffset"]);
|
||||
}
|
||||
|
||||
glm::vec3 dirOffset = Vectors::UP;
|
||||
if (propMap["dirOffset"].isValid()) {
|
||||
dirOffset = vec3FromVariant(propMap["dirOffset"]);
|
||||
}
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled));
|
||||
|
||||
} else {
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(filter, maxDistance, enabled));
|
||||
}
|
||||
} else if (propMap["position"].isValid()) {
|
||||
glm::vec3 position = vec3FromVariant(propMap["position"]);
|
||||
|
||||
glm::vec3 direction = -Vectors::UP;
|
||||
if (propMap["direction"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["direction"]);
|
||||
}
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled));
|
||||
glm::vec3 position = Vectors::ZERO;
|
||||
if (propMap["position"].isValid()) {
|
||||
position = vec3FromVariant(propMap["position"]);
|
||||
} else if (propMap["posOffset"].isValid()) {
|
||||
position = vec3FromVariant(propMap["posOffset"]);
|
||||
}
|
||||
|
||||
return PickManager::INVALID_PICK_ID;
|
||||
// direction has two defaults to ensure compatibility with older scripts
|
||||
// Joint ray picks had default direction = Vec3.UP
|
||||
// Static ray picks had default direction = -Vec3.UP
|
||||
glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::UP;
|
||||
if (propMap["orientation"].isValid()) {
|
||||
direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;
|
||||
} else if (propMap["direction"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["direction"]);
|
||||
} else if (propMap["dirOffset"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["dirOffset"]);
|
||||
}
|
||||
|
||||
auto rayPick = std::make_shared<RayPick>(position, direction, filter, maxDistance, enabled);
|
||||
setParentTransform(rayPick, propMap);
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, rayPick);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -153,23 +140,25 @@ unsigned int PickScriptingInterface::createStylusPick(const QVariant& properties
|
|||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Stylus, std::make_shared<StylusPick>(side, filter, maxDistance, enabled));
|
||||
}
|
||||
|
||||
// NOTE: Laser pointer still uses scaleWithAvatar. Until scaleWithAvatar is also deprecated for pointers, scaleWithAvatar should not be removed from the pick API.
|
||||
/**jsdoc
|
||||
* A set of properties that can be passed to {@link Picks.createPick} to create a new Parabola Pick.
|
||||
* @typedef {object} Picks.ParabolaPickProperties
|
||||
* @property {boolean} [enabled=false] If this Pick should start enabled or not. Disabled Picks do not updated their pick results.
|
||||
* @property {number} [filter=Picks.PICK_NOTHING] The filter for this Pick to use, constructed using filter flags combined using bitwise OR.
|
||||
* @property {number} [maxDistance=0.0] The max distance at which this Pick will intersect. 0.0 = no max. < 0.0 is invalid.
|
||||
* @property {string} [joint] Only for Joint or Mouse Parabola Picks. If "Mouse", it will create a Parabola Pick that follows the system mouse, in desktop or HMD.
|
||||
* If "Avatar", it will create a Joint Parabola Pick that follows your avatar's head. Otherwise, it will create a Joint Parabola Pick that follows the given joint, if it
|
||||
* exists on your current avatar.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {Vec3} [posOffset=Vec3.ZERO] Only for Joint Parabola Picks. A local joint position offset, in meters. x = upward, y = forward, z = lateral
|
||||
* @property {Vec3} [dirOffset=Vec3.UP] Only for Joint Parabola Picks. A local joint direction offset. x = upward, y = forward, z = lateral
|
||||
* @property {Vec3} [position] Only for Static Parabola Picks. The world-space origin of the parabola segment.
|
||||
* @property {Vec3} [direction=-Vec3.FRONT] Only for Static Parabola Picks. The world-space direction of the parabola segment.
|
||||
* @property {number} [speed=1] The initial speed of the parabola, i.e. the initial speed of the projectile whose trajectory defines the parabola.
|
||||
* @property {Vec3} [accelerationAxis=-Vec3.UP] The acceleration of the parabola, i.e. the acceleration of the projectile whose trajectory defines the parabola, both magnitude and direction.
|
||||
* @property {boolean} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with your avatar's local Y axis.
|
||||
* @property {boolean} [scaleWithAvatar=false] If true, the velocity and acceleration of the Pick will scale linearly with your avatar.
|
||||
* @property {boolean} [rotateAccelerationWithAvatar=true] Whether or not the acceleration axis should rotate with the avatar's local Y axis.
|
||||
* @property {boolean} [rotateAccelerationWithParent=false] Whether or not the acceleration axis should rotate with the parent's local Y axis, if available.
|
||||
* @property {boolean} [scaleWithParent=true] If true, the velocity and acceleration of the Pick will scale linearly with the parent, if available. scaleWithAvatar is an alias but is deprecated.
|
||||
*/
|
||||
unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properties) {
|
||||
QVariantMap propMap = properties.toMap();
|
||||
|
@ -204,48 +193,37 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
|
|||
rotateAccelerationWithAvatar = propMap["rotateAccelerationWithAvatar"].toBool();
|
||||
}
|
||||
|
||||
bool scaleWithAvatar = false;
|
||||
if (propMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithAvatar = propMap["scaleWithAvatar"].toBool();
|
||||
bool rotateAccelerationWithParent = false;
|
||||
if (propMap["rotateAccelerationWithParent"].isValid()) {
|
||||
rotateAccelerationWithParent = propMap["rotateAccelerationWithParent"].toBool();
|
||||
}
|
||||
|
||||
if (propMap["joint"].isValid()) {
|
||||
std::string jointName = propMap["joint"].toString().toStdString();
|
||||
|
||||
if (jointName != "Mouse") {
|
||||
// x = upward, y = forward, z = lateral
|
||||
glm::vec3 posOffset = Vectors::ZERO;
|
||||
if (propMap["posOffset"].isValid()) {
|
||||
posOffset = vec3FromVariant(propMap["posOffset"]);
|
||||
}
|
||||
|
||||
glm::vec3 dirOffset = Vectors::UP;
|
||||
if (propMap["dirOffset"].isValid()) {
|
||||
dirOffset = vec3FromVariant(propMap["dirOffset"]);
|
||||
}
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<JointParabolaPick>(jointName, posOffset, dirOffset,
|
||||
speed, accelerationAxis, rotateAccelerationWithAvatar,
|
||||
scaleWithAvatar, filter, maxDistance, enabled));
|
||||
|
||||
} else {
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<MouseParabolaPick>(speed, accelerationAxis, rotateAccelerationWithAvatar,
|
||||
scaleWithAvatar, filter, maxDistance, enabled));
|
||||
}
|
||||
} else if (propMap["position"].isValid()) {
|
||||
glm::vec3 position = vec3FromVariant(propMap["position"]);
|
||||
|
||||
glm::vec3 direction = -Vectors::FRONT;
|
||||
if (propMap["direction"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["direction"]);
|
||||
}
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, std::make_shared<StaticParabolaPick>(position, direction, speed, accelerationAxis,
|
||||
rotateAccelerationWithAvatar, scaleWithAvatar,
|
||||
filter, maxDistance, enabled));
|
||||
bool scaleWithParent = true;
|
||||
if (propMap["scaleWithParent"].isValid()) {
|
||||
scaleWithParent = propMap["scaleWithParent"].toBool();
|
||||
} else if (propMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithParent = propMap["scaleWithAvatar"].toBool();
|
||||
}
|
||||
|
||||
return PickManager::INVALID_PICK_ID;
|
||||
glm::vec3 position = Vectors::ZERO;
|
||||
glm::vec3 direction = propMap["joint"].isValid() ? Vectors::UP : -Vectors::FRONT;
|
||||
if (propMap["position"].isValid()) {
|
||||
position = vec3FromVariant(propMap["position"]);
|
||||
} else if (propMap["posOffset"].isValid()) {
|
||||
position = vec3FromVariant(propMap["posOffset"]);
|
||||
}
|
||||
if (propMap["orientation"].isValid()) {
|
||||
direction = quatFromVariant(propMap["orientation"]) * Vectors::UP;
|
||||
} else if (propMap["direction"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["direction"]);
|
||||
} else if (propMap["dirOffset"].isValid()) {
|
||||
direction = vec3FromVariant(propMap["dirOffset"]);
|
||||
}
|
||||
|
||||
auto parabolaPick = std::make_shared<ParabolaPick>(position, direction, speed, accelerationAxis,
|
||||
rotateAccelerationWithAvatar, rotateAccelerationWithParent, scaleWithParent, filter, maxDistance, enabled);
|
||||
setParentTransform(parabolaPick, propMap);
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Parabola, parabolaPick);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -272,9 +250,10 @@ unsigned int PickScriptingInterface::createParabolaPick(const QVariant& properti
|
|||
* The depth is measured in world space, but will scale with the parent if defined.
|
||||
* @property {CollisionMask} [collisionGroup=8] - The type of object this collision pick collides as. Objects whose collision masks overlap with the pick's collision group
|
||||
* will be considered colliding with the pick.
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, or an overlay.
|
||||
* @property {number} parentJointIndex - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {Uuid} parentID - The ID of the parent, either an avatar, an entity, an overlay, or a pick.
|
||||
* @property {number} [parentJointIndex=0] - The joint of the parent to parent to, for example, the joints on the model of an avatar. (default = 0, no joint)
|
||||
* @property {string} joint - If "Mouse," parents the pick to the mouse. If "Avatar," parents the pick to MyAvatar's head. Otherwise, parents to the joint of the given name on MyAvatar.
|
||||
* @property {boolean} [scaleWithParent=true] If true, the collision pick's dimensions and threshold will adjust according to the scale of the parent.
|
||||
*/
|
||||
unsigned int PickScriptingInterface::createCollisionPick(const QVariant& properties) {
|
||||
QVariantMap propMap = properties.toMap();
|
||||
|
@ -294,9 +273,14 @@ unsigned int PickScriptingInterface::createCollisionPick(const QVariant& propert
|
|||
maxDistance = propMap["maxDistance"].toFloat();
|
||||
}
|
||||
|
||||
bool scaleWithParent = true;
|
||||
if (propMap["scaleWithParent"].isValid()) {
|
||||
scaleWithParent = propMap["scaleWithParent"].toBool();
|
||||
}
|
||||
|
||||
CollisionRegion collisionRegion(propMap);
|
||||
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, collisionRegion, qApp->getPhysicsEngine());
|
||||
collisionPick->parentTransform = createTransformNode(propMap);
|
||||
auto collisionPick = std::make_shared<CollisionPick>(filter, maxDistance, enabled, scaleWithParent, collisionRegion, qApp->getPhysicsEngine());
|
||||
setParentTransform(collisionPick, propMap);
|
||||
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Collision, collisionPick);
|
||||
}
|
||||
|
@ -373,51 +357,63 @@ void PickScriptingInterface::setPerFrameTimeBudget(unsigned int numUsecs) {
|
|||
DependencyManager::get<PickManager>()->setPerFrameTimeBudget(numUsecs);
|
||||
}
|
||||
|
||||
std::shared_ptr<TransformNode> PickScriptingInterface::createTransformNode(const QVariantMap& propMap) {
|
||||
if (propMap["parentID"].isValid()) {
|
||||
QUuid parentUuid = propMap["parentID"].toUuid();
|
||||
if (!parentUuid.isNull()) {
|
||||
// Infer object type from parentID
|
||||
// For now, assume a QUuuid is a SpatiallyNestable. This should change when picks are converted over to QUuids.
|
||||
bool success;
|
||||
std::weak_ptr<SpatiallyNestable> nestablePointer = DependencyManager::get<SpatialParentFinder>()->find(parentUuid, success, nullptr);
|
||||
int parentJointIndex = 0;
|
||||
if (propMap["parentJointIndex"].isValid()) {
|
||||
parentJointIndex = propMap["parentJointIndex"].toInt();
|
||||
}
|
||||
auto sharedNestablePointer = nestablePointer.lock();
|
||||
if (success && sharedNestablePointer) {
|
||||
NestableType nestableType = sharedNestablePointer->getNestableType();
|
||||
if (nestableType == NestableType::Avatar) {
|
||||
return std::make_shared<AvatarTransformNode>(std::static_pointer_cast<Avatar>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Overlay) {
|
||||
return std::make_shared<OverlayTransformNode>(std::static_pointer_cast<Base3DOverlay>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Entity) {
|
||||
return std::make_shared<EntityTransformNode>(std::static_pointer_cast<EntityItem>(sharedNestablePointer), parentJointIndex);
|
||||
} else {
|
||||
return std::make_shared<NestableTransformNode>(nestablePointer, parentJointIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
void PickScriptingInterface::setParentTransform(std::shared_ptr<PickQuery> pick, const QVariantMap& propMap) {
|
||||
QUuid parentUuid;
|
||||
int parentJointIndex = 0;
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
unsigned int pickID = propMap["parentID"].toUInt();
|
||||
if (pickID != 0) {
|
||||
return std::make_shared<PickTransformNode>(pickID);
|
||||
if (propMap["parentID"].isValid()) {
|
||||
parentUuid = propMap["parentID"].toUuid();
|
||||
if (propMap["parentJointIndex"].isValid()) {
|
||||
parentJointIndex = propMap["parentJointIndex"].toInt();
|
||||
}
|
||||
}
|
||||
|
||||
if (propMap["joint"].isValid()) {
|
||||
} else if (propMap["joint"].isValid()) {
|
||||
QString joint = propMap["joint"].toString();
|
||||
if (joint == "Mouse") {
|
||||
return std::make_shared<MouseTransformNode>();
|
||||
pick->parentTransform = std::make_shared<MouseTransformNode>();
|
||||
pick->setJointState(PickQuery::JOINT_STATE_MOUSE);
|
||||
return;
|
||||
} else if (joint == "Avatar") {
|
||||
return std::make_shared<MyAvatarHeadTransformNode>();
|
||||
} else if (!joint.isNull()) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
int jointIndex = myAvatar->getJointIndex(joint);
|
||||
return std::make_shared<AvatarTransformNode>(myAvatar, jointIndex);
|
||||
pick->parentTransform = std::make_shared<MyAvatarHeadTransformNode>();
|
||||
return;
|
||||
} else {
|
||||
parentUuid = myAvatar->getSessionUUID();
|
||||
parentJointIndex = myAvatar->getJointIndex(joint);
|
||||
}
|
||||
}
|
||||
|
||||
return std::shared_ptr<TransformNode>();
|
||||
if (parentUuid == myAvatar->getSessionUUID()) {
|
||||
if (parentJointIndex == CONTROLLER_LEFTHAND_INDEX || parentJointIndex == CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX) {
|
||||
pick->setJointState(PickQuery::JOINT_STATE_LEFT_HAND);
|
||||
} else if (parentJointIndex == CONTROLLER_RIGHTHAND_INDEX || parentJointIndex == CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX) {
|
||||
pick->setJointState(PickQuery::JOINT_STATE_RIGHT_HAND);
|
||||
}
|
||||
|
||||
pick->parentTransform = std::make_shared<AvatarTransformNode>(myAvatar, parentJointIndex);
|
||||
} else if (!parentUuid.isNull()) {
|
||||
// Infer object type from parentID
|
||||
// For now, assume a QUuid is a SpatiallyNestable. This should change when picks are converted over to QUuids.
|
||||
bool success;
|
||||
std::weak_ptr<SpatiallyNestable> nestablePointer = DependencyManager::get<SpatialParentFinder>()->find(parentUuid, success, nullptr);
|
||||
auto sharedNestablePointer = nestablePointer.lock();
|
||||
|
||||
if (success && sharedNestablePointer) {
|
||||
NestableType nestableType = sharedNestablePointer->getNestableType();
|
||||
if (nestableType == NestableType::Avatar) {
|
||||
pick->parentTransform = std::make_shared<AvatarTransformNode>(std::static_pointer_cast<Avatar>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Overlay) {
|
||||
pick->parentTransform = std::make_shared<OverlayTransformNode>(std::static_pointer_cast<Base3DOverlay>(sharedNestablePointer), parentJointIndex);
|
||||
} else if (nestableType == NestableType::Entity) {
|
||||
pick->parentTransform = std::make_shared<EntityTransformNode>(std::static_pointer_cast<EntityItem>(sharedNestablePointer), parentJointIndex);
|
||||
} else {
|
||||
pick->parentTransform = std::make_shared<NestableTransformNode>(nestablePointer, parentJointIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unsigned int pickID = propMap["parentID"].toUInt();
|
||||
|
||||
if (pickID != 0) {
|
||||
pick->parentTransform = std::make_shared<PickTransformNode>(pickID);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -320,7 +320,7 @@ public slots:
|
|||
static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
|
||||
|
||||
protected:
|
||||
static std::shared_ptr<TransformNode> createTransformNode(const QVariantMap& propMap);
|
||||
static void setParentTransform(std::shared_ptr<PickQuery> pick, const QVariantMap& propMap);
|
||||
};
|
||||
|
||||
#endif // hifi_PickScriptingInterface_h
|
||||
|
|
|
@ -97,7 +97,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
|
|||
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
||||
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
|
||||
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
||||
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
||||
* @property {boolean} [scaleWithParent=false] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated.
|
||||
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
||||
* @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. <code>0-1</code>. If 0 or 1,
|
||||
* the normal will follow exactly.
|
||||
|
@ -134,9 +134,11 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
|||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||
}
|
||||
|
||||
bool scaleWithAvatar = false;
|
||||
if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
|
||||
bool scaleWithParent = false;
|
||||
if (propertyMap["scaleWithParent"].isValid()) {
|
||||
scaleWithParent = propertyMap["scaleWithParent"].toBool();
|
||||
} else if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
|
||||
}
|
||||
|
||||
bool followNormal = false;
|
||||
|
@ -207,7 +209,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
|||
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
|
||||
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd,
|
||||
distanceScaleEnd, scaleWithAvatar, enabled));
|
||||
distanceScaleEnd, scaleWithParent, enabled));
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -249,7 +251,7 @@ unsigned int PointerScriptingInterface::createLaserPointer(const QVariant& prope
|
|||
* @property {boolean} [centerEndY=true] If false, the end of the Pointer will be moved up by half of its height.
|
||||
* @property {boolean} [lockEnd=false] If true, the end of the Pointer will lock on to the center of the object at which the pointer is pointing.
|
||||
* @property {boolean} [distanceScaleEnd=false] If true, the dimensions of the end of the Pointer will scale linearly with distance.
|
||||
* @property {boolean} [scaleWithAvatar=false] If true, the width of the Pointer's path will scale linearly with your avatar's scale.
|
||||
* @property {boolean} [scaleWithParent=true] If true, the width of the Pointer's path will scale linearly with the pick parent's scale. scaleWithAvatar is an alias but is deprecated.
|
||||
* @property {boolean} [followNormal=false] If true, the end of the Pointer will rotate to follow the normal of the intersected surface.
|
||||
* @property {number} [followNormalStrength=0.0] The strength of the interpolation between the real normal and the visual normal if followNormal is true. <code>0-1</code>. If 0 or 1,
|
||||
* the normal will follow exactly.
|
||||
|
@ -286,9 +288,11 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
|
|||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||
}
|
||||
|
||||
bool scaleWithAvatar = false;
|
||||
if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool();
|
||||
bool scaleWithParent = true;
|
||||
if (propertyMap["scaleWithParent"].isValid()) {
|
||||
scaleWithParent = propertyMap["scaleWithParent"].toBool();
|
||||
} else if (propertyMap["scaleWithAvatar"].isValid()) {
|
||||
scaleWithParent = propertyMap["scaleWithAvatar"].toBool();
|
||||
}
|
||||
|
||||
bool followNormal = false;
|
||||
|
@ -359,7 +363,7 @@ unsigned int PointerScriptingInterface::createParabolaPointer(const QVariant& pr
|
|||
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<ParabolaPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
|
||||
faceAvatar, followNormal, followNormalStrength, centerEndY, lockEnd, distanceScaleEnd,
|
||||
scaleWithAvatar, enabled));
|
||||
scaleWithParent, enabled));
|
||||
}
|
||||
|
||||
void PointerScriptingInterface::editRenderState(unsigned int uid, const QString& renderState, const QVariant& properties) const {
|
||||
|
|
|
@ -15,6 +15,17 @@
|
|||
#include "DependencyManager.h"
|
||||
#include "PickManager.h"
|
||||
|
||||
PickRay RayPick::getMathematicalPick() const {
|
||||
if (!parentTransform) {
|
||||
return _mathPick;
|
||||
}
|
||||
|
||||
Transform currentParentTransform = parentTransform->getTransform();
|
||||
glm::vec3 origin = currentParentTransform.transform(_mathPick.origin);
|
||||
glm::vec3 direction = glm::normalize(currentParentTransform.transformDirection(_mathPick.direction));
|
||||
return PickRay(origin, direction);
|
||||
}
|
||||
|
||||
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
||||
bool precisionPicking = !(getFilter().doesPickCoarse() || DependencyManager::get<PickManager>()->getForceCoarsePicking());
|
||||
RayToEntityIntersectionResult entityRes =
|
||||
|
|
|
@ -70,7 +70,11 @@ public:
|
|||
class RayPick : public Pick<PickRay> {
|
||||
|
||||
public:
|
||||
RayPick(const PickFilter& filter, float maxDistance, bool enabled) : Pick(filter, maxDistance, enabled) {}
|
||||
RayPick(glm::vec3 position, glm::vec3 direction, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
Pick(PickRay(position, direction), filter, maxDistance, enabled) {
|
||||
}
|
||||
|
||||
PickRay getMathematicalPick() const override;
|
||||
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(pickVariant); }
|
||||
PickResultPointer getEntityIntersection(const PickRay& pick) override;
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
|
||||
#include <PickManager.h>
|
||||
|
||||
#include "StaticRayPick.h"
|
||||
#include "JointRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
|
||||
unsigned int RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
||||
return DependencyManager::get<PickScriptingInterface>()->createRayPick(properties);
|
||||
}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 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 "StaticParabolaPick.h"
|
||||
|
||||
StaticParabolaPick::StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis,
|
||||
bool scaleWithAvatar, bool rotateAccelerationWithAvatar, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
ParabolaPick(speed, accelerationAxis, rotateAccelerationWithAvatar, scaleWithAvatar, filter, maxDistance, enabled),
|
||||
_position(position), _velocity(direction)
|
||||
{
|
||||
}
|
||||
|
||||
PickParabola StaticParabolaPick::getMathematicalPick() const {
|
||||
return PickParabola(_position, getSpeed() * _velocity, getAcceleration());
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/2/2018
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_StaticParabolaPick_h
|
||||
#define hifi_StaticParabolaPick_h
|
||||
|
||||
#include "ParabolaPick.h"
|
||||
|
||||
class StaticParabolaPick : public ParabolaPick {
|
||||
|
||||
public:
|
||||
StaticParabolaPick(const glm::vec3& position, const glm::vec3& direction, float speed, const glm::vec3& accelerationAxis, bool rotateAccelerationWithAvatar,
|
||||
bool scaleWithAvatar, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickParabola getMathematicalPick() const override;
|
||||
|
||||
private:
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _velocity;
|
||||
};
|
||||
|
||||
#endif // hifi_StaticParabolaPick_h
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 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 "StaticRayPick.h"
|
||||
|
||||
StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
RayPick(filter, maxDistance, enabled),
|
||||
_pickRay(position, direction)
|
||||
{
|
||||
}
|
||||
|
||||
PickRay StaticRayPick::getMathematicalPick() const {
|
||||
return _pickRay;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// Created by Sam Gondelman 7/11/2017
|
||||
// Copyright 2017 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_StaticRayPick_h
|
||||
#define hifi_StaticRayPick_h
|
||||
|
||||
#include "RayPick.h"
|
||||
|
||||
class StaticRayPick : public RayPick {
|
||||
|
||||
public:
|
||||
StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance = 0.0f, bool enabled = false);
|
||||
|
||||
PickRay getMathematicalPick() const override;
|
||||
|
||||
private:
|
||||
PickRay _pickRay;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_StaticRayPick_h
|
|
@ -65,8 +65,7 @@ bool StylusPickResult::checkOrFilterAgainstMaxDistance(float maxDistance) {
|
|||
}
|
||||
|
||||
StylusPick::StylusPick(Side side, const PickFilter& filter, float maxDistance, bool enabled) :
|
||||
Pick(filter, maxDistance, enabled),
|
||||
_side(side)
|
||||
Pick(StylusTip(side), filter, maxDistance, enabled)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -130,9 +129,9 @@ static StylusTip getControllerWorldLocation(Side side) {
|
|||
StylusTip StylusPick::getMathematicalPick() const {
|
||||
StylusTip result;
|
||||
if (qApp->getPreferAvatarFingerOverStylus()) {
|
||||
result = getFingerWorldLocation(_side);
|
||||
result = getFingerWorldLocation(_mathPick.side);
|
||||
} else {
|
||||
result = getControllerWorldLocation(_side);
|
||||
result = getControllerWorldLocation(_mathPick.side);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -68,11 +68,9 @@ public:
|
|||
PickResultPointer getHUDIntersection(const StylusTip& pick) override;
|
||||
Transform getResultTransform() const override;
|
||||
|
||||
bool isLeftHand() const override { return _side == Side::Left; }
|
||||
bool isRightHand() const override { return _side == Side::Right; }
|
||||
|
||||
private:
|
||||
const Side _side;
|
||||
bool isLeftHand() const override { return _mathPick.side == Side::Left; }
|
||||
bool isRightHand() const override { return _mathPick.side == Side::Right; }
|
||||
bool isMouse() const override { return false; }
|
||||
};
|
||||
|
||||
#endif // hifi_StylusPick_h
|
|
@ -118,14 +118,24 @@ AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& av
|
|||
float oneFrameDistance = glm::length(currentPosition - _lastPosition);
|
||||
const float MAX_TRANSIT_DISTANCE = 30.0f;
|
||||
float scaledMaxTransitDistance = MAX_TRANSIT_DISTANCE * _scale;
|
||||
if (oneFrameDistance > config._triggerDistance && oneFrameDistance < scaledMaxTransitDistance && !_isTransiting) {
|
||||
start(deltaTime, _lastPosition, currentPosition, config);
|
||||
if (oneFrameDistance > config._triggerDistance && !_isTransiting) {
|
||||
if (oneFrameDistance < scaledMaxTransitDistance) {
|
||||
start(deltaTime, _lastPosition, currentPosition, config);
|
||||
} else {
|
||||
_lastPosition = currentPosition;
|
||||
return Status::ABORT_TRANSIT;
|
||||
}
|
||||
}
|
||||
_lastPosition = currentPosition;
|
||||
_status = updatePosition(deltaTime);
|
||||
return _status;
|
||||
}
|
||||
|
||||
void AvatarTransit::reset() {
|
||||
_lastPosition = _endPosition;
|
||||
_currentPosition = _endPosition;
|
||||
_isTransiting = false;
|
||||
}
|
||||
void AvatarTransit::start(float deltaTime, const glm::vec3& startPosition, const glm::vec3& endPosition, const AvatarTransit::TransitConfig& config) {
|
||||
_startPosition = startPosition;
|
||||
_endPosition = endPosition;
|
||||
|
@ -510,9 +520,13 @@ void Avatar::relayJointDataToChildren() {
|
|||
modelEntity->setLocalJointTranslation(jointIndex, jointTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
Transform finalTransform;
|
||||
Transform avatarTransform = _skeletonModel->getTransform();
|
||||
avatarTransform.setScale(_skeletonModel->getScale());
|
||||
modelEntity->setOverrideTransform(avatarTransform, _skeletonModel->getOffset());
|
||||
Transform entityTransform = modelEntity->getLocalTransform();
|
||||
Transform::mult(finalTransform, avatarTransform, entityTransform);
|
||||
finalTransform.setScale(_skeletonModel->getScale());
|
||||
modelEntity->setOverrideTransform(finalTransform, _skeletonModel->getOffset());
|
||||
modelEntity->simulateRelayedJoints();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ public:
|
|||
IDLE = 0,
|
||||
START_TRANSIT,
|
||||
TRANSITING,
|
||||
END_TRANSIT
|
||||
END_TRANSIT,
|
||||
ABORT_TRANSIT
|
||||
};
|
||||
|
||||
enum EaseType {
|
||||
|
@ -84,6 +85,7 @@ public:
|
|||
glm::vec3 getEndPosition() { return _endPosition; }
|
||||
float getTransitTime() { return _totalTime; }
|
||||
void setScale(float scale) { _scale = scale; }
|
||||
void reset();
|
||||
|
||||
private:
|
||||
Status updatePosition(float deltaTime);
|
||||
|
|
|
@ -594,7 +594,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
// The dot product for larger rotations is a lower number.
|
||||
// So if the dot() is less than the value, then the rotation is a larger angle of rotation
|
||||
if (sendAll || last.rotationIsDefaultPose || (!cullSmallChanges && last.rotation != data.rotation)
|
||||
|| (cullSmallChanges && glm::dot(last.rotation, data.rotation) < minRotationDOT) ) {
|
||||
|| (cullSmallChanges && fabsf(glm::dot(last.rotation, data.rotation)) < minRotationDOT) ) {
|
||||
validity |= (1 << validityBit);
|
||||
#ifdef WANT_DEBUG
|
||||
rotationSentCount++;
|
||||
|
|
|
@ -1190,6 +1190,9 @@ public:
|
|||
void setReplicaIndex(int replicaIndex) { _replicaIndex = replicaIndex; }
|
||||
int getReplicaIndex() { return _replicaIndex; }
|
||||
|
||||
void setIsNewAvatar(bool isNewAvatar) { _isNewAvatar = isNewAvatar; }
|
||||
bool getIsNewAvatar() { return _isNewAvatar; }
|
||||
|
||||
signals:
|
||||
|
||||
/**jsdoc
|
||||
|
@ -1452,6 +1455,7 @@ protected:
|
|||
bool _hasProcessedFirstIdentity { false };
|
||||
float _density;
|
||||
int _replicaIndex { 0 };
|
||||
bool _isNewAvatar { true };
|
||||
|
||||
// null unless MyAvatar or ScriptableAvatar sending traits data to mixer
|
||||
std::unique_ptr<ClientTraitsHandler> _clientTraitsHandler;
|
||||
|
|
|
@ -259,18 +259,20 @@ AvatarSharedPointer AvatarHashMap::parseAvatarData(QSharedPointer<ReceivedMessag
|
|||
if (isNewAvatar) {
|
||||
QWriteLocker locker(&_hashLock);
|
||||
_pendingAvatars.insert(sessionUUID, { std::chrono::steady_clock::now(), 0, avatar });
|
||||
avatar->setIsNewAvatar(true);
|
||||
auto replicaIDs = _replicas.getReplicaIDs(sessionUUID);
|
||||
for (auto replicaID : replicaIDs) {
|
||||
auto replicaAvatar = addAvatar(replicaID, sendingNode);
|
||||
replicaAvatar->setIsNewAvatar(true);
|
||||
_replicas.addReplica(sessionUUID, replicaAvatar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// have the matching (or new) avatar parse the data from the packet
|
||||
int bytesRead = avatar->parseDataFromBuffer(byteArray);
|
||||
message->seek(positionBeforeRead + bytesRead);
|
||||
_replicas.parseDataFromBuffer(sessionUUID, byteArray);
|
||||
|
||||
|
||||
return avatar;
|
||||
} else {
|
||||
|
|
|
@ -1754,8 +1754,9 @@ int EntityScriptingInterface::getJointIndex(const QUuid& entityID, const QString
|
|||
return -1;
|
||||
}
|
||||
int result;
|
||||
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointIndex",
|
||||
Q_RETURN_ARG(int, result), Q_ARG(QUuid, entityID), Q_ARG(QString, name));
|
||||
_entityTree->withReadLock([&] {
|
||||
result = _entityTree->getJointIndex(entityID, name);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1764,8 +1765,9 @@ QStringList EntityScriptingInterface::getJointNames(const QUuid& entityID) {
|
|||
return QStringList();
|
||||
}
|
||||
QStringList result;
|
||||
BLOCKING_INVOKE_METHOD(_entityTree.get(), "getJointNames",
|
||||
Q_RETURN_ARG(QStringList, result), Q_ARG(QUuid, entityID));
|
||||
_entityTree->withReadLock([&] {
|
||||
result = _entityTree->getJointNames(entityID);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,13 @@ public:
|
|||
};
|
||||
Q_ENUM(PickType)
|
||||
|
||||
enum JointState {
|
||||
JOINT_STATE_NONE = 0,
|
||||
JOINT_STATE_LEFT_HAND,
|
||||
JOINT_STATE_RIGHT_HAND,
|
||||
JOINT_STATE_MOUSE
|
||||
};
|
||||
|
||||
void enable(bool enabled = true);
|
||||
void disable() { enable(false); }
|
||||
|
||||
|
@ -211,9 +218,11 @@ public:
|
|||
void setIgnoreItems(const QVector<QUuid>& items);
|
||||
void setIncludeItems(const QVector<QUuid>& items);
|
||||
|
||||
virtual bool isLeftHand() const { return false; }
|
||||
virtual bool isRightHand() const { return false; }
|
||||
virtual bool isMouse() const { return false; }
|
||||
virtual bool isLeftHand() const { return _jointState == JOINT_STATE_LEFT_HAND; }
|
||||
virtual bool isRightHand() const { return _jointState == JOINT_STATE_RIGHT_HAND; }
|
||||
virtual bool isMouse() const { return _jointState == JOINT_STATE_MOUSE; }
|
||||
|
||||
void setJointState(JointState jointState) { _jointState = jointState; }
|
||||
|
||||
virtual Transform getResultTransform() const = 0;
|
||||
|
||||
|
@ -227,13 +236,15 @@ private:
|
|||
|
||||
QVector<QUuid> _ignoreItems;
|
||||
QVector<QUuid> _includeItems;
|
||||
|
||||
JointState _jointState { JOINT_STATE_NONE };
|
||||
};
|
||||
Q_DECLARE_METATYPE(PickQuery::PickType)
|
||||
|
||||
template<typename T>
|
||||
class Pick : public PickQuery {
|
||||
public:
|
||||
Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled) {}
|
||||
Pick(const T& mathPick, const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled), _mathPick(mathPick) {}
|
||||
virtual ~Pick() {}
|
||||
|
||||
virtual T getMathematicalPick() const = 0;
|
||||
|
@ -242,6 +253,9 @@ public:
|
|||
virtual PickResultPointer getOverlayIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getAvatarIntersection(const T& pick) = 0;
|
||||
virtual PickResultPointer getHUDIntersection(const T& pick) = 0;
|
||||
|
||||
protected:
|
||||
T _mathPick;
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
|
|
@ -90,6 +90,17 @@ void PickManager::setIncludeItems(unsigned int uid, const QVector<QUuid>& includ
|
|||
}
|
||||
}
|
||||
|
||||
Transform PickManager::getParentTransform(unsigned int uid) const {
|
||||
auto pick = findPick(uid);
|
||||
if (pick) {
|
||||
auto parentTransform = pick->parentTransform;
|
||||
if (parentTransform) {
|
||||
return parentTransform->getTransform();
|
||||
}
|
||||
}
|
||||
return Transform();
|
||||
}
|
||||
|
||||
Transform PickManager::getResultTransform(unsigned int uid) const {
|
||||
auto pick = findPick(uid);
|
||||
if (pick) {
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
void setIgnoreItems(unsigned int uid, const QVector<QUuid>& ignore) const;
|
||||
void setIncludeItems(unsigned int uid, const QVector<QUuid>& include) const;
|
||||
|
||||
Transform getParentTransform(unsigned int uid) const;
|
||||
Transform getResultTransform(unsigned int uid) const;
|
||||
|
||||
bool isLeftHand(unsigned int uid);
|
||||
|
|
|
@ -202,6 +202,8 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
|||
class StylusTip : public MathPick {
|
||||
public:
|
||||
StylusTip() : position(NAN), velocity(NAN) {}
|
||||
StylusTip(const bilateral::Side& side, const glm::vec3& position = Vectors::ZERO, const glm::quat& orientation = Quaternions::IDENTITY, const glm::vec3& velocity = Vectors::ZERO) :
|
||||
side(side), position(position), orientation(orientation), velocity(velocity) {}
|
||||
StylusTip(const QVariantMap& pickVariant) : side(bilateral::Side(pickVariant["side"].toInt())), position(vec3FromVariant(pickVariant["position"])),
|
||||
orientation(quatFromVariant(pickVariant["orientation"])), velocity(vec3FromVariant(pickVariant["velocity"])) {}
|
||||
|
||||
|
|
|
@ -429,7 +429,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}],
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true),
|
||||
hover: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: LEFT_HAND
|
||||
});
|
||||
|
@ -439,7 +439,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}],
|
||||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true),
|
||||
hover: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: RIGHT_HAND
|
||||
});
|
||||
|
@ -450,7 +450,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true),
|
||||
triggers: [{action: Controller.Standard.LTClick, button: "Focus"}, {action: Controller.Standard.LTClick, button: "Primary"}],
|
||||
hover: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: LEFT_HAND
|
||||
});
|
||||
|
@ -461,7 +461,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true),
|
||||
triggers: [{action: Controller.Standard.RTClick, button: "Focus"}, {action: Controller.Standard.RTClick, button: "Primary"}],
|
||||
hover: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
distanceScaleEnd: true,
|
||||
hand: RIGHT_HAND
|
||||
});
|
||||
|
|
|
@ -298,7 +298,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
centerEndY: false,
|
||||
speed: speed,
|
||||
accelerationAxis: accelerationAxis,
|
||||
|
@ -314,7 +314,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
centerEndY: false,
|
||||
speed: speed,
|
||||
accelerationAxis: accelerationAxis,
|
||||
|
@ -327,7 +327,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
joint: "Avatar",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
centerEndY: false,
|
||||
speed: speed,
|
||||
accelerationAxis: accelerationAxis,
|
||||
|
@ -341,7 +341,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
joint: "Avatar",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
centerEndY: false,
|
||||
speed: speed,
|
||||
accelerationAxis: accelerationAxis,
|
||||
|
|
|
@ -272,7 +272,7 @@ function Grabber() {
|
|||
joint: "Mouse",
|
||||
filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE,
|
||||
faceAvatar: true,
|
||||
scaleWithAvatar: true,
|
||||
scaleWithParent: true,
|
||||
enabled: true,
|
||||
renderStates: renderStates
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue