Merge branch 'master' of https://github.com/highfidelity/hifi into align-body-to-head-on-reset

This commit is contained in:
Howard Stearns 2015-10-09 13:13:22 -07:00
commit 700835a6d1
38 changed files with 2972 additions and 1147 deletions

View file

@ -39,8 +39,6 @@
const QString ASSIGNMENT_CLIENT_TARGET_NAME = "assignment-client";
const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QString assignmentPool,
quint16 listenPort, QUuid walletUUID, QString assignmentServerHostname,
quint16 assignmentServerPort, quint16 assignmentMonitorPort) :

View file

@ -32,7 +32,7 @@ var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to thei
var DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR = 2.0; // object rotates this much more than hand did
var NO_INTERSECT_COLOR = { red: 10, green: 10, blue: 255}; // line color when pick misses
var INTERSECT_COLOR = { red: 250, green: 10, blue: 10}; // line color when pick hits
var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000, z: 1000};
var LINE_ENTITY_DIMENSIONS = { x: 1000, y: 1000,z: 1000};
var LINE_LENGTH = 500;
@ -77,7 +77,9 @@ var STATE_NEAR_GRABBING = 4;
var STATE_CONTINUE_NEAR_GRABBING = 5;
var STATE_NEAR_GRABBING_NON_COLLIDING = 6;
var STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING = 7;
var STATE_RELEASE = 8;
var STATE_FAR_GRABBING_NON_COLLIDING = 8;
var STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING = 9;
var STATE_RELEASE = 10;
var GRABBABLE_DATA_KEY = "grabbableKey"; // shared with grab.js
var GRAB_USER_DATA_KEY = "grabKey"; // shared with grab.js
@ -120,7 +122,7 @@ function MyController(hand, triggerAction) {
var TIP_CONTROLLER_OFFSET = 1;
this.triggerAction = triggerAction;
this.palm = SPATIAL_CONTROLLERS_PER_PALM * hand;
this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET;
this.tip = SPATIAL_CONTROLLERS_PER_PALM * hand + TIP_CONTROLLER_OFFSET;
this.actionID = null; // action this script created...
this.grabbedEntity = null; // on this entity.
@ -161,6 +163,12 @@ function MyController(hand, triggerAction) {
case STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING:
this.continueNearGrabbingNonColliding();
break;
case STATE_FAR_GRABBING_NON_COLLIDING:
this.farGrabbingNonColliding();
break;
case STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING:
this.continueFarGrabbingNonColliding();
break;
case STATE_RELEASE:
this.release();
break;
@ -210,7 +218,7 @@ function MyController(hand, triggerAction) {
this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) +
(triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO));
}
this.triggerSmoothedSqueezed = function() {
return this.triggerValue > TRIGGER_ON_VALUE;
};
@ -251,9 +259,7 @@ function MyController(hand, triggerAction) {
};
var intersection = Entities.findRayIntersection(pickRay, true);
if (intersection.intersects &&
intersection.properties.collisionsWillMove === 1 &&
intersection.properties.locked === 0) {
if (intersection.intersects && intersection.properties.locked === 0) {
// the ray is intersecting something we can move.
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection);
@ -266,14 +272,22 @@ function MyController(hand, triggerAction) {
}
if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) {
// the hand is very close to the intersected object. go into close-grabbing mode.
this.setState(STATE_NEAR_GRABBING);
if (intersection.properties.collisionsWillMove === 1) {
this.setState(STATE_NEAR_GRABBING);
} else {
this.setState(STATE_NEAR_GRABBING_NON_COLLIDING);
}
} else {
// don't allow two people to distance grab the same object
if (entityIsGrabbedByOther(intersection.entityID)) {
this.grabbedEntity = null;
} else {
// the hand is far from the intersected object. go into distance-holding mode
this.setState(STATE_DISTANCE_HOLDING);
if (intersection.properties.collisionsWillMove === 1) {
this.setState(STATE_DISTANCE_HOLDING);
} else {
this.setState(STATE_FAR_GRABBING_NON_COLLIDING);
}
}
}
} else {
@ -369,19 +383,19 @@ function MyController(hand, triggerAction) {
// how far did avatar move this timestep?
var currentPosition = MyAvatar.position;
var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition);
var avatarDeltaPosition = Vec3.subtract(currentPosition, this.currentAvatarPosition);
this.currentAvatarPosition = currentPosition;
// How far did the avatar turn this timestep?
// Note: The following code is too long because we need a Quat.quatBetween() function
// that returns the minimum quaternion between two quaternions.
var currentOrientation = MyAvatar.orientation;
if (Quat.dot(currentOrientation, this.currentAvatarOrientation) < 0.0) {
var negativeCurrentOrientation = {
x: -currentOrientation.x,
y: -currentOrientation.y,
z: -currentOrientation.z,
w: -currentOrientation.w
var negativeCurrentOrientation = {
x: -currentOrientation.x,
y: -currentOrientation.y,
z: -currentOrientation.z,
w: -currentOrientation.w
};
var avatarDeltaOrientation = Quat.multiply(negativeCurrentOrientation, Quat.inverse(this.currentAvatarOrientation));
} else {
@ -389,8 +403,8 @@ function MyController(hand, triggerAction) {
}
var handToAvatar = Vec3.subtract(handControllerPosition, this.currentAvatarPosition);
var objectToAvatar = Vec3.subtract(this.currentObjectPosition, this.currentAvatarPosition);
var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar);
var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar);
var handMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, handToAvatar), handToAvatar);
var objectMovementFromTurning = Vec3.subtract(Quat.multiply(avatarDeltaOrientation, objectToAvatar), objectToAvatar);
this.currentAvatarOrientation = currentOrientation;
// how far did hand move this timestep?
@ -411,7 +425,7 @@ function MyController(hand, triggerAction) {
var now = Date.now();
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
this.computeReleaseVelocity(deltaPosition, deltaTime, false);
this.currentObjectPosition = newObjectPosition;
this.currentObjectTime = now;
@ -440,7 +454,7 @@ function MyController(hand, triggerAction) {
this.lineOff();
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity,
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity,
["position", "rotation", "gravity", "ignoreForCollisions"]);
this.activateEntity(this.grabbedEntity, grabbedProperties);
@ -504,7 +518,9 @@ function MyController(hand, triggerAction) {
this.currentObjectTime = now;
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
Entities.updateAction(this.grabbedEntity, this.actionID, {lifetime: ACTION_LIFETIME});
Entities.updateAction(this.grabbedEntity, this.actionID, {
lifetime: ACTION_LIFETIME
});
};
this.nearGrabbingNonColliding = function() {
@ -521,14 +537,46 @@ function MyController(hand, triggerAction) {
this.setState(STATE_CONTINUE_NEAR_GRABBING_NON_COLLIDING);
};
this.farGrabbingNonColliding = function() {
if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
return;
}
if (this.hand === RIGHT_HAND) {
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
} else {
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
}
Entities.callEntityMethod(this.grabbedEntity, "startFarGrabNonColliding");
this.setState(STATE_CONTINUE_FAR_GRABBING_NON_COLLIDING);
};
this.continueNearGrabbingNonColliding = function() {
if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
return;
}
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrabbingNonColliding");
};
this.continueFarGrabbingNonColliding = function() {
if (this.triggerSmoothedReleased()) {
this.setState(STATE_RELEASE);
return;
}
var handPosition = this.getHandPosition();
var pickRay = {
origin: handPosition,
direction: Quat.getUp(this.getHandRotation())
};
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
Entities.callEntityMethod(this.grabbedEntity, "continueFarGrabbingNonColliding");
};
_this.allTouchedIDs = {};
this.touchTest = function() {
var maxDistance = 0.05;
@ -618,8 +666,8 @@ function MyController(hand, triggerAction) {
this.lineOff();
if (this.grabbedEntity !== null) {
if(this.actionID !== null) {
Entities.deleteAction(this.grabbedEntity, this.actionID);
if (this.actionID !== null) {
Entities.deleteAction(this.grabbedEntity, this.actionID);
}
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
}
@ -650,7 +698,14 @@ function MyController(hand, triggerAction) {
if (data["refCount"] == 1) {
data["gravity"] = grabbedProperties.gravity;
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
Entities.editEntity(entityID, {gravity: {x:0, y:0, z:0}, ignoreForCollisions: true});
Entities.editEntity(entityID, {
gravity: {
x: 0,
y: 0,
z: 0
},
ignoreForCollisions: true
});
}
setEntityCustomData(GRAB_USER_DATA_KEY, entityID, data);
};
@ -687,4 +742,4 @@ function cleanup() {
}
Script.scriptEnding.connect(cleanup);
Script.update.connect(update);
Script.update.connect(update);

View file

@ -305,15 +305,12 @@
var elParticleSections = document.querySelectorAll(".particle-section");
allSections.push(elParticleSections);
var elParticleIsEmitting = document.getElementById("property-particle-is-emitting");
var elParticleMaxParticles = document.getElementById("property-particle-maxparticles");
var elParticleLifeSpan = document.getElementById("property-particle-lifespan");
var elParticleEmitRate = document.getElementById("property-particle-emit-rate");
var elParticleEmitDirectionX = document.getElementById("property-particle-emit-direction-x");
var elParticleEmitDirectionY = document.getElementById("property-particle-emit-direction-y");
var elParticleEmitDirectionZ = document.getElementById("property-particle-emit-direction-z");
var elParticleEmitStrength = document.getElementById("property-particle-emit-strength");
var elParticleLocalGravity = document.getElementById("property-particle-localgravity");
var elParticleRadius = document.getElementById("property-particle-radius");
var elParticleTextures = document.getElementById("property-particle-textures");
var elTextSections = document.querySelectorAll(".text-section");
allSections.push(elTextSections);
@ -511,7 +508,7 @@
elColorSection.style.display = 'none';
}
if (properties.type == "Model" || properties.type == "ParticleEffect") {
if (properties.type == "Model") {
for (var i = 0; i < elModelSections.length; i++) {
elModelSections[i].style.display = 'block';
}
@ -529,7 +526,7 @@
elModelAnimationHold.checked = properties.animation.hold;
elModelAnimationStartAutomatically.checked = properties.animation.startAutomatically;
elModelTextures.value = properties.textures;
elModelOriginalTextures.value = properties.originalTextures;
elModelOriginalTextures.value = properties.originalTextures;
} else if (properties.type == "Web") {
for (var i = 0; i < elWebSections.length; i++) {
elWebSections[i].style.display = 'block';
@ -617,15 +614,13 @@
elParticleSections[i].style.display = 'block';
}
elParticleIsEmitting.checked = properties.isEmitting;
elParticleMaxParticles.value = properties.maxParticles;
elParticleLifeSpan.value = properties.lifespan.toFixed(2);
elParticleEmitRate.value = properties.emitRate.toFixed(1);
elParticleEmitDirectionX.value = properties.emitDirection.x.toFixed(2);
elParticleEmitDirectionY.value = properties.emitDirection.y.toFixed(2);
elParticleEmitDirectionZ.value = properties.emitDirection.z.toFixed(2);
elParticleEmitStrength.value = properties.emitStrength.toFixed(2);
elParticleLocalGravity.value = properties.localGravity.toFixed(2);
elParticleRadius.value = properties.particleRadius.toFixed(3);
elParticleTextures.value = properties.textures;
} else if (properties.type == "PolyVox") {
for (var i = 0; i < elPolyVoxSections.length; i++) {
elPolyVoxSections[i].style.display = 'block';
@ -758,17 +753,12 @@
elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl'));
elParticleIsEmitting.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isEmitting'));
elParticleMaxParticles.addEventListener('change', createEmitNumberPropertyUpdateFunction('maxParticles'));
elParticleLifeSpan.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifespan'));
elParticleEmitRate.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitRate'));
var particleEmitDirectionChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier(
'emitDirection', elParticleEmitDirectionX, elParticleEmitDirectionY, elParticleEmitDirectionZ, DEGREES_TO_RADIANS);
elParticleEmitDirectionX.addEventListener('change', particleEmitDirectionChangeFunction);
elParticleEmitDirectionY.addEventListener('change', particleEmitDirectionChangeFunction);
elParticleEmitDirectionZ.addEventListener('change', particleEmitDirectionChangeFunction);
elParticleEmitStrength.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitStrength'));
elParticleLocalGravity.addEventListener('change', createEmitNumberPropertyUpdateFunction('localGravity'));
elParticleRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('particleRadius'));
elParticleTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType'));
@ -1335,13 +1325,13 @@
<div class="model-section property">
<div class="label">Textures</div>
<div class="value">
<textarea id="property-model-textures" value='asdfasdf'></textarea>
<textarea id="property-model-textures" value=''></textarea>
</div>
</div>
<div class="model-section property">
<div class="label">Original Textures</div>
<div class="value">
<textarea id="property-model-original-textures" readonly value='asdfasdf'></textarea>
<textarea id="property-model-original-textures" readonly value=''></textarea>
</div>
</div>
@ -1362,6 +1352,12 @@
<label>Particle</label>
</div>
<div class="particle-section property">
<span class="label">Is Emitting</span>
<span class="value">
<input type='checkbox' id="property-particle-is-emitting">
</span>
</div>
<div class="particle-section property">
<div class="label">Max Particles</div>
<div class="value">
@ -1380,30 +1376,16 @@
<input type='number' id="property-particle-emit-rate" min="0" step="0.5">
</div>
</div>
<div class="particle-section property">
<div class="label">Particle Emission Direction</div>
<div class="value">
<div class="input-area">X <input class="coord" type='number' id="property-particle-emit-direction-x"></div>
<div class="input-area">Y <input class="coord" type='number' id="property-particle-emit-direction-y"></div>
<div class="input-area">Z <input class="coord" type='number' id="property-particle-emit-direction-z"></div>
</div>
</div>
<div class="particle-section property">
<div class="label">Particle Emission Strength</div>
<div class="value">
<input type='number' id="property-particle-emit-strength" min="0" step="0.1">
</div>
</div>
<div class="particle-section property">
<div class="label">Particle Local Gravity</div>
<div class="value">
<input class="coord" type='number' id="property-particle-localgravity" step="0.05">
</div>
</div>
<div class="particle-section property">
<div class="label">Particle Radius</div>
<div class="value">
<input class="coord" type='number' id="property-particle-radius" min="0" step="0.005">
<input class="coord" type='number' id="property-particle-radius" min="0" step="0.005">
</div>
</div>
<div class="particle-section property">
<div class="label">Textures</div>
<div class="value">
<textarea id="property-particle-textures" value=''></textarea>
</div>
</div>

View file

@ -13,8 +13,8 @@ Script.include("../../utilities.js");
var scriptURL = Script.resolvePath('pingPongGun.js');
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx?123'
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj?123';
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx'
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj';
var center = Vec3.sum(Vec3.sum(MyAvatar.position, {
x: 0,

View file

@ -0,0 +1,154 @@
// createTargets.js
//
// Script Type: Entity Spawner
// Created by James B. Pollack on 9/30/2015
// Copyright 2015 High Fidelity, Inc.
//
// This script creates targets that fall down when you shoot them and then automatically reset to their original position.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */
Script.include("../../utilities.js");
Script.include("../../libraries/utils.js");
var scriptURL = Script.resolvePath('wallTarget.js');
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target.fbx';
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/target_collision_hull.obj';
var RESET_DISTANCE = 1;
var TARGET_USER_DATA_KEY = 'hifi-ping_pong_target';
var NUMBER_OF_TARGETS = 6;
var TARGETS_PER_ROW = 3;
var TARGET_DIMENSIONS = {
x: 0.06,
y: 0.42,
z: 0.42
};
var VERTICAL_SPACING = TARGET_DIMENSIONS.y + 0.5;
var HORIZONTAL_SPACING = TARGET_DIMENSIONS.z + 0.5;
var startPosition = {
x: 548.68,
y: 497.30,
z: 509.74
};
var rotation = Quat.fromPitchYawRollDegrees(0, -55.25, 0);
var targetIntervalClearer = Entities.addEntity({
name: 'Target Interval Clearer - delete me to clear',
type: 'Box',
position: startPosition,
dimensions: TARGET_DIMENSIONS,
color: {
red: 0,
green: 255,
blue: 0
},
rotation: rotation,
visible: false,
collisionsWillMove: false,
ignoreForCollisions: true,
});
var targets = [];
var originalPositions = [];
function addTargets() {
var i;
var row = -1;
for (i = 0; i < NUMBER_OF_TARGETS; i++) {
if (i % TARGETS_PER_ROW === 0) {
row++;
}
var vHat = Quat.getFront(rotation);
var spacer = HORIZONTAL_SPACING * (i % TARGETS_PER_ROW) + (row * HORIZONTAL_SPACING / 2);
var multiplier = Vec3.multiply(spacer, vHat);
var position = Vec3.sum(startPosition, multiplier);
position.y = startPosition.y - (row * VERTICAL_SPACING);
originalPositions.push(position);
var targetProperties = {
name: 'Target',
type: 'Model',
modelURL: MODEL_URL,
shapeType: 'compound',
collisionsWillMove: true,
dimensions: TARGET_DIMENSIONS,
compoundShapeURL: COLLISION_HULL_URL,
position: position,
rotation: rotation,
script: scriptURL
};
targets.push(Entities.addEntity(targetProperties));
}
}
function testTargetDistanceFromStart() {
targets.forEach(function(target, index) {
var currentPosition = Entities.getEntityProperties(target, "position").position;
var originalPosition = originalPositions[index];
var distance = Vec3.subtract(originalPosition, currentPosition);
var length = Vec3.length(distance);
if (length > RESET_DISTANCE) {
Entities.deleteEntity(target);
var targetProperties = {
name: 'Target',
type: 'Model',
modelURL: MODEL_URL,
shapeType: 'compound',
collisionsWillMove: true,
dimensions: TARGET_DIMENSIONS,
compoundShapeURL: COLLISION_HULL_URL,
position: originalPositions[index],
rotation: rotation,
script: scriptURL
};
targets[index] = Entities.addEntity(targetProperties);
}
});
}
function deleteEntity(entityID) {
if (entityID === targetIntervalClearer) {
deleteTargets();
Script.clearInterval(distanceCheckInterval);
Entities.deletingEntity.disconnect(deleteEntity);
}
}
function deleteTargets() {
while (targets.length > 0) {
Entities.deleteEntity(targets.pop());
}
Entities.deleteEntity(targetIntervalClearer);
}
Entities.deletingEntity.connect(deleteEntity);
var distanceCheckInterval = Script.setInterval(testTargetDistanceFromStart, 1000);
addTargets();
function atEnd() {
Script.clearInterval(distanceCheckInterval);
deleteTargets();
}
Script.scriptEnding.connect(atEnd);

View file

@ -14,6 +14,7 @@
Script.include("../../libraries/utils.js");
var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/ping_pong_gun/pong_sound.wav';
var PING_PONG_BALL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_ball.fbx';
function PingPongGun() {
return;
@ -115,7 +116,10 @@
forwardVec = Vec3.multiply(forwardVec, GUN_FORCE);
var properties = {
type: 'Sphere',
// type: 'Model',
// modelURL:PING_PONG_BALL_URL,
shapeType:'sphere',
type:'Sphere',
color: BALL_COLOR,
dimensions: BALL_DIMENSIONS,
linearDamping: BALL_LINEAR_DAMPING,
@ -164,4 +168,4 @@
// entity scripts always need to return a newly constructed object of our type
return new PingPongGun();
});
});

View file

@ -0,0 +1,56 @@
// wallTarget.js
//
// Script Type: Entity
// Created by James B. Pollack @imgntn on 9/21/2015
// Copyright 2015 High Fidelity, Inc.
//
// This script resets an object to its original position when it stops moving after a collision
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */
(function() {
function Target() {
return;
}
Target.prototype = {
hasPlayedSound: false,
preload: function(entityID) {
this.entityID = entityID;
var SOUND_URL = "http://hifi-public.s3.amazonaws.com/sounds/Clay_Pigeon_02.L.wav";
this.hitSound = SoundCache.getSound(SOUND_URL);
},
collisionWithEntity: function(me, otherEntity) {
var position = Entities.getEntityProperties(me, "position").position;
Entities.editEntity(me, {
gravity: {
x: 0,
y: -9.8,
z: 0
},
velocity: {
x: 0,
y: -0.01,
z: 0
}
});
if (this.hasPlayedSound === false) {
this.audioInjector = Audio.playSound(this.hitSound, {
position: position,
volume: 0.5
});
this.hasPlayedSound = true;
}
}
};
// entity scripts always need to return a newly constructed object of our type
return new Target();
});

View file

@ -1825,17 +1825,16 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
}
#endif
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
_entities.mouseMoveEvent(event, deviceID);
{
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
_controllerScriptingInterface.emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
}
_entities.mouseMoveEvent(&mappedEvent, deviceID);
_controllerScriptingInterface.emitMouseMoveEvent(&mappedEvent, deviceID); // send events to any registered scripts
// if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface.isMouseCaptured()) {
@ -1851,19 +1850,19 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
// Inhibit the menu if the user is using alt-mouse dragging
_altPressed = false;
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
if (!_aboutToQuit) {
_entities.mousePressEvent(event, deviceID);
_entities.mousePressEvent(&mappedEvent, deviceID);
}
{
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
_controllerScriptingInterface.emitMousePressEvent(&mappedEvent); // send events to any registered scripts
}
_controllerScriptingInterface.emitMousePressEvent(&mappedEvent); // send events to any registered scripts
// if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface.isMouseCaptured()) {
@ -1879,7 +1878,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
if (event->button() == Qt::LeftButton) {
// nobody handled this - make it an action event on the _window object
HFActionEvent actionEvent(HFActionEvent::startType(),
computePickRay(event->x(), event->y()));
computePickRay(mappedEvent.x(), mappedEvent.y()));
sendEvent(this, &actionEvent);
} else if (event->button() == Qt::RightButton) {
@ -1907,19 +1906,18 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI
void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
if (!_aboutToQuit) {
_entities.mouseReleaseEvent(event, deviceID);
_entities.mouseReleaseEvent(&mappedEvent, deviceID);
}
{
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QPointF transformedPos = offscreenUi->mapToVirtualScreen(event->localPos(), _glWidget);
QMouseEvent mappedEvent(event->type(),
transformedPos,
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
_controllerScriptingInterface.emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
}
_controllerScriptingInterface.emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
// if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface.isMouseCaptured()) {
@ -1934,7 +1932,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
if (event->button() == Qt::LeftButton) {
// fire an action end event
HFActionEvent actionEvent(HFActionEvent::endType(),
computePickRay(event->x(), event->y()));
computePickRay(mappedEvent.x(), mappedEvent.y()));
sendEvent(this, &actionEvent);
}
}

View file

@ -215,7 +215,7 @@ bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) c
}
bool JointState::translationIsDefault(const glm::vec3& translation, float tolerance) const {
return glm::distance(_defaultTranslation * _unitsScale, translation * _unitsScale) < tolerance;
return glm::distance(_defaultTranslation * _unitsScale, translation) < tolerance;
}
glm::quat JointState::getDefaultRotationInParentFrame() const {

View file

@ -287,6 +287,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
#ifdef WANT_DEBUG
int rotationSentCount = 0;
unsigned char* beforeRotations = destinationBuffer;
#endif
_lastSentJointData.resize(_jointData.size());
@ -335,6 +336,7 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
#ifdef WANT_DEBUG
int translationSentCount = 0;
unsigned char* beforeTranslations = destinationBuffer;
#endif
float maxTranslationDimension = 0.0;
@ -387,10 +389,15 @@ QByteArray AvatarData::toByteArray(bool cullSmallChanges, bool sendAll) {
#ifdef WANT_DEBUG
if (sendAll) {
qDebug() << "SENDING -- rotations:" << rotationSentCount << "translations:" << translationSentCount
qDebug() << "AvatarData::toByteArray" << cullSmallChanges << sendAll
<< "rotations:" << rotationSentCount << "translations:" << translationSentCount
<< "largest:" << maxTranslationDimension
<< "radix:" << translationCompressionRadix
<< "size:" << (int)(destinationBuffer - startPosition);
<< "size:"
<< (beforeRotations - startPosition) << "+"
<< (beforeTranslations - beforeRotations) << "+"
<< (destinationBuffer - beforeTranslations) << "="
<< (destinationBuffer - startPosition);
}
#endif
@ -409,7 +416,8 @@ void AvatarData::doneEncoding(bool cullSmallChanges) {
_lastSentJointData[i].rotation = data.rotation;
}
}
}
if (_lastSentJointData[i].translation != data.translation) {
if (!cullSmallChanges ||
glm::distance(data.translation, _lastSentJointData[i].translation) > AVATAR_MIN_TRANSLATION) {
if (data.translationSet) {

View file

@ -313,6 +313,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_TEXT_COLOR, textColor);
CHECK_PROPERTY_CHANGE(PROP_BACKGROUND_COLOR, backgroundColor);
CHECK_PROPERTY_CHANGE(PROP_SHAPE_TYPE, shapeType);
CHECK_PROPERTY_CHANGE(PROP_EMITTING_PARTICLES, isEmitting);
CHECK_PROPERTY_CHANGE(PROP_MAX_PARTICLES, maxParticles);
CHECK_PROPERTY_CHANGE(PROP_LIFESPAN, lifespan);
CHECK_PROPERTY_CHANGE(PROP_EMIT_RATE, emitRate);
@ -424,6 +425,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
// Particles only
if (_type == EntityTypes::ParticleEffect) {
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTING_PARTICLES, isEmitting);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MAX_PARTICLES, maxParticles);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LIFESPAN, lifespan);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMIT_RATE, emitRate);
@ -1118,6 +1120,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData());
APPEND_ENTITY_PROPERTY(PROP_ALPHA, properties.getAlpha());
}
if (propertyCount > 0) {
int endOfEntityItemData = packetData->getUncompressedByteOffset();
@ -1472,6 +1475,7 @@ void EntityItemProperties::markAllChanged() {
_backgroundColorChanged = true;
_shapeTypeChanged = true;
_isEmittingChanged = true;
_maxParticlesChanged = true;
_lifespanChanged = true;
_emitRateChanged = true;

View file

@ -329,7 +329,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); // FIXME - this doesn't appear to get used
COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isEmitting, getIsEmitting);

