mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:03:53 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into controllers
This commit is contained in:
commit
c7b9d7d26e
20 changed files with 241 additions and 122 deletions
|
@ -12,7 +12,6 @@
|
|||
#include <QThread>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "ScriptableAvatar.h"
|
||||
|
||||
// hold and priority unused but kept so that client side JS can run.
|
||||
|
@ -48,14 +47,12 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() {
|
|||
}
|
||||
|
||||
void ScriptableAvatar::update(float deltatime) {
|
||||
if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton.
|
||||
_bind = DependencyManager::get<AnimationCache>()->getAnimation(_skeletonFBXURL);
|
||||
}
|
||||
|
||||
// Run animation
|
||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0) {
|
||||
QStringList modelJoints = getJointNames();
|
||||
QStringList animationJoints = _animation->getJointNames();
|
||||
|
||||
if (_jointData.size() != modelJoints.size()) {
|
||||
_jointData.resize(modelJoints.size());
|
||||
}
|
||||
if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && _bind->isLoaded()) {
|
||||
|
||||
float currentFrame = _animationDetails.currentFrame + deltatime * _animationDetails.fps;
|
||||
if (_animationDetails.loop || currentFrame < _animationDetails.lastFrame) {
|
||||
|
@ -63,19 +60,29 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
currentFrame -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
|
||||
}
|
||||
_animationDetails.currentFrame = currentFrame;
|
||||
|
||||
const QVector<FBXJoint>& modelJoints = _bind->getGeometry().joints;
|
||||
QStringList animationJointNames = _animation->getJointNames();
|
||||
|
||||
if (_jointData.size() != modelJoints.size()) {
|
||||
_jointData.resize(modelJoints.size());
|
||||
}
|
||||
|
||||
const int frameCount = _animation->getFrames().size();
|
||||
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(currentFrame) % frameCount);
|
||||
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const float frameFraction = glm::fract(currentFrame);
|
||||
|
||||
for (int i = 0; i < animationJoints.size(); i++) {
|
||||
const QString& name = animationJoints[i];
|
||||
int mapping = getJointIndex(name);
|
||||
for (int i = 0; i < animationJointNames.size(); i++) {
|
||||
const QString& name = animationJointNames[i];
|
||||
// As long as we need the model preRotations anyway, let's get the jointIndex from the bind skeleton rather than
|
||||
// trusting the .fst (which is sometimes not updated to match changes to .fbx).
|
||||
int mapping = _bind->getGeometry().getJointIndex(name);
|
||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||
JointData& data = _jointData[mapping];
|
||||
|
||||
auto newRotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||
auto newRotation = modelJoints[mapping].preRotation *
|
||||
safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||
// We could probably do translations as in interpolation in model space (rather than the parent space that each frame is in),
|
||||
// but we don't do so for MyAvatar yet, so let's not be different here.
|
||||
if (data.rotation != newRotation) {
|
||||
|
|
|
@ -33,6 +33,7 @@ private:
|
|||
AnimationPointer _animation;
|
||||
AnimationDetails _animationDetails;
|
||||
QStringList _maskedJoints;
|
||||
AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies
|
||||
};
|
||||
|
||||
#endif // hifi_ScriptableAvatar_h
|
|
@ -43,6 +43,7 @@ void OctreeInboundPacketProcessor::resetStats() {
|
|||
_totalPackets = 0;
|
||||
_lastNackTime = usecTimestampNow();
|
||||
|
||||
QWriteLocker locker(&_senderStatsLock);
|
||||
_singleSenderStats.clear();
|
||||
}
|
||||
|
||||
|
@ -220,6 +221,8 @@ void OctreeInboundPacketProcessor::trackInboundPacket(const QUuid& nodeUUID, uns
|
|||
_totalElementsInPacket += editsInPacket;
|
||||
_totalPackets++;
|
||||
|
||||
QWriteLocker locker(&_senderStatsLock);
|
||||
|
||||
// find the individual senders stats and track them there too...
|
||||
// see if this is the first we've heard of this node...
|
||||
if (_singleSenderStats.find(nodeUUID) == _singleSenderStats.end()) {
|
||||
|
@ -242,6 +245,8 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
|||
int packetsSent = 0;
|
||||
int totalBytesSent = 0;
|
||||
|
||||
QWriteLocker locker(&_senderStatsLock);
|
||||
|
||||
NodeToSenderStatsMapIterator i = _singleSenderStats.begin();
|
||||
while (i != _singleSenderStats.end()) {
|
||||
|
||||
|
@ -262,10 +267,9 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
|
|||
}
|
||||
|
||||
const SharedNodePointer& destinationNode = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);
|
||||
// If the node no longer exists, wait until the ReceivedPacketProcessor has cleaned up the node
|
||||
// to remove it from our stats list.
|
||||
// FIXME Is it safe to clean it up here before ReceivedPacketProcess has?
|
||||
// if the node no longer exists, remove its stats
|
||||
if (!destinationNode) {
|
||||
i = _singleSenderStats.erase(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ public:
|
|||
|
||||
void resetStats();
|
||||
|
||||
NodeToSenderStatsMap& getSingleSenderStats() { return _singleSenderStats; }
|
||||
NodeToSenderStatsMap getSingleSenderStats() { QReadLocker locker(&_senderStatsLock); return _singleSenderStats; }
|
||||
|
||||
virtual void terminating() { _shuttingDown = true; ReceivedPacketProcessor::terminating(); }
|
||||
|
||||
|
@ -94,15 +94,16 @@ private:
|
|||
OctreeServer* _myServer;
|
||||
int _receivedPacketCount;
|
||||
|
||||
quint64 _totalTransitTime;
|
||||
quint64 _totalProcessTime;
|
||||
quint64 _totalLockWaitTime;
|
||||
quint64 _totalElementsInPacket;
|
||||
quint64 _totalPackets;
|
||||
std::atomic<uint64_t> _totalTransitTime;
|
||||
std::atomic<uint64_t> _totalProcessTime;
|
||||
std::atomic<uint64_t> _totalLockWaitTime;
|
||||
std::atomic<uint64_t> _totalElementsInPacket;
|
||||
std::atomic<uint64_t> _totalPackets;
|
||||
|
||||
NodeToSenderStatsMap _singleSenderStats;
|
||||
QReadWriteLock _senderStatsLock;
|
||||
|
||||
quint64 _lastNackTime;
|
||||
std::atomic<uint64_t> _lastNackTime;
|
||||
bool _shuttingDown;
|
||||
};
|
||||
#endif // hifi_OctreeInboundPacketProcessor_h
|
||||
|
|
|
@ -711,7 +711,7 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
|
||||
|
||||
int senderNumber = 0;
|
||||
NodeToSenderStatsMap& allSenderStats = _octreeInboundPacketProcessor->getSingleSenderStats();
|
||||
NodeToSenderStatsMap allSenderStats = _octreeInboundPacketProcessor->getSingleSenderStats();
|
||||
for (NodeToSenderStatsMapConstIterator i = allSenderStats.begin(); i != allSenderStats.end(); i++) {
|
||||
senderNumber++;
|
||||
QUuid senderID = i.key();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
/*jslint vars: true, plusplus: true*/
|
||||
/*global Agent, Avatar, Script, Entities, Vec3, print*/
|
||||
/*global Agent, Avatar, Script, Entities, Vec3, Quat, print*/
|
||||
//
|
||||
// animatedAvatar.js
|
||||
// examples/acScripts
|
||||
|
@ -16,15 +16,62 @@
|
|||
|
||||
var origin = {x: 500, y: 500, z: 500};
|
||||
var spread = 20; // meters
|
||||
var turnSpread = 90; // How many degrees should turn from front range over.
|
||||
var animationData = {url: "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", lastFrame: 35};
|
||||
Avatar.skeletonModelURL = "https://hifi-public.s3.amazonaws.com/marketplace/contents/dd03b8e3-52fb-4ab3-9ac9-3b17e00cd85d/98baa90b3b66803c5d7bd4537fca6993.fst"; //lovejoy
|
||||
Avatar.displayName = "'Bot";
|
||||
var models = [ // Commented-out avatars do not animate properly on AC's. Presumably because ScriptableAvatar doesn't use model pre-rotations.
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/alan/alan.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/andrew/andrew.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/austin/austin.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/birarda/birarda.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/brad/brad.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/chris/chris2.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/clement/clement.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/emily/emily.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/ewing/ewing.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/howard/howard.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/huffman/huffman.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/james/james.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/philip/philip.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/ryan/ryan.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/sam/sam.fst",
|
||||
"https://hifi-public.s3.amazonaws.com/ozan/avatars/hifi_team/tony/tony.fst",
|
||||
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/1e57c395-612e-4acd-9561-e79dbda0bc49/faafb83c63a3e5e265884d270fc29f8b.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/615ca447-06ee-4215-8dd1-a609c2fcd0cd/c7af6d4224c501fdd9cb54e0101ff281.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/731c39d7-559a-4ce2-947c-3e2768f5471c/8d5eba2fd5bf068259556aec1861c5dd.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/8bdaa1ec-99df-4a29-a249-6941c7fd1930/37351a18a3dea468088fc3d822aaf29c.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/0909d7b7-c67e-45fb-acd9-a07380dc6b9c/da76b8c59dbc680bdda90df4b9a46faa.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/ad0dffd7-f811-487b-a20a-2509235491ef/29106da1f7e6a42c7907603421fd7df5.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/3ebe5c84-8b88-4d91-86ac-f104f3620fe3/3534b032d079514aa8960a316500ce13.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/dd03b8e3-52fb-4ab3-9ac9-3b17e00cd85d/98baa90b3b66803c5d7bd4537fca6993.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/ff060580-2fc7-4b6c-8e12-f023d05363cf/dadef29b1e60f23b413d1850d7e0dd4a.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/b55d3baf-4eb3-4cac-af4c-0fb66d0c907b/ad2c9157f3924ab1f7f6ea87a8cce6cc.fst",
|
||||
"https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/contents/d029ae8d-2905-4eb7-ba46-4bd1b8cb9d73/4618d52e711fbb34df442b414da767bb.fst"
|
||||
];
|
||||
var nameMap = {
|
||||
faafb83c63a3e5e265884d270fc29f8b: 'albert',
|
||||
c7af6d4224c501fdd9cb54e0101ff281: 'boss',
|
||||
'8d5eba2fd5bf068259556aec1861c5dd': 'dougland',
|
||||
'37351a18a3dea468088fc3d822aaf29c': 'fightbot blue',
|
||||
da76b8c59dbc680bdda90df4b9a46faa: 'judd',
|
||||
'29106da1f7e6a42c7907603421fd7df5': 'kate',
|
||||
'3534b032d079514aa8960a316500ce13': 'lenny',
|
||||
'98baa90b3b66803c5d7bd4537fca6993': 'lovejoy',
|
||||
dadef29b1e60f23b413d1850d7e0dd4a: 'mery', // eyes no good
|
||||
ad2c9157f3924ab1f7f6ea87a8cce6cc: 'owen',
|
||||
'4618d52e711fbb34df442b414da767bb': 'will'
|
||||
};
|
||||
|
||||
Avatar.skeletonModelURL = models[Math.round(Math.random() * (models.length - 1))]; // pick one
|
||||
Avatar.displayName = Avatar.skeletonModelURL.match(/\/(\w*).fst/)[1]; // grab the file basename
|
||||
Avatar.displayName = nameMap[Avatar.displayName] || Avatar.displayName;
|
||||
var millisecondsToWaitBeforeStarting = 10 * 1000; // To give the various servers a chance to start.
|
||||
|
||||
Agent.isAvatar = true;
|
||||
function coord() { return (Math.random() * spread) - (spread / 2); } // randomly distribute a coordinate zero += spread/2.
|
||||
Script.setTimeout(function () {
|
||||
Avatar.position = Vec3.sum(origin, {x: coord(), y: 0, z: coord()});
|
||||
Avatar.orientation = Quat.fromPitchYawRollDegrees(0, turnSpread * (Math.random() - 0.5), 0);
|
||||
print("Starting at", JSON.stringify(Avatar.position));
|
||||
Avatar.startAnimation(animationData.url, animationData.fps || 30, 1, true, false, animationData.firstFrame || 0, animationData.lastFrame);
|
||||
}, millisecondsToWaitBeforeStarting);
|
||||
|
|
|
@ -200,6 +200,7 @@ function entityIsGrabbedByOther(entityID) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
function MyController(hand) {
|
||||
this.hand = hand;
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
|
@ -223,6 +224,8 @@ function MyController(hand) {
|
|||
this.rawTriggerValue = 0;
|
||||
this.rawBumperValue = 0;
|
||||
|
||||
this.overlayLine = null;
|
||||
|
||||
this.offsetPosition = {
|
||||
x: 0.0,
|
||||
y: 0.0,
|
||||
|
@ -318,6 +321,33 @@ function MyController(hand) {
|
|||
});
|
||||
}
|
||||
|
||||
this.overlayLineOn = function(closePoint, farPoint, color) {
|
||||
if (this.overlayLine === null) {
|
||||
var lineProperties = {
|
||||
lineWidth: 5,
|
||||
start: closePoint,
|
||||
end: farPoint,
|
||||
color: color,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
visible: true,
|
||||
alpha: 1
|
||||
};
|
||||
|
||||
this.overlayLine = Overlays.addOverlay("line3d", lineProperties);
|
||||
|
||||
} else {
|
||||
var success = Overlays.editOverlay(this.overlayLine, {
|
||||
lineWidth: 5,
|
||||
start: closePoint,
|
||||
end: farPoint,
|
||||
color: color,
|
||||
visible: true,
|
||||
ignoreRayIntersection: true, // always ignore this
|
||||
alpha: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.lineOn = function(closePoint, farPoint, color) {
|
||||
// draw a line
|
||||
if (this.pointer === null) {
|
||||
|
@ -356,6 +386,13 @@ function MyController(hand) {
|
|||
this.pointer = null;
|
||||
};
|
||||
|
||||
this.overlayLineOff = function() {
|
||||
if (this.overlayLine !== null) {
|
||||
Overlays.deleteOverlay(this.overlayLine);
|
||||
}
|
||||
this.overlayLine = null;
|
||||
};
|
||||
|
||||
this.triggerPress = function(value) {
|
||||
_this.rawTriggerValue = value;
|
||||
};
|
||||
|
@ -604,7 +641,8 @@ function MyController(hand) {
|
|||
}
|
||||
}
|
||||
|
||||
this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
//this.lineOn(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
this.overlayLineOn(distantPickRay.origin, Vec3.sum(distantPickRay.origin, Vec3.multiply(distantPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR);
|
||||
};
|
||||
|
||||
this.distanceHolding = function() {
|
||||
|
@ -650,6 +688,9 @@ function MyController(hand) {
|
|||
this.currentAvatarPosition = MyAvatar.position;
|
||||
this.currentAvatarOrientation = MyAvatar.orientation;
|
||||
|
||||
this.overlayLineOff();
|
||||
|
||||
|
||||
};
|
||||
|
||||
this.continueDistanceHolding = function() {
|
||||
|
@ -757,6 +798,7 @@ function MyController(hand) {
|
|||
}
|
||||
|
||||
this.lineOff();
|
||||
this.overlayLineOff();
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||
this.activateEntity(this.grabbedEntity, grabbedProperties);
|
||||
|
@ -898,6 +940,7 @@ function MyController(hand) {
|
|||
|
||||
this.pullTowardEquipPosition = function() {
|
||||
this.lineOff();
|
||||
this.overlayLineOff();
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
||||
|
@ -1101,7 +1144,7 @@ function MyController(hand) {
|
|||
this.release = function() {
|
||||
|
||||
this.lineOff();
|
||||
|
||||
this.overlayLineOff();
|
||||
if (this.grabbedEntity !== null) {
|
||||
if (this.actionID !== null) {
|
||||
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||
|
@ -1223,10 +1266,10 @@ Controller.enableMapping(MAPPING_NAME);
|
|||
var handToDisable = 'none';
|
||||
|
||||
function update() {
|
||||
if (handToDisable !== LEFT_HAND) {
|
||||
if (handToDisable !== LEFT_HAND && handToDisable!=='both') {
|
||||
leftController.update();
|
||||
}
|
||||
if (handToDisable !== RIGHT_HAND) {
|
||||
if (handToDisable !== RIGHT_HAND && handToDisable!=='both') {
|
||||
rightController.update();
|
||||
}
|
||||
}
|
||||
|
@ -1234,15 +1277,20 @@ function update() {
|
|||
Messages.subscribe('Hifi-Hand-Disabler');
|
||||
|
||||
handleHandDisablerMessages = function(channel, message, sender) {
|
||||
|
||||
|
||||
if (sender === MyAvatar.sessionUUID) {
|
||||
handToDisable = message;
|
||||
if (message === 'left') {
|
||||
handToDisable = LEFT_HAND;
|
||||
}
|
||||
if (message === 'right') {
|
||||
handToDisable = RIGHT_HAND;
|
||||
}
|
||||
if(message==='both'){
|
||||
handToDisable='both';
|
||||
}
|
||||
if(message==='none'){
|
||||
handToDisable='none';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,10 @@ var laserPointer = (function () {
|
|||
];
|
||||
|
||||
function isHandPointing(hand) {
|
||||
var MINIMUM_TRIGGER_PULL = 0.9;
|
||||
return Controller.getTriggerValue(hand) > MINIMUM_TRIGGER_PULL;
|
||||
var MINIMUM_TRIGGER_PULL = 0.9,
|
||||
controller;
|
||||
controller = hand === 0 ? Controller.Standard.LT : Controller.Standard.RT;
|
||||
return Controller.getValue(controller) > MINIMUM_TRIGGER_PULL;
|
||||
}
|
||||
|
||||
function isFingerPointing(hand) {
|
||||
|
|
|
@ -193,13 +193,12 @@ var leapHands = (function () {
|
|||
}
|
||||
|
||||
// Set avatar arms vertical, forearms horizontal, as "zero" position for calibration
|
||||
MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, -90.0));
|
||||
MyAvatar.setJointData("LeftForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0));
|
||||
MyAvatar.setJointData("LeftHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
|
||||
MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 90.0));
|
||||
MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 180.0));
|
||||
MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
|
||||
|
||||
MyAvatar.setJointRotation("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 0.0));
|
||||
MyAvatar.setJointRotation("LeftForeArm", Quat.fromPitchYawRollDegrees(0.0, 90.0, 90.0));
|
||||
MyAvatar.setJointRotation("LeftHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
|
||||
MyAvatar.setJointRotation("RightArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 0.0));
|
||||
MyAvatar.setJointRotation("RightForeArm", Quat.fromPitchYawRollDegrees(0.0, -90.0, -90.0));
|
||||
MyAvatar.setJointRotation("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
|
||||
|
||||
// Wait for arms to assume their positions before calculating
|
||||
Script.setTimeout(finishCalibration, CALIBRATION_TIME);
|
||||
|
@ -382,23 +381,14 @@ var leapHands = (function () {
|
|||
|
||||
// Hand rotation in camera coordinates ...
|
||||
handRotation = {
|
||||
x: handRotation.z,
|
||||
y: handRotation.y,
|
||||
z: handRotation.x,
|
||||
x: -handRotation.x,
|
||||
y: -handRotation.z,
|
||||
z: -handRotation.y,
|
||||
w: handRotation.w
|
||||
};
|
||||
|
||||
// Hand rotation in avatar coordinates ...
|
||||
if (h === 0) {
|
||||
handRotation.x = -handRotation.x;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation);
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 0, z: 1 }), handRotation);
|
||||
} else {
|
||||
handRotation.z = -handRotation.z;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation);
|
||||
handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 0, z: 1 }), handRotation);
|
||||
}
|
||||
|
||||
handRotation = Quat.multiply(Quat.angleAxis(180.0, { x: 0, y: 1, z: 0 }), handRotation);
|
||||
cameraOrientation.x = -cameraOrientation.x;
|
||||
cameraOrientation.z = -cameraOrientation.z;
|
||||
handRotation = Quat.multiply(cameraOrientation, handRotation);
|
||||
|
@ -421,22 +411,14 @@ var leapHands = (function () {
|
|||
|
||||
// Hand rotation in camera coordinates ...
|
||||
handRotation = {
|
||||
x: handRotation.z,
|
||||
y: handRotation.y,
|
||||
z: handRotation.x,
|
||||
x: -handRotation.x,
|
||||
y: -handRotation.z,
|
||||
z: -handRotation.y,
|
||||
w: handRotation.w
|
||||
};
|
||||
|
||||
// Hand rotation in avatar coordinates ...
|
||||
if (h === 0) {
|
||||
handRotation.x = -handRotation.x;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }),
|
||||
handRotation);
|
||||
} else {
|
||||
handRotation.z = -handRotation.z;
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 1, z: 0 }),
|
||||
handRotation);
|
||||
}
|
||||
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation);
|
||||
}
|
||||
|
||||
// Set hand position and orientation ...
|
||||
|
@ -462,7 +444,7 @@ var leapHands = (function () {
|
|||
w: locRotation.w
|
||||
};
|
||||
}
|
||||
MyAvatar.setJointData(fingers[h][i][j].jointName, locRotation);
|
||||
MyAvatar.setJointRotation(fingers[h][i][j].jointName, locRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ Script.include("../../../libraries/constants.js");
|
|||
|
||||
var GUN_FORCE =20;
|
||||
|
||||
Messages.sendMessage('Hifi-Hand-Disabler', "both");
|
||||
|
||||
var gameName = "Kill All The Rats!"
|
||||
// var HOST = "localhost:5000"
|
||||
|
@ -194,6 +195,7 @@ function fire(side, value) {
|
|||
|
||||
|
||||
function scriptEnding() {
|
||||
Messages.sendMessage('Hifi-Hand-Disabler', 'none');
|
||||
mapping.disable();
|
||||
for (var i = 0; i < pointers.length; ++i) {
|
||||
Overlays.deleteOverlay(pointers[i]);
|
||||
|
|
|
@ -36,14 +36,10 @@
|
|||
Entities.editEntity(this.entityID, {
|
||||
animation: {
|
||||
url: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx",
|
||||
currentFrame: 0
|
||||
running: true
|
||||
}
|
||||
});
|
||||
|
||||
Entities.editEntity(_this.entityID, {
|
||||
animationIsPlaying: true
|
||||
});
|
||||
|
||||
var position = Entities.getEntityProperties(this.entityID, "position").position;
|
||||
this.audioInjector = Audio.playSound(this.screamSounds[randInt(0, this.screamSounds.length)], {
|
||||
position: position,
|
||||
|
@ -67,8 +63,10 @@
|
|||
this.audioInjector.stop();
|
||||
Entities.editEntity(this.entityID, {
|
||||
animation: {
|
||||
url: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx",
|
||||
currentFrame: 0
|
||||
// Providing actual model fbx for animation used to work, now contorts doll into a weird ball
|
||||
// See bug: https://app.asana.com/0/26225263936266/70097355490098
|
||||
// url: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx",
|
||||
running: false,
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
Controller.Standard.LT,
|
||||
Controller.Standard.RT,
|
||||
];
|
||||
var RELOAD_THRESHOLD = 0.95;
|
||||
|
||||
Pistol = function() {
|
||||
_this = this;
|
||||
this.equipped = false;
|
||||
|
@ -36,7 +38,7 @@
|
|||
this.fireSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Guns/GUN-SHOT2.raw");
|
||||
this.ricochetSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Guns/Ricochet.L.wav");
|
||||
this.playRichochetSoundChance = 0.1;
|
||||
this.fireVolume = 0.5;
|
||||
this.fireVolume = 0.2;
|
||||
this.bulletForce = 10;
|
||||
|
||||
|
||||
|
@ -45,6 +47,7 @@
|
|||
};
|
||||
|
||||
Pistol.prototype = {
|
||||
canShoot: false,
|
||||
|
||||
startEquip: function(id, params) {
|
||||
this.equipped = true;
|
||||
|
@ -62,6 +65,17 @@
|
|||
},
|
||||
toggleWithTriggerPressure: function() {
|
||||
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
|
||||
|
||||
if (this.triggerValue < RELOAD_THRESHOLD) {
|
||||
// print('RELOAD');
|
||||
this.canShoot = true;
|
||||
}
|
||||
if (this.canShoot === true && this.triggerValue === 1) {
|
||||
// print('SHOOT');
|
||||
this.fire();
|
||||
this.canShoot = false;
|
||||
}
|
||||
|
||||
if (this.triggerValue < DISABLE_LASER_THRESHOLD && this.showLaser === true) {
|
||||
this.showLaser = false;
|
||||
Overlays.editOverlay(this.laser, {
|
||||
|
@ -74,6 +88,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
updateLaser: function() {
|
||||
var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
||||
|
@ -101,7 +116,7 @@
|
|||
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
this.initControllerMapping();
|
||||
// this.initControllerMapping();
|
||||
this.laser = Overlays.addOverlay("line3d", {
|
||||
start: ZERO_VECTOR,
|
||||
end: ZERO_VECTOR,
|
||||
|
@ -150,22 +165,7 @@
|
|||
}
|
||||
},
|
||||
|
||||
initControllerMapping: function() {
|
||||
this.mapping = Controller.newMapping();
|
||||
this.mapping.from(Controller.Standard.LT).hysteresis(0.0, 0.75).to(function(value) {
|
||||
_this.triggerPress(0, value);
|
||||
});
|
||||
|
||||
|
||||
this.mapping.from(Controller.Standard.RT).hysteresis(0.0, 0.75).to(function(value) {
|
||||
_this.triggerPress(1, value);
|
||||
});
|
||||
this.mapping.enable();
|
||||
|
||||
},
|
||||
|
||||
unload: function() {
|
||||
this.mapping.disable();
|
||||
Overlays.deleteOverlay(this.laser);
|
||||
},
|
||||
|
||||
|
|
|
@ -2856,6 +2856,8 @@ void Application::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
_controllerScriptingInterface->updateInputControllers();
|
||||
|
||||
// Transfer the user inputs to the driveKeys
|
||||
// FIXME can we drop drive keys and just have the avatar read the action states directly?
|
||||
myAvatar->clearDriveKeys();
|
||||
|
|
|
@ -84,13 +84,12 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
|
|||
return qApp->getUiSize();
|
||||
}
|
||||
|
||||
controller::InputController::Pointer ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
||||
// This is where we retreive the Device Tracker category and then the sub tracker within it
|
||||
controller::InputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) {
|
||||
// This is where we retrieve the Device Tracker category and then the sub tracker within it
|
||||
auto icIt = _inputControllers.find(0);
|
||||
if (icIt != _inputControllers.end()) {
|
||||
return (*icIt).second;
|
||||
}
|
||||
|
||||
return (*icIt).second.get();
|
||||
}
|
||||
|
||||
// Look for device
|
||||
DeviceTracker::ID deviceID = DeviceTracker::getDeviceID(deviceName.toStdString());
|
||||
|
@ -110,18 +109,24 @@ controller::InputController::Pointer ControllerScriptingInterface::createInputCo
|
|||
controller::InputController::Pointer inputController = std::make_shared<InputController>(deviceID, trackerID, this);
|
||||
controller::InputController::Key key = inputController->getKey();
|
||||
_inputControllers.insert(InputControllerMap::value_type(key, inputController));
|
||||
return inputController;
|
||||
return inputController.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return controller::InputController::Pointer();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ControllerScriptingInterface::releaseInputController(controller::InputController::Pointer input) {
|
||||
void ControllerScriptingInterface::releaseInputController(controller::InputController* input) {
|
||||
_inputControllers.erase(input->getKey());
|
||||
}
|
||||
|
||||
void ControllerScriptingInterface::updateInputControllers() {
|
||||
for (auto it = _inputControllers.begin(); it != _inputControllers.end(); it++) {
|
||||
(*it).second->update();
|
||||
}
|
||||
}
|
||||
|
||||
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
||||
_deviceTrackerId(deviceTrackerId),
|
||||
_subTrackerId(subTrackerId),
|
||||
|
|
|
@ -85,6 +85,8 @@ public:
|
|||
bool isKeyCaptured(const KeyEvent& event) const;
|
||||
bool isJoystickCaptured(int joystickIndex) const;
|
||||
|
||||
void updateInputControllers();
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void captureKeyEvents(const KeyEvent& event);
|
||||
|
@ -96,8 +98,8 @@ public slots:
|
|||
virtual glm::vec2 getViewportDimensions() const;
|
||||
|
||||
/// Factory to create an InputController
|
||||
virtual controller::InputController::Pointer createInputController(const QString& deviceName, const QString& tracker);
|
||||
virtual void releaseInputController(controller::InputController::Pointer input);
|
||||
virtual controller::InputController* createInputController(const QString& deviceName, const QString& tracker);
|
||||
virtual void releaseInputController(controller::InputController* input);
|
||||
|
||||
signals:
|
||||
void keyPressEvent(const KeyEvent& event);
|
||||
|
|
|
@ -116,7 +116,7 @@ void AvatarData::setOrientation(const glm::quat& orientation, bool overideRefere
|
|||
glm::vec3 eulerAngles = glm::degrees(safeEulerAngles(orientation));
|
||||
_bodyPitch = eulerAngles.x;
|
||||
_bodyYaw = eulerAngles.y;
|
||||
_bodyRoll = eulerAngles.z;
|
||||
_bodyRoll = eulerAngles.z;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1212,7 +1212,14 @@ void AvatarData::setJointMappingsFromNetworkReply() {
|
|||
|
||||
QByteArray line;
|
||||
while (!(line = networkReply->readLine()).isEmpty()) {
|
||||
if (!(line = line.trimmed()).startsWith("jointIndex")) {
|
||||
line = line.trimmed();
|
||||
if (line.startsWith("filename")) {
|
||||
int filenameIndex = line.indexOf('=') + 1;
|
||||
if (filenameIndex > 0) {
|
||||
_skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed()));
|
||||
}
|
||||
}
|
||||
if (!line.startsWith("jointIndex")) {
|
||||
continue;
|
||||
}
|
||||
int jointNameIndex = line.indexOf('=') + 1;
|
||||
|
@ -1522,6 +1529,17 @@ QJsonObject AvatarData::toJson() const {
|
|||
}
|
||||
|
||||
void AvatarData::fromJson(const QJsonObject& json) {
|
||||
// The head setOrientation likes to overwrite the avatar orientation,
|
||||
// so lets do the head first
|
||||
// Most head data is relative to the avatar, and needs no basis correction,
|
||||
// but the lookat vector does need correction
|
||||
if (json.contains(JSON_AVATAR_HEAD)) {
|
||||
if (!_headData) {
|
||||
_headData = new HeadData(this);
|
||||
}
|
||||
_headData->fromJson(json[JSON_AVATAR_HEAD].toObject());
|
||||
}
|
||||
|
||||
if (json.contains(JSON_AVATAR_HEAD_MODEL)) {
|
||||
auto faceModelURL = json[JSON_AVATAR_HEAD_MODEL].toString();
|
||||
if (faceModelURL != getFaceModelURL().toString()) {
|
||||
|
@ -1593,15 +1611,6 @@ void AvatarData::fromJson(const QJsonObject& json) {
|
|||
}
|
||||
setRawJointData(jointArray);
|
||||
}
|
||||
|
||||
// Most head data is relative to the avatar, and needs no basis correction,
|
||||
// but the lookat vector does need correction
|
||||
if (json.contains(JSON_AVATAR_HEAD)) {
|
||||
if (!_headData) {
|
||||
_headData = new HeadData(this);
|
||||
}
|
||||
_headData->fromJson(json[JSON_AVATAR_HEAD].toObject());
|
||||
}
|
||||
}
|
||||
|
||||
// Every frame will store both a basis for the recording and a relative transform
|
||||
|
|
|
@ -392,6 +392,7 @@ protected:
|
|||
|
||||
QUrl _faceModelURL; // These need to be empty so that on first time setting them they will not short circuit
|
||||
QUrl _skeletonModelURL; // These need to be empty so that on first time setting them they will not short circuit
|
||||
QUrl _skeletonFBXURL;
|
||||
QVector<AttachmentData> _attachmentData;
|
||||
QString _displayName;
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) {
|
|||
out = qobject_cast<AvatarData*>(object.toQObject());
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(controller::InputController*)
|
||||
static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
|
||||
|
||||
QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) {
|
||||
return engine->newQObject(in);
|
||||
}
|
||||
|
@ -89,8 +92,6 @@ void inputControllerFromScriptValue(const QScriptValue &object, controller::Inpu
|
|||
out = qobject_cast<controller::InputController*>(object.toQObject());
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool hasCorrectSyntax(const QScriptProgram& program) {
|
||||
const auto syntaxCheck = QScriptEngine::checkSyntax(program.sourceCode());
|
||||
if (syntaxCheck.state() != QScriptSyntaxCheckResult::Valid) {
|
||||
|
|
|
@ -132,11 +132,12 @@
|
|||
createLights();
|
||||
|
||||
createCat({
|
||||
x: 551.09,
|
||||
y: 494.98,
|
||||
z: 503.49
|
||||
x: 551.0,
|
||||
y: 495.3,
|
||||
z: 503.3
|
||||
});
|
||||
|
||||
|
||||
createSprayCan({
|
||||
x: 549.7,
|
||||
y: 495.6,
|
||||
|
@ -240,6 +241,7 @@
|
|||
gravity: BOW_GRAVITY,
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL: COLLISION_HULL_URL,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/bow_fall.L.wav",
|
||||
script: bowScriptURL,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
|
@ -648,6 +650,7 @@
|
|||
z: 0.08
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/flashlight_drop.L.wav",
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -3.5,
|
||||
|
@ -1184,10 +1187,11 @@
|
|||
z: 0.07
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/SpryPntCnDrp1.L.wav",
|
||||
shapeType: 'box',
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -0.5,
|
||||
y: -3.0,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
|
|
|
@ -110,9 +110,9 @@ MasterReset = function() {
|
|||
|
||||
|
||||
createCat({
|
||||
x: 551.09,
|
||||
y: 494.98,
|
||||
z: 503.49
|
||||
x: 551.0,
|
||||
y: 495.3,
|
||||
z: 503.3
|
||||
});
|
||||
|
||||
createSprayCan({
|
||||
|
@ -220,6 +220,7 @@ MasterReset = function() {
|
|||
gravity: BOW_GRAVITY,
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL: COLLISION_HULL_URL,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/bow_fall.L.wav",
|
||||
script: bowScriptURL,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
|
@ -629,6 +630,7 @@ MasterReset = function() {
|
|||
z: 0.08
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/flashlight_drop.L.wav",
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -3.5,
|
||||
|
@ -1165,10 +1167,11 @@ MasterReset = function() {
|
|||
z: 0.07
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: "http://hifi-public.s3.amazonaws.com/sounds/SpryPntCnDrp1.L.wav",
|
||||
shapeType: 'box',
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -0.5,
|
||||
y: -3.0,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
|
|
Loading…
Reference in a new issue