mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-30 04:31:16 +02:00
fix merge conflicts
This commit is contained in:
commit
118f919c8b
16 changed files with 3955 additions and 1029 deletions
|
@ -286,7 +286,7 @@ function MyController(hand) {
|
||||||
//for visualizations
|
//for visualizations
|
||||||
this.overlayLine = null;
|
this.overlayLine = null;
|
||||||
this.particleBeam = null;
|
this.particleBeam = null;
|
||||||
|
|
||||||
//for lights
|
//for lights
|
||||||
this.spotlight = null;
|
this.spotlight = null;
|
||||||
this.pointlight = null;
|
this.pointlight = null;
|
||||||
|
@ -296,7 +296,7 @@ function MyController(hand) {
|
||||||
// how far from camera to search intersection?
|
// how far from camera to search intersection?
|
||||||
this.intersectionDistance = 0.0;
|
this.intersectionDistance = 0.0;
|
||||||
this.searchSphereDistance = 0.0;
|
this.searchSphereDistance = 0.0;
|
||||||
|
|
||||||
this.ignoreIK = false;
|
this.ignoreIK = false;
|
||||||
this.offsetPosition = Vec3.ZERO;
|
this.offsetPosition = Vec3.ZERO;
|
||||||
this.offsetRotation = Quat.IDENTITY;
|
this.offsetRotation = Quat.IDENTITY;
|
||||||
|
@ -401,7 +401,7 @@ function MyController(hand) {
|
||||||
userData: JSON.stringify({
|
userData: JSON.stringify({
|
||||||
grabbableKey: {
|
grabbableKey: {
|
||||||
grabbable: false
|
grabbable: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -475,7 +475,7 @@ function MyController(hand) {
|
||||||
this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan);
|
this.createParticleBeam(position, finalRotation, color, speed, spread, lifespan);
|
||||||
} else {
|
} else {
|
||||||
this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan);
|
this.updateParticleBeam(position, finalRotation, color, speed, spread, lifespan);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.handleDistantParticleBeam = function(handPosition, objectPosition, color) {
|
this.handleDistantParticleBeam = function(handPosition, objectPosition, color) {
|
||||||
|
@ -563,12 +563,12 @@ function MyController(hand) {
|
||||||
Entities.editEntity(this.particleBeam, {
|
Entities.editEntity(this.particleBeam, {
|
||||||
rotation: orientation,
|
rotation: orientation,
|
||||||
position: position,
|
position: position,
|
||||||
visible: true,
|
visible: true,
|
||||||
color: color,
|
color: color,
|
||||||
emitSpeed: speed,
|
emitSpeed: speed,
|
||||||
speedSpread: spread,
|
speedSpread: spread,
|
||||||
lifespan: lifespan
|
lifespan: lifespan
|
||||||
})
|
})
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -584,7 +584,7 @@ function MyController(hand) {
|
||||||
x: 1,
|
x: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 0
|
z: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)),
|
p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)),
|
||||||
|
@ -818,19 +818,28 @@ function MyController(hand) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Messages.sendMessage('Hifi-Light-Overlay-Ray-Check', JSON.stringify(pickRayBacked));
|
||||||
|
|
||||||
var intersection;
|
var intersection;
|
||||||
|
|
||||||
if (USE_BLACKLIST === true && blacklist.length !== 0) {
|
if (USE_BLACKLIST === true && blacklist.length !== 0) {
|
||||||
intersection = Entities.findRayIntersection(pickRay, true, [], blacklist);
|
intersection = Entities.findRayIntersection(pickRayBacked, true, [], blacklist);
|
||||||
} else {
|
} else {
|
||||||
intersection = Entities.findRayIntersection(pickRayBacked, true);
|
intersection = Entities.findRayIntersection(pickRayBacked, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
|
|
||||||
// the ray is intersecting something we can move.
|
// the ray is intersecting something we can move.
|
||||||
this.intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
|
this.intersectionDistance = Vec3.distance(pickRay.origin, intersection.intersection);
|
||||||
|
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA);
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, intersection.entityID, DEFAULT_GRABBABLE_DATA);
|
||||||
|
var defaultDisableNearGrabData = {
|
||||||
|
disableNearGrab: false
|
||||||
|
};
|
||||||
|
//sometimes we want things to stay right where they are when we let go.
|
||||||
|
var disableNearGrabData = getEntityCustomData('handControllerKey', intersection.entityID, defaultDisableNearGrabData);
|
||||||
|
|
||||||
if (intersection.properties.name == "Grab Debug Entity") {
|
if (intersection.properties.name == "Grab Debug Entity") {
|
||||||
continue;
|
continue;
|
||||||
|
@ -852,7 +861,11 @@ function MyController(hand) {
|
||||||
} else if (!intersection.properties.locked) {
|
} else if (!intersection.properties.locked) {
|
||||||
this.grabbedEntity = intersection.entityID;
|
this.grabbedEntity = intersection.entityID;
|
||||||
if (this.state == STATE_SEARCHING) {
|
if (this.state == STATE_SEARCHING) {
|
||||||
this.setState(STATE_NEAR_GRABBING);
|
if (disableNearGrabData.disableNearGrab !== true) {
|
||||||
|
this.setState(STATE_NEAR_GRABBING);
|
||||||
|
} else {
|
||||||
|
//disable near grab on this thing
|
||||||
|
}
|
||||||
} else { // equipping
|
} else { // equipping
|
||||||
if (typeof grabbableData.spatialKey !== 'undefined') {
|
if (typeof grabbableData.spatialKey !== 'undefined') {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -976,7 +989,18 @@ function MyController(hand) {
|
||||||
this.setState(STATE_NEAR_TRIGGER);
|
this.setState(STATE_NEAR_TRIGGER);
|
||||||
return;
|
return;
|
||||||
} else if (!props.locked && props.collisionsWillMove) {
|
} else if (!props.locked && props.collisionsWillMove) {
|
||||||
this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP)
|
var defaultDisableNearGrabData = {
|
||||||
|
disableNearGrab: false
|
||||||
|
};
|
||||||
|
//sometimes we want things to stay right where they are when we let go.
|
||||||
|
var disableNearGrabData = getEntityCustomData('handControllerKey', this.grabbedEntity, defaultDisableNearGrabData);
|
||||||
|
if (disableNearGrabData.disableNearGrab === true) {
|
||||||
|
//do nothing because near grab is disabled for this object
|
||||||
|
} else {
|
||||||
|
this.setState(this.state == STATE_SEARCHING ? STATE_NEAR_GRABBING : STATE_EQUIP)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1144,22 +1168,54 @@ function MyController(hand) {
|
||||||
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
|
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
|
||||||
|
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab");
|
Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab");
|
||||||
// mix in head motion
|
|
||||||
if (MOVE_WITH_HEAD) {
|
var defaultMoveWithHeadData = {
|
||||||
var objDistance = Vec3.length(objectToAvatar);
|
disableMoveWithHead: false
|
||||||
var before = Vec3.multiplyQbyV(this.currentCameraOrientation, {
|
};
|
||||||
x: 0.0,
|
|
||||||
y: 0.0,
|
var handControllerData = getEntityCustomData('handControllerKey', this.grabbedEntity, defaultMoveWithHeadData);
|
||||||
z: objDistance
|
|
||||||
});
|
if (handControllerData.disableMoveWithHead !== true) {
|
||||||
var after = Vec3.multiplyQbyV(Camera.orientation, {
|
// mix in head motion
|
||||||
x: 0.0,
|
if (MOVE_WITH_HEAD) {
|
||||||
y: 0.0,
|
var objDistance = Vec3.length(objectToAvatar);
|
||||||
z: objDistance
|
var before = Vec3.multiplyQbyV(this.currentCameraOrientation, {
|
||||||
});
|
x: 0.0,
|
||||||
var change = Vec3.subtract(before, after);
|
y: 0.0,
|
||||||
this.currentCameraOrientation = Camera.orientation;
|
z: objDistance
|
||||||
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change);
|
});
|
||||||
|
var after = Vec3.multiplyQbyV(Camera.orientation, {
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
z: objDistance
|
||||||
|
});
|
||||||
|
var change = Vec3.subtract(before, after);
|
||||||
|
this.currentCameraOrientation = Camera.orientation;
|
||||||
|
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, change);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// print('should not head move!');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var defaultConstraintData = {
|
||||||
|
axisStart: false,
|
||||||
|
axisEnd: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
var constraintData = getEntityCustomData('lightModifierKey', this.grabbedEntity, defaultConstraintData);
|
||||||
|
var clampedVector;
|
||||||
|
var targetPosition;
|
||||||
|
if (constraintData.axisStart !== false) {
|
||||||
|
clampedVector = this.projectVectorAlongAxis(this.currentObjectPosition, constraintData.axisStart, constraintData.axisEnd);
|
||||||
|
targetPosition = clampedVector;
|
||||||
|
} else {
|
||||||
|
targetPosition = {
|
||||||
|
x: this.currentObjectPosition.x,
|
||||||
|
y: this.currentObjectPosition.y,
|
||||||
|
z: this.currentObjectPosition.z
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1182,7 +1238,7 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||||
targetPosition: this.currentObjectPosition,
|
targetPosition: targetPosition,
|
||||||
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||||
targetRotation: this.currentObjectRotation,
|
targetRotation: this.currentObjectRotation,
|
||||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||||
|
@ -1190,98 +1246,122 @@ function MyController(hand) {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.nearGrabbing = function() {
|
this.projectVectorAlongAxis = function(position, axisStart, axisEnd) {
|
||||||
var now = Date.now();
|
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
|
||||||
|
|
||||||
if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
|
var aPrime = Vec3.subtract(position, axisStart);
|
||||||
this.setState(STATE_RELEASE);
|
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.turnOffVisualizations();
|
|
||||||
|
|
||||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
var bPrime = Vec3.subtract(axisEnd, axisStart);
|
||||||
this.activateEntity(this.grabbedEntity, grabbedProperties);
|
|
||||||
if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) {
|
|
||||||
Entities.editEntity(this.grabbedEntity, {
|
|
||||||
collisionsWillMove: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var handRotation = this.getHandRotation();
|
|
||||||
var handPosition = this.getHandPosition();
|
|
||||||
|
|
||||||
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
var bPrimeMagnitude = Vec3.length(bPrime);
|
||||||
var objectRotation = grabbedProperties.rotation;
|
|
||||||
var currentObjectPosition = grabbedProperties.position;
|
var dotProduct = Vec3.dot(aPrime, bPrime);
|
||||||
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
|
||||||
if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) {
|
|
||||||
// if an object is "equipped" and has a spatialKey, use it.
|
var scalar = dotProduct / bPrimeMagnitude;
|
||||||
this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
|
|
||||||
if (grabbableData.spatialKey.relativePosition || grabbableData.spatialKey.rightRelativePosition
|
if (scalar < 0) {
|
||||||
|| grabbableData.spatialKey.leftRelativePosition) {
|
scalar = 0;
|
||||||
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
|
||||||
} else {
|
|
||||||
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
|
||||||
}
|
}
|
||||||
if (grabbableData.spatialKey.relativeRotation || grabbableData.spatialKey.rightRelativeRotation
|
|
||||||
|| grabbableData.spatialKey.leftRelativeRotation) {
|
if (scalar > 1) {
|
||||||
|
scalar = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var projection = Vec3.sum(axisStart, Vec3.multiply(scalar, Vec3.normalize(bPrime)));
|
||||||
|
|
||||||
|
return projection
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
this.nearGrabbing = function() {
|
||||||
|
var now = Date.now();
|
||||||
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
||||||
|
|
||||||
|
if (this.state == STATE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
|
||||||
|
this.setState(STATE_RELEASE);
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lineOff();
|
||||||
|
this.overlayLineOff();
|
||||||
|
|
||||||
|
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, GRABBABLE_PROPERTIES);
|
||||||
|
this.activateEntity(this.grabbedEntity, grabbedProperties);
|
||||||
|
if (grabbedProperties.collisionsWillMove && NEAR_GRABBING_KINEMATIC) {
|
||||||
|
Entities.editEntity(this.grabbedEntity, {
|
||||||
|
collisionsWillMove: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var handRotation = this.getHandRotation();
|
||||||
|
var handPosition = this.getHandPosition();
|
||||||
|
|
||||||
|
var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedEntity, DEFAULT_GRABBABLE_DATA);
|
||||||
|
|
||||||
|
if (this.state != STATE_NEAR_GRABBING && grabbableData.spatialKey) {
|
||||||
|
// if an object is "equipped" and has a spatialKey, use it.
|
||||||
|
this.ignoreIK = grabbableData.spatialKey.ignoreIK ? grabbableData.spatialKey.ignoreIK : false;
|
||||||
|
this.offsetPosition = getSpatialOffsetPosition(this.hand, grabbableData.spatialKey);
|
||||||
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
this.offsetRotation = getSpatialOffsetRotation(this.hand, grabbableData.spatialKey);
|
||||||
} else {
|
} else {
|
||||||
|
this.ignoreIK = false;
|
||||||
|
|
||||||
|
var objectRotation = grabbedProperties.rotation;
|
||||||
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.ignoreIK = false;
|
|
||||||
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
|
||||||
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.actionID = NULL_ACTION_ID;
|
var currentObjectPosition = grabbedProperties.position;
|
||||||
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
||||||
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
||||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
}
|
||||||
relativePosition: this.offsetPosition,
|
|
||||||
relativeRotation: this.offsetRotation,
|
this.actionID = NULL_ACTION_ID;
|
||||||
ttl: ACTION_TTL,
|
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
||||||
kinematic: NEAR_GRABBING_KINEMATIC,
|
hand: this.hand === RIGHT_HAND ? "right" : "left",
|
||||||
kinematicSetVelocity: true,
|
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||||
ignoreIK: this.ignoreIK
|
relativePosition: this.offsetPosition,
|
||||||
});
|
relativeRotation: this.offsetRotation,
|
||||||
if (this.actionID === NULL_ACTION_ID) {
|
ttl: ACTION_TTL,
|
||||||
this.actionID = null;
|
kinematic: NEAR_GRABBING_KINEMATIC,
|
||||||
} else {
|
kinematicSetVelocity: true,
|
||||||
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
ignoreIK: this.ignoreIK
|
||||||
if (this.state == STATE_NEAR_GRABBING) {
|
});
|
||||||
this.setState(STATE_CONTINUE_NEAR_GRABBING);
|
if (this.actionID === NULL_ACTION_ID) {
|
||||||
|
this.actionID = null;
|
||||||
} else {
|
} else {
|
||||||
// equipping
|
this.actionTimeout = now + (ACTION_TTL * MSEC_PER_SEC);
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]);
|
if (this.state == STATE_NEAR_GRABBING) {
|
||||||
this.startHandGrasp();
|
this.setState(STATE_CONTINUE_NEAR_GRABBING);
|
||||||
|
} else {
|
||||||
|
// equipping
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "startEquip", [JSON.stringify(this.hand)]);
|
||||||
|
this.startHandGrasp();
|
||||||
|
|
||||||
|
this.setState(STATE_CONTINUE_EQUIP_BD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hand === RIGHT_HAND) {
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||||
|
} else {
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||||
|
}
|
||||||
|
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]);
|
||||||
|
|
||||||
|
Entities.callEntityMethod(this.grabbedEntity, "startNearGrab");
|
||||||
|
|
||||||
this.setState(STATE_CONTINUE_EQUIP_BD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hand === RIGHT_HAND) {
|
this.currentHandControllerTipPosition =
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
(this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
||||||
} else {
|
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
|
||||||
}
|
|
||||||
|
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "setHand", [this.hand]);
|
this.currentObjectTime = Date.now();
|
||||||
|
};
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "startNearGrab");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentHandControllerTipPosition =
|
|
||||||
(this.hand === RIGHT_HAND) ? MyAvatar.rightHandTipPosition : MyAvatar.leftHandTipPosition;
|
|
||||||
|
|
||||||
this.currentObjectTime = Date.now();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.continueNearGrabbing = function() {
|
this.continueNearGrabbing = function() {
|
||||||
if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
|
if (this.state == STATE_CONTINUE_NEAR_GRABBING && this.triggerSmoothedReleased()) {
|
||||||
|
@ -1470,7 +1550,7 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USE_ENTITY_LINES_FOR_MOVING === true) {
|
if (USE_ENTITY_LINES_FOR_MOVING === true) {
|
||||||
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger");
|
Entities.callEntityMethod(this.grabbedEntity, "continueFarTrigger");
|
||||||
|
@ -1551,7 +1631,34 @@ function MyController(hand) {
|
||||||
|
|
||||||
if (this.grabbedEntity !== null) {
|
if (this.grabbedEntity !== null) {
|
||||||
if (this.actionID !== null) {
|
if (this.actionID !== null) {
|
||||||
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
//add velocity whatnot
|
||||||
|
var defaultReleaseVelocityData = {
|
||||||
|
disableReleaseVelocity: false
|
||||||
|
};
|
||||||
|
//sometimes we want things to stay right where they are when we let go.
|
||||||
|
var releaseVelocityData = getEntityCustomData('handControllerKey', this.grabbedEntity, defaultReleaseVelocityData);
|
||||||
|
if (releaseVelocityData.disableReleaseVelocity === true) {
|
||||||
|
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||||
|
|
||||||
|
Entities.editEntity(this.grabbedEntity, {
|
||||||
|
velocity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
angularVelocity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//don't make adjustments
|
||||||
|
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1681,7 +1788,7 @@ Controller.enableMapping(MAPPING_NAME);
|
||||||
var handToDisable = 'none';
|
var handToDisable = 'none';
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
if (handToDisable !== LEFT_HAND && handToDisable!=='both') {
|
if (handToDisable !== LEFT_HAND && handToDisable !== 'both') {
|
||||||
leftController.update();
|
leftController.update();
|
||||||
}
|
}
|
||||||
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
|
if (handToDisable !== RIGHT_HAND && handToDisable !== 'both') {
|
||||||
|
@ -1707,22 +1814,22 @@ handleHandMessages = function(channel, message, sender) {
|
||||||
}
|
}
|
||||||
} else if (channel === 'Hifi-Hand-Grab') {
|
} else if (channel === 'Hifi-Hand-Grab') {
|
||||||
try {
|
try {
|
||||||
var data = JSON.parse(message);
|
var data = JSON.parse(message);
|
||||||
var selectedController = (data.hand === 'left') ? leftController : rightController;
|
var selectedController = (data.hand === 'left') ? leftController : rightController;
|
||||||
selectedController.release();
|
selectedController.release();
|
||||||
selectedController.setState(STATE_EQUIP);
|
selectedController.setState(STATE_EQUIP);
|
||||||
selectedController.grabbedEntity = data.entityID;
|
selectedController.grabbedEntity = data.entityID;
|
||||||
|
|
||||||
} catch (e) { }
|
} catch (e) {}
|
||||||
}
|
|
||||||
else if (channel === 'Hifi-Hand-RayPick-Blacklist' && sender === MyAvatar.sessionUUID) {
|
} else if (channel === 'Hifi-Hand-RayPick-Blacklist') {
|
||||||
try {
|
try {
|
||||||
var data = JSON.parse(message);
|
var data = JSON.parse(message);
|
||||||
var action = data.action;
|
var action = data.action;
|
||||||
var id = data.id;
|
var id = data.id;
|
||||||
var index = blacklist.indexOf(id);
|
var index = blacklist.indexOf(id);
|
||||||
|
|
||||||
if (action === 'add' && index ===-1) {
|
if (action === 'add' && index === -1) {
|
||||||
blacklist.push(id);
|
blacklist.push(id);
|
||||||
}
|
}
|
||||||
if (action === 'remove') {
|
if (action === 'remove') {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -53,7 +53,9 @@ LightOverlayManager = function() {
|
||||||
if (visible != isVisible) {
|
if (visible != isVisible) {
|
||||||
visible = isVisible;
|
visible = isVisible;
|
||||||
for (var id in entityOverlays) {
|
for (var id in entityOverlays) {
|
||||||
Overlays.editOverlay(entityOverlays[id], { visible: visible });
|
Overlays.editOverlay(entityOverlays[id], {
|
||||||
|
visible: visible
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -61,8 +63,7 @@ LightOverlayManager = function() {
|
||||||
// Allocate or get an unused overlay
|
// Allocate or get an unused overlay
|
||||||
function getOverlay() {
|
function getOverlay() {
|
||||||
if (unusedOverlays.length == 0) {
|
if (unusedOverlays.length == 0) {
|
||||||
var overlay = Overlays.addOverlay("image3d", {
|
var overlay = Overlays.addOverlay("image3d", {});
|
||||||
});
|
|
||||||
allOverlays.push(overlay);
|
allOverlays.push(overlay);
|
||||||
} else {
|
} else {
|
||||||
var overlay = unusedOverlays.pop();
|
var overlay = unusedOverlays.pop();
|
||||||
|
@ -72,7 +73,9 @@ LightOverlayManager = function() {
|
||||||
|
|
||||||
function releaseOverlay(overlay) {
|
function releaseOverlay(overlay) {
|
||||||
unusedOverlays.push(overlay);
|
unusedOverlays.push(overlay);
|
||||||
Overlays.editOverlay(overlay, { visible: false });
|
Overlays.editOverlay(overlay, {
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEntity(entityID) {
|
function addEntity(entityID) {
|
||||||
|
@ -88,7 +91,11 @@ LightOverlayManager = function() {
|
||||||
visible: visible,
|
visible: visible,
|
||||||
alpha: 0.9,
|
alpha: 0.9,
|
||||||
scale: 0.5,
|
scale: 0.5,
|
||||||
color: { red: 255, green: 255, blue: 255 }
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,4 +130,4 @@ LightOverlayManager = function() {
|
||||||
Overlays.deleteOverlay(allOverlays[i]);
|
Overlays.deleteOverlay(allOverlays[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
29
examples/light_modifier/README.md
Normal file
29
examples/light_modifier/README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
This PR demonstrates one way in-world editing of objects might work.
|
||||||
|
|
||||||
|
Running this script will show light overlay icons in-world. Enter edit mode by running your distance beam through a light overlay. Exit using the red X.
|
||||||
|
|
||||||
|
When you distant grab the sliders, you can move them along their axis to change their values. You may also rotate / move the block to which the spotlight is attached.
|
||||||
|
|
||||||
|
To test: https://rawgit.com/imgntn/hifi/light_mod/examples/lights/lightLoader.js
|
||||||
|
To reset, I recommend stopping all scripts then re-loading lightLoader.js
|
||||||
|
|
||||||
|
When you run the lightLoader.js script, several scripts will be loaded:
|
||||||
|
- handControllerGrab.js (will not impart velocity when you move the parent or a slider, will not move sliders with head movement,will constrain movement for a slider to a given axis start and end, will support blacklisting of entities for raypicking during search for objects)
|
||||||
|
- lightModifier.js (listens for message to create sliders for a given light. will start with slider set to the light's initial properties)
|
||||||
|
- lightModifierTestScene.js (creates a light)
|
||||||
|
- slider.js (attached to each slider entity)
|
||||||
|
- lightParent.js (attached to a 3d model of a light, to which a light is parented, so you can move it around. or keep the current parent if a light already has a parent)
|
||||||
|
- visiblePanel.js (the transparent panel)
|
||||||
|
- closeButton.js (for closing the ui)
|
||||||
|
- ../libraries/lightOverlayManager.js (shows 2d overlays for lights in the world)
|
||||||
|
- ../libraries/entitySelectionTool.js (visualizes volume of the lights)
|
||||||
|
|
||||||
|
Current sliders are (top to bottom):
|
||||||
|
red
|
||||||
|
green
|
||||||
|
blue
|
||||||
|
intensity
|
||||||
|
cutoff
|
||||||
|
exponent
|
||||||
|
|
||||||
|

|
36
examples/light_modifier/closeButton.js
Normal file
36
examples/light_modifier/closeButton.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// closeButton.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Entity script that closes sliders when interacted with.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function CloseButton() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseButton.prototype = {
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
var entityProperties = Entities.getEntityProperties(this.entityID, "userData");
|
||||||
|
this.initialProperties = entityProperties
|
||||||
|
this.userData = JSON.parse(entityProperties.userData);
|
||||||
|
},
|
||||||
|
startNearGrab: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
startFarTrigger: function() {
|
||||||
|
Messages.sendMessage('Hifi-Light-Modifier-Cleanup', 'callCleanup')
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new CloseButton();
|
||||||
|
});
|
20
examples/light_modifier/lightLoader.js
Normal file
20
examples/light_modifier/lightLoader.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// lightLoader.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Loads a test scene showing sliders that you can grab and move to change entity properties.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var grabScript = Script.resolvePath('../controllers/handControllerGrab.js?' + Math.random(0 - 100));
|
||||||
|
Script.load(grabScript);
|
||||||
|
var lightModifier = Script.resolvePath('lightModifier.js?' + Math.random(0 - 100));
|
||||||
|
Script.load(lightModifier);
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
var lightModifierTestScene = Script.resolvePath('lightModifierTestScene.js?' + Math.random(0 - 100));
|
||||||
|
Script.load(lightModifierTestScene);
|
||||||
|
}, 750)
|
876
examples/light_modifier/lightModifier.js
Normal file
876
examples/light_modifier/lightModifier.js
Normal file
|
@ -0,0 +1,876 @@
|
||||||
|
//
|
||||||
|
// lightModifier.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Given a selected light, instantiate some entities that represent various values you can dynamically adjust by grabbing and moving.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
//some experimental options
|
||||||
|
var ONLY_I_CAN_EDIT = false;
|
||||||
|
var SLIDERS_SHOULD_STAY_WITH_AVATAR = false;
|
||||||
|
var VERTICAL_SLIDERS = false;
|
||||||
|
var SHOW_OVERLAYS = true;
|
||||||
|
var SHOW_LIGHT_VOLUME = true;
|
||||||
|
var USE_PARENTED_PANEL = true;
|
||||||
|
var VISIBLE_PANEL = true;
|
||||||
|
var USE_LABELS = true;
|
||||||
|
var LEFT_LABELS = false;
|
||||||
|
var RIGHT_LABELS = true;
|
||||||
|
var ROTATE_CLOSE_BUTTON = false;
|
||||||
|
|
||||||
|
//variables for managing overlays
|
||||||
|
var selectionDisplay;
|
||||||
|
var selectionManager;
|
||||||
|
var lightOverlayManager;
|
||||||
|
|
||||||
|
//for when we make a 3d model of a light a parent for the light
|
||||||
|
var PARENT_SCRIPT_URL = Script.resolvePath('lightParent.js?' + Math.random(0 - 100));
|
||||||
|
|
||||||
|
if (SHOW_OVERLAYS === true) {
|
||||||
|
|
||||||
|
Script.include('../libraries/gridTool.js');
|
||||||
|
Script.include('../libraries/entitySelectionTool.js?' + Math.random(0 - 100));
|
||||||
|
Script.include('../libraries/lightOverlayManager.js');
|
||||||
|
|
||||||
|
var grid = Grid();
|
||||||
|
gridTool = GridTool({
|
||||||
|
horizontalGrid: grid
|
||||||
|
});
|
||||||
|
gridTool.setVisible(false);
|
||||||
|
|
||||||
|
selectionDisplay = SelectionDisplay;
|
||||||
|
selectionManager = SelectionManager;
|
||||||
|
lightOverlayManager = new LightOverlayManager();
|
||||||
|
selectionManager.addEventListener(function() {
|
||||||
|
selectionDisplay.updateHandles();
|
||||||
|
lightOverlayManager.updatePositions();
|
||||||
|
});
|
||||||
|
lightOverlayManager.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var DEFAULT_PARENT_ID = '{00000000-0000-0000-0000-000000000000}'
|
||||||
|
|
||||||
|
var AXIS_SCALE = 1;
|
||||||
|
var COLOR_MAX = 255;
|
||||||
|
var INTENSITY_MAX = 0.05;
|
||||||
|
var CUTOFF_MAX = 360;
|
||||||
|
var EXPONENT_MAX = 1;
|
||||||
|
|
||||||
|
var SLIDER_SCRIPT_URL = Script.resolvePath('slider.js?' + Math.random(0, 100));
|
||||||
|
var LIGHT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/light_modifier/source4_very_good.fbx';
|
||||||
|
var CLOSE_BUTTON_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/light_modifier/red_x.fbx';
|
||||||
|
var CLOSE_BUTTON_SCRIPT_URL = Script.resolvePath('closeButton.js?' + Math.random(0, 100));
|
||||||
|
var TRANSPARENT_PANEL_URL = 'http://hifi-content.s3.amazonaws.com/james/light_modifier/transparent_box_alpha_15.fbx';
|
||||||
|
var VISIBLE_PANEL_SCRIPT_URL = Script.resolvePath('visiblePanel.js?' + Math.random(0, 100));
|
||||||
|
|
||||||
|
var RED = {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var GREEN = {
|
||||||
|
red: 0,
|
||||||
|
green: 255,
|
||||||
|
blue: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var BLUE = {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 255
|
||||||
|
};
|
||||||
|
|
||||||
|
var PURPLE = {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 255
|
||||||
|
};
|
||||||
|
|
||||||
|
var WHITE = {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
};
|
||||||
|
|
||||||
|
var ORANGE = {
|
||||||
|
red: 255,
|
||||||
|
green: 165,
|
||||||
|
blue: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var SLIDER_DIMENSIONS = {
|
||||||
|
x: 0.075,
|
||||||
|
y: 0.075,
|
||||||
|
z: 0.075
|
||||||
|
};
|
||||||
|
|
||||||
|
var CLOSE_BUTTON_DIMENSIONS = {
|
||||||
|
x: 0.1,
|
||||||
|
y: 0.025,
|
||||||
|
z: 0.1
|
||||||
|
}
|
||||||
|
|
||||||
|
var LIGHT_MODEL_DIMENSIONS = {
|
||||||
|
x: 0.58,
|
||||||
|
y: 1.21,
|
||||||
|
z: 0.57
|
||||||
|
}
|
||||||
|
|
||||||
|
var PER_ROW_OFFSET = {
|
||||||
|
x: 0,
|
||||||
|
y: -0.2,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
var sliders = [];
|
||||||
|
var slidersRef = {
|
||||||
|
'color_red': null,
|
||||||
|
'color_green': null,
|
||||||
|
'color_blue': null,
|
||||||
|
intensity: null,
|
||||||
|
cutoff: null,
|
||||||
|
exponent: null
|
||||||
|
};
|
||||||
|
var light = null;
|
||||||
|
|
||||||
|
var basePosition;
|
||||||
|
var avatarRotation;
|
||||||
|
|
||||||
|
function entitySlider(light, color, sliderType, displayText, row) {
|
||||||
|
this.light = light;
|
||||||
|
this.lightID = light.id.replace(/[{}]/g, "");
|
||||||
|
this.initialProperties = light.initialProperties;
|
||||||
|
this.color = color;
|
||||||
|
this.sliderType = sliderType;
|
||||||
|
this.displayText = displayText;
|
||||||
|
this.verticalOffset = Vec3.multiply(row, PER_ROW_OFFSET);
|
||||||
|
this.avatarRot = Quat.fromPitchYawRollDegrees(0, MyAvatar.bodyYaw, 0.0);
|
||||||
|
this.basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(1.5, Quat.getFront(this.avatarRot)));
|
||||||
|
this.basePosition.y += 1;
|
||||||
|
basePosition = this.basePosition;
|
||||||
|
avatarRot = this.avatarRot;
|
||||||
|
|
||||||
|
var message = {
|
||||||
|
lightID: this.lightID,
|
||||||
|
sliderType: this.sliderType,
|
||||||
|
sliderValue: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.sliderType === 'color_red') {
|
||||||
|
message.sliderValue = this.initialProperties.color.red
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'color_green') {
|
||||||
|
message.sliderValue = this.initialProperties.color.green
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'color_blue') {
|
||||||
|
message.sliderValue = this.initialProperties.color.blue
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'intensity') {
|
||||||
|
message.sliderValue = this.initialProperties.intensity
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'exponent') {
|
||||||
|
message.sliderValue = this.initialProperties.exponent
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'cutoff') {
|
||||||
|
message.sliderValue = this.initialProperties.cutoff
|
||||||
|
this.setValueFromMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setInitialSliderPositions();
|
||||||
|
this.createAxis();
|
||||||
|
this.createSliderIndicator();
|
||||||
|
if (USE_LABELS === true) {
|
||||||
|
this.createLabel()
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//what's the ux for adjusting values? start with simple entities, try image overlays etc
|
||||||
|
entitySlider.prototype = {
|
||||||
|
createAxis: function() {
|
||||||
|
//start of line
|
||||||
|
var position;
|
||||||
|
var extension;
|
||||||
|
|
||||||
|
if (VERTICAL_SLIDERS == true) {
|
||||||
|
position = Vec3.sum(this.basePosition, Vec3.multiply(row, (Vec3.multiply(0.2, Quat.getRight(this.avatarRot)))));
|
||||||
|
//line starts on bottom and goes up
|
||||||
|
var upVector = Quat.getUp(this.avatarRot);
|
||||||
|
extension = Vec3.multiply(AXIS_SCALE, upVector);
|
||||||
|
} else {
|
||||||
|
position = Vec3.sum(this.basePosition, this.verticalOffset);
|
||||||
|
//line starts on left and goes to right
|
||||||
|
//set the end of the line to the right
|
||||||
|
var rightVector = Quat.getRight(this.avatarRot);
|
||||||
|
extension = Vec3.multiply(AXIS_SCALE, rightVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.axisStart = position;
|
||||||
|
this.endOfAxis = Vec3.sum(position, extension);
|
||||||
|
this.createEndOfAxisEntity();
|
||||||
|
|
||||||
|
var properties = {
|
||||||
|
type: 'Line',
|
||||||
|
name: 'Hifi-Slider-Axis::' + this.sliderType,
|
||||||
|
color: this.color,
|
||||||
|
collisionsWillMove: false,
|
||||||
|
ignoreForCollisions: true,
|
||||||
|
dimensions: {
|
||||||
|
x: 3,
|
||||||
|
y: 3,
|
||||||
|
z: 3
|
||||||
|
},
|
||||||
|
position: position,
|
||||||
|
linePoints: [{
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
}, extension],
|
||||||
|
lineWidth: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.axis = Entities.addEntity(properties);
|
||||||
|
},
|
||||||
|
createEndOfAxisEntity: function() {
|
||||||
|
//we use this to track the end of the axis while parented to a panel
|
||||||
|
var properties = {
|
||||||
|
name: 'Hifi-End-Of-Axis',
|
||||||
|
type: 'Box',
|
||||||
|
collisionsWillMove: false,
|
||||||
|
ignoreForCollisions: true,
|
||||||
|
dimensions: {
|
||||||
|
x: 0.01,
|
||||||
|
y: 0.01,
|
||||||
|
z: 0.01
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
|
position: this.endOfAxis,
|
||||||
|
parentID: this.axis,
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.endOfAxisEntity = Entities.addEntity(this.endOfAxis);
|
||||||
|
},
|
||||||
|
createLabel: function() {
|
||||||
|
|
||||||
|
var LABEL_WIDTH = 0.25
|
||||||
|
var PER_LETTER_SPACING = 0.1;
|
||||||
|
var textWidth = this.displayText.length * PER_LETTER_SPACING;
|
||||||
|
|
||||||
|
var position;
|
||||||
|
if (LEFT_LABELS === true) {
|
||||||
|
var leftVector = Vec3.multiply(-1, Quat.getRight(this.avatarRot));
|
||||||
|
|
||||||
|
var extension = Vec3.multiply(textWidth, leftVector);
|
||||||
|
|
||||||
|
position = Vec3.sum(this.axisStart, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RIGHT_LABELS === true) {
|
||||||
|
var rightVector = Quat.getRight(this.avatarRot);
|
||||||
|
|
||||||
|
var extension = Vec3.multiply(textWidth / 1.75, rightVector);
|
||||||
|
|
||||||
|
position = Vec3.sum(this.endOfAxis, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var labelProperties = {
|
||||||
|
name: 'Hifi-Slider-Label-' + this.sliderType,
|
||||||
|
type: 'Text',
|
||||||
|
dimensions: {
|
||||||
|
x: textWidth,
|
||||||
|
y: 0.2,
|
||||||
|
z: 0.1
|
||||||
|
},
|
||||||
|
textColor: {
|
||||||
|
red: 255,
|
||||||
|
green: 255,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
|
text: this.displayText,
|
||||||
|
lineHeight: 0.14,
|
||||||
|
backgroundColor: {
|
||||||
|
red: 0,
|
||||||
|
green: 0,
|
||||||
|
blue: 0
|
||||||
|
},
|
||||||
|
position: position,
|
||||||
|
rotation: this.avatarRot,
|
||||||
|
}
|
||||||
|
print('BEFORE CREATE LABEL' + JSON.stringify(labelProperties))
|
||||||
|
this.label = Entities.addEntity(labelProperties);
|
||||||
|
print('AFTER CREATE LABEL')
|
||||||
|
},
|
||||||
|
createSliderIndicator: function() {
|
||||||
|
var extensionVector;
|
||||||
|
var position;
|
||||||
|
if (VERTICAL_SLIDERS == true) {
|
||||||
|
position = Vec3.sum(this.basePosition, Vec3.multiply(row, (Vec3.multiply(0.2, Quat.getRight(this.avatarRot)))));
|
||||||
|
extensionVector = Quat.getUp(this.avatarRot);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
position = Vec3.sum(this.basePosition, this.verticalOffset);
|
||||||
|
extensionVector = Quat.getRight(this.avatarRot);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var initialDistance;
|
||||||
|
if (this.sliderType === 'color_red') {
|
||||||
|
initialDistance = this.distanceRed;
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'color_green') {
|
||||||
|
initialDistance = this.distanceGreen;
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'color_blue') {
|
||||||
|
initialDistance = this.distanceBlue;
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'intensity') {
|
||||||
|
initialDistance = this.distanceIntensity;
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'cutoff') {
|
||||||
|
initialDistance = this.distanceCutoff;
|
||||||
|
}
|
||||||
|
if (this.sliderType === 'exponent') {
|
||||||
|
initialDistance = this.distanceExponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var extension = Vec3.multiply(initialDistance, extensionVector);
|
||||||
|
var sliderPosition = Vec3.sum(position, extension);
|
||||||
|
|
||||||
|
var properties = {
|
||||||
|
type: 'Sphere',
|
||||||
|
name: 'Hifi-Slider-' + this.sliderType,
|
||||||
|
dimensions: SLIDER_DIMENSIONS,
|
||||||
|
collisionsWillMove: true,
|
||||||
|
color: this.color,
|
||||||
|
position: sliderPosition,
|
||||||
|
script: SLIDER_SCRIPT_URL,
|
||||||
|
ignoreForCollisions: true,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
lightModifierKey: {
|
||||||
|
lightID: this.lightID,
|
||||||
|
sliderType: this.sliderType,
|
||||||
|
axisStart: position,
|
||||||
|
axisEnd: this.endOfAxis,
|
||||||
|
},
|
||||||
|
handControllerKey: {
|
||||||
|
disableReleaseVelocity: true,
|
||||||
|
disableMoveWithHead: true,
|
||||||
|
disableNearGrab:true
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sliderIndicator = Entities.addEntity(properties);
|
||||||
|
},
|
||||||
|
setValueFromMessage: function(message) {
|
||||||
|
|
||||||
|
//message is not for our light
|
||||||
|
if (message.lightID !== this.lightID) {
|
||||||
|
// print('not our light')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//message is not our type
|
||||||
|
if (message.sliderType !== this.sliderType) {
|
||||||
|
// print('not our slider type')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var lightProperties = Entities.getEntityProperties(this.lightID);
|
||||||
|
|
||||||
|
if (this.sliderType === 'color_red') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
color: {
|
||||||
|
red: message.sliderValue,
|
||||||
|
green: lightProperties.color.green,
|
||||||
|
blue: lightProperties.color.blue
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'color_green') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
color: {
|
||||||
|
red: lightProperties.color.red,
|
||||||
|
green: message.sliderValue,
|
||||||
|
blue: lightProperties.color.blue
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'color_blue') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
color: {
|
||||||
|
red: lightProperties.color.red,
|
||||||
|
green: lightProperties.color.green,
|
||||||
|
blue: message.sliderValue,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'intensity') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
intensity: message.sliderValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'cutoff') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
cutoff: message.sliderValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.sliderType === 'exponent') {
|
||||||
|
Entities.editEntity(this.lightID, {
|
||||||
|
exponent: message.sliderValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setInitialSliderPositions: function() {
|
||||||
|
this.distanceRed = (this.initialProperties.color.red / COLOR_MAX) * AXIS_SCALE;
|
||||||
|
this.distanceGreen = (this.initialProperties.color.green / COLOR_MAX) * AXIS_SCALE;
|
||||||
|
this.distanceBlue = (this.initialProperties.color.blue / COLOR_MAX) * AXIS_SCALE;
|
||||||
|
this.distanceIntensity = (this.initialProperties.intensity / INTENSITY_MAX) * AXIS_SCALE;
|
||||||
|
this.distanceCutoff = (this.initialProperties.cutoff / CUTOFF_MAX) * AXIS_SCALE;
|
||||||
|
this.distanceExponent = (this.initialProperties.exponent / EXPONENT_MAX) * AXIS_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var panel;
|
||||||
|
var visiblePanel;
|
||||||
|
|
||||||
|
function makeSliders(light) {
|
||||||
|
|
||||||
|
if (USE_PARENTED_PANEL === true) {
|
||||||
|
panel = createPanelEntity(MyAvatar.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (light.type === 'spotlight') {
|
||||||
|
var USE_COLOR_SLIDER = true;
|
||||||
|
var USE_INTENSITY_SLIDER = true;
|
||||||
|
var USE_CUTOFF_SLIDER = true;
|
||||||
|
var USE_EXPONENT_SLIDER = true;
|
||||||
|
}
|
||||||
|
if (light.type === 'pointlight') {
|
||||||
|
var USE_COLOR_SLIDER = true;
|
||||||
|
var USE_INTENSITY_SLIDER = true;
|
||||||
|
var USE_CUTOFF_SLIDER = false;
|
||||||
|
var USE_EXPONENT_SLIDER = false;
|
||||||
|
}
|
||||||
|
if (USE_COLOR_SLIDER === true) {
|
||||||
|
slidersRef.color_red = new entitySlider(light, RED, 'color_red', 'Red', 1);
|
||||||
|
slidersRef.color_green = new entitySlider(light, GREEN, 'color_green', 'Green', 2);
|
||||||
|
slidersRef.color_blue = new entitySlider(light, BLUE, 'color_blue', 'Blue', 3);
|
||||||
|
|
||||||
|
sliders.push(slidersRef.color_red);
|
||||||
|
sliders.push(slidersRef.color_green);
|
||||||
|
sliders.push(slidersRef.color_blue);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (USE_INTENSITY_SLIDER === true) {
|
||||||
|
slidersRef.intensity = new entitySlider(light, WHITE, 'intensity', 'Intensity', 4);
|
||||||
|
sliders.push(slidersRef.intensity);
|
||||||
|
}
|
||||||
|
if (USE_CUTOFF_SLIDER === true) {
|
||||||
|
slidersRef.cutoff = new entitySlider(light, PURPLE, 'cutoff', 'Cutoff', 5);
|
||||||
|
sliders.push(slidersRef.cutoff);
|
||||||
|
}
|
||||||
|
if (USE_EXPONENT_SLIDER === true) {
|
||||||
|
slidersRef.exponent = new entitySlider(light, ORANGE, 'exponent', 'Exponent', 6);
|
||||||
|
sliders.push(slidersRef.exponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
createCloseButton(slidersRef.color_red.axisStart);
|
||||||
|
|
||||||
|
subscribeToSliderMessages();
|
||||||
|
|
||||||
|
if (USE_PARENTED_PANEL === true) {
|
||||||
|
parentEntitiesToPanel(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SLIDERS_SHOULD_STAY_WITH_AVATAR === true) {
|
||||||
|
parentPanelToAvatar(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VISIBLE_PANEL === true) {
|
||||||
|
visiblePanel = createVisiblePanel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function parentPanelToAvatar(panel) {
|
||||||
|
//this is going to need some more work re: the sliders actually being grabbable. probably something to do with updating axis movement
|
||||||
|
Entities.editEntity(panel, {
|
||||||
|
parentID: MyAvatar.sessionUUID,
|
||||||
|
//actually figure out which one to parent it to -- probably a spine or something.
|
||||||
|
parentJointIndex: 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function parentEntitiesToPanel(panel) {
|
||||||
|
|
||||||
|
sliders.forEach(function(slider) {
|
||||||
|
Entities.editEntity(slider.axis, {
|
||||||
|
parentID: panel
|
||||||
|
})
|
||||||
|
Entities.editEntity(slider.sliderIndicator, {
|
||||||
|
parentID: panel
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
closeButtons.forEach(function(button) {
|
||||||
|
Entities.editEntity(button, {
|
||||||
|
parentID: panel
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPanelEntity(position) {
|
||||||
|
print('CREATING PANEL at ' + JSON.stringify(position));
|
||||||
|
var panelProperties = {
|
||||||
|
name: 'Hifi-Slider-Panel',
|
||||||
|
type: 'Box',
|
||||||
|
dimensions: {
|
||||||
|
x: 0.1,
|
||||||
|
y: 0.1,
|
||||||
|
z: 0.1
|
||||||
|
},
|
||||||
|
visible: false,
|
||||||
|
collisionsWillMove: false,
|
||||||
|
ignoreForCollisions: true
|
||||||
|
}
|
||||||
|
|
||||||
|
var panel = Entities.addEntity(panelProperties);
|
||||||
|
return panel
|
||||||
|
}
|
||||||
|
|
||||||
|
function createVisiblePanel() {
|
||||||
|
var totalOffset = -PER_ROW_OFFSET.y * sliders.length;
|
||||||
|
|
||||||
|
var moveRight = Vec3.sum(basePosition, Vec3.multiply(AXIS_SCALE / 2, Quat.getRight(avatarRot)));
|
||||||
|
|
||||||
|
var moveDown = Vec3.sum(moveRight, Vec3.multiply((sliders.length + 1) / 2, PER_ROW_OFFSET))
|
||||||
|
var panelProperties = {
|
||||||
|
name: 'Hifi-Visible-Transparent-Panel',
|
||||||
|
type: 'Model',
|
||||||
|
modelURL: TRANSPARENT_PANEL_URL,
|
||||||
|
dimensions: {
|
||||||
|
x: AXIS_SCALE + 0.1,
|
||||||
|
y: totalOffset,
|
||||||
|
z: SLIDER_DIMENSIONS.z / 4
|
||||||
|
},
|
||||||
|
visible: true,
|
||||||
|
collisionsWillMove: false,
|
||||||
|
ignoreForCollisions: true,
|
||||||
|
position: moveDown,
|
||||||
|
rotation: avatarRot,
|
||||||
|
script: VISIBLE_PANEL_SCRIPT_URL
|
||||||
|
}
|
||||||
|
|
||||||
|
var panel = Entities.addEntity(panelProperties);
|
||||||
|
|
||||||
|
return panel
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createLightModel(position, rotation) {
|
||||||
|
var blockProperties = {
|
||||||
|
name: 'Hifi-Spotlight-Model',
|
||||||
|
type: 'Model',
|
||||||
|
shapeType: 'box',
|
||||||
|
modelURL: LIGHT_MODEL_URL,
|
||||||
|
dimensions: LIGHT_MODEL_DIMENSIONS,
|
||||||
|
collisionsWillMove: true,
|
||||||
|
position: position,
|
||||||
|
rotation: rotation,
|
||||||
|
script: PARENT_SCRIPT_URL,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
handControllerKey: {
|
||||||
|
disableReleaseVelocity: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var block = Entities.addEntity(blockProperties);
|
||||||
|
|
||||||
|
return block
|
||||||
|
}
|
||||||
|
|
||||||
|
var closeButtons = [];
|
||||||
|
|
||||||
|
function createCloseButton(axisStart) {
|
||||||
|
var MARGIN = 0.10;
|
||||||
|
var VERTICAL_OFFFSET = {
|
||||||
|
x: 0,
|
||||||
|
y: 0.15,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
var leftVector = Vec3.multiply(-1, Quat.getRight(avatarRot));
|
||||||
|
var extension = Vec3.multiply(MARGIN, leftVector);
|
||||||
|
var position = Vec3.sum(axisStart, extension);
|
||||||
|
|
||||||
|
var buttonProperties = {
|
||||||
|
name: 'Hifi-Close-Button',
|
||||||
|
type: 'Model',
|
||||||
|
modelURL: CLOSE_BUTTON_MODEL_URL,
|
||||||
|
dimensions: CLOSE_BUTTON_DIMENSIONS,
|
||||||
|
position: Vec3.sum(position, VERTICAL_OFFFSET),
|
||||||
|
rotation: Quat.multiply(avatarRot, Quat.fromPitchYawRollDegrees(90, 0, 45)),
|
||||||
|
//rotation: Quat.fromPitchYawRollDegrees(0, 0, 90),
|
||||||
|
collisionsWillMove: false,
|
||||||
|
ignoreForCollisions: true,
|
||||||
|
script: CLOSE_BUTTON_SCRIPT_URL,
|
||||||
|
userData: JSON.stringify({
|
||||||
|
grabbableKey: {
|
||||||
|
wantsTrigger: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var button = Entities.addEntity(buttonProperties);
|
||||||
|
|
||||||
|
closeButtons.push(button);
|
||||||
|
|
||||||
|
if (ROTATE_CLOSE_BUTTON === true) {
|
||||||
|
Script.update.connect(rotateCloseButtons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotateCloseButtons() {
|
||||||
|
closeButtons.forEach(function(button) {
|
||||||
|
Entities.editEntity(button, {
|
||||||
|
angularVelocity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0.5,
|
||||||
|
z: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function subScribeToNewLights() {
|
||||||
|
Messages.subscribe('Hifi-Light-Mod-Receiver');
|
||||||
|
Messages.messageReceived.connect(handleLightModMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function subscribeToSliderMessages() {
|
||||||
|
Messages.subscribe('Hifi-Slider-Value-Reciever');
|
||||||
|
Messages.messageReceived.connect(handleValueMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function subscribeToLightOverlayRayCheckMessages() {
|
||||||
|
Messages.subscribe('Hifi-Light-Overlay-Ray-Check');
|
||||||
|
Messages.messageReceived.connect(handleLightOverlayRayCheckMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function subscribeToCleanupMessages() {
|
||||||
|
Messages.subscribe('Hifi-Light-Modifier-Cleanup');
|
||||||
|
Messages.messageReceived.connect(handleCleanupMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function handleLightModMessages(channel, message, sender) {
|
||||||
|
if (channel !== 'Hifi-Light-Mod-Receiver') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sender !== MyAvatar.sessionUUID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var parsedMessage = JSON.parse(message);
|
||||||
|
|
||||||
|
makeSliders(parsedMessage.light);
|
||||||
|
light = parsedMessage.light.id
|
||||||
|
if (SHOW_LIGHT_VOLUME === true) {
|
||||||
|
selectionManager.setSelections([parsedMessage.light.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleValueMessages(channel, message, sender) {
|
||||||
|
|
||||||
|
if (channel !== 'Hifi-Slider-Value-Reciever') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ONLY_I_CAN_EDIT === true && sender !== MyAvatar.sessionUUID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var parsedMessage = JSON.parse(message);
|
||||||
|
|
||||||
|
slidersRef[parsedMessage.sliderType].setValueFromMessage(parsedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentLight;
|
||||||
|
var block;
|
||||||
|
var oldParent = null;
|
||||||
|
var hasParent = false;
|
||||||
|
|
||||||
|
function handleLightOverlayRayCheckMessages(channel, message, sender) {
|
||||||
|
if (channel !== 'Hifi-Light-Overlay-Ray-Check') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ONLY_I_CAN_EDIT === true && sender !== MyAvatar.sessionUUID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pickRay = JSON.parse(message);
|
||||||
|
|
||||||
|
var doesIntersect = lightOverlayManager.findRayIntersection(pickRay);
|
||||||
|
// print('DOES INTERSECT A LIGHT WE HAVE???' + doesIntersect.intersects);
|
||||||
|
if (doesIntersect.intersects === true) {
|
||||||
|
// print('FULL MESSAGE:::' + JSON.stringify(doesIntersect))
|
||||||
|
|
||||||
|
var lightID = doesIntersect.entityID;
|
||||||
|
if (currentLight === lightID) {
|
||||||
|
// print('ALREADY HAVE A BLOCK, EXIT')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLight = lightID;
|
||||||
|
var lightProperties = Entities.getEntityProperties(lightID);
|
||||||
|
if (lightProperties.parentID !== DEFAULT_PARENT_ID) {
|
||||||
|
//this light has a parent already. so lets call our block the parent and then make sure not to delete it at the end;
|
||||||
|
oldParent = lightProperties.parentID;
|
||||||
|
hasParent = true;
|
||||||
|
block = lightProperties.parentID;
|
||||||
|
if (lightProperties.parentJointIndex !== -1) {
|
||||||
|
//should make sure to retain the parent too. but i don't actually know what the
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
block = createLightModel(lightProperties.position, lightProperties.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
var light = {
|
||||||
|
id: lightID,
|
||||||
|
type: 'spotlight',
|
||||||
|
initialProperties: lightProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
makeSliders(light);
|
||||||
|
|
||||||
|
if (SHOW_LIGHT_VOLUME === true) {
|
||||||
|
selectionManager.setSelections([lightID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entities.editEntity(lightID, {
|
||||||
|
parentID: block,
|
||||||
|
parentJointIndex: -1
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCleanupMessages(channel, message, sender) {
|
||||||
|
|
||||||
|
if (channel !== 'Hifi-Light-Modifier-Cleanup') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ONLY_I_CAN_EDIT === true && sender !== MyAvatar.sessionUUID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (message === 'callCleanup') {
|
||||||
|
cleanup(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSliderAxis() {
|
||||||
|
sliders.forEach(function(slider) {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup(fromMessage) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < sliders.length; i++) {
|
||||||
|
Entities.deleteEntity(sliders[i].axis);
|
||||||
|
Entities.deleteEntity(sliders[i].sliderIndicator);
|
||||||
|
Entities.deleteEntity(sliders[i].label);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (closeButtons.length > 0) {
|
||||||
|
Entities.deleteEntity(closeButtons.pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
//if the light was already parented to something we will want to restore that. or come up with groups or something clever.
|
||||||
|
if (oldParent !== null) {
|
||||||
|
Entities.editEntity(currentLight, {
|
||||||
|
parentID: oldParent,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Entities.editEntity(currentLight, {
|
||||||
|
parentID: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (fromMessage !== true) {
|
||||||
|
Messages.messageReceived.disconnect(handleLightModMessages);
|
||||||
|
Messages.messageReceived.disconnect(handleValueMessages);
|
||||||
|
Messages.messageReceived.disconnect(handleLightOverlayRayCheckMessages);
|
||||||
|
lightOverlayManager.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Entities.deleteEntity(panel);
|
||||||
|
Entities.deleteEntity(visiblePanel);
|
||||||
|
|
||||||
|
selectionManager.clearSelections();
|
||||||
|
|
||||||
|
if (ROTATE_CLOSE_BUTTON === true) {
|
||||||
|
Script.update.disconnect(rotateCloseButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasParent === false) {
|
||||||
|
Entities.deleteEntity(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldParent = null;
|
||||||
|
hasParent = false;
|
||||||
|
currentLight = null;
|
||||||
|
sliders = [];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
lightOverlayManager.setVisible(false);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
subscribeToLightOverlayRayCheckMessages();
|
||||||
|
subScribeToNewLights();
|
||||||
|
subscribeToCleanupMessages();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//other light properties
|
||||||
|
// diffuseColor: { red: 255, green: 255, blue: 255 },
|
||||||
|
// ambientColor: { red: 255, green: 255, blue: 255 },
|
||||||
|
// specularColor: { red: 255, green: 255, blue: 255 },
|
||||||
|
// constantAttenuation: 1,
|
||||||
|
// linearAttenuation: 0,
|
||||||
|
// quadraticAttenuation: 0,
|
||||||
|
// exponent: 0,
|
||||||
|
// cutoff: 180, // in degrees
|
73
examples/light_modifier/lightModifierTestScene.js
Normal file
73
examples/light_modifier/lightModifierTestScene.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
//
|
||||||
|
// lightModifierTestScene.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Given a selected light, instantiate some entities that represent various values you can dynamically adjust.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var PARENT_SCRIPT_URL = Script.resolvePath('lightParent.js?' + Math.random(0 - 100));
|
||||||
|
var basePosition, avatarRot;
|
||||||
|
avatarRot = Quat.fromPitchYawRollDegrees(0, MyAvatar.bodyYaw, 0.0);
|
||||||
|
basePosition = Vec3.sum(MyAvatar.position, Vec3.multiply(0, Quat.getUp(avatarRot)));
|
||||||
|
|
||||||
|
var light;
|
||||||
|
|
||||||
|
function createLight() {
|
||||||
|
var position = basePosition;
|
||||||
|
position.y += 2;
|
||||||
|
var lightTransform = evalLightWorldTransform(position, avatarRot);
|
||||||
|
var lightProperties = {
|
||||||
|
name: 'Hifi-Spotlight',
|
||||||
|
type: "Light",
|
||||||
|
isSpotlight: true,
|
||||||
|
dimensions: {
|
||||||
|
x: 2,
|
||||||
|
y: 2,
|
||||||
|
z: 8
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
red: 255,
|
||||||
|
green: 0,
|
||||||
|
blue: 255
|
||||||
|
},
|
||||||
|
intensity: 0.035,
|
||||||
|
exponent: 1,
|
||||||
|
cutoff: 30,
|
||||||
|
lifetime: -1,
|
||||||
|
position: lightTransform.p,
|
||||||
|
rotation: lightTransform.q
|
||||||
|
};
|
||||||
|
|
||||||
|
light = Entities.addEntity(lightProperties);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function evalLightWorldTransform(modelPos, modelRot) {
|
||||||
|
var MODEL_LIGHT_POSITION = {
|
||||||
|
x: 0,
|
||||||
|
y: -0.3,
|
||||||
|
z: 0
|
||||||
|
};
|
||||||
|
var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, {
|
||||||
|
x: 1,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)),
|
||||||
|
q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
Entities.deleteEntity(light);
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
|
||||||
|
createLight();
|
40
examples/light_modifier/lightParent.js
Normal file
40
examples/light_modifier/lightParent.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// lightParent.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Entity script that tells the light parent to update the selection tool when we move it.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function LightParent() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LightParent.prototype = {
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
var entityProperties = Entities.getEntityProperties(this.entityID, "userData");
|
||||||
|
this.initialProperties = entityProperties
|
||||||
|
this.userData = JSON.parse(entityProperties.userData);
|
||||||
|
},
|
||||||
|
startNearGrab: function() {},
|
||||||
|
startDistantGrab: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
continueNearGrab: function() {
|
||||||
|
this.continueDistantGrab();
|
||||||
|
},
|
||||||
|
continueDistantGrab: function() {
|
||||||
|
Messages.sendMessage('entityToolUpdates', 'callUpdate');
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new LightParent();
|
||||||
|
});
|
105
examples/light_modifier/slider.js
Normal file
105
examples/light_modifier/slider.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
//
|
||||||
|
// slider.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Entity script that sends a scaled value to a light based on its distance from the start of its constraint axis.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var AXIS_SCALE = 1;
|
||||||
|
var COLOR_MAX = 255;
|
||||||
|
var INTENSITY_MAX = 0.05;
|
||||||
|
var CUTOFF_MAX = 360;
|
||||||
|
var EXPONENT_MAX = 1;
|
||||||
|
|
||||||
|
function Slider() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider.prototype = {
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
var entityProperties = Entities.getEntityProperties(this.entityID, "userData");
|
||||||
|
var parsedUserData = JSON.parse(entityProperties.userData);
|
||||||
|
this.userData = parsedUserData.lightModifierKey;
|
||||||
|
},
|
||||||
|
startNearGrab: function() {
|
||||||
|
this.setInitialProperties();
|
||||||
|
},
|
||||||
|
startDistantGrab: function() {
|
||||||
|
this.setInitialProperties();
|
||||||
|
},
|
||||||
|
setInitialProperties: function() {
|
||||||
|
this.initialProperties = Entities.getEntityProperties(this.entityID);
|
||||||
|
},
|
||||||
|
continueNearGrab: function() {
|
||||||
|
// this.continueDistantGrab();
|
||||||
|
},
|
||||||
|
continueDistantGrab: function() {
|
||||||
|
this.setSliderValueBasedOnDistance();
|
||||||
|
},
|
||||||
|
setSliderValueBasedOnDistance: function() {
|
||||||
|
var currentPosition = Entities.getEntityProperties(this.entityID, "position").position;
|
||||||
|
|
||||||
|
var distance = Vec3.distance(this.userData.axisStart, currentPosition);
|
||||||
|
|
||||||
|
if (this.userData.sliderType === 'color_red' || this.userData.sliderType === 'color_green' || this.userData.sliderType === 'color_blue') {
|
||||||
|
this.sliderValue = this.scaleValueBasedOnDistanceFromStart(distance, 0, COLOR_MAX);
|
||||||
|
}
|
||||||
|
if (this.userData.sliderType === 'intensity') {
|
||||||
|
this.sliderValue = this.scaleValueBasedOnDistanceFromStart(distance, 0, INTENSITY_MAX);
|
||||||
|
}
|
||||||
|
if (this.userData.sliderType === 'cutoff') {
|
||||||
|
this.sliderValue = this.scaleValueBasedOnDistanceFromStart(distance, 0, CUTOFF_MAX);
|
||||||
|
}
|
||||||
|
if (this.userData.sliderType === 'exponent') {
|
||||||
|
this.sliderValue = this.scaleValueBasedOnDistanceFromStart(distance, 0, EXPONENT_MAX);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sendValueToSlider();
|
||||||
|
},
|
||||||
|
releaseGrab: function() {
|
||||||
|
Entities.editEntity(this.entityID, {
|
||||||
|
velocity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
},
|
||||||
|
angularVelocity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
z: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.sendValueToSlider();
|
||||||
|
},
|
||||||
|
scaleValueBasedOnDistanceFromStart: function(value, min2, max2) {
|
||||||
|
var min1 = 0;
|
||||||
|
var max1 = AXIS_SCALE;
|
||||||
|
var min2 = min2;
|
||||||
|
var max2 = max2;
|
||||||
|
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
|
||||||
|
},
|
||||||
|
sendValueToSlider: function() {
|
||||||
|
var _t = this;
|
||||||
|
var message = {
|
||||||
|
lightID: _t.userData.lightID,
|
||||||
|
sliderType: _t.userData.sliderType,
|
||||||
|
sliderValue: _t.sliderValue
|
||||||
|
}
|
||||||
|
Messages.sendMessage('Hifi-Slider-Value-Reciever', JSON.stringify(message));
|
||||||
|
if (_t.userData.sliderType === 'cutoff') {
|
||||||
|
Messages.sendMessage('entityToolUpdates', 'callUpdate');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Slider();
|
||||||
|
});
|
40
examples/light_modifier/visiblePanel.js
Normal file
40
examples/light_modifier/visiblePanel.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// visiblePanel.js
|
||||||
|
//
|
||||||
|
// Created by James Pollack @imgntn on 12/15/2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Entity script that disables picking on this panel.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
function VisiblePanel() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisiblePanel.prototype = {
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
action: 'add',
|
||||||
|
id: this.entityID
|
||||||
|
};
|
||||||
|
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data))
|
||||||
|
},
|
||||||
|
unload: function() {
|
||||||
|
var data = {
|
||||||
|
action: 'remove',
|
||||||
|
id: this.entityID
|
||||||
|
};
|
||||||
|
Messages.sendMessage('Hifi-Hand-RayPick-Blacklist', JSON.stringify(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return new VisiblePanel();
|
||||||
|
});
|
|
@ -29,21 +29,14 @@
|
||||||
this.equipped = false;
|
this.equipped = false;
|
||||||
this.forceMultiplier = 1;
|
this.forceMultiplier = 1;
|
||||||
this.laserLength = 100;
|
this.laserLength = 100;
|
||||||
this.laserOffsets = {
|
|
||||||
y: .095
|
|
||||||
};
|
|
||||||
this.firingOffsets = {
|
|
||||||
z: 0.16
|
|
||||||
}
|
|
||||||
this.fireSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Guns/GUN-SHOT2.raw");
|
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.ricochetSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Guns/Ricochet.L.wav");
|
||||||
this.playRichochetSoundChance = 0.1;
|
this.playRichochetSoundChance = 0.1;
|
||||||
this.fireVolume = 0.2;
|
this.fireVolume = 0.2;
|
||||||
this.bulletForce = 10;
|
this.bulletForce = 10;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.showLaser = false;
|
this.showLaser = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Pistol.prototype = {
|
Pistol.prototype = {
|
||||||
|
@ -58,20 +51,36 @@
|
||||||
if (!this.equipped) {
|
if (!this.equipped) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.toggleWithTriggerPressure();
|
this.updateProps();
|
||||||
if (this.showLaser) {
|
if (this.showLaser) {
|
||||||
this.updateLaser();
|
this.updateLaser();
|
||||||
}
|
}
|
||||||
|
this.toggleWithTriggerPressure();
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
updateProps: function() {
|
||||||
|
var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
||||||
|
this.position = gunProps.position;
|
||||||
|
this.rotation = gunProps.rotation;
|
||||||
|
this.firingDirection = Quat.getFront(this.rotation);
|
||||||
|
var upVec = Quat.getUp(this.rotation);
|
||||||
|
this.barrelPoint = Vec3.sum(this.position, Vec3.multiply(upVec, this.laserOffsets.y));
|
||||||
|
this.laserTip = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.laserLength));
|
||||||
|
this.barrelPoint = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.firingOffsets.z))
|
||||||
|
var pickRay = {
|
||||||
|
origin: this.barrelPoint,
|
||||||
|
direction: this.firingDirection
|
||||||
|
};
|
||||||
},
|
},
|
||||||
toggleWithTriggerPressure: function() {
|
toggleWithTriggerPressure: function() {
|
||||||
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
|
this.triggerValue = Controller.getValue(TRIGGER_CONTROLS[this.hand]);
|
||||||
|
|
||||||
if (this.triggerValue < RELOAD_THRESHOLD) {
|
if (this.triggerValue < RELOAD_THRESHOLD) {
|
||||||
// print('RELOAD');
|
|
||||||
this.canShoot = true;
|
this.canShoot = true;
|
||||||
}
|
}
|
||||||
if (this.canShoot === true && this.triggerValue === 1) {
|
if (this.canShoot === true && this.triggerValue === 1) {
|
||||||
// print('SHOOT');
|
|
||||||
this.fire();
|
this.fire();
|
||||||
this.canShoot = false;
|
this.canShoot = false;
|
||||||
}
|
}
|
||||||
|
@ -91,17 +100,10 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
updateLaser: function() {
|
updateLaser: function() {
|
||||||
var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
|
||||||
var position = gunProps.position;
|
|
||||||
var rotation = gunProps.rotation;
|
|
||||||
this.firingDirection = Quat.getFront(rotation);
|
|
||||||
var upVec = Quat.getUp(rotation);
|
|
||||||
this.barrelPoint = Vec3.sum(position, Vec3.multiply(upVec, this.laserOffsets.y));
|
|
||||||
var laserTip = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.laserLength));
|
|
||||||
this.barrelPoint = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.firingOffsets.z))
|
|
||||||
Overlays.editOverlay(this.laser, {
|
Overlays.editOverlay(this.laser, {
|
||||||
start: this.barrelPoint,
|
start: this.barrelPoint,
|
||||||
end: laserTip,
|
end: this.laserTip,
|
||||||
alpha: 1
|
alpha: 1
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -114,19 +116,6 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
preload: function(entityID) {
|
|
||||||
this.entityID = entityID;
|
|
||||||
// this.initControllerMapping();
|
|
||||||
this.laser = Overlays.addOverlay("line3d", {
|
|
||||||
start: ZERO_VECTOR,
|
|
||||||
end: ZERO_VECTOR,
|
|
||||||
color: COLORS.RED,
|
|
||||||
alpha: 1,
|
|
||||||
visible: true,
|
|
||||||
lineWidth: 2
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
triggerPress: function(hand, value) {
|
triggerPress: function(hand, value) {
|
||||||
if (this.hand === hand && value === 1) {
|
if (this.hand === hand && value === 1) {
|
||||||
//We are pulling trigger on the hand we have the gun in, so fire
|
//We are pulling trigger on the hand we have the gun in, so fire
|
||||||
|
@ -135,15 +124,16 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
fire: function() {
|
fire: function() {
|
||||||
var pickRay = {
|
|
||||||
origin: this.barrelPoint,
|
|
||||||
direction: this.firingDirection
|
|
||||||
};
|
|
||||||
Audio.playSound(this.fireSound, {
|
Audio.playSound(this.fireSound, {
|
||||||
position: this.barrelPoint,
|
position: this.barrelPoint,
|
||||||
volume: this.fireVolume
|
volume: this.fireVolume
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var pickRay = {
|
||||||
|
origin: this.barrelPoint,
|
||||||
|
direction: this.firingDirection
|
||||||
|
};
|
||||||
this.createGunFireEffect(this.barrelPoint)
|
this.createGunFireEffect(this.barrelPoint)
|
||||||
var intersection = Entities.findRayIntersectionBlocking(pickRay, true);
|
var intersection = Entities.findRayIntersectionBlocking(pickRay, true);
|
||||||
if (intersection.intersects) {
|
if (intersection.intersects) {
|
||||||
|
@ -170,11 +160,11 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
createEntityHitEffect: function(position) {
|
createEntityHitEffect: function(position) {
|
||||||
var flash = Entities.addEntity({
|
var sparks = Entities.addEntity({
|
||||||
type: "ParticleEffect",
|
type: "ParticleEffect",
|
||||||
position: position,
|
position: position,
|
||||||
lifetime: 4,
|
lifetime: 4,
|
||||||
"name": "Flash Emitter",
|
"name": "Sparks Emitter",
|
||||||
"color": {
|
"color": {
|
||||||
red: 228,
|
red: 228,
|
||||||
green: 128,
|
green: 128,
|
||||||
|
@ -228,7 +218,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
Script.setTimeout(function() {
|
Script.setTimeout(function() {
|
||||||
Entities.editEntity(flash, {
|
Entities.editEntity(sparks, {
|
||||||
isEmitting: false
|
isEmitting: false
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
|
@ -261,11 +251,11 @@
|
||||||
"z": 0
|
"z": 0
|
||||||
},
|
},
|
||||||
"accelerationSpread": {
|
"accelerationSpread": {
|
||||||
"x": .2,
|
"x": 0.2,
|
||||||
"y": 0,
|
"y": 0,
|
||||||
"z": .2
|
"z": 0.2
|
||||||
},
|
},
|
||||||
"radiusSpread": .04,
|
"radiusSpread": 0.04,
|
||||||
"particleRadius": 0.07,
|
"particleRadius": 0.07,
|
||||||
"radiusStart": 0.07,
|
"radiusStart": 0.07,
|
||||||
"radiusFinish": 0.07,
|
"radiusFinish": 0.07,
|
||||||
|
@ -282,11 +272,46 @@
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
var flash = Entities.addEntity({
|
Entities.editEntity(this.flash, {
|
||||||
|
isEmitting: true
|
||||||
|
});
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
Entities.editEntity(_this.flash, {
|
||||||
|
isEmitting: false
|
||||||
|
});
|
||||||
|
}, 100)
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
preload: function(entityID) {
|
||||||
|
this.entityID = entityID;
|
||||||
|
this.laser = Overlays.addOverlay("line3d", {
|
||||||
|
start: ZERO_VECTOR,
|
||||||
|
end: ZERO_VECTOR,
|
||||||
|
color: COLORS.RED,
|
||||||
|
alpha: 1,
|
||||||
|
visible: true,
|
||||||
|
lineWidth: 2
|
||||||
|
});
|
||||||
|
this.laserOffsets = {
|
||||||
|
y: 0.095
|
||||||
|
};
|
||||||
|
this.firingOffsets = {
|
||||||
|
z: 0.16
|
||||||
|
}
|
||||||
|
var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);
|
||||||
|
var position = gunProps.position;
|
||||||
|
var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||||
|
this.firingDirection = Quat.getFront(rotation);
|
||||||
|
var upVec = Quat.getUp(rotation);
|
||||||
|
this.barrelPoint = Vec3.sum(position, Vec3.multiply(upVec, this.laserOffsets.y));
|
||||||
|
this.barrelPoint = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.firingOffsets.z))
|
||||||
|
|
||||||
|
this.flash = Entities.addEntity({
|
||||||
type: "ParticleEffect",
|
type: "ParticleEffect",
|
||||||
position: position,
|
position: this.barrelPoint,
|
||||||
lifetime: 4,
|
|
||||||
"name": "Muzzle Flash",
|
"name": "Muzzle Flash",
|
||||||
|
isEmitting: false,
|
||||||
"color": {
|
"color": {
|
||||||
red: 228,
|
red: 228,
|
||||||
green: 128,
|
green: 128,
|
||||||
|
@ -339,16 +364,13 @@
|
||||||
"textures": "http://ericrius1.github.io/PartiArt/assets/star.png"
|
"textures": "http://ericrius1.github.io/PartiArt/assets/star.png"
|
||||||
});
|
});
|
||||||
|
|
||||||
Script.setTimeout(function() {
|
Script.setTimeout(function() {
|
||||||
Entities.editEntity(flash, {
|
Entities.editEntity(_this.flash, {parentID: _this.entityID});
|
||||||
isEmitting: false
|
}, 500)
|
||||||
});
|
|
||||||
}, 100)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// entity scripts always need to return a newly constructed object of our type
|
// entity scripts always need to return a newly constructed object of our type
|
||||||
return new Pistol();
|
return new Pistol();
|
||||||
});
|
});
|
||||||
|
|
|
@ -3486,78 +3486,86 @@ namespace render {
|
||||||
|
|
||||||
// Background rendering decision
|
// Background rendering decision
|
||||||
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
|
||||||
if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) {
|
auto backgroundMode = skyStage->getBackgroundMode();
|
||||||
|
|
||||||
|
if (backgroundMode == model::SunSkyStage::NO_BACKGROUND) {
|
||||||
// this line intentionally left blank
|
// this line intentionally left blank
|
||||||
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) {
|
} else {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
if (backgroundMode == model::SunSkyStage::SKY_BOX) {
|
||||||
PerformanceTimer perfTimer("stars");
|
auto skybox = skyStage->getSkybox();
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
if (skybox && skybox->getCubemap() && skybox->getCubemap()->isDefined()) {
|
||||||
"Application::payloadRender<BackgroundRenderData>() ... stars...");
|
PerformanceTimer perfTimer("skybox");
|
||||||
// should be the first rendering pass - w/o depth buffer / lighting
|
skybox->render(batch, *(args->_viewFrustum));
|
||||||
|
} else {
|
||||||
// compute starfield alpha based on distance from atmosphere
|
// If no skybox texture is available, render the SKY_DOME while it loads
|
||||||
float alpha = 1.0f;
|
backgroundMode = model::SunSkyStage::SKY_DOME;
|
||||||
bool hasStars = true;
|
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
|
||||||
// TODO: handle this correctly for zones
|
|
||||||
const EnvironmentData& closestData = background->_environment->getClosestData(args->_viewFrustum->getPosition()); // was theCamera instead of _viewFrustum
|
|
||||||
|
|
||||||
if (closestData.getHasStars()) {
|
|
||||||
const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f;
|
|
||||||
const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f;
|
|
||||||
|
|
||||||
glm::vec3 sunDirection = (args->_viewFrustum->getPosition()/*getAvatarPosition()*/ - closestData.getSunLocation())
|
|
||||||
/ closestData.getAtmosphereOuterRadius();
|
|
||||||
float height = glm::distance(args->_viewFrustum->getPosition()/*theCamera.getPosition()*/, closestData.getAtmosphereCenter());
|
|
||||||
if (height < closestData.getAtmosphereInnerRadius()) {
|
|
||||||
// If we're inside the atmosphere, then determine if our keyLight is below the horizon
|
|
||||||
alpha = 0.0f;
|
|
||||||
|
|
||||||
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
|
||||||
float directionY = glm::clamp(sunDirection.y,
|
|
||||||
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
|
||||||
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
|
||||||
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else if (height < closestData.getAtmosphereOuterRadius()) {
|
|
||||||
alpha = (height - closestData.getAtmosphereInnerRadius()) /
|
|
||||||
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
|
|
||||||
|
|
||||||
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
|
||||||
float directionY = glm::clamp(sunDirection.y,
|
|
||||||
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
|
||||||
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
|
||||||
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hasStars = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally render the starfield
|
|
||||||
if (hasStars) {
|
|
||||||
background->_stars.render(args, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw the sky dome
|
|
||||||
if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
|
||||||
PerformanceTimer perfTimer("atmosphere");
|
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
|
||||||
"Application::displaySide() ... atmosphere...");
|
|
||||||
|
|
||||||
background->_environment->renderAtmospheres(batch, *(args->_viewFrustum));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
|
if (backgroundMode == model::SunSkyStage::SKY_DOME) {
|
||||||
PerformanceTimer perfTimer("skybox");
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
||||||
auto skybox = skyStage->getSkybox();
|
PerformanceTimer perfTimer("stars");
|
||||||
if (skybox) {
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
skybox->render(batch, *(args->_viewFrustum));
|
"Application::payloadRender<BackgroundRenderData>() ... stars...");
|
||||||
|
// should be the first rendering pass - w/o depth buffer / lighting
|
||||||
|
|
||||||
|
// compute starfield alpha based on distance from atmosphere
|
||||||
|
float alpha = 1.0f;
|
||||||
|
bool hasStars = true;
|
||||||
|
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
||||||
|
// TODO: handle this correctly for zones
|
||||||
|
const EnvironmentData& closestData = background->_environment->getClosestData(args->_viewFrustum->getPosition()); // was theCamera instead of _viewFrustum
|
||||||
|
|
||||||
|
if (closestData.getHasStars()) {
|
||||||
|
const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f;
|
||||||
|
const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f;
|
||||||
|
|
||||||
|
glm::vec3 sunDirection = (args->_viewFrustum->getPosition()/*getAvatarPosition()*/ - closestData.getSunLocation())
|
||||||
|
/ closestData.getAtmosphereOuterRadius();
|
||||||
|
float height = glm::distance(args->_viewFrustum->getPosition()/*theCamera.getPosition()*/, closestData.getAtmosphereCenter());
|
||||||
|
if (height < closestData.getAtmosphereInnerRadius()) {
|
||||||
|
// If we're inside the atmosphere, then determine if our keyLight is below the horizon
|
||||||
|
alpha = 0.0f;
|
||||||
|
|
||||||
|
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
||||||
|
float directionY = glm::clamp(sunDirection.y,
|
||||||
|
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
||||||
|
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
||||||
|
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if (height < closestData.getAtmosphereOuterRadius()) {
|
||||||
|
alpha = (height - closestData.getAtmosphereInnerRadius()) /
|
||||||
|
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
|
||||||
|
|
||||||
|
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
||||||
|
float directionY = glm::clamp(sunDirection.y,
|
||||||
|
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
||||||
|
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
||||||
|
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hasStars = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally render the starfield
|
||||||
|
if (hasStars) {
|
||||||
|
background->_stars.render(args, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the sky dome
|
||||||
|
if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
||||||
|
PerformanceTimer perfTimer("atmosphere");
|
||||||
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
|
"Application::displaySide() ... atmosphere...");
|
||||||
|
|
||||||
|
background->_environment->renderAtmospheres(batch, *(args->_viewFrustum));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,11 @@ void RenderablePolyLineEntityItem::updateVertices() {
|
||||||
_vertices << v1 << v2;
|
_vertices << v1 << v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guard against an empty polyline
|
||||||
|
if (finalIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// For last point we can assume binormals are the same since it represents the last two vertices of quad
|
// For last point we can assume binormals are the same since it represents the last two vertices of quad
|
||||||
point = _points.at(finalIndex);
|
point = _points.at(finalIndex);
|
||||||
v1 = point + binormal;
|
v1 = point + binormal;
|
||||||
|
|
|
@ -96,7 +96,12 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
|
gpu::TexturePointer skymap = skybox.getCubemap();
|
||||||
|
// FIXME: skymap->isDefined may not be threadsafe
|
||||||
|
assert(skymap && skymap->isDefined());
|
||||||
|
|
||||||
glm::mat4 projMat;
|
glm::mat4 projMat;
|
||||||
viewFrustum.evalProjectionMatrix(projMat);
|
viewFrustum.evalProjectionMatrix(projMat);
|
||||||
|
|
||||||
|
@ -106,11 +111,6 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
||||||
batch.setViewTransform(viewTransform);
|
batch.setViewTransform(viewTransform);
|
||||||
batch.setModelTransform(Transform()); // only for Mac
|
batch.setModelTransform(Transform()); // only for Mac
|
||||||
|
|
||||||
gpu::TexturePointer skymap;
|
|
||||||
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
|
|
||||||
skymap = skybox.getCubemap();
|
|
||||||
}
|
|
||||||
|
|
||||||
batch.setPipeline(thePipeline);
|
batch.setPipeline(thePipeline);
|
||||||
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, skybox._dataBuffer);
|
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, skybox._dataBuffer);
|
||||||
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, skymap);
|
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, skymap);
|
||||||
|
@ -118,6 +118,5 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, nullptr);
|
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, nullptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,10 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) {
|
if (skybox._procedural && skybox._procedural->_enabled && skybox._procedural->ready()) {
|
||||||
|
gpu::TexturePointer skymap = skybox.getCubemap();
|
||||||
|
// FIXME: skymap->isDefined may not be threadsafe
|
||||||
|
assert(skymap && skymap->isDefined());
|
||||||
|
|
||||||
glm::mat4 projMat;
|
glm::mat4 projMat;
|
||||||
viewFrustum.evalProjectionMatrix(projMat);
|
viewFrustum.evalProjectionMatrix(projMat);
|
||||||
|
|
||||||
|
@ -56,10 +60,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum,
|
||||||
batch.setProjectionTransform(projMat);
|
batch.setProjectionTransform(projMat);
|
||||||
batch.setViewTransform(viewTransform);
|
batch.setViewTransform(viewTransform);
|
||||||
batch.setModelTransform(Transform()); // only for Mac
|
batch.setModelTransform(Transform()); // only for Mac
|
||||||
|
batch.setResourceTexture(0, skybox.getCubemap());
|
||||||
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
|
|
||||||
batch.setResourceTexture(0, skybox.getCubemap());
|
|
||||||
}
|
|
||||||
|
|
||||||
skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1));
|
skybox._procedural->prepare(batch, glm::vec3(0), glm::vec3(1));
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
Loading…
Reference in a new issue