View file

@ -1512,7 +1512,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS
}
extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex);
buildModelMesh(extracted, url);
buildModelMesh(extracted.mesh, url);
if (extracted.mesh.isEye) {
if (maxJointIndex == geometry.leftEyeJointIndex) {

View file

@ -388,7 +388,7 @@ public:
ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex);
QHash<QString, ExtractedMesh> meshes;
void buildModelMesh(ExtractedMesh& extracted, const QString& url);
static void buildModelMesh(FBXMesh& extractedMesh, const QString& url);
FBXTexture getTexture(const QString& textureID);

View file

@ -386,11 +386,11 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
return data.extracted;
}
void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) {
void FBXReader::buildModelMesh(FBXMesh& extractedMesh, const QString& url) {
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("buildModelMesh failed -- .*");
unsigned int totalSourceIndices = 0;
foreach(const FBXMeshPart& part, extracted.mesh.parts) {
foreach(const FBXMeshPart& part, extractedMesh.parts) {
totalSourceIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
}
@ -399,18 +399,18 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) {
return;
}
if (extracted.mesh.vertices.size() == 0) {
if (extractedMesh.vertices.size() == 0) {
qCDebug(modelformat) << "buildModelMesh failed -- no vertices, url = " << url;
return;
}
FBXMesh& fbxMesh = extracted.mesh;
FBXMesh& fbxMesh = extractedMesh;
model::MeshPointer mesh(new model::Mesh());
// Grab the vertices in a buffer
auto vb = std::make_shared<gpu::Buffer>();
vb->setData(extracted.mesh.vertices.size() * sizeof(glm::vec3),
(const gpu::Byte*) extracted.mesh.vertices.data());
vb->setData(extractedMesh.vertices.size() * sizeof(glm::vec3),
(const gpu::Byte*) extractedMesh.vertices.data());
gpu::BufferView vbv(vb, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
mesh->setVertexBuffer(vbv);
@ -486,7 +486,7 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) {
unsigned int totalIndices = 0;
foreach(const FBXMeshPart& part, extracted.mesh.parts) {
foreach(const FBXMeshPart& part, extractedMesh.parts) {
totalIndices += (part.quadTrianglesIndices.size() + part.triangleIndices.size());
}
@ -502,10 +502,10 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) {
int offset = 0;
std::vector< model::Mesh::Part > parts;
if (extracted.mesh.parts.size() > 1) {
if (extractedMesh.parts.size() > 1) {
indexNum = 0;
}
foreach(const FBXMeshPart& part, extracted.mesh.parts) {
foreach(const FBXMeshPart& part, extractedMesh.parts) {
model::Mesh::Part modelPart(indexNum, 0, 0, model::Mesh::TRIANGLES);
if (part.quadTrianglesIndices.size()) {
@ -545,5 +545,5 @@ void FBXReader::buildModelMesh(ExtractedMesh& extracted, const QString& url) {
// model::Box box =
mesh->evalPartBound(0);
extracted.mesh._mesh = mesh;
extractedMesh._mesh = mesh;
}

View file

@ -532,6 +532,8 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping,
mesh.meshExtents.addPoint(vertex);
geometry.meshExtents.addPoint(vertex);
}
FBXReader::buildModelMesh(mesh, url.toString());
// fbxDebugDump(geometry);
} catch(const std::exception& e) {
qCDebug(modelformat) << "OBJ reader fail: " << e.what();

View file

@ -205,6 +205,13 @@ void Batch::setViewportTransform(const Vec4i& viewport) {
_params.push_back(cacheData(sizeof(Vec4i), &viewport));
}
void Batch::setDepthRangeTransform(float nearDepth, float farDepth) {
ADD_COMMAND(setDepthRangeTransform);
_params.push_back(farDepth);
_params.push_back(nearDepth);
}
void Batch::setPipeline(const PipelinePointer& pipeline) {
ADD_COMMAND(setPipeline);

View file

@ -187,6 +187,7 @@ public:
void setProjectionTransform(const Mat4& proj);
// Viewport is xy = low left corner in framebuffer, zw = width height of the viewport, expressed in pixels
void setViewportTransform(const Vec4i& viewport);
void setDepthRangeTransform(float nearDepth, float farDepth);
// Pipeline Stage
void setPipeline(const PipelinePointer& pipeline);
@ -285,6 +286,7 @@ public:
COMMAND_setViewTransform,
COMMAND_setProjectionTransform,
COMMAND_setViewportTransform,
COMMAND_setDepthRangeTransform,
COMMAND_setPipeline,
COMMAND_setStateBlendFactor,

View file

@ -14,11 +14,12 @@
out vec2 varTexCoord0;
void main(void) {
const float depth = 1.0;
const vec4 UNIT_QUAD[4] = vec4[4](
vec4(-1.0, -1.0, 0.0, 1.0),
vec4(1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0)
vec4(-1.0, -1.0, depth, 1.0),
vec4(1.0, -1.0, depth, 1.0),
vec4(-1.0, 1.0, depth, 1.0),
vec4(1.0, 1.0, depth, 1.0)
);
vec4 pos = UNIT_QUAD[gl_VertexID];

View file

@ -35,6 +35,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_setViewTransform),
(&::gpu::GLBackend::do_setProjectionTransform),
(&::gpu::GLBackend::do_setViewportTransform),
(&::gpu::GLBackend::do_setDepthRangeTransform),
(&::gpu::GLBackend::do_setPipeline),
(&::gpu::GLBackend::do_setStateBlendFactor),

View file

@ -314,6 +314,7 @@ protected:
void do_setViewTransform(Batch& batch, uint32 paramOffset);
void do_setProjectionTransform(Batch& batch, uint32 paramOffset);
void do_setViewportTransform(Batch& batch, uint32 paramOffset);
void do_setDepthRangeTransform(Batch& batch, uint32 paramOffset);
void initTransform();
void killTransform();
@ -339,6 +340,7 @@ protected:
Transform _view;
Mat4 _projection;
Vec4i _viewport{ 0, 0, 1, 1 };
Vec2 _depthRange{ 0.0f, 1.0f };
bool _invalidModel{true};
bool _invalidView{false};
bool _invalidProj{false};

View file

@ -45,10 +45,21 @@ void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) {
glViewport(vp.x, vp.y, vp.z, vp.w);
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and willl need update on next drawcall
// The Viewport is tagged invalid because the CameraTransformUBO is not up to date and will need update on next drawcall
_transform._invalidViewport = true;
}
void GLBackend::do_setDepthRangeTransform(Batch& batch, uint32 paramOffset) {
Vec2 depthRange(batch._params[paramOffset + 0]._float, batch._params[paramOffset + 1]._float);
if ((depthRange.x != _transform._depthRange.x) || (depthRange.y != _transform._depthRange.y)) {
_transform._depthRange = depthRange;
glDepthRangef(depthRange.x, depthRange.y);
}
}
void GLBackend::initTransform() {
glGenBuffers(1, &_transform._objectBuffer);
glGenBuffers(1, &_transform._cameraBuffer);
@ -75,6 +86,8 @@ void GLBackend::syncTransformStateCache() {
glGetIntegerv(GL_VIEWPORT, (GLint*) &_transform._viewport);
glGetFloatv(GL_DEPTH_RANGE, (GLfloat*)&_transform._depthRange);
Mat4 modelView;
auto modelViewInv = glm::inverse(modelView);
_transform._view.evalFromRawMatrix(modelViewInv);

View file

@ -16,7 +16,7 @@
#include "HifiSockAddr.h"
#include "NetworkLogging.h"
static int hifiSockAddrMetaTypeId = qMetaTypeId<HifiSockAddr>();
static int hifiSockAddrMetaTypeId = qRegisterMetaType<HifiSockAddr>();
HifiSockAddr::HifiSockAddr() :
_address(),

View file

@ -94,6 +94,6 @@ namespace std {
QHostAddress getLocalAddress();
Q_DECLARE_METATYPE(HifiSockAddr)
Q_DECLARE_METATYPE(HifiSockAddr);
#endif // hifi_HifiSockAddr_h

View file

@ -501,7 +501,7 @@ SharedNodePointer LimitedNodeList::addOrUpdateNode(const QUuid& uuid, NodeType_t
LimitedNodeList::flagTimeForConnectionStep(LimitedNodeList::AddedAudioMixer);
}
SharedNodePointer newNodePointer(newNode);
SharedNodePointer newNodePointer(newNode, &QObject::deleteLater);
_nodeHash.insert(UUIDNodePair(newNode->getUUID(), newNodePointer));

View file

@ -60,8 +60,6 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo
const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username";
class HifiSockAddr;
using namespace tbb;
typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
typedef concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;

View file

@ -150,6 +150,8 @@ void PacketList::preparePackets(MessageNumber messageNumber) {
}
}
const qint64 PACKET_LIST_WRITE_ERROR = -1;
qint64 PacketList::writeData(const char* data, qint64 maxSize) {
auto sizeRemaining = maxSize;
@ -176,26 +178,41 @@ qint64 PacketList::writeData(const char* data, qint64 maxSize) {
// We need to try and pull the first part of the segment out to our new packet
// check now to see if this is an unsupported write
int numBytesToEnd = _currentPacket->bytesAvailableForWrite();
if ((newPacket->size() - numBytesToEnd) < sizeRemaining) {
int segmentSize = _currentPacket->pos() - _segmentStartIndex;
if (segmentSize + sizeRemaining > newPacket->getPayloadCapacity()) {
// this is an unsupported case - the segment is bigger than the size of an individual packet
// but the PacketList is not going to be sent ordered
qDebug() << "Error in PacketList::writeData - attempted to write a segment to an unordered packet that is"
<< "larger than the payload size.";
Q_ASSERT(false);
// we won't be writing this new data to the packet
// go back before the current segment and return -1 to indicate error
_currentPacket->seek(_segmentStartIndex);
_currentPacket->setPayloadSize(_segmentStartIndex);
return PACKET_LIST_WRITE_ERROR;
} else {
// copy from currentPacket where the segment started to the beginning of the newPacket
newPacket->write(_currentPacket->getPayload() + _segmentStartIndex, segmentSize);
// shrink the current payload to the actual size of the packet
_currentPacket->setPayloadSize(_segmentStartIndex);
// the current segment now starts at the beginning of the new packet
_segmentStartIndex = _extendedHeader.size();
}
int segmentSize = _currentPacket->pos() - _segmentStartIndex;
// copy from currentPacket where the segment started to the beginning of the newPacket
newPacket->write(_currentPacket->getPayload() + _segmentStartIndex, segmentSize);
// the current segment now starts at the beginning of the new packet
_segmentStartIndex = _extendedHeader.size();
// shrink the current payload to the actual size of the packet
_currentPacket->setPayloadSize(_segmentStartIndex);
}
if (sizeRemaining > newPacket->getPayloadCapacity()) {
// this is an unsupported case - attempting to write a block of data larger
// than the capacity of a new packet in an unordered PacketList
qDebug() << "Error in PacketList::writeData - attempted to write data to an unordered packet that is"
<< "larger than the payload size.";
Q_ASSERT(false);
return PACKET_LIST_WRITE_ERROR;
}
// move the current packet to our list of packets

View file

@ -355,11 +355,12 @@ bool SendQueue::maybeResendPacket() {
// we found the packet - grab it
auto& resendPacket = *(it->second);
// send it off
sendPacket(resendPacket);
// unlock the sent packets
sentLocker.unlock();
// send it off
sendPacket(resendPacket);
emit packetRetransmitted();
// Signal that we did resend a packet

View file

@ -31,8 +31,8 @@ Socket::Socket(QObject* parent) :
QObject(parent),
_synTimer(new QTimer(this))
{
qRegisterMetaType<Packet*>();
qRegisterMetaType<PacketList*>();
qRegisterMetaType<Packet*>("Packet*");
qRegisterMetaType<PacketList*>("PacketList*");
connect(&_udpSocket, &QUdpSocket::readyRead, this, &Socket::readPendingDatagrams);

View file

@ -35,9 +35,7 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
_frameBufferSize = frameBufferSize;
_primaryFramebufferFull.reset();
_primaryFramebufferDepthColor.reset();
_primaryFramebufferStencilColor.reset();
_primaryDepthTexture.reset();
_primaryStencilTexture.reset();
_primaryColorTexture.reset();
_primaryNormalTexture.reset();
_primarySpecularTexture.reset();
@ -49,7 +47,6 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
void FramebufferCache::createPrimaryFramebuffer() {
_primaryFramebufferFull = gpu::FramebufferPointer(gpu::Framebuffer::create());
_primaryFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create());
_primaryFramebufferStencilColor = gpu::FramebufferPointer(gpu::Framebuffer::create());
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
auto width = _frameBufferSize.width();
@ -66,20 +63,14 @@ void FramebufferCache::createPrimaryFramebuffer() {
_primaryFramebufferDepthColor->setRenderBuffer(0, _primaryColorTexture);
_primaryFramebufferStencilColor->setRenderBuffer(0, _primaryColorTexture);
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
// auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
auto stencilFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); // Depth24_Stencil8 texel format
_primaryStencilTexture = gpu::TexturePointer(gpu::Texture::create2D(stencilFormat, width, height, defaultSampler));
_primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
_primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
_primaryFramebufferStencilColor->setDepthStencilBuffer(_primaryStencilTexture, stencilFormat);
_selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler));
_selfieFramebuffer->setRenderBuffer(0, tex);
@ -99,13 +90,6 @@ gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() {
return _primaryFramebufferDepthColor;
}
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferStencilColor() {
if (!_primaryFramebufferStencilColor) {
createPrimaryFramebuffer();
}
return _primaryFramebufferStencilColor;
}
gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() {
if (!_primaryDepthTexture) {
createPrimaryFramebuffer();
@ -113,13 +97,6 @@ gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() {
return _primaryDepthTexture;
}
gpu::TexturePointer FramebufferCache::getPrimaryStencilTexture() {
if (!_primaryStencilTexture) {
createPrimaryFramebuffer();
}
return _primaryStencilTexture;
}
gpu::TexturePointer FramebufferCache::getPrimaryColorTexture() {
if (!_primaryColorTexture) {
createPrimaryFramebuffer();

View file

@ -31,10 +31,8 @@ public:
/// used for scene rendering.
gpu::FramebufferPointer getPrimaryFramebuffer();
gpu::FramebufferPointer getPrimaryFramebufferDepthColor();
gpu::FramebufferPointer getPrimaryFramebufferStencilColor();
gpu::TexturePointer getPrimaryDepthTexture();
gpu::TexturePointer getPrimaryStencilTexture();
gpu::TexturePointer getPrimaryColorTexture();
gpu::TexturePointer getPrimaryNormalTexture();
gpu::TexturePointer getPrimarySpecularTexture();
@ -60,9 +58,8 @@ private:
gpu::FramebufferPointer _primaryFramebufferFull;
gpu::FramebufferPointer _primaryFramebufferDepthColor;
gpu::FramebufferPointer _primaryFramebufferStencilColor;
gpu::TexturePointer _primaryDepthTexture;
gpu::TexturePointer _primaryStencilTexture;
gpu::TexturePointer _primaryColorTexture;
gpu::TexturePointer _primaryNormalTexture;
gpu::TexturePointer _primarySpecularTexture;

View file

@ -37,22 +37,17 @@ void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderCon
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
auto primaryFboStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
batch.enableStereo(false);
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
batch.setFramebuffer(primaryFboStencil);
batch.clearFramebuffer(
gpu::Framebuffer::BUFFER_STENCIL,
vec4(vec3(0), 1), 1.0, 0.0, true);
batch.setFramebuffer(primaryFbo);
batch.clearFramebuffer(
gpu::Framebuffer::BUFFER_COLOR0 |
gpu::Framebuffer::BUFFER_DEPTH,
gpu::Framebuffer::BUFFER_DEPTH |
gpu::Framebuffer::BUFFER_STENCIL,
vec4(vec3(0), 1), 1.0, 0.0, true);
});
}
@ -313,7 +308,8 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
gpu::Shader::makeProgram((*program));
auto state = std::make_shared<gpu::State>();
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE));
state->setDepthTest(true, false, gpu::LESS_EQUAL);
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_REPLACE));
state->setColorWriteMask(0);
_opaquePipeline.reset(gpu::Pipeline::create(program, state));
@ -330,9 +326,8 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren
doInBatch(args->_context, [=](gpu::Batch& batch) {
args->_batch = &batch;
auto primaryFboColorDepthStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
auto primaryDepth = DependencyManager::get<FramebufferCache>()->getPrimaryDepthTexture();
auto primaryFboColorDepthStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
batch.enableStereo(false);
batch.setFramebuffer(primaryFboColorDepthStencil);
@ -340,7 +335,6 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren
batch.setStateScissorRect(args->_viewport);
batch.setPipeline(getOpaquePipeline());
batch.setResourceTexture(0, primaryDepth);
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.setResourceTexture(0, nullptr);
@ -367,12 +361,12 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
doInBatch(args->_context, [=](gpu::Batch& batch) {
args->_batch = &batch;
auto primaryFboColorStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
auto primaryFboColorDepthStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
auto primaryFboFull = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
batch.enableSkybox(true);
batch.setFramebuffer(primaryFboColorStencil);
batch.setFramebuffer(primaryFboColorDepthStencil);
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);

View file

@ -12,13 +12,5 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
in vec2 varTexCoord0;
uniform sampler2D depthTexture;
void main(void) {
float depth = texture(depthTexture, varTexCoord0.xy).r;
if (depth >= 1.0) {
discard;
}
}

View file

@ -11,12 +11,13 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop>
#include <QtCore/QFileInfo>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QScriptEngine>
#include <QScriptValue>
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
#include <AudioConstants.h>
#include <AudioEffectOptions.h>
@ -942,6 +943,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
#endif
auto scriptCache = DependencyManager::get<ScriptCache>();
bool isFileUrl = isURL && scriptOrURL.startsWith("file://");
// first check the syntax of the script contents
QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(contents);
@ -950,7 +952,9 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
qCDebug(scriptengine) << " " << syntaxCheck.errorMessage() << ":"
<< syntaxCheck.errorLineNumber() << syntaxCheck.errorColumnNumber();
qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
scriptCache->addScriptToBadScriptList(scriptOrURL);
if (!isFileUrl) {
scriptCache->addScriptToBadScriptList(scriptOrURL);
}
return; // done processing script
}
@ -965,14 +969,21 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co
qCDebug(scriptengine) << "ScriptEngine::loadEntityScript() entity:" << entityID;
qCDebug(scriptengine) << " NOT CONSTRUCTOR";
qCDebug(scriptengine) << " SCRIPT:" << scriptOrURL;
scriptCache->addScriptToBadScriptList(scriptOrURL);
if (!isFileUrl) {
scriptCache->addScriptToBadScriptList(scriptOrURL);
}
return; // done processing script
}
QScriptValue entityScriptConstructor = evaluate(contents);
int64_t lastModified = 0;
if (isFileUrl) {
QString file = QUrl(scriptOrURL).toLocalFile();
lastModified = (quint64)QFileInfo(file).lastModified().toMSecsSinceEpoch();
}
QScriptValue entityScriptConstructor = evaluate(contents);
QScriptValue entityScriptObject = entityScriptConstructor.construct();
EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject };
EntityScriptDetails newDetails = { scriptOrURL, entityScriptObject, lastModified };
_entityScripts[entityID] = newDetails;
if (isURL) {
setParentURL("");
@ -1022,6 +1033,41 @@ void ScriptEngine::unloadAllEntityScripts() {
_entityScripts.clear();
}
void ScriptEngine::refreshFileScript(const EntityItemID& entityID) {
if (!_entityScripts.contains(entityID)) {
return;
}
static bool recurseGuard = false;
if (recurseGuard) {
return;
}
recurseGuard = true;
EntityScriptDetails details = _entityScripts[entityID];
// Check to see if a file based script needs to be reloaded (easier debugging)
if (details.lastModified > 0) {
QString filePath = QUrl(details.scriptText).toLocalFile();
auto lastModified = QFileInfo(filePath).lastModified().toMSecsSinceEpoch();
if (lastModified > details.lastModified) {
qDebug() << "Reloading modified script " << details.scriptText;
QFile file(filePath);
file.open(QIODevice::ReadOnly);
QString scriptContents = QTextStream(&file).readAll();
this->unloadEntityScript(entityID);
this->entityScriptContentAvailable(entityID, details.scriptText, scriptContents, true, true);
if (!_entityScripts.contains(entityID)) {
qWarning() << "Reload script " << details.scriptText << " failed";
} else {
details = _entityScripts[entityID];
}
}
}
recurseGuard = false;
}
void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QString& methodName) {
if (QThread::currentThread() != thread()) {
#ifdef THREAD_DEBUGGING
@ -1039,6 +1085,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
"entityID:" << entityID << "methodName:" << methodName;
#endif
refreshFileScript(entityID);
if (_entityScripts.contains(entityID)) {
EntityScriptDetails details = _entityScripts[entityID];
QScriptValue entityScript = details.scriptObject; // previously loaded
@ -1069,6 +1116,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
"entityID:" << entityID << "methodName:" << methodName << "event: mouseEvent";
#endif
refreshFileScript(entityID);
if (_entityScripts.contains(entityID)) {
EntityScriptDetails details = _entityScripts[entityID];
QScriptValue entityScript = details.scriptObject; // previously loaded
@ -1101,6 +1149,7 @@ void ScriptEngine::callEntityScriptMethod(const EntityItemID& entityID, const QS
"entityID:" << entityID << "methodName:" << methodName << "otherID:" << otherID << "collision: collision";
#endif
refreshFileScript(entityID);
if (_entityScripts.contains(entityID)) {
EntityScriptDetails details = _entityScripts[entityID];
QScriptValue entityScript = details.scriptObject; // previously loaded

View file

@ -45,6 +45,7 @@ class EntityScriptDetails {
public:
QString scriptText;
QScriptValue scriptObject;
int64_t lastModified;
};
class ScriptEngine : public QScriptEngine, public ScriptUser, public EntitiesScriptEngineProvider {
@ -171,6 +172,7 @@ private:
bool evaluatePending() const { return _evaluatesPending > 0; }
void timerFired();
void stopAllTimers();
void refreshFileScript(const EntityItemID& entityID);
void setParentURL(const QString& parentURL) { _parentURL = parentURL; }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
// immediateClientReset.js
// Created by Eric Levin on 9/23/2015
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */
var masterResetScript = Script.resolvePath("masterReset.js");
var hiddenEntityScriptURL = Script.resolvePath("hiddenEntityReset.js");
Script.include(masterResetScript);
function createHiddenMasterSwitch() {
var resetKey = "resetMe";
var masterSwitch = Entities.addEntity({
type: "Box",
name: "Master Switch",
script: hiddenEntityScriptURL,
dimensions: {x: 0.7, y: 0.2, z: 0.1},
position: {x: 543.9, y: 496.05, z: 502.43},
rotation: Quat.fromPitchYawRollDegrees(0, 33, 0),
visible: false
});
}
var entities = Entities.findEntities(MyAvatar.position, 100);
entities.forEach(function(entity) {
//params: customKey, id, defaultValue
var name = Entities.getEntityProperties(entity, "name").name
if (name === "Master Switch") {
Entities.deleteEntity(entity);
}
});
createHiddenMasterSwitch();
MasterReset();

File diff suppressed because it is too large Load diff