Merge branch 'master' of https://github.com/highfidelity/hifi into controllers

This commit is contained in:
samcake 2015-12-02 09:49:03 -08:00
commit c7b9d7d26e
20 changed files with 241 additions and 122 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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();

View file

@ -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);

View file

@ -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';
}
}
}

View file

@ -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) {

View file

@ -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);
}
}
}

View file

@ -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]);

View file

@ -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,
}
});

View file

@ -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);
},

View file

@ -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();

View file

@ -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),

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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) {

View file

@ -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: {

View file

@ -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: {