mirror of
https://github.com/overte-org/overte.git
synced 2025-08-12 12:53:55 +02:00
Merge branch 'toybox' of https://github.com/ericrius1/hifi into ericrius1-toybox
This commit is contained in:
commit
ec5bfff183
7 changed files with 1099 additions and 534 deletions
|
@ -1,441 +0,0 @@
|
|||
// hydraGrab.js
|
||||
// examples
|
||||
//
|
||||
// Created by Eric Levin on 9/2/15
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Grabs physically moveable entities with hydra-like controllers; it works for either near or far objects.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("../libraries/utils.js");
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// these tune time-averaging and "on" value for analog trigger
|
||||
//
|
||||
|
||||
var TRIGGER_SMOOTH_RATIO = 0.1; // 0.0 disables smoothing of trigger value
|
||||
var TRIGGER_ON_VALUE = 0.2;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// distant manipulation
|
||||
//
|
||||
|
||||
var DISTANCE_HOLDING_RADIUS_FACTOR = 5; // multiplied by distance between hand and object
|
||||
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
||||
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_LENGTH = 500;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// near grabbing
|
||||
//
|
||||
|
||||
var GRAB_RADIUS = 0.3; // if the ray misses but an object is this close, it will still be selected
|
||||
var NEAR_GRABBING_ACTION_TIMEFRAME = 0.05; // how quickly objects move to their new position
|
||||
var NEAR_GRABBING_VELOCITY_SMOOTH_RATIO = 1.0; // adjust time-averaging of held object's velocity. 1.0 to disable.
|
||||
var NEAR_PICK_MAX_DISTANCE = 0.6; // max length of pick-ray for close grabbing to be selected
|
||||
var RELEASE_VELOCITY_MULTIPLIER = 1.5; // affects throwing things
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// other constants
|
||||
//
|
||||
|
||||
var RIGHT_HAND = 1;
|
||||
var LEFT_HAND = 0;
|
||||
|
||||
var ZERO_VEC = {x: 0, y: 0, z: 0};
|
||||
var NULL_ACTION_ID = "{00000000-0000-0000-000000000000}";
|
||||
var MSEC_PER_SEC = 1000.0;
|
||||
|
||||
// these control how long an abandoned pointer line will hang around
|
||||
var startTime = Date.now();
|
||||
var LIFETIME = 10;
|
||||
|
||||
// states for the state machine
|
||||
var STATE_SEARCHING = 0;
|
||||
var STATE_DISTANCE_HOLDING = 1;
|
||||
var STATE_CONTINUE_DISTANCE_HOLDING = 2;
|
||||
var STATE_NEAR_GRABBING = 3;
|
||||
var STATE_CONTINUE_NEAR_GRABBING = 4;
|
||||
var STATE_RELEASE = 5;
|
||||
|
||||
var GRAB_USER_DATA_KEY = "grabKey";
|
||||
|
||||
function controller(hand, triggerAction) {
|
||||
this.hand = hand;
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
this.getHandPosition = MyAvatar.getRightPalmPosition;
|
||||
this.getHandRotation = MyAvatar.getRightPalmRotation;
|
||||
} else {
|
||||
this.getHandPosition = MyAvatar.getLeftPalmPosition;
|
||||
this.getHandRotation = MyAvatar.getLeftPalmRotation;
|
||||
}
|
||||
this.triggerAction = triggerAction;
|
||||
this.palm = 2 * hand;
|
||||
// this.tip = 2 * hand + 1; // unused, but I'm leaving this here for fear it will be needed
|
||||
|
||||
this.actionID = null; // action this script created...
|
||||
this.grabbedEntity = null; // on this entity.
|
||||
this.grabbedVelocity = ZERO_VEC; // rolling average of held object's velocity
|
||||
this.state = 0;
|
||||
this.pointer = null; // entity-id of line object
|
||||
this.triggerValue = 0; // rolling average of trigger value
|
||||
|
||||
this.update = function() {
|
||||
switch(this.state) {
|
||||
case STATE_SEARCHING:
|
||||
this.search();
|
||||
break;
|
||||
case STATE_DISTANCE_HOLDING:
|
||||
this.distanceHolding();
|
||||
break;
|
||||
case STATE_CONTINUE_DISTANCE_HOLDING:
|
||||
this.continueDistanceHolding();
|
||||
break;
|
||||
case STATE_NEAR_GRABBING:
|
||||
this.nearGrabbing();
|
||||
break;
|
||||
case STATE_CONTINUE_NEAR_GRABBING:
|
||||
this.continueNearGrabbing();
|
||||
break;
|
||||
case STATE_RELEASE:
|
||||
this.release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.lineOn = function(closePoint, farPoint, color) {
|
||||
// draw a line
|
||||
if (this.pointer == null) {
|
||||
this.pointer = Entities.addEntity({
|
||||
type: "Line",
|
||||
name: "pointer",
|
||||
dimensions: LINE_ENTITY_DIMENSIONS,
|
||||
visible: true,
|
||||
position: closePoint,
|
||||
linePoints: [ ZERO_VEC, farPoint ],
|
||||
color: color,
|
||||
lifetime: LIFETIME
|
||||
});
|
||||
} else {
|
||||
Entities.editEntity(this.pointer, {
|
||||
position: closePoint,
|
||||
linePoints: [ ZERO_VEC, farPoint ],
|
||||
color: color,
|
||||
lifetime: (Date.now() - startTime) / MSEC_PER_SEC + LIFETIME
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.lineOff = function() {
|
||||
if (this.pointer != null) {
|
||||
Entities.deleteEntity(this.pointer);
|
||||
}
|
||||
this.pointer = null;
|
||||
}
|
||||
|
||||
|
||||
this.triggerSmoothedSqueezed = function() {
|
||||
var triggerValue = Controller.getActionValue(this.triggerAction);
|
||||
// smooth out trigger value
|
||||
this.triggerValue = (this.triggerValue * TRIGGER_SMOOTH_RATIO) +
|
||||
(triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO));
|
||||
return this.triggerValue > TRIGGER_ON_VALUE;
|
||||
}
|
||||
|
||||
|
||||
this.triggerSqueezed = function() {
|
||||
var triggerValue = Controller.getActionValue(this.triggerAction);
|
||||
return triggerValue > TRIGGER_ON_VALUE;
|
||||
}
|
||||
|
||||
|
||||
this.search = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
}
|
||||
|
||||
// the trigger is being pressed, do a ray test
|
||||
var handPosition = this.getHandPosition();
|
||||
var pickRay = {origin: handPosition, direction: Quat.getUp(this.getHandRotation())};
|
||||
var intersection = Entities.findRayIntersection(pickRay, true);
|
||||
if (intersection.intersects &&
|
||||
intersection.properties.collisionsWillMove === 1 &&
|
||||
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);
|
||||
this.grabbedEntity = intersection.entityID;
|
||||
if (intersectionDistance < NEAR_PICK_MAX_DISTANCE) {
|
||||
// the hand is very close to the intersected object. go into close-grabbing mode.
|
||||
this.state = STATE_NEAR_GRABBING;
|
||||
} else {
|
||||
// the hand is far from the intersected object. go into distance-holding mode
|
||||
this.state = STATE_DISTANCE_HOLDING;
|
||||
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
}
|
||||
} else {
|
||||
// forward ray test failed, try sphere test.
|
||||
var nearbyEntities = Entities.findEntities(handPosition, GRAB_RADIUS);
|
||||
var minDistance = GRAB_RADIUS;
|
||||
var grabbedEntity = null;
|
||||
for (var i = 0; i < nearbyEntities.length; i++) {
|
||||
var props = Entities.getEntityProperties(nearbyEntities[i]);
|
||||
var distance = Vec3.distance(props.position, handPosition);
|
||||
if (distance < minDistance && props.name !== "pointer" &&
|
||||
props.collisionsWillMove === 1 &&
|
||||
props.locked === 0) {
|
||||
this.grabbedEntity = nearbyEntities[i];
|
||||
minDistance = distance;
|
||||
}
|
||||
}
|
||||
if (this.grabbedEntity === null) {
|
||||
this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR);
|
||||
} else {
|
||||
this.state = STATE_NEAR_GRABBING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.distanceHolding = function() {
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position","rotation"]);
|
||||
|
||||
// add the action and initialize some variables
|
||||
this.currentObjectPosition = grabbedProperties.position;
|
||||
this.currentObjectRotation = grabbedProperties.rotation;
|
||||
this.currentObjectTime = Date.now();
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
this.handPreviousRotation = handRotation;
|
||||
|
||||
this.actionID = Entities.addAction("spring", this.grabbedEntity, {
|
||||
targetPosition: this.currentObjectPosition,
|
||||
linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation,
|
||||
angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
if (this.actionID == NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
}
|
||||
|
||||
if (this.actionID != null) {
|
||||
this.state = STATE_CONTINUE_DISTANCE_HOLDING;
|
||||
this.activateEntity(this.grabbedEntity);
|
||||
Entities.callEntityMethod(this.grabbedEntity, "startDistantGrab");
|
||||
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||
} else {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.continueDistanceHolding = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
}
|
||||
|
||||
var handPosition = this.getHandPosition();
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var handRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(this.palm));
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]);
|
||||
|
||||
this.lineOn(handPosition, Vec3.subtract(grabbedProperties.position, handPosition), INTERSECT_COLOR);
|
||||
|
||||
// the action was set up on a previous call. update the targets.
|
||||
var radius = Math.max(Vec3.distance(this.currentObjectPosition,
|
||||
handControllerPosition) * DISTANCE_HOLDING_RADIUS_FACTOR,
|
||||
DISTANCE_HOLDING_RADIUS_FACTOR);
|
||||
|
||||
var handMoved = Vec3.subtract(handControllerPosition, this.handPreviousPosition);
|
||||
this.handPreviousPosition = handControllerPosition;
|
||||
var superHandMoved = Vec3.multiply(handMoved, radius);
|
||||
|
||||
var newObjectPosition = Vec3.sum(this.currentObjectPosition, superHandMoved);
|
||||
var deltaPosition = Vec3.subtract(newObjectPosition, this.currentObjectPosition); // meters
|
||||
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;
|
||||
|
||||
// this doubles hand rotation
|
||||
var handChange = Quat.multiply(Quat.slerp(this.handPreviousRotation, handRotation,
|
||||
DISTANCE_HOLDING_ROTATION_EXAGGERATION_FACTOR),
|
||||
Quat.inverse(this.handPreviousRotation));
|
||||
this.handPreviousRotation = handRotation;
|
||||
this.currentObjectRotation = Quat.multiply(handChange, this.currentObjectRotation);
|
||||
|
||||
Entities.callEntityMethod(this.grabbedEntity, "continueDistantGrab");
|
||||
|
||||
Entities.updateAction(this.grabbedEntity, this.actionID, {
|
||||
targetPosition: this.currentObjectPosition, linearTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME,
|
||||
targetRotation: this.currentObjectRotation, angularTimeScale: DISTANCE_HOLDING_ACTION_TIMEFRAME
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
this.nearGrabbing = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
}
|
||||
|
||||
this.lineOff();
|
||||
|
||||
this.activateEntity(this.grabbedEntity);
|
||||
|
||||
var grabbedProperties = Entities.getEntityProperties(this.grabbedEntity, ["position", "rotation"]);
|
||||
|
||||
var handRotation = this.getHandRotation();
|
||||
var handPosition = this.getHandPosition();
|
||||
|
||||
var objectRotation = grabbedProperties.rotation;
|
||||
var offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||
|
||||
currentObjectPosition = grabbedProperties.position;
|
||||
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
||||
var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset);
|
||||
|
||||
this.actionID = Entities.addAction("hold", this.grabbedEntity, {
|
||||
hand: this.hand == RIGHT_HAND ? "right" : "left",
|
||||
timeScale: NEAR_GRABBING_ACTION_TIMEFRAME,
|
||||
relativePosition: offsetPosition,
|
||||
relativeRotation: offsetRotation
|
||||
});
|
||||
if (this.actionID == NULL_ACTION_ID) {
|
||||
this.actionID = null;
|
||||
} else {
|
||||
this.state = STATE_CONTINUE_NEAR_GRABBING;
|
||||
Entities.callEntityMethod(this.grabbedEntity, "startNearGrab");
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setRightHand");
|
||||
} else {
|
||||
Entities.callEntityMethod(this.grabbedEntity, "setLeftHand");
|
||||
}
|
||||
}
|
||||
|
||||
this.currentHandControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
this.currentObjectTime = Date.now();
|
||||
}
|
||||
|
||||
|
||||
this.continueNearGrabbing = function() {
|
||||
if (!this.triggerSmoothedSqueezed()) {
|
||||
this.state = STATE_RELEASE;
|
||||
return;
|
||||
}
|
||||
|
||||
// keep track of the measured velocity of the held object
|
||||
var handControllerPosition = Controller.getSpatialControlPosition(this.palm);
|
||||
var now = Date.now();
|
||||
|
||||
var deltaPosition = Vec3.subtract(handControllerPosition, this.currentHandControllerPosition); // meters
|
||||
var deltaTime = (now - this.currentObjectTime) / MSEC_PER_SEC; // convert to seconds
|
||||
this.computeReleaseVelocity(deltaPosition, deltaTime, true);
|
||||
|
||||
this.currentHandControllerPosition = handControllerPosition;
|
||||
this.currentObjectTime = now;
|
||||
Entities.callEntityMethod(this.grabbedEntity, "continueNearGrab");
|
||||
}
|
||||
|
||||
|
||||
this.computeReleaseVelocity = function(deltaPosition, deltaTime, useMultiplier) {
|
||||
if (deltaTime > 0.0 && !vec3equal(deltaPosition, ZERO_VEC)) {
|
||||
var grabbedVelocity = Vec3.multiply(deltaPosition, 1.0 / deltaTime);
|
||||
// don't update grabbedVelocity if the trigger is off. the smoothing of the trigger
|
||||
// value would otherwise give the held object time to slow down.
|
||||
if (this.triggerSqueezed()) {
|
||||
this.grabbedVelocity =
|
||||
Vec3.sum(Vec3.multiply(this.grabbedVelocity,
|
||||
(1.0 - NEAR_GRABBING_VELOCITY_SMOOTH_RATIO)),
|
||||
Vec3.multiply(grabbedVelocity, NEAR_GRABBING_VELOCITY_SMOOTH_RATIO));
|
||||
}
|
||||
|
||||
if (useMultiplier) {
|
||||
this.grabbedVelocity = Vec3.multiply(this.grabbedVelocity, RELEASE_VELOCITY_MULTIPLIER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.release = function() {
|
||||
this.lineOff();
|
||||
|
||||
if (this.grabbedEntity != null && this.actionID != null) {
|
||||
Entities.deleteAction(this.grabbedEntity, this.actionID);
|
||||
Entities.callEntityMethod(this.grabbedEntity, "releaseGrab");
|
||||
}
|
||||
|
||||
// the action will tend to quickly bring an object's velocity to zero. now that
|
||||
// the action is gone, set the objects velocity to something the holder might expect.
|
||||
Entities.editEntity(this.grabbedEntity, {velocity: this.grabbedVelocity});
|
||||
this.deactivateEntity(this.grabbedEntity);
|
||||
|
||||
this.grabbedVelocity = ZERO_VEC;
|
||||
this.grabbedEntity = null;
|
||||
this.actionID = null;
|
||||
this.state = STATE_SEARCHING;
|
||||
}
|
||||
|
||||
|
||||
this.cleanup = function() {
|
||||
release();
|
||||
}
|
||||
|
||||
this.activateEntity = function(entity) {
|
||||
var data = {
|
||||
activated: true,
|
||||
avatarId: MyAvatar.sessionUUID
|
||||
};
|
||||
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||
}
|
||||
|
||||
this.deactivateEntity = function(entity) {
|
||||
var data = {
|
||||
activated: false,
|
||||
avatarId: null
|
||||
};
|
||||
setEntityCustomData(GRAB_USER_DATA_KEY, this.grabbedEntity, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var rightController = new controller(RIGHT_HAND, Controller.findAction("RIGHT_HAND_CLICK"));
|
||||
var leftController = new controller(LEFT_HAND, Controller.findAction("LEFT_HAND_CLICK"));
|
||||
|
||||
|
||||
function update() {
|
||||
rightController.update();
|
||||
leftController.update();
|
||||
}
|
||||
|
||||
|
||||
function cleanup() {
|
||||
rightController.cleanup();
|
||||
leftController.cleanup();
|
||||
}
|
||||
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
Script.update.connect(update)
|
59
examples/toys/cat.js
Normal file
59
examples/toys/cat.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// doll.js
|
||||
// examples/toybox/entityScripts
|
||||
//
|
||||
// Created by Eric Levin on 9/21/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This entity script breathes movement and sound- one might even say life- into a doll.
|
||||
//
|
||||
// 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 _this;
|
||||
|
||||
// this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember
|
||||
// our this object, so we can access it in cases where we're called without a this (like in the case of various global signals)
|
||||
Cat = function() {
|
||||
_this = this;
|
||||
this.meowSound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/Animals/cat_meow.wav");
|
||||
this.distanceThreshold = 1;
|
||||
this.canMeow = true;
|
||||
this.meowBreakTime = 3000;
|
||||
};
|
||||
|
||||
Cat.prototype = {
|
||||
|
||||
startTouch: function() {
|
||||
print("START TOUCH")
|
||||
this.meow();
|
||||
}
|
||||
|
||||
meow: function() {
|
||||
|
||||
Audio.playSound(this.meowSound, {
|
||||
position: this.position,
|
||||
volume: .1
|
||||
});
|
||||
},
|
||||
// preload() will be called when the entity has become visible (or known) to the interface
|
||||
// it gives us a chance to set our local JavaScript object up. In this case it means:
|
||||
// * remembering our entityID, so we can access it in cases where we're called without an entityID
|
||||
// * connecting to the update signal so we can check our grabbed state
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
this.position = Entities.getEntityProperties(this.entityID, "position").position;
|
||||
Script.update.connect(this.update);
|
||||
},
|
||||
|
||||
unload: function() {
|
||||
Script.update.disconnect(this.update);
|
||||
}
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Cat();
|
||||
});
|
73
examples/toys/doll.js
Normal file
73
examples/toys/doll.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// doll.js
|
||||
// examples/toybox/entityScripts
|
||||
//
|
||||
// Created by Eric Levin on 9/21/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This entity script breathes movement and sound- one might even say life- into a doll.
|
||||
//
|
||||
// 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 _this;
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
|
||||
// this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember
|
||||
// our this object, so we can access it in cases where we're called without a this (like in the case of various global signals)
|
||||
Doll = function() {
|
||||
_this = this;
|
||||
var screamSoundDirectory = HIFI_PUBLIC_BUCKET + "eric/sounds/"
|
||||
this.screamSounds = [SoundCache.getSound("https://hifi-public.s3.amazonaws.com/sounds/KenDoll_1%2303.wav")];
|
||||
this.startAnimationSetting = JSON.stringify({
|
||||
running: true,
|
||||
startFrame: 0,
|
||||
lastFrame: 128
|
||||
});
|
||||
|
||||
this.stopAnimationSetting = JSON.stringify({
|
||||
running: false,
|
||||
});
|
||||
};
|
||||
|
||||
Doll.prototype = {
|
||||
|
||||
|
||||
startNearGrab: function() {
|
||||
Entities.editEntity(this.entityID, {
|
||||
animationURL: "https://hifi-public.s3.amazonaws.com/models/Bboys/zombie_scream.fbx",
|
||||
animationSettings: this.startAnimationSetting
|
||||
});
|
||||
|
||||
var position = Entities.getEntityProperties(this.entityID, "position").position;
|
||||
Audio.playSound(this.screamSounds[randInt(0, this.screamSounds.length)], {
|
||||
position: position,
|
||||
volume: 0.1
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
releaseGrab: function() {
|
||||
Entities.editEntity(this.entityID, {
|
||||
animationURL: "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx",
|
||||
// animationSettings: this.stopAnimationSetting,
|
||||
// animationFrameIndex: 0
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// preload() will be called when the entity has become visible (or known) to the interface
|
||||
// it gives us a chance to set our local JavaScript object up. In this case it means:
|
||||
// * remembering our entityID, so we can access it in cases where we're called without an entityID
|
||||
// * connecting to the update signal so we can check our grabbed state
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
},
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new Doll();
|
||||
})
|
212
examples/toys/lightSwitchGarage.js
Normal file
212
examples/toys/lightSwitchGarage.js
Normal file
|
@ -0,0 +1,212 @@
|
|||
//
|
||||
// detectGrabExample.js
|
||||
// examples/entityScripts
|
||||
//
|
||||
// Created by Eric Levin on 9/21/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example of an entity script which when assigned to an entity, will detect when the entity is being grabbed by the hydraGrab script
|
||||
//
|
||||
// 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 _this;
|
||||
|
||||
|
||||
// this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember
|
||||
// our this object, so we can access it in cases where we're called without a this (like in the case of various global signals)
|
||||
LightSwitchGarage = function() {
|
||||
_this = this;
|
||||
|
||||
this.lightStateKey = "lightStateKey";
|
||||
this.resetKey = "resetMe";
|
||||
|
||||
this.switchSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_2.wav");
|
||||
|
||||
};
|
||||
|
||||
LightSwitchGarage.prototype = {
|
||||
|
||||
clickReleaseOnEntity: function(entityID, mouseEvent) {
|
||||
if (!mouseEvent.isLeftButton) {
|
||||
return;
|
||||
}
|
||||
this.toggleLights();
|
||||
},
|
||||
|
||||
startNearTouch: function() {
|
||||
this.toggleLights();
|
||||
},
|
||||
|
||||
toggleLights: function() {
|
||||
var defaultLightData = {
|
||||
on: false
|
||||
};
|
||||
var lightState = getEntityCustomData(this.lightStateKey, this.entityID, defaultLightData);
|
||||
if (lightState.on === true) {
|
||||
this.clearLights();
|
||||
} else if (lightState.on === false) {
|
||||
this.createLights();
|
||||
}
|
||||
|
||||
this.flipLights();
|
||||
|
||||
Audio.playSound(this.switchSound, {
|
||||
volume: 0.5,
|
||||
position: this.position
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
clearLights: function() {
|
||||
var entities = Entities.findEntities(MyAvatar.position, 100);
|
||||
var self = this;
|
||||
entities.forEach(function(entity) {
|
||||
var resetData = getEntityCustomData(self.resetKey, entity, {})
|
||||
if (resetData.resetMe === true && resetData.lightType === "Sconce Light Garage") {
|
||||
Entities.deleteEntity(entity);
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.lightStateKey, this.entityID, {
|
||||
on: false
|
||||
});
|
||||
},
|
||||
|
||||
createLights: function() {
|
||||
|
||||
|
||||
var sconceLight3 = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: {
|
||||
x: 545.49468994140625,
|
||||
y: 496.24026489257812,
|
||||
z: 500.63516235351562
|
||||
},
|
||||
|
||||
name: "Sconce 3 Light",
|
||||
dimensions: {
|
||||
x: 2.545,
|
||||
y: 2.545,
|
||||
z: 2.545
|
||||
},
|
||||
cutoff: 90,
|
||||
color: {
|
||||
red: 217,
|
||||
green: 146,
|
||||
blue: 24
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.resetKey, sconceLight3, {
|
||||
resetMe: true,
|
||||
lightType: "Sconce Light Garage"
|
||||
});
|
||||
|
||||
var sconceLight4 = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: {
|
||||
x: 550.90399169921875,
|
||||
y: 496.24026489257812,
|
||||
z: 507.90237426757812
|
||||
},
|
||||
|
||||
name: "Sconce 4 Light",
|
||||
dimensions: {
|
||||
x: 2.545,
|
||||
y: 2.545,
|
||||
z: 2.545
|
||||
},
|
||||
cutoff: 90,
|
||||
color: {
|
||||
red: 217,
|
||||
green: 146,
|
||||
blue: 24
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.resetKey, sconceLight4, {
|
||||
resetMe: true,
|
||||
lightType: "Sconce Light Garage"
|
||||
});
|
||||
|
||||
var sconceLight5 = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: {
|
||||
x: 548.407958984375,
|
||||
y: 496.24026489257812,
|
||||
z: 509.5504150390625
|
||||
},
|
||||
name: "Sconce 5 Light",
|
||||
dimensions: {
|
||||
x: 2.545,
|
||||
y: 2.545,
|
||||
z: 2.545
|
||||
},
|
||||
cutoff: 90,
|
||||
color: {
|
||||
red: 217,
|
||||
green: 146,
|
||||
blue: 24
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.resetKey, sconceLight5, {
|
||||
resetMe: true,
|
||||
lightType: "Sconce Light Garage"
|
||||
});
|
||||
|
||||
|
||||
|
||||
setEntityCustomData(this.lightStateKey, this.entityID, {
|
||||
on: true
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
flipLights: function() {
|
||||
// flip model to give illusion of light switch being flicked
|
||||
var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation;
|
||||
var axis = {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 0
|
||||
};
|
||||
var dQ = Quat.angleAxis(180, axis);
|
||||
rotation = Quat.multiply(rotation, dQ);
|
||||
|
||||
|
||||
Entities.editEntity(this.entityID, {
|
||||
rotation: rotation
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
||||
// preload() will be called when the entity has become visible (or known) to the interface
|
||||
// it gives us a chance to set our local JavaScript object up. In this case it means:
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
|
||||
//The light switch is static, so just cache its position once
|
||||
this.position = Entities.getEntityProperties(this.entityID, "position").position;
|
||||
var defaultLightData = {
|
||||
on: false
|
||||
};
|
||||
var lightState = getEntityCustomData(this.lightStateKey, this.entityID, defaultLightData);
|
||||
|
||||
//If light is off, then we create two new lights- at the position of the sconces
|
||||
if (lightState.on === false) {
|
||||
this.createLights();
|
||||
this.flipLights();
|
||||
}
|
||||
//If lights are on, do nothing!
|
||||
},
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new LightSwitchGarage();
|
||||
})
|
181
examples/toys/lightSwitchHall.js
Normal file
181
examples/toys/lightSwitchHall.js
Normal file
|
@ -0,0 +1,181 @@
|
|||
//
|
||||
// detectGrabExample.js
|
||||
// examples/entityScripts
|
||||
//
|
||||
// Created by Eric Levin on 9/21/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This is an example of an entity script which when assigned to an entity, will detect when the entity is being grabbed by the hydraGrab script
|
||||
//
|
||||
// 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 _this;
|
||||
|
||||
|
||||
// this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember
|
||||
// our this object, so we can access it in cases where we're called without a this (like in the case of various global signals)
|
||||
LightSwitchHall = function() {
|
||||
_this = this;
|
||||
|
||||
this.lightStateKey = "lightStateKey";
|
||||
this.resetKey = "resetMe";
|
||||
|
||||
this.switchSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_2.wav");
|
||||
|
||||
};
|
||||
|
||||
LightSwitchHall.prototype = {
|
||||
|
||||
clickReleaseOnEntity: function(entityId, mouseEvent) {
|
||||
if (!mouseEvent.isLeftButton) {
|
||||
return;
|
||||
}
|
||||
this.toggleLights();
|
||||
},
|
||||
|
||||
startNearTouch: function() {
|
||||
this.toggleLights();
|
||||
},
|
||||
|
||||
toggleLights: function() {
|
||||
var defaultLightData = {
|
||||
on: false
|
||||
};
|
||||
var lightState = getEntityCustomData(this.lightStateKey, this.entityID, defaultLightData);
|
||||
if (lightState.on === true) {
|
||||
this.clearLights();
|
||||
} else if (lightState.on === false) {
|
||||
this.createLights();
|
||||
}
|
||||
|
||||
// flip model to give illusion of light switch being flicked
|
||||
this.flipLights();
|
||||
|
||||
Audio.playSound(this.switchSound, {
|
||||
volume: 0.5,
|
||||
position: this.position
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
clearLights: function() {
|
||||
var entities = Entities.findEntities(MyAvatar.position, 100);
|
||||
var self = this;
|
||||
entities.forEach(function(entity) {
|
||||
var resetData = getEntityCustomData(self.resetKey, entity, {})
|
||||
if (resetData.resetMe === true && resetData.lightType === "Sconce Light Hall") {
|
||||
Entities.deleteEntity(entity);
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.lightStateKey, this.entityID, {
|
||||
on: false
|
||||
});
|
||||
},
|
||||
|
||||
createLights: function() {
|
||||
var sconceLight1 = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: {
|
||||
x: 543.75,
|
||||
y: 496.24,
|
||||
z: 511.13
|
||||
},
|
||||
name: "Sconce 1 Light",
|
||||
dimensions: {
|
||||
x: 2.545,
|
||||
y: 2.545,
|
||||
z: 2.545
|
||||
},
|
||||
cutoff: 90,
|
||||
color: {
|
||||
red: 217,
|
||||
green: 146,
|
||||
blue: 24
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.resetKey, sconceLight1, {
|
||||
resetMe: true,
|
||||
lightType: "Sconce Light Hall"
|
||||
});
|
||||
|
||||
var sconceLight2 = Entities.addEntity({
|
||||
type: "Light",
|
||||
position: {
|
||||
x: 540.1,
|
||||
y: 496.24,
|
||||
z: 505.57
|
||||
},
|
||||
name: "Sconce 2 Light",
|
||||
dimensions: {
|
||||
x: 2.545,
|
||||
y: 2.545,
|
||||
z: 2.545
|
||||
},
|
||||
cutoff: 90,
|
||||
color: {
|
||||
red: 217,
|
||||
green: 146,
|
||||
blue: 24
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(this.resetKey, sconceLight2, {
|
||||
resetMe: true,
|
||||
lightType: "Sconce Light Hall"
|
||||
});
|
||||
|
||||
setEntityCustomData(this.lightStateKey, this.entityID, {
|
||||
on: true
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
flipLights: function() {
|
||||
// flip model to give illusion of light switch being flicked
|
||||
var rotation = Entities.getEntityProperties(this.entityID, "rotation").rotation;
|
||||
var axis = {
|
||||
x: 0,
|
||||
y: 1,
|
||||
z: 0
|
||||
};
|
||||
var dQ = Quat.angleAxis(180, axis);
|
||||
rotation = Quat.multiply(rotation, dQ);
|
||||
|
||||
|
||||
Entities.editEntity(this.entityID, {
|
||||
rotation: rotation
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
// preload() will be called when the entity has become visible (or known) to the interface
|
||||
// it gives us a chance to set our local JavaScript object up. In this case it means:
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
|
||||
//The light switch is static, so just cache its position once
|
||||
this.position = Entities.getEntityProperties(this.entityID, "position").position;
|
||||
var defaultLightData = {
|
||||
on: false
|
||||
};
|
||||
var lightState = getEntityCustomData(this.lightStateKey, this.entityID, defaultLightData);
|
||||
|
||||
//If light is off, then we create two new lights- at the position of the sconces
|
||||
if (lightState.on === false) {
|
||||
this.createLights();
|
||||
this.flipLights();
|
||||
|
||||
}
|
||||
//If lights are on, do nothing!
|
||||
},
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new LightSwitchHall();
|
||||
})
|
545
examples/toys/masterResetEntity.js
Normal file
545
examples/toys/masterResetEntity.js
Normal file
|
@ -0,0 +1,545 @@
|
|||
//
|
||||
// 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 deleteAllToys, 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, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */
|
||||
//per script
|
||||
/*global createAllToys, createBasketBall, createSprayCan, createDoll, createWand, createDice, createCat, deleteAllToys, createFlashlight, createBlocks, createMagballs, createLightSwitches */
|
||||
var utilitiesScript = Script.resolvePath("../libraries/utils.js");
|
||||
Script.include(utilitiesScript);
|
||||
|
||||
var resetKey = "resetMe";
|
||||
|
||||
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
||||
|
||||
var shouldDeleteOnEndScript = false;
|
||||
|
||||
|
||||
//Before creating anything, first search a radius and delete all the things that should be deleted
|
||||
deleteAllToys();
|
||||
createAllToys();
|
||||
|
||||
function createAllToys() {
|
||||
createBlocks({
|
||||
x: 548.3,
|
||||
y: 495.55,
|
||||
z: 504.4
|
||||
});
|
||||
|
||||
createSprayCan({
|
||||
x: 549.8,
|
||||
y: 495.6,
|
||||
z: 503.94
|
||||
});
|
||||
|
||||
createBasketBall({
|
||||
x: 547.73,
|
||||
y: 495.5,
|
||||
z: 505.47
|
||||
});
|
||||
|
||||
createDoll({
|
||||
x: 546.67,
|
||||
y: 495.41,
|
||||
z: 505.09
|
||||
});
|
||||
|
||||
createWand({
|
||||
x: 546.71,
|
||||
y: 495.55,
|
||||
z: 506.15
|
||||
});
|
||||
|
||||
createDice();
|
||||
|
||||
createFlashlight({
|
||||
x: 545.72,
|
||||
y: 495.41,
|
||||
z: 505.78
|
||||
});
|
||||
|
||||
createCat({
|
||||
x: 551.49859619140625,
|
||||
y: 495.49111938476562,
|
||||
z: 502.26498413085938
|
||||
});
|
||||
|
||||
createMagballs({
|
||||
x: 548.73,
|
||||
y: 495.51,
|
||||
z: 503.54
|
||||
});
|
||||
|
||||
//Handles toggling of all sconce lights
|
||||
createLightSwitches();
|
||||
}
|
||||
|
||||
function deleteAllToys() {
|
||||
var entities = Entities.findEntities(MyAvatar.position, 100);
|
||||
|
||||
entities.forEach(function (entity) {
|
||||
//params: customKey, id, defaultValue
|
||||
var shouldReset = getEntityCustomData(resetKey, entity, {}).resetMe;
|
||||
if (shouldReset === true) {
|
||||
Entities.deleteEntity(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createMagballs(position) {
|
||||
|
||||
|
||||
var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/tin2.fbx";
|
||||
var tinCan = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
name: "Tin Can",
|
||||
position: position,
|
||||
rotation: {
|
||||
w: 0.93041884899139404,
|
||||
x: -1.52587890625e-05,
|
||||
y: 0.36647593975067139,
|
||||
z: -1.52587890625e-05
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.16946873068809509,
|
||||
y: 0.21260403096675873,
|
||||
z: 0.16946862637996674
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
setEntityCustomData(resetKey, tinCan, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
setEntityCustomData("OmniTool", tinCan, {
|
||||
script: "../toys/magBalls.js"
|
||||
});
|
||||
}
|
||||
|
||||
function createCat(position) {
|
||||
var scriptURL = Script.resolvePath("cat.js?v1");
|
||||
var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/Dark_Cat.fbx";
|
||||
var animationURL = "http://hifi-public.s3.amazonaws.com/ryan/sleeping.fbx";
|
||||
var animationSettings = JSON.stringify({
|
||||
running: true,
|
||||
});
|
||||
var cat = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
name: "cat",
|
||||
script: scriptURL,
|
||||
animationURL: animationURL,
|
||||
animationSettings: animationSettings,
|
||||
position: position,
|
||||
rotation: {
|
||||
w: 0.35020983219146729,
|
||||
x: -4.57763671875e-05,
|
||||
y: 0.93664455413818359,
|
||||
z: -1.52587890625e-05
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.15723302960395813,
|
||||
y: 0.50762706995010376,
|
||||
z: 0.90716040134429932
|
||||
},
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, cat, {
|
||||
resetMe: true
|
||||
});
|
||||
}
|
||||
|
||||
function createFlashlight(position) {
|
||||
var scriptURL = Script.resolvePath('flashlight/flashlight.js');
|
||||
var modelURL = "https://hifi-public.s3.amazonaws.com/models/props/flashlight.fbx";
|
||||
|
||||
var flashlight = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
name: "flashlight",
|
||||
script: scriptURL,
|
||||
position: position,
|
||||
dimensions: {
|
||||
x: 0.08,
|
||||
y: 0.30,
|
||||
z: 0.08
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -3.5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
shapeType: 'box',
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, flashlight, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function createLightSwitches() {
|
||||
var modelURL = "http://hifi-public.s3.amazonaws.com/ryan/lightswitch.fbx?v1";
|
||||
var scriptURL = Script.resolvePath("lightSwitchHall.js?v1");
|
||||
|
||||
var lightSwitchHall = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
name: "Light Switch Hall",
|
||||
script: scriptURL,
|
||||
position: {
|
||||
x: 543.27764892578125,
|
||||
y: 495.67999267578125,
|
||||
z: 511.00564575195312
|
||||
},
|
||||
rotation: {
|
||||
w: 0.63280689716339111,
|
||||
x: 0.63280689716339111,
|
||||
y: -0.31551080942153931,
|
||||
z: 0.31548023223876953
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.10546875,
|
||||
y: 0.032372996211051941,
|
||||
z: 0.16242524981498718
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, lightSwitchHall, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
scriptURL = Script.resolvePath("lightSwitchGarage.js?v1");
|
||||
|
||||
var lightSwitchGarage = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
name: "Light Switch Garage",
|
||||
script: scriptURL,
|
||||
position: {
|
||||
x: 545.62,
|
||||
y: 495.68,
|
||||
z: 500.21
|
||||
},
|
||||
rotation: {
|
||||
w: 0.20082402229309082,
|
||||
x: 0.20082402229309082,
|
||||
y: -0.67800414562225342,
|
||||
z: 0.67797362804412842
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.10546875,
|
||||
y: 0.032372996211051941,
|
||||
z: 0.16242524981498718
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, lightSwitchGarage, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function createDice() {
|
||||
var diceProps = {
|
||||
type: "Model",
|
||||
modelURL: "http://s3.amazonaws.com/hifi-public/models/props/Dice/goldDie.fbx",
|
||||
collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav",
|
||||
name: "dice",
|
||||
position: {
|
||||
x: 541,
|
||||
y: 494.96,
|
||||
z: 509.1
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.09,
|
||||
y: 0.09,
|
||||
z: 0.09
|
||||
},
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -3.5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
shapeType: "box",
|
||||
collisionsWillMove: true
|
||||
};
|
||||
var dice1 = Entities.addEntity(diceProps);
|
||||
|
||||
diceProps.position = {
|
||||
x: 541.05,
|
||||
y: 494.96,
|
||||
z: 509.0
|
||||
};
|
||||
|
||||
var dice2 = Entities.addEntity(diceProps);
|
||||
|
||||
setEntityCustomData(resetKey, dice1, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, dice2, {
|
||||
resetMe: true
|
||||
});
|
||||
}
|
||||
|
||||
function createWand(position) {
|
||||
var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx';
|
||||
var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj';
|
||||
//Just using abs path for demo purposes on sunday, since this PR for wand has not been merged
|
||||
var scriptURL = Script.resolvePath("bubblewand/wand.js");
|
||||
|
||||
var entity = Entities.addEntity({
|
||||
name: 'Bubble Wand',
|
||||
type: "Model",
|
||||
modelURL: WAND_MODEL,
|
||||
position: position,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0,
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.05,
|
||||
y: 0.25,
|
||||
z: 0.05
|
||||
},
|
||||
//must be enabled to be grabbable in the physics engine
|
||||
collisionsWillMove: true,
|
||||
compoundShapeURL: WAND_COLLISION_SHAPE,
|
||||
//Look into why bubble wand is going through table when gravity is enabled
|
||||
// gravity: {x: 0, y: -3.5, z: 0},
|
||||
// velocity: {x: 0, y: -0.01, z:0},
|
||||
script: scriptURL
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, entity, {
|
||||
resetMe: true
|
||||
});
|
||||
}
|
||||
|
||||
function createBasketBall(position) {
|
||||
|
||||
var modelURL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx";
|
||||
|
||||
var entity = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
position: position,
|
||||
collisionsWillMove: true,
|
||||
shapeType: "sphere",
|
||||
name: "basketball",
|
||||
dimensions: {
|
||||
x: 0.25,
|
||||
y: 0.26,
|
||||
z: 0.25
|
||||
},
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -7,
|
||||
z: 0
|
||||
},
|
||||
restitution: 10,
|
||||
linearDamping: 0.0,
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
},
|
||||
collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/basketball/basketball.wav"
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, entity, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function createDoll(position) {
|
||||
var modelURL = "http://hifi-public.s3.amazonaws.com/models/Bboys/bboy2/bboy2.fbx";
|
||||
var scriptURL = Script.resolvePath("doll.js");
|
||||
|
||||
var naturalDimensions = {
|
||||
x: 1.63,
|
||||
y: 1.67,
|
||||
z: 0.26
|
||||
};
|
||||
var desiredDimensions = Vec3.multiply(naturalDimensions, 0.15);
|
||||
var entity = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "doll",
|
||||
modelURL: modelURL,
|
||||
script: scriptURL,
|
||||
position: position,
|
||||
shapeType: 'box',
|
||||
dimensions: desiredDimensions,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
collisionsWillMove: true
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, entity, {
|
||||
resetMe: true
|
||||
});
|
||||
}
|
||||
|
||||
function createSprayCan(position) {
|
||||
var scriptURL = Script.resolvePath("sprayPaintCan.js");
|
||||
var modelURL = "https://hifi-public.s3.amazonaws.com/eric/models/paintcan.fbx";
|
||||
|
||||
var entity = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "spraycan",
|
||||
modelURL: modelURL,
|
||||
position: position,
|
||||
rotation: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0,
|
||||
w: 1
|
||||
},
|
||||
dimensions: {
|
||||
x: 0.07,
|
||||
y: 0.17,
|
||||
z: 0.07
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
shapeType: 'box',
|
||||
script: scriptURL,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -0.5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -1,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
|
||||
setEntityCustomData(resetKey, entity, {
|
||||
resetMe: true
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function createBlocks(position) {
|
||||
var baseURL = HIFI_PUBLIC_BUCKET + "models/content/planky/";
|
||||
var NUM_BLOCKS_PER_COLOR = 4;
|
||||
var i, j;
|
||||
|
||||
var blockTypes = [{
|
||||
url: "planky_blue.fbx",
|
||||
dimensions: {
|
||||
x: 0.05,
|
||||
y: 0.05,
|
||||
z: 0.25
|
||||
}
|
||||
}, {
|
||||
url: "planky_green.fbx",
|
||||
dimensions: {
|
||||
x: 0.1,
|
||||
y: 0.1,
|
||||
z: 0.25
|
||||
}
|
||||
}, {
|
||||
url: "planky_natural.fbx",
|
||||
dimensions: {
|
||||
x: 0.05,
|
||||
y: 0.05,
|
||||
z: 0.05
|
||||
}
|
||||
}, {
|
||||
url: "planky_yellow.fbx",
|
||||
dimensions: {
|
||||
x: 0.03,
|
||||
y: 0.05,
|
||||
z: 0.25
|
||||
}
|
||||
}, {
|
||||
url: "planky_red.fbx",
|
||||
dimensions: {
|
||||
x: 0.1,
|
||||
y: 0.05,
|
||||
z: 0.25
|
||||
}
|
||||
}];
|
||||
|
||||
var modelURL, entity;
|
||||
for (i = 0; i < blockTypes.length; i++) {
|
||||
for (j = 0; j < NUM_BLOCKS_PER_COLOR; j++) {
|
||||
modelURL = baseURL + blockTypes[i].url;
|
||||
entity = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: modelURL,
|
||||
position: Vec3.sum(position, {
|
||||
x: j / 10,
|
||||
y: i / 10,
|
||||
z: 0
|
||||
}),
|
||||
shapeType: 'box',
|
||||
name: "block",
|
||||
dimensions: blockTypes[i].dimensions,
|
||||
collisionsWillMove: true,
|
||||
gravity: {
|
||||
x: 0,
|
||||
y: -2.5,
|
||||
z: 0
|
||||
},
|
||||
velocity: {
|
||||
x: 0,
|
||||
y: -0.01,
|
||||
z: 0
|
||||
}
|
||||
});
|
||||
|
||||
//customKey, id, data
|
||||
setEntityCustomData(resetKey, entity, {
|
||||
resetMe: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
deleteAllToys();
|
||||
}
|
||||
|
||||
if (shouldDeleteOnEndScript) {
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}
|
||||
|
||||
function randFloat(low, high) {
|
||||
return low + Math.random() * (high - low);
|
||||
}
|
||||
|
||||
function randInt(low, high) {
|
||||
return Math.floor(randFloat(low, high));
|
||||
}
|
|
@ -3,9 +3,10 @@
|
|||
//Need absolute path for now, for testing before PR merge and s3 cloning. Will change post-merge
|
||||
|
||||
Script.include("../libraries/utils.js");
|
||||
GRAB_FRAME_USER_DATA_KEY = "grabFrame";
|
||||
this.userData = {};
|
||||
|
||||
this.spraySound = SoundCache.getSound("https://s3.amazonaws.com/hifi-public/sounds/sprayPaintSound.wav");
|
||||
|
||||
var TIP_OFFSET_Z = 0.14;
|
||||
var TIP_OFFSET_Y = 0.04;
|
||||
|
||||
|
@ -19,59 +20,17 @@
|
|||
var MIN_POINT_DISTANCE = 0.01;
|
||||
var STROKE_WIDTH = 0.02;
|
||||
|
||||
var self = this;
|
||||
|
||||
var timeSinceLastMoved = 0;
|
||||
var RESET_TIME_THRESHOLD = 5;
|
||||
var DISTANCE_FROM_HOME_THRESHOLD = 0.5;
|
||||
var HOME_POSITION = {
|
||||
x: 549.12,
|
||||
y: 495.555,
|
||||
z: 503.77
|
||||
};
|
||||
this.getUserData = function() {
|
||||
|
||||
|
||||
if (this.properties.userData) {
|
||||
this.userData = JSON.parse(this.properties.userData);
|
||||
}
|
||||
this.setRightHand = function() {
|
||||
this.hand = 'RIGHT';
|
||||
}
|
||||
|
||||
this.updateUserData = function() {
|
||||
Entities.editEntity(this.entityId, {
|
||||
userData: JSON.stringify(this.userData)
|
||||
});
|
||||
this.setLeftHand = function() {
|
||||
this.hand = 'LEFT';
|
||||
}
|
||||
|
||||
this.update = function(deltaTime) {
|
||||
self.getUserData();
|
||||
self.properties = Entities.getEntityProperties(self.entityId);
|
||||
|
||||
if (Vec3.length(self.properties.velocity) < 0.1 && Vec3.distance(HOME_POSITION, self.properties.position) > DISTANCE_FROM_HOME_THRESHOLD) {
|
||||
timeSinceLastMoved += deltaTime;
|
||||
if (timeSinceLastMoved > RESET_TIME_THRESHOLD) {
|
||||
self.reset();
|
||||
timeSinceLastMoved = 0;
|
||||
}
|
||||
} else {
|
||||
timeSinceLastMoved = 0;
|
||||
}
|
||||
|
||||
//Only activate for the user who grabbed the object
|
||||
if (self.userData.grabKey && self.userData.grabKey.activated === true && self.userData.grabKey.avatarId == MyAvatar.sessionUUID) {
|
||||
if (self.activated !== true) {
|
||||
//We were just grabbed, so create a particle system
|
||||
self.grab();
|
||||
}
|
||||
//Move emitter to where entity is always when its activated
|
||||
self.sprayStream();
|
||||
} else if (self.userData.grabKey && self.userData.grabKey.activated === false && self.activated) {
|
||||
self.letGo();
|
||||
}
|
||||
}
|
||||
|
||||
this.grab = function() {
|
||||
this.activated = true;
|
||||
this.startNearGrab = function() {
|
||||
this.whichHand = this.hand;
|
||||
var position = Entities.getEntityProperties(this.entityId, "position").position;
|
||||
var animationSettings = JSON.stringify({
|
||||
fps: 30,
|
||||
loop: true,
|
||||
|
@ -83,7 +42,7 @@
|
|||
this.paintStream = Entities.addEntity({
|
||||
type: "ParticleEffect",
|
||||
animationSettings: animationSettings,
|
||||
position: this.properties.position,
|
||||
position: position,
|
||||
textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png",
|
||||
emitVelocity: ZERO_VEC,
|
||||
emitAcceleration: ZERO_VEC,
|
||||
|
@ -101,31 +60,31 @@
|
|||
},
|
||||
lifetime: 50, //probably wont be holding longer than this straight
|
||||
});
|
||||
}
|
||||
|
||||
this.letGo = function() {
|
||||
this.activated = false;
|
||||
Entities.deleteEntity(this.paintStream);
|
||||
this.paintStream = null;
|
||||
}
|
||||
|
||||
this.reset = function() {
|
||||
Entities.editEntity(self.entityId, {
|
||||
position: HOME_POSITION,
|
||||
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
||||
angularVelocity: ZERO_VEC,
|
||||
velocity: ZERO_VEC
|
||||
this.sprayInjector = Audio.playSound(this.spraySound, {
|
||||
position: position,
|
||||
volume: 0.1
|
||||
});
|
||||
}
|
||||
|
||||
this.sprayStream = function() {
|
||||
var forwardVec = Quat.getFront(Quat.multiply(self.properties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0)));
|
||||
|
||||
this.releaseGrab = function() {
|
||||
Entities.deleteEntity(this.paintStream);
|
||||
this.paintStream = null;
|
||||
this.painting = false;
|
||||
this.sprayInjector.stop();
|
||||
}
|
||||
|
||||
|
||||
this.continueNearGrab = function() {
|
||||
var props = Entities.getEntityProperties(this.entityId, ["position, rotation"]);
|
||||
var forwardVec = Quat.getFront(Quat.multiply(props.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)));
|
||||
forwardVec = Vec3.normalize(forwardVec);
|
||||
|
||||
var upVec = Quat.getUp(self.properties.rotation);
|
||||
var position = Vec3.sum(self.properties.position, Vec3.multiply(forwardVec, TIP_OFFSET_Z));
|
||||
var upVec = Quat.getUp(props.rotation);
|
||||
var position = Vec3.sum(props.position, Vec3.multiply(forwardVec, TIP_OFFSET_Z));
|
||||
position = Vec3.sum(position, Vec3.multiply(upVec, TIP_OFFSET_Y))
|
||||
Entities.editEntity(self.paintStream, {
|
||||
Entities.editEntity(this.paintStream, {
|
||||
position: position,
|
||||
emitVelocity: Vec3.multiply(5, forwardVec)
|
||||
});
|
||||
|
@ -143,8 +102,6 @@
|
|||
var normal = Vec3.multiply(-1, Quat.getFront(intersection.properties.rotation));
|
||||
this.paint(intersection.intersection, normal);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
this.paint = function(position, normal) {
|
||||
|
@ -206,39 +163,18 @@
|
|||
|
||||
this.preload = function(entityId) {
|
||||
this.strokes = [];
|
||||
this.activated = false;
|
||||
this.entityId = entityId;
|
||||
this.properties = Entities.getEntityProperties(self.entityId);
|
||||
this.getUserData();
|
||||
|
||||
//Only activate for the avatar who is grabbing the can!
|
||||
if (this.userData.grabKey && this.userData.grabKey.activated) {
|
||||
this.activated = true;
|
||||
}
|
||||
if (!this.userData.grabFrame) {
|
||||
var data = {
|
||||
relativePosition: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
relativeRotation: Quat.fromPitchYawRollDegrees(0, 0, 0)
|
||||
}
|
||||
setEntityCustomData(GRAB_FRAME_USER_DATA_KEY, this.entityId, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.unload = function() {
|
||||
Script.update.disconnect(this.update);
|
||||
if(this.paintStream) {
|
||||
if (this.paintStream) {
|
||||
Entities.deleteEntity(this.paintStream);
|
||||
}
|
||||
this.strokes.forEach(function(stroke) {
|
||||
Entities.deleteEntity(stroke);
|
||||
});
|
||||
}
|
||||
Script.update.connect(this.update);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in a new issue