mirror of
https://github.com/overte-org/overte.git
synced 2025-04-18 07:56:25 +02:00
Added cart, cash, inspect and readme
This commit is contained in:
parent
40279c8fc5
commit
e4501e3a8f
9 changed files with 1741 additions and 0 deletions
51
examples/vrShop/README.txt
Normal file
51
examples/vrShop/README.txt
Normal file
|
@ -0,0 +1,51 @@
|
|||
Instructions for experiencing vrShop
|
||||
Alessandro Signa and Edgar Pironti, 13 Jan 2016
|
||||
|
||||
To avoid weird issues we suggest to run this build https://github.com/highfidelity/hifi/pull/6786
|
||||
To test the experience in the current release of interface that PR needs to be merged
|
||||
and the scripts need to be updated to the new collisionMask system.
|
||||
|
||||
Go to the vrShop domain.
|
||||
|
||||
When you get closer to the shop (entering the Zone - GrabSwapper) you should notice that
|
||||
shopItemGrab is in your running scripts. At this point the handControllerGrab should be disabled
|
||||
(it will be re-enabled automatically when leaving the zone), but if you still see rays
|
||||
coming out from your hands when you squeeze the triggers something went wrong so you probably
|
||||
want to remove manually handControllerGrab
|
||||
|
||||
Once you're here you can do two different experiences: buyer and reviewr.
|
||||
Both of them are designed to be done entirely using HMD and hand controllers,
|
||||
so please put your Oculus on and equip your hydra.
|
||||
|
||||
BUYER
|
||||
First of all you have to pass through the pick cart line, the Zone - CartSpawner is there.
|
||||
Now you see a cart following you (look at your right).
|
||||
Reach the shelf and grab an item (you can only near grab here).
|
||||
An inspection area should now stay in front of you, drop the item inside it to inspect. Be sure
|
||||
to see the overlay turning green before releasing the item.
|
||||
|
||||
In inspect mode you can't move or rotate your avatar but you can scale and rotate the item.
|
||||
Interact with the UI buttons using your bumpers: you can change the color of the item,
|
||||
see the reviews (looking at the review cabin) and you can also try some of the items on (but
|
||||
this feature at the moment works well only with the Will avatar increasing its default size once).
|
||||
|
||||
If you are good with your item you can put it in the cart, otherwise just drop it around.
|
||||
You can also pick again an item from your cart to inspect it or to discard it.
|
||||
To empty the cart you can push the right primary button.
|
||||
|
||||
Then you can go to the cashier for the "payment": once you enter the Zone - CashDesk
|
||||
a credit card will appear above the register and a bot will give you some informations.
|
||||
Just drag that card to the register to confirm the purchase.
|
||||
|
||||
When you're ready to exit pass again through the leave cart line.
|
||||
|
||||
REVIEWER
|
||||
Go and grab the item you want to review, this time don't pick the cart.
|
||||
Enter into the review cabin holding the item in your hand , if all goes right the item should disappear
|
||||
and a UI appears allowing you to rate the item.
|
||||
Now you can follow the instrucions to record a review: both the voice and the animation of your avatar
|
||||
will be recorded and stored into the DB of that item.
|
||||
|
||||
|
||||
|
||||
|
324
examples/vrShop/cart/shopCartEntityScript.js
Normal file
324
examples/vrShop/cart/shopCartEntityScript.js
Normal file
|
@ -0,0 +1,324 @@
|
|||
// shopCartEntityScript.js
|
||||
//
|
||||
// This script makes the cart follow the avatar who picks it and manage interations with items (store and delete them) and with cash register (send the item prices)
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
|
||||
(function() {
|
||||
var utilitiesScript = Script.resolvePath("../../libraries/utils.js");
|
||||
var overlayManagerScript = Script.resolvePath("../../libraries/overlayManager.js");
|
||||
Script.include(utilitiesScript);
|
||||
Script.include(overlayManagerScript);
|
||||
|
||||
var COMFORT_ARM_LENGTH = 0.5;
|
||||
var CART_REGISTER_CHANNEL = "Hifi-vrShop-Register";
|
||||
var PENETRATION_THRESHOLD = 0.2;
|
||||
|
||||
var _this;
|
||||
var cartIsMine = false;
|
||||
var originalY = 0;
|
||||
var itemsID = [];
|
||||
var scaleFactor = 0.7; //TODO: The scale factor will dipend on the number of items in the cart. We would resize even the items already present.
|
||||
var cartTargetPosition;
|
||||
var singlePrices = [];
|
||||
var singlePriceTagsAreShowing = false;
|
||||
var collidedItemID = null;
|
||||
|
||||
// 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)
|
||||
ShopCart = function() {
|
||||
_this = this;
|
||||
};
|
||||
|
||||
function update(deltaTime) {
|
||||
_this.followAvatar();
|
||||
|
||||
if (Controller.getValue(Controller.Standard.RightPrimaryThumb)) {
|
||||
_this.resetCart();
|
||||
_this.computeAndSendTotalPrice();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function receivingMessage(channel, message, senderID) {
|
||||
if (senderID === MyAvatar.sessionUUID && channel == CART_REGISTER_CHANNEL) {
|
||||
var messageObj = JSON.parse(message);
|
||||
if (messageObj.senderEntity != _this.entityID) {
|
||||
print("--------------- cart received message");
|
||||
//Receiving this message means that the register wants the total price
|
||||
_this.computeAndSendTotalPrice();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ShopCart.prototype = {
|
||||
|
||||
// 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;
|
||||
//get the owner ID from user data and compare to the mine
|
||||
//so the update will be connected just for the owner
|
||||
var ownerObj = getEntityCustomData('ownerKey', this.entityID, null);
|
||||
if (ownerObj.ownerID === MyAvatar.sessionUUID) {
|
||||
cartIsMine = true;
|
||||
cartTargetPosition = Entities.getEntityProperties(_this.entityID).position; //useful if the entity script is assigned manually
|
||||
Script.update.connect(update);
|
||||
Messages.subscribe(CART_REGISTER_CHANNEL);
|
||||
Messages.messageReceived.connect(receivingMessage);
|
||||
}
|
||||
},
|
||||
|
||||
//update cart's target position. It will be at the right of the avatar as long as he moves
|
||||
followAvatar: function() {
|
||||
if (Vec3.length(MyAvatar.getVelocity()) > 0.1) {
|
||||
var radius = (Entities.getEntityProperties(_this.entityID).dimensions.x) / 2 + COMFORT_ARM_LENGTH;
|
||||
var properY = MyAvatar.position.y + ((MyAvatar.getHeadPosition().y - MyAvatar.position.y) / 2);
|
||||
var targetPositionPrecomputing = {x: MyAvatar.position.x, y: properY, z: MyAvatar.position.z};
|
||||
cartTargetPosition = Vec3.sum(targetPositionPrecomputing, Vec3.multiply(Quat.getRight(MyAvatar.orientation), radius));
|
||||
}
|
||||
|
||||
var cartPosition = Entities.getEntityProperties(_this.entityID).position;
|
||||
var positionDifference = Vec3.subtract(cartTargetPosition, cartPosition);
|
||||
if (Vec3.length(positionDifference) > 0.1) {
|
||||
//give to the cart the proper velocity and make it ignore for collision
|
||||
Entities.editEntity(_this.entityID, { velocity: positionDifference });
|
||||
Entities.editEntity(_this.entityID, { ignoreForCollisions: true });
|
||||
if (collidedItemID != null) {
|
||||
Entities.callEntityMethod(collidedItemID, 'setCartOverlayNotVisible', null);
|
||||
collidedItemID = null;
|
||||
}
|
||||
} else if (Vec3.length(positionDifference) > 0.01) {
|
||||
//give to the cart the proper velocity and make it NOT ignore for collision
|
||||
Entities.editEntity(_this.entityID, { velocity: positionDifference });
|
||||
Entities.editEntity(_this.entityID, { ignoreForCollisions: false });
|
||||
} else if (Vec3.length(positionDifference) > 0) {
|
||||
//set the position to be at the right of MyAvatar and make it NOT ignore for collision
|
||||
Entities.editEntity(_this.entityID, { position: cartTargetPosition });
|
||||
positionDifference = Vec3.subtract(cartTargetPosition, cartPosition);
|
||||
Entities.editEntity(_this.entityID, { velocity: positionDifference });
|
||||
Entities.editEntity(_this.entityID, { ignoreForCollisions: false });
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// delete all items stored into the cart
|
||||
resetCart: function () {
|
||||
|
||||
//print("RESET CART - USER DATA: " + Entities.getEntityProperties(_this.entityID).userData);
|
||||
if (itemsID.length != 0) {
|
||||
if (singlePriceTagsAreShowing) {
|
||||
_this.singlePriceOff();
|
||||
}
|
||||
for (var i=0; i < itemsID.length; i++) {
|
||||
Entities.deleteEntity(itemsID[i]);
|
||||
}
|
||||
|
||||
// Clear the userData field for the cart
|
||||
Entities.editEntity(this.entityID, { userData: ""});
|
||||
|
||||
setEntityCustomData('ownerKey', this.entityID, {
|
||||
ownerID: MyAvatar.sessionUUID
|
||||
});
|
||||
|
||||
setEntityCustomData('grabbableKey', this.entityID, {
|
||||
grabbable: false
|
||||
});
|
||||
|
||||
itemsID = [];
|
||||
}
|
||||
},
|
||||
|
||||
//delete the item pointed by dataArray (data.id) from the cart because it's been grabbed from there
|
||||
refreshCartContent: function (entityID, dataArray) {
|
||||
var data = JSON.parse(dataArray[0]);
|
||||
|
||||
for (var i=0; i < itemsID.length; i++) {
|
||||
if(itemsID[i] == data.id) {
|
||||
itemsID.splice(i, 1);
|
||||
//if the price tags are showing we have to remove also the proper tag
|
||||
if (singlePriceTagsAreShowing) {
|
||||
singlePrices[i].destroy();
|
||||
singlePrices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_this.computeAndSendTotalPrice();
|
||||
},
|
||||
|
||||
//show the prices on each item into the cart
|
||||
singlePriceOn: function () {
|
||||
//create an array of text3D which follows the structure of the itemsID array. Each text3D is like the 'Store the item!' one
|
||||
var i = 0;
|
||||
itemsID.forEach( function(itemID) {
|
||||
singlePrices[i] = new OverlayPanel({
|
||||
anchorPositionBinding: { entity: itemID },
|
||||
offsetPosition: { x: 0, y: 0.15, z: 0 },
|
||||
isFacingAvatar: true,
|
||||
|
||||
});
|
||||
|
||||
var textPrice = new Text3DOverlay({
|
||||
text: "" + getEntityCustomData('infoKey', itemID, null).price + " $",
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.02,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3,
|
||||
visible: true
|
||||
});
|
||||
|
||||
singlePrices[i].addChild(textPrice);
|
||||
i++;
|
||||
});
|
||||
|
||||
singlePriceTagsAreShowing = true;
|
||||
},
|
||||
|
||||
singlePriceOff: function () {
|
||||
//destroy or make invisible the text3D, or both
|
||||
singlePrices.forEach(function(panel) {
|
||||
panel.destroy();
|
||||
});
|
||||
singlePrices = [];
|
||||
singlePriceTagsAreShowing = false;
|
||||
},
|
||||
|
||||
//Send to the register the total price for all the items in the cart
|
||||
computeAndSendTotalPrice: function () {
|
||||
var totalPrice = 0;
|
||||
itemsID.forEach( function(itemID) {
|
||||
var infoObj = getEntityCustomData('infoKey', itemID, null);
|
||||
if(infoObj != null) {
|
||||
totalPrice += infoObj.price;
|
||||
}
|
||||
});
|
||||
|
||||
var messageObj = {senderEntity: _this.entityID, totalPrice: totalPrice};
|
||||
Messages.sendMessage(CART_REGISTER_CHANNEL, JSON.stringify(messageObj));
|
||||
},
|
||||
|
||||
//dataArray stores the ID of the item which has to be stored into the cart
|
||||
//this entity method is invoked by shopItemEntityScript.js
|
||||
doSomething: function (entityID, dataArray) {
|
||||
collidedItemID = null;
|
||||
var data = JSON.parse(dataArray[0]);
|
||||
var itemOwnerObj = getEntityCustomData('ownerKey', data.id, null);
|
||||
|
||||
var cartOwnerObj = getEntityCustomData('ownerKey', this.entityID, null);
|
||||
|
||||
if (cartOwnerObj == null) {
|
||||
//print("The cart doesn't have a owner.");
|
||||
Entities.deleteEntity(data.id);
|
||||
}
|
||||
|
||||
if (itemOwnerObj.ownerID === cartOwnerObj.ownerID) {
|
||||
// TODO if itemsQuantity == fullCart resize all the items present in the cart and change the scaleFactor for this and next insert
|
||||
|
||||
print("Going to put item in the cart!");
|
||||
var itemsQuantity = itemsID.length;
|
||||
|
||||
itemsID[itemsQuantity] = data.id;
|
||||
|
||||
var oldDimension = Entities.getEntityProperties(data.id).dimensions;
|
||||
Entities.editEntity(data.id, { dimensions: Vec3.multiply(oldDimension, scaleFactor) });
|
||||
Entities.editEntity(data.id, { velocity: {x: 0.0, y: 0.0, z: 0.0} });
|
||||
// parent item to the cart
|
||||
Entities.editEntity(data.id, { parentID: this.entityID });
|
||||
|
||||
itemsQuantity = itemsID.length;
|
||||
|
||||
setEntityCustomData('statusKey', data.id, {
|
||||
status: "inCart"
|
||||
});
|
||||
|
||||
_this.computeAndSendTotalPrice();
|
||||
|
||||
//if the single price tags are showing we have to put a tag also in the new item
|
||||
if (singlePriceTagsAreShowing) {
|
||||
singlePrices[itemsQuantity-1] = new OverlayPanel({
|
||||
anchorPositionBinding: { entity: data.id },
|
||||
offsetPosition: { x: 0, y: 0.15, z: 0 },
|
||||
isFacingAvatar: true,
|
||||
|
||||
});
|
||||
|
||||
var textPrice = new Text3DOverlay({
|
||||
text: "" + getEntityCustomData('infoKey', data.id, null).price + " $",
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.02,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3,
|
||||
visible: true
|
||||
});
|
||||
|
||||
singlePrices[itemsQuantity-1].addChild(textPrice);
|
||||
}
|
||||
} else {
|
||||
print("Not your cart!");
|
||||
Entities.deleteEntity(data.id);
|
||||
}
|
||||
},
|
||||
|
||||
//detect when the item enters or leave the cart while it's grabbed
|
||||
collisionWithEntity: function(myID, otherID, collisionInfo) {
|
||||
var penetrationValue = Vec3.length(collisionInfo.penetration);
|
||||
|
||||
var cartOwnerObj = getEntityCustomData('ownerKey', myID, null);
|
||||
var itemOwnerObj = getEntityCustomData('ownerKey', otherID, null);
|
||||
|
||||
if (penetrationValue > PENETRATION_THRESHOLD && collidedItemID === null) {
|
||||
if (itemOwnerObj != null && itemOwnerObj.ownerID === cartOwnerObj.ownerID) {
|
||||
Entities.callEntityMethod(otherID, 'setCartOverlayVisible', null);
|
||||
collidedItemID = otherID;
|
||||
}
|
||||
} else if (penetrationValue < PENETRATION_THRESHOLD && collidedItemID !== null) {
|
||||
if (itemOwnerObj != null && itemOwnerObj.ownerID === cartOwnerObj.ownerID) {
|
||||
Entities.callEntityMethod(otherID, 'setCartOverlayNotVisible', null);
|
||||
collidedItemID = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
print("UNLOAD CART");
|
||||
if(cartIsMine){
|
||||
Script.update.disconnect(update);
|
||||
_this.resetCart(); //useful if the script is reloaded manually
|
||||
//Entities.deleteEntity(_this.entityID); //comment for manual reload
|
||||
Messages.unsubscribe(CART_REGISTER_CHANNEL);
|
||||
Messages.messageReceived.disconnect(receivingMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new ShopCart();
|
||||
})
|
91
examples/vrShop/cart/shopCartSpawnEntityScript.js
Normal file
91
examples/vrShop/cart/shopCartSpawnEntityScript.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
// shopCartSpawnEntityScript.js
|
||||
//
|
||||
// If an avatar doesn't own a cart and enters the zone, a cart is added.
|
||||
// Otherwise if it already has a cart, this will be destroyed
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
|
||||
(function () {
|
||||
var CART_MASTER_NAME = "ShopCartZero";
|
||||
var CART_SCRIPT_URL = Script.resolvePath("shopCartEntityScript.js");
|
||||
var SHOP_GRAB_SCRIPT_URL = Script.resolvePath("../item/shopItemGrab.js");
|
||||
var _this;
|
||||
var isOwningACart = false;
|
||||
var cartMasterID = null;
|
||||
var myCartID = null;
|
||||
|
||||
|
||||
function SpawnCartZone() {
|
||||
_this = this;
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
|
||||
SpawnCartZone.prototype = {
|
||||
|
||||
preload: function (entityID) {
|
||||
this.entityID = entityID;
|
||||
// Look for the ShopCartZero. Every cart created by this script is a copy of it
|
||||
var ids = Entities.findEntities(Entities.getEntityProperties(this.entityID).position, 50);
|
||||
ids.forEach(function(id) {
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
if (properties.name == CART_MASTER_NAME) {
|
||||
cartMasterID = id;
|
||||
print("Master Cart found");
|
||||
Entities.editEntity(_this.entityID, { collisionMask: "static,dynamic,otherAvatar" });
|
||||
|
||||
return;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
enterEntity: function (entityID) {
|
||||
print("entering in the spawn cart area");
|
||||
|
||||
if (myCartID) {
|
||||
Entities.callEntityMethod(myCartID, "resetCart");
|
||||
Entities.deleteEntity (myCartID);
|
||||
myCartID = null;
|
||||
} else {
|
||||
var entityProperties = Entities.getEntityProperties(cartMasterID);
|
||||
myCartID = Entities.addEntity({
|
||||
type: entityProperties.type,
|
||||
name: "Shopping cart",
|
||||
ignoreForCollisions: false,
|
||||
collisionsWillMove: false,
|
||||
position: entityProperties.position,
|
||||
dimensions: entityProperties.dimensions,
|
||||
modelURL: entityProperties.modelURL,
|
||||
shapeType: entityProperties.shapeType,
|
||||
originalTextures: entityProperties.originalTextures,
|
||||
script: CART_SCRIPT_URL,
|
||||
userData: JSON.stringify({
|
||||
ownerKey: {
|
||||
ownerID: MyAvatar.sessionUUID
|
||||
},
|
||||
grabbableKey: {
|
||||
grabbable: false
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
leaveEntity: function (entityID) {
|
||||
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return new SpawnCartZone();
|
||||
});
|
39
examples/vrShop/cart/shopCartZeroEntityScript.js
Normal file
39
examples/vrShop/cart/shopCartZeroEntityScript.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
// shopCartZeroEntityScript.js
|
||||
//
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
|
||||
(function() {
|
||||
BALL_ANGULAR_VELOCITY = {x:0, y:5, z:0}
|
||||
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)
|
||||
ShopCartZero = function() {
|
||||
_this = this;
|
||||
};
|
||||
|
||||
|
||||
ShopCartZero.prototype = {
|
||||
|
||||
// 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;
|
||||
Entities.editEntity(_this.entityID, { angularVelocity: BALL_ANGULAR_VELOCITY });
|
||||
Entities.editEntity(_this.entityID, { angularDamping: 0 });
|
||||
},
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new ShopCartZero();
|
||||
})
|
94
examples/vrShop/cash/shopCashEntityScript.js
Normal file
94
examples/vrShop/cash/shopCashEntityScript.js
Normal file
|
@ -0,0 +1,94 @@
|
|||
// shopCashEntityScript.js
|
||||
//
|
||||
// When an avatar enters the zone the cashier bot (agent) is activated and the cash register as well.
|
||||
// A credit card model will be added to the scene for make the payment
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
|
||||
(function () {
|
||||
var AGENT_PLAYBACK_CHANNEL = "playbackChannel";
|
||||
var PLAY_MESSAGE = "Play";
|
||||
var REGISTER_NAME = "CashRegister";
|
||||
var CARD_ANGULAR_VELOCITY = {x: 0, y: 2, z: 0};
|
||||
var CARD_POSITION_OFFSET = {x: 0, y: 0.5, z: 0};
|
||||
var CARD_INITIAL_ORIENTATION = {x: 0, y: 0, z: 40};
|
||||
var CARD_DIMENSIONS = {x: 0.02, y: 0.09, z: 0.15};
|
||||
var SCRIPT_URL = Script.resolvePath("shopCreditCardEntityScript.js");
|
||||
|
||||
var _this;
|
||||
var cashRegisterID = null;
|
||||
var cardID = null;
|
||||
|
||||
|
||||
function CashZone() {
|
||||
_this = this;
|
||||
return;
|
||||
};
|
||||
|
||||
CashZone.prototype = {
|
||||
|
||||
preload: function (entityID) {
|
||||
},
|
||||
|
||||
enterEntity: function (entityID) {
|
||||
print("entering in the cash area");
|
||||
Messages.sendMessage(AGENT_PLAYBACK_CHANNEL, PLAY_MESSAGE);
|
||||
print("Play sent.");
|
||||
|
||||
// Look for the register
|
||||
var entitiesInZone = Entities.findEntities(Entities.getEntityProperties(entityID).position, (Entities.getEntityProperties(entityID).dimensions.x)/2);
|
||||
entitiesInZone.forEach( function(e) {
|
||||
if (Entities.getEntityProperties(e).name == REGISTER_NAME) {
|
||||
cashRegisterID = Entities.getEntityProperties(e).id;
|
||||
print(cashRegisterID);
|
||||
}
|
||||
});
|
||||
|
||||
// create a credit card above register position
|
||||
var cardPosition = Vec3.sum(Entities.getEntityProperties(cashRegisterID).position, CARD_POSITION_OFFSET);
|
||||
var cardOrientationQuat = Quat.fromVec3Degrees(CARD_INITIAL_ORIENTATION);
|
||||
|
||||
cardID = Entities.addEntity({
|
||||
type: "Model",
|
||||
name: "CreditCard",
|
||||
position: cardPosition,
|
||||
rotation: cardOrientationQuat,
|
||||
dimensions: CARD_DIMENSIONS,
|
||||
collisionsWillMove: false,
|
||||
ignoreForCollisions: false,
|
||||
angularVelocity: CARD_ANGULAR_VELOCITY,
|
||||
angularDamping: 0,
|
||||
script: Script.resolvePath(SCRIPT_URL),
|
||||
// We have to put the ownerID in the card, and check this property when grabbing the card. Otherwise it cannot be grabbed - I can only grab my card
|
||||
userData: JSON.stringify({
|
||||
ownerKey: {
|
||||
ownerID: MyAvatar.sessionUUID
|
||||
}
|
||||
}),
|
||||
modelURL: "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/CreditCard.fbx",
|
||||
shapeType: "box"
|
||||
});
|
||||
|
||||
Entities.callEntityMethod(cashRegisterID, 'cashRegisterOn', null);
|
||||
},
|
||||
|
||||
leaveEntity: function (entityID) {
|
||||
// destroy card
|
||||
Entities.deleteEntity(cardID);
|
||||
cardID = null;
|
||||
|
||||
Entities.callEntityMethod(cashRegisterID, 'cashRegisterOff', null);
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
}
|
||||
}
|
||||
|
||||
return new CashZone();
|
||||
});
|
166
examples/vrShop/cash/shopCashRegisterEntityScript.js
Normal file
166
examples/vrShop/cash/shopCashRegisterEntityScript.js
Normal file
|
@ -0,0 +1,166 @@
|
|||
// shopCashRegisterEntityScript.js
|
||||
//
|
||||
// The register manages the total price overlay and the payment through collision with credit card
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
(function () {
|
||||
var overlayManagerScript = Script.resolvePath("../../libraries/overlayManager.js");
|
||||
Script.include(overlayManagerScript);
|
||||
|
||||
var SHOPPING_CART_NAME = "Shopping cart";
|
||||
var CART_REGISTER_CHANNEL = "Hifi-vrShop-Register";
|
||||
var CREDIT_CARD_NAME = "CreditCard";
|
||||
|
||||
var _this;
|
||||
var cartID = null;
|
||||
var registerPanel = null;
|
||||
var priceText = null;
|
||||
var payingAvatarID = null;
|
||||
var totalPrice = 0;
|
||||
|
||||
function CashRegister() {
|
||||
_this = this;
|
||||
return;
|
||||
};
|
||||
|
||||
function receivingMessage(channel, message, senderID) {
|
||||
if (senderID === MyAvatar.sessionUUID && channel == CART_REGISTER_CHANNEL) {
|
||||
var messageObj = JSON.parse(message);
|
||||
if (messageObj.senderEntity != _this.entityID) {
|
||||
//This message means that the cart sent the total price: create or update the Overlay on the register
|
||||
var price = messageObj.totalPrice.toFixed(2);
|
||||
_this.cashRegisterOverlayOn("" + price + " $");
|
||||
totalPrice = messageObj.totalPrice;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CashRegister.prototype = {
|
||||
|
||||
preload: function (entityID) {
|
||||
this.entityID = entityID;
|
||||
},
|
||||
|
||||
//This method is called by the cashZone when an avatar comes in it
|
||||
//It has to find the cart belonging to that avatar and ask it the total price of the items
|
||||
cashRegisterOn: function() {
|
||||
print("cashRegister ON");
|
||||
Messages.subscribe(CART_REGISTER_CHANNEL);
|
||||
Messages.messageReceived.connect(receivingMessage);
|
||||
var cashRegisterPosition = Entities.getEntityProperties(_this.entityID).position;
|
||||
var foundEntities = Entities.findEntities(cashRegisterPosition, 50);
|
||||
foundEntities.forEach( function (foundEntityID) {
|
||||
var entityName = Entities.getEntityProperties(foundEntityID).name;
|
||||
if (entityName == SHOPPING_CART_NAME) {
|
||||
var cartOwnerID = getEntityCustomData('ownerKey', foundEntityID, null).ownerID;
|
||||
if (cartOwnerID == MyAvatar.sessionUUID) {
|
||||
cartID = foundEntityID;
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
if (cartID != null) {
|
||||
payingAvatarID = MyAvatar.sessionUUID;
|
||||
Messages.sendMessage(CART_REGISTER_CHANNEL, JSON.stringify({senderEntity: _this.entityID})); //with this message the cart know that it has to compute and send back the total price of the items
|
||||
Entities.callEntityMethod(cartID, 'singlePriceOn', null);
|
||||
//sometimes the cart is unable to receive the message. I think it's a message mixer problem
|
||||
} else {
|
||||
payingAvatarID = null;
|
||||
// Show anyway the overlay with the price 0$
|
||||
_this.cashRegisterOverlayOn("0 $");
|
||||
}
|
||||
},
|
||||
|
||||
cashRegisterOff: function() {
|
||||
print("cashRegister OFF");
|
||||
Messages.unsubscribe(CART_REGISTER_CHANNEL);
|
||||
Messages.messageReceived.disconnect(receivingMessage);
|
||||
priceText.visible = false;
|
||||
if (cartID != null) {
|
||||
Entities.callEntityMethod(cartID, 'singlePriceOff', null);
|
||||
}
|
||||
},
|
||||
|
||||
cashRegisterOverlayOn: function (string) {
|
||||
print("cashRegister OVERLAY ON");
|
||||
var stringOffset = string.length * 0.018;
|
||||
if (priceText == null) {
|
||||
|
||||
registerPanel = new OverlayPanel({
|
||||
anchorPositionBinding: { entity: _this.entityID },
|
||||
offsetPosition: { x: 0, y: 0.21, z: -0.14 },
|
||||
isFacingAvatar: false,
|
||||
|
||||
});
|
||||
|
||||
priceText = new Text3DOverlay({
|
||||
text: string,
|
||||
isFacingAvatar: false,
|
||||
ignoreRayIntersection: true,
|
||||
dimensions: { x: 0, y: 0 },
|
||||
offsetPosition: {
|
||||
x: -stringOffset,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 255, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.06,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3,
|
||||
visible: true
|
||||
});
|
||||
|
||||
registerPanel.addChild(priceText);
|
||||
} else {
|
||||
priceText.text = string;
|
||||
priceText.visible = true;
|
||||
priceText.offsetPosition = {
|
||||
x: -stringOffset,
|
||||
y: 0,
|
||||
z: 0
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
//Manage the collision with credit card
|
||||
collisionWithEntity: function (myID, otherID, collisionInfo) {
|
||||
var entityName = Entities.getEntityProperties(otherID).name;
|
||||
var entityOwnerID = getEntityCustomData('ownerKey', otherID, null).ownerID;
|
||||
if (entityName == CREDIT_CARD_NAME && entityOwnerID == payingAvatarID) {
|
||||
//The register collided with the right credit card - CHECKOUT
|
||||
Entities.deleteEntity(otherID);
|
||||
Entities.callEntityMethod(cartID, 'resetCart', null);
|
||||
_this.cashRegisterOverlayOn("THANK YOU!");
|
||||
_this.clean();
|
||||
}
|
||||
},
|
||||
|
||||
//clean all the variable related to the cart
|
||||
clean: function () {
|
||||
cartID = null;
|
||||
payingAvatarID = null;
|
||||
totalPrice = 0;
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
_this.clean();
|
||||
if (registerPanel != null) {
|
||||
registerPanel.destroy();
|
||||
}
|
||||
registerPanel = priceText = null;
|
||||
}
|
||||
}
|
||||
|
||||
return new CashRegister();
|
||||
});
|
73
examples/vrShop/cash/shopCashierAC.js
Normal file
73
examples/vrShop/cash/shopCashierAC.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
// shopCashierAC.js
|
||||
//
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
|
||||
// Set the following variable to the values needed
|
||||
var clip_url = "atp:6865d9c89472d58b18929aff0ac779026bc129190f7536f71d3835f7e2629c93.hfr"; // This url is working in VRshop
|
||||
|
||||
|
||||
var PLAYBACK_CHANNEL = "playbackChannel";
|
||||
var playFromCurrentLocation = false;
|
||||
var useDisplayName = true;
|
||||
var useAttachments = true;
|
||||
var useAvatarModel = true;
|
||||
|
||||
var totalTime = 0;
|
||||
var subscribed = false;
|
||||
var WAIT_FOR_AUDIO_MIXER = 1;
|
||||
|
||||
var PLAY = "Play";
|
||||
|
||||
function getAction(channel, message, senderID) {
|
||||
if(subscribed) {
|
||||
print("I'm the agent and I received this: " + message);
|
||||
|
||||
switch(message) {
|
||||
case PLAY:
|
||||
print("Play");
|
||||
if (!Recording.isPlaying()) {
|
||||
Recording.setPlayerTime(0.0);
|
||||
Recording.startPlaying();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
print("Unknown action: " + action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function update(deltaTime) {
|
||||
|
||||
totalTime += deltaTime;
|
||||
|
||||
if (totalTime > WAIT_FOR_AUDIO_MIXER) {
|
||||
if (!subscribed) {
|
||||
Messages.subscribe(PLAYBACK_CHANNEL);
|
||||
subscribed = true;
|
||||
Recording.loadRecording(clip_url);
|
||||
Recording.setPlayFromCurrentLocation(playFromCurrentLocation);
|
||||
Recording.setPlayerUseDisplayName(useDisplayName);
|
||||
Recording.setPlayerUseAttachments(useAttachments);
|
||||
Recording.setPlayerUseHeadModel(false);
|
||||
Recording.setPlayerUseSkeletonModel(useAvatarModel);
|
||||
Agent.isAvatar = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Messages.messageReceived.connect(function (channel, message, senderID) {
|
||||
if (channel == PLAYBACK_CHANNEL) {
|
||||
getAction(channel, message, senderID);
|
||||
}
|
||||
});
|
||||
|
||||
Script.update.connect(update);
|
45
examples/vrShop/cash/shopCreditCardEntityScript.js
Normal file
45
examples/vrShop/cash/shopCreditCardEntityScript.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
// shopCreditCardEntityScript.js
|
||||
//
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
(function() {
|
||||
|
||||
var _this;
|
||||
var entityProperties = null;
|
||||
|
||||
// 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)
|
||||
CreditCard = function() {
|
||||
_this = this;
|
||||
};
|
||||
|
||||
CreditCard.prototype = {
|
||||
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
var ownerObj = getEntityCustomData('ownerKey', this.entityID, null);
|
||||
if (ownerObj.ownerID === MyAvatar.sessionUUID) {
|
||||
myCard = true;
|
||||
entityProperties = Entities.getEntityProperties(this.entityID);
|
||||
}
|
||||
},
|
||||
|
||||
releaseGrab: function () {
|
||||
//reset the card to its original properties (position, angular velocity, ecc)
|
||||
Entities.editEntity(_this.entityID, entityProperties);
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
Entities.deleteEntity(this.entityID);
|
||||
}
|
||||
};
|
||||
|
||||
// entity scripts always need to return a newly constructed object of our type
|
||||
return new CreditCard();
|
||||
})
|
858
examples/vrShop/inspect/shopInspectEntityScript.js
Normal file
858
examples/vrShop/inspect/shopInspectEntityScript.js
Normal file
|
@ -0,0 +1,858 @@
|
|||
// shopInspectEntityScript.js
|
||||
//
|
||||
// The inspection entity which runs this entity script will be in fron of the avatar while he's grabbing an item.
|
||||
// This script gives some information to the avatar using interactive 3DOverlays:
|
||||
// - Drive the customer to put he item in the correct zone to inspect it
|
||||
// - Create the UI while inspecting with text and buttons and manages the clicks on them modifying the item and communicating with agents
|
||||
// And also it creates the MyController which are in charge to render the rays from the hands during inspecting and analysing their intersection with other overlays
|
||||
|
||||
// Created by Alessandro Signa and Edgar Pironti on 01/13/2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
|
||||
var utilitiesScript = Script.resolvePath("../../libraries/utils.js");
|
||||
var overlayManagerScript = Script.resolvePath("../../libraries/overlayManager.js");
|
||||
Script.include(utilitiesScript);
|
||||
Script.include(overlayManagerScript);
|
||||
|
||||
var AGENT_REVIEW_CHANNEL = "reviewChannel";
|
||||
var NO_REVIEWS_AVAILABLE = "No reviews available";
|
||||
var SEPARATOR = "Separator";
|
||||
var CAMERA_REVIEW = "CameraReview";
|
||||
|
||||
var ZERO_STAR_URL = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/0Star.png";
|
||||
var ONE_STAR_URL = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/1Star.png";
|
||||
var TWO_STAR_URL = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/2Star.png";
|
||||
var THREE_STAR_URL = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/3Star.png";
|
||||
|
||||
var POINTER_ICON_URL = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/Pointer.png";
|
||||
var TRY_ON_ICON = "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/TryOn.png"
|
||||
|
||||
var MIN_DIMENSION_THRESHOLD = null;
|
||||
var IN_HAND_STATUS = "inHand";
|
||||
var IN_INSPECT_STATUS = "inInspect";
|
||||
|
||||
var RIGHT_HAND = 1;
|
||||
var LEFT_HAND = 0;
|
||||
|
||||
var LINE_LENGTH = 100;
|
||||
var COLOR = {
|
||||
red: 165,
|
||||
green: 199,
|
||||
blue: 218
|
||||
};
|
||||
|
||||
var COMFORT_ARM_LENGTH = 0.4;
|
||||
|
||||
var PENETRATION_THRESHOLD = 0.2;
|
||||
|
||||
var _this;
|
||||
var inspecting = false;
|
||||
var inspectingMyItem = false;
|
||||
var inspectedEntityID = null;
|
||||
var isUIWorking = false;
|
||||
var wantToStopTrying = false;
|
||||
var rightController = null;
|
||||
var leftController = null;
|
||||
var workingHand = null;
|
||||
var collidedItemID = null;
|
||||
var tempTryEntity = null;
|
||||
var tryingOnAvatar = false;
|
||||
var itemOriginalDimensions = null;
|
||||
|
||||
var mainPanel = null;
|
||||
var mirrorPanel = null;
|
||||
var buttons = [];
|
||||
var tryOnAvatarButton = null;
|
||||
var playButton = null;
|
||||
var nextButton = null;
|
||||
var textReviewerName = null;
|
||||
var modelURLsArray = [];
|
||||
var previewURLsArray = [];
|
||||
var starURL = null;
|
||||
|
||||
var reviewIndex = 0;
|
||||
var reviewsNumber = 0;
|
||||
var dbMatrix = null;
|
||||
|
||||
var separator = null;
|
||||
var cameraReview = null;
|
||||
|
||||
|
||||
var pointer = new Image3DOverlay({ //maybe we want to use one pointer for each hand ?
|
||||
url: POINTER_ICON_URL,
|
||||
dimensions: {
|
||||
x: 0.015,
|
||||
y: 0.015
|
||||
},
|
||||
alpha: 1,
|
||||
emissive: true,
|
||||
isFacingAvatar: false,
|
||||
ignoreRayIntersection: true,
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 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)
|
||||
InspectEntity = function() {
|
||||
_this = this;
|
||||
};
|
||||
|
||||
|
||||
function MyController(hand) {
|
||||
this.hand = hand;
|
||||
if (this.hand === RIGHT_HAND) {
|
||||
this.getHandPosition = MyAvatar.getRightPalmPosition;
|
||||
this.getHandRotation = MyAvatar.getRightPalmRotation;
|
||||
this.bumper = Controller.Standard.RB;
|
||||
} else {
|
||||
this.getHandPosition = MyAvatar.getLeftPalmPosition;
|
||||
this.getHandRotation = MyAvatar.getLeftPalmRotation;
|
||||
this.bumper = Controller.Standard.LB;
|
||||
}
|
||||
|
||||
this.pickRay = null; // ray object
|
||||
this.overlayLine = null; // id of line overlay
|
||||
this.waitingForBumpReleased = false;
|
||||
|
||||
this.overlayLineOn = function(closePoint, farPoint, color) {
|
||||
if (this.overlayLine == null) {
|
||||
var lineProperties = {
|
||||
lineWidth: 5,
|
||||
start: closePoint,
|
||||
end: farPoint,
|
||||
color: color,
|
||||
ignoreRayIntersection: true,
|
||||
visible: true,
|
||||
alpha: 1
|
||||
};
|
||||
this.overlayLine = new Line3DOverlay(lineProperties);
|
||||
} else {
|
||||
this.overlayLine.start = closePoint;
|
||||
this.overlayLine.end = farPoint;
|
||||
}
|
||||
},
|
||||
|
||||
this.updateRay = function() {
|
||||
//update the ray object
|
||||
this.pickRay = {
|
||||
origin: this.getHandPosition(),
|
||||
direction: Quat.getUp(this.getHandRotation())
|
||||
};
|
||||
|
||||
//update the ray overlay and the pointer
|
||||
var rayPickResult = OverlayManager.findRayIntersection(this.pickRay);
|
||||
if (rayPickResult.intersects) {
|
||||
var normal = Vec3.multiply(Quat.getFront(Camera.getOrientation()), -1);
|
||||
var offset = Vec3.multiply(normal, 0.001);
|
||||
pointer.position = Vec3.sum(rayPickResult.intersection, offset); //pointer is a global Image3DOverlay
|
||||
pointer.rotation = Camera.getOrientation();
|
||||
pointer.visible = true;
|
||||
} else {
|
||||
pointer.visible = false;
|
||||
}
|
||||
|
||||
var farPoint = rayPickResult.intersects ? rayPickResult.intersection : Vec3.sum(this.pickRay.origin, Vec3.multiply(this.pickRay.direction, LINE_LENGTH));
|
||||
this.overlayLineOn(this.pickRay.origin, farPoint, COLOR);
|
||||
|
||||
},
|
||||
//the update of each hand has to update the ray belonging to that hand and handle the bumper event
|
||||
this.updateHand = function() {
|
||||
//detect the bumper event
|
||||
var bumperPressed = Controller.getValue(this.bumper);
|
||||
if (bumperPressed && this != workingHand) {
|
||||
workingHand.clean();
|
||||
workingHand = this;
|
||||
} else if (this != workingHand) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateRay();
|
||||
|
||||
//manage event on UI
|
||||
if (bumperPressed && !this.waitingForBumpReleased) {
|
||||
this.waitingForBumpReleased = true; //to avoid looping on the button while keep pressing the bumper
|
||||
var triggeredButton = OverlayManager.findOnRay(this.pickRay);
|
||||
if (triggeredButton != null) {
|
||||
//search the index of the UI element triggered
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
if (buttons[i] == triggeredButton) {
|
||||
|
||||
_this.changeModel(i);
|
||||
}
|
||||
}
|
||||
|
||||
//the nextButton moves to the next customer review, changing the agent accordingly
|
||||
if (nextButton == triggeredButton) {
|
||||
|
||||
reviewIndex ++;
|
||||
if (reviewIndex == reviewsNumber) {
|
||||
reviewIndex = 0;
|
||||
}
|
||||
|
||||
var message = {
|
||||
command: "Show",
|
||||
clip_url: dbMatrix[reviewIndex].clip_url
|
||||
};
|
||||
|
||||
Messages.sendMessage(AGENT_REVIEW_CHANNEL, JSON.stringify(message));
|
||||
print("Show sent to agent");
|
||||
|
||||
// update UI
|
||||
textReviewerName.text = dbMatrix[reviewIndex].name;
|
||||
reviewerScore.url = starConverter(dbMatrix[reviewIndex].score);
|
||||
print("UI updated");
|
||||
}
|
||||
|
||||
//the playButton sends the play command to the agent
|
||||
if (playButton == triggeredButton) {
|
||||
var message = {
|
||||
command: "Play",
|
||||
clip_url: dbMatrix[reviewIndex].clip_url
|
||||
};
|
||||
|
||||
Messages.sendMessage(AGENT_REVIEW_CHANNEL, JSON.stringify(message));
|
||||
print("Play sent to agent");
|
||||
|
||||
}
|
||||
|
||||
//the tryOnAvatarButton change the camera mode and puts t a copy of the inspected item in a proper position on the the avatar
|
||||
if (tryOnAvatarButton == triggeredButton) {
|
||||
print("tryOnAvatar pressed!");
|
||||
|
||||
var itemPositionWhileTrying = null;
|
||||
//All the offset here are good just for Will avatar increasing its size by one
|
||||
switch (Entities.getEntityProperties(inspectedEntityID).name) {
|
||||
case "Item_Sunglasses":
|
||||
itemPositionWhileTrying = {x: 0, y: 0.04, z: 0.05};
|
||||
break;
|
||||
case "Item_Hat":
|
||||
itemPositionWhileTrying = {x: 0, y: 0.16, z: 0.025};
|
||||
break;
|
||||
default:
|
||||
//there isn't any position specified for that item, use a default one
|
||||
itemPositionWhileTrying = {x: 0, y: 0.16, z: 0.025};
|
||||
break;
|
||||
}
|
||||
|
||||
//Code for the overlay text for the mirror.
|
||||
mirrorPanel = new OverlayPanel({
|
||||
anchorPositionBinding: { avatar: "MyAvatar" },
|
||||
anchorRotationBinding: { avatar: "MyAvatar" },
|
||||
offsetPosition: {
|
||||
x: 0.5,
|
||||
y: 0.9,
|
||||
z: 0
|
||||
},
|
||||
offsetRotation: Quat.fromVec3Degrees({x: 0, y: 180, z: 0}),
|
||||
|
||||
isFacingAvatar: false
|
||||
});
|
||||
var mirrorText = new Text3DOverlay({
|
||||
text: "Press the bumper to go back in inspection",
|
||||
isFacingAvatar: false,
|
||||
ignoreRayIntersection: true,
|
||||
|
||||
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 200, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.05,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3,
|
||||
visible: true
|
||||
});
|
||||
mirrorPanel.addChild(mirrorText);
|
||||
|
||||
tryingOnAvatar = true;
|
||||
|
||||
//Clean inspect Overlays and related stuff
|
||||
workingHand.clean();
|
||||
mainPanel.destroy();
|
||||
mainPanel = null;
|
||||
isUIWorking = false;
|
||||
Entities.editEntity(inspectedEntityID, { visible: false }); //the inspected item becomes invisible
|
||||
|
||||
|
||||
Camera.mode = "entity";
|
||||
Camera.cameraEntity = _this.entityID;
|
||||
var entityProperties = Entities.getEntityProperties(inspectedEntityID);
|
||||
tempTryEntity = Entities.addEntity({
|
||||
type: entityProperties.type,
|
||||
name: entityProperties.name,
|
||||
localPosition: itemPositionWhileTrying,
|
||||
dimensions: itemOriginalDimensions,
|
||||
collisionsWillMove: false,
|
||||
ignoreForCollisions: true,
|
||||
modelURL: entityProperties.modelURL,
|
||||
shapeType: entityProperties.shapeType,
|
||||
originalTextures: entityProperties.originalTextures,
|
||||
parentID: MyAvatar.sessionUUID,
|
||||
parentJointIndex: MyAvatar.getJointIndex("Head")
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (!bumperPressed && this.waitingForBumpReleased) {
|
||||
this.waitingForBumpReleased = false;
|
||||
}
|
||||
},
|
||||
|
||||
this.clean = function() {
|
||||
this.pickRay = null;
|
||||
this.overlayLine.destroy();
|
||||
this.overlayLine = null;
|
||||
pointer.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
function update(deltaTime) {
|
||||
|
||||
if (tryingOnAvatar) {
|
||||
// if trying the item on avatar, wait for a bumper being pressed to exit this mode
|
||||
//the bumper is already pressed when we get here because we triggered the button pressing the bumper so we have to wait it's released
|
||||
if(Controller.getValue(workingHand.bumper) && wantToStopTrying) {
|
||||
Camera.cameraEntity = null;
|
||||
Camera.mode = "first person";
|
||||
mirrorPanel.destroy();
|
||||
mirrorPanel = null;
|
||||
Entities.deleteEntity(tempTryEntity);
|
||||
tempTryEntity = null;
|
||||
Entities.editEntity(inspectedEntityID, { visible: true });
|
||||
_this.createInspectUI();
|
||||
tryingOnAvatar = false;
|
||||
wantToStopTrying = false;
|
||||
} else if (!Controller.getValue(workingHand.bumper) && !wantToStopTrying) {
|
||||
//no bumper is pressed
|
||||
wantToStopTrying = true;
|
||||
}
|
||||
return;
|
||||
} else if (inspecting) {
|
||||
//update the rays from both hands
|
||||
leftController.updateHand();
|
||||
rightController.updateHand();
|
||||
|
||||
//check the item status for consistency
|
||||
var entityStatus = getEntityCustomData('statusKey', inspectedEntityID, null).status;
|
||||
if (entityStatus == IN_HAND_STATUS) {
|
||||
//the inspection is over
|
||||
inspecting = false;
|
||||
inspectedEntityID = null;
|
||||
}
|
||||
} else if (isUIWorking) {
|
||||
//getting here when the inspect phase end, so we want to clean the UI
|
||||
// Destroy rays
|
||||
workingHand.clean();
|
||||
|
||||
// Destroy overlay
|
||||
mainPanel.destroy();
|
||||
isUIWorking = false;
|
||||
|
||||
var message = {
|
||||
command: "Hide",
|
||||
clip_url: ""
|
||||
};
|
||||
|
||||
Messages.sendMessage(AGENT_REVIEW_CHANNEL, JSON.stringify(message));
|
||||
print("Hide sent to agent");
|
||||
|
||||
if (separator != null || cameraReview != null) {
|
||||
Entities.editEntity(separator, { visible: true });
|
||||
Entities.editEntity(separator, { locked: true });
|
||||
Entities.editEntity(cameraReview, { visible: true });
|
||||
Entities.editEntity(cameraReview, { locked: true });
|
||||
}
|
||||
}
|
||||
|
||||
_this.positionRotationUpdate();
|
||||
};
|
||||
|
||||
function starConverter(value) {
|
||||
var starURL = ZERO_STAR_URL;
|
||||
|
||||
switch(value) {
|
||||
case 0:
|
||||
starURL = ZERO_STAR_URL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
starURL = ONE_STAR_URL;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
starURL = TWO_STAR_URL;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
starURL = THREE_STAR_URL;
|
||||
break;
|
||||
|
||||
default:
|
||||
starURL = ZERO_STAR_URL;
|
||||
break;
|
||||
}
|
||||
|
||||
return starURL;
|
||||
};
|
||||
|
||||
|
||||
// look for the database entity relative to the inspected item
|
||||
function findItemDataBase(entityID, item) {
|
||||
var dataBaseID = null;
|
||||
var databaseEntityName = item + "DB";
|
||||
var entitiesInZone = Entities.findEntities(Entities.getEntityProperties(entityID).position, (Entities.getEntityProperties(entityID).dimensions.x)*100);
|
||||
|
||||
for (var i = 0; i < entitiesInZone.length && dataBaseID == null; i++) {
|
||||
if (Entities.getEntityProperties(entitiesInZone[i]).name == databaseEntityName) {
|
||||
dataBaseID = entitiesInZone[i];
|
||||
print("Database found! " + entitiesInZone[i]);
|
||||
return dataBaseID;
|
||||
}
|
||||
}
|
||||
print("No database for this item.");
|
||||
return null;
|
||||
};
|
||||
|
||||
function findItemByName(searchingPointEntityID, itemName) {
|
||||
print("Looking for item: " + itemName);
|
||||
var entitiesInZone = Entities.findEntities(Entities.getEntityProperties(searchingPointEntityID).position, (Entities.getEntityProperties(searchingPointEntityID).dimensions.x)*100);
|
||||
|
||||
for (var i = 0; i < entitiesInZone.length; i++) {
|
||||
if (Entities.getEntityProperties(entitiesInZone[i]).name == itemName) {
|
||||
print(itemName + " found! " + entitiesInZone[i]);
|
||||
return entitiesInZone[i];
|
||||
}
|
||||
}
|
||||
print("Item " + itemName + " not found");
|
||||
return null;
|
||||
};
|
||||
|
||||
InspectEntity.prototype = {
|
||||
|
||||
preload: function(entityID) {
|
||||
this.entityID = entityID;
|
||||
print("PRELOAD INSPECT ENTITY");
|
||||
//get the owner ID from user data and compare to the mine
|
||||
//the update will be connected just for the owner
|
||||
var ownerObj = getEntityCustomData('ownerKey', this.entityID, null);
|
||||
if (ownerObj.ownerID === MyAvatar.sessionUUID) {
|
||||
rightController = new MyController(RIGHT_HAND); //rightController and leftController are two objects
|
||||
leftController = new MyController(LEFT_HAND);
|
||||
workingHand = rightController;
|
||||
inspectingMyItem = true;
|
||||
inspectRadius = (Entities.getEntityProperties(_this.entityID).dimensions.x) / 2 + COMFORT_ARM_LENGTH;
|
||||
Script.update.connect(update);
|
||||
}
|
||||
},
|
||||
|
||||
//Put the item which calls this method in inspect mode if it belongs to the owner of the inspect zone
|
||||
doSomething: function (entityID, dataArray) {
|
||||
var data = JSON.parse(dataArray[0]);
|
||||
var itemOwnerObj = getEntityCustomData('ownerKey', data.id, null);
|
||||
|
||||
var inspectOwnerObj = getEntityCustomData('ownerKey', this.entityID, null);
|
||||
|
||||
if (inspectOwnerObj == null) {
|
||||
Entities.deleteEntity(data.id);
|
||||
}
|
||||
|
||||
if (itemOwnerObj.ownerID === inspectOwnerObj.ownerID) {
|
||||
//setup the things for inspecting the item
|
||||
inspecting = true;
|
||||
inspectedEntityID = data.id; //store the ID of the inspected entity
|
||||
setEntityCustomData('statusKey', data.id, {
|
||||
status: IN_INSPECT_STATUS
|
||||
});
|
||||
_this.createInspectUI();
|
||||
itemOriginalDimensions = Entities.getEntityProperties(inspectedEntityID).dimensions;
|
||||
|
||||
// find separator and camera and hide
|
||||
separator = findItemByName(inspectedEntityID, SEPARATOR);
|
||||
Entities.editEntity(separator, { locked: false });
|
||||
Entities.editEntity(separator, { visible: false });
|
||||
print("Got here! Entity to hide: " + separator);
|
||||
cameraReview = findItemByName(inspectedEntityID, CAMERA_REVIEW);
|
||||
Entities.editEntity(cameraReview, { locked: false });
|
||||
Entities.editEntity(cameraReview, { visible: false });
|
||||
print("Got here! Entity to hide: " + cameraReview);
|
||||
} else {
|
||||
Entities.deleteEntity(data.id);
|
||||
}
|
||||
},
|
||||
|
||||
//make the inspection entity stay at the proper position with respect to the avatar and camera positions
|
||||
positionRotationUpdate: function() {
|
||||
var newRotation;
|
||||
if (tryingOnAvatar) {
|
||||
newRotation = Vec3.sum(Quat.safeEulerAngles(MyAvatar.orientation), {x:0, y: 180, z: 0}); //neccessary to set properly the camera in entity mode when trying on avatar
|
||||
Entities.editEntity(_this.entityID, { rotation: Quat.fromVec3Degrees(newRotation) });
|
||||
} else {
|
||||
var newPosition = Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), inspectRadius));
|
||||
Entities.editEntity(_this.entityID, { position: newPosition });
|
||||
newRotation = MyAvatar.orientation;
|
||||
Entities.editEntity(_this.entityID, { rotation: newRotation });
|
||||
}
|
||||
|
||||
newPosition = Vec3.sum(newPosition, Vec3.multiply(Quat.getRight(newRotation), 0.34));
|
||||
|
||||
},
|
||||
|
||||
createInspectUI : function() {
|
||||
|
||||
var infoObj = getEntityCustomData('infoKey', inspectedEntityID, null);
|
||||
var itemDescriptionString = null;
|
||||
var priceNumber = -1;
|
||||
var availabilityNumber = -1;
|
||||
var wearable = false;
|
||||
|
||||
if(infoObj != null) {
|
||||
//var modelURLsLoop = infoObj.modelURLs; ??
|
||||
var rootURLString = infoObj.rootURL;
|
||||
for (var i = 0; i < infoObj.modelURLs.length; i++) {
|
||||
modelURLsArray[i] = rootURLString + infoObj.modelURLs[i];
|
||||
previewURLsArray[i] = rootURLString + infoObj.previewURLs[i];
|
||||
}
|
||||
|
||||
itemDescriptionString = infoObj.description;
|
||||
priceNumber = infoObj.price;
|
||||
availabilityNumber = infoObj.availability;
|
||||
wearable = infoObj.wearable;
|
||||
infoObj = null;
|
||||
}
|
||||
|
||||
//Looking for the item DB, this entity has in its userData the info of the customer reviews for the item
|
||||
var DBID = findItemDataBase(_this.entityID, Entities.getEntityProperties(inspectedEntityID).name);
|
||||
|
||||
if (DBID != null) {
|
||||
infoObj = getEntityCustomData('infoKey', DBID, null);
|
||||
var scoreAverage = null;
|
||||
var reviewerName = null;
|
||||
|
||||
if(infoObj != null) {
|
||||
dbMatrix = infoObj.dbKey;
|
||||
reviewsNumber = infoObj.dbKey.length;
|
||||
//print("DB matrix is " + dbMatrix + " with element number: " + reviewsNumber);
|
||||
var scoreSum = null;
|
||||
|
||||
for (var i = 0; i < dbMatrix.length; i++) {
|
||||
scoreSum += dbMatrix[i].score;
|
||||
}
|
||||
|
||||
if (dbMatrix.length) {
|
||||
scoreAverage = Math.round(scoreSum / dbMatrix.length);
|
||||
reviewerName = dbMatrix[reviewIndex].name;
|
||||
|
||||
var message = {
|
||||
command: "Show",
|
||||
clip_url: dbMatrix[reviewIndex].clip_url
|
||||
};
|
||||
|
||||
Messages.sendMessage(AGENT_REVIEW_CHANNEL, JSON.stringify(message));
|
||||
print("Show sent to agent");
|
||||
} else {
|
||||
//some default value if the DB is empty
|
||||
scoreAverage = 0;
|
||||
reviewerName = NO_REVIEWS_AVAILABLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
print ("Creating inspect UI");
|
||||
//set the main panel to follow the inspect entity
|
||||
mainPanel = new OverlayPanel({
|
||||
anchorPositionBinding: { entity: _this.entityID },
|
||||
anchorRotationBinding: { entity: _this.entityID },
|
||||
isFacingAvatar: false
|
||||
});
|
||||
|
||||
var offsetPositionY = 0.2;
|
||||
var offsetPositionX = -0.4;
|
||||
|
||||
//these buttons are the 3 previews of the item
|
||||
for (var i = 0; i < previewURLsArray.length; i++) {
|
||||
buttons[i] = new Image3DOverlay({
|
||||
url: previewURLsArray[i],
|
||||
dimensions: {
|
||||
x: 0.15,
|
||||
y: 0.15
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 0.8,
|
||||
ignoreRayIntersection: false,
|
||||
offsetPosition: {
|
||||
x: offsetPositionX,
|
||||
y: offsetPositionY - (i * offsetPositionY),
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
mainPanel.addChild(buttons[i]);
|
||||
}
|
||||
|
||||
//aggregateScore is the average between those given by the reviewers
|
||||
var aggregateScore = new Image3DOverlay({
|
||||
url: starConverter(scoreAverage),
|
||||
dimensions: {
|
||||
x: 0.25,
|
||||
y: 0.25
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 1,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: 0,
|
||||
y: 0.27,
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
mainPanel.addChild(aggregateScore);
|
||||
|
||||
//if any review is available create buttons to manage them
|
||||
if (dbMatrix.length) {
|
||||
|
||||
playButton = new Image3DOverlay({
|
||||
url: "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/Play.png",
|
||||
dimensions: {
|
||||
x: 0.08,
|
||||
y: 0.08
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 1,
|
||||
ignoreRayIntersection: false,
|
||||
offsetPosition: {
|
||||
x: 0.42,
|
||||
y: 0.27,
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
mainPanel.addChild(playButton);
|
||||
|
||||
|
||||
reviewerScore = new Image3DOverlay({
|
||||
url: starConverter(dbMatrix[reviewIndex].score),
|
||||
dimensions: {
|
||||
x: 0.15,
|
||||
y: 0.15
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 1,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: 0.31,
|
||||
y: 0.26,
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
mainPanel.addChild(reviewerScore);
|
||||
|
||||
nextButton = new Image3DOverlay({
|
||||
url: "https://dl.dropboxusercontent.com/u/14127429/FBX/VRshop/Next.png",
|
||||
dimensions: {
|
||||
x: 0.2,
|
||||
y: 0.2
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 1,
|
||||
ignoreRayIntersection: false,
|
||||
offsetPosition: {
|
||||
x: 0.36,
|
||||
y: 0.18,
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
|
||||
mainPanel.addChild(nextButton);
|
||||
|
||||
}
|
||||
|
||||
textReviewerName = new Text3DOverlay({
|
||||
text: reviewerName,
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: 0.23,
|
||||
y: 0.31,
|
||||
z: 0
|
||||
},
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.02,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3
|
||||
});
|
||||
|
||||
mainPanel.addChild(textReviewerName);
|
||||
|
||||
//if the item is wearable create a tryOnAvatarButton
|
||||
if (wearable) {
|
||||
tryOnAvatarButton = new Image3DOverlay({
|
||||
url: TRY_ON_ICON,
|
||||
dimensions: {
|
||||
x: 0.2,
|
||||
y: 0.2
|
||||
},
|
||||
isFacingAvatar: false,
|
||||
alpha: 1,
|
||||
ignoreRayIntersection: false,
|
||||
offsetPosition: {
|
||||
x: 0.35,
|
||||
y: -0.22,
|
||||
z: 0
|
||||
},
|
||||
emissive: true,
|
||||
});
|
||||
|
||||
mainPanel.addChild(tryOnAvatarButton);
|
||||
}
|
||||
|
||||
|
||||
var textQuantityString = new Text3DOverlay({
|
||||
text: "Quantity: ",
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: 0.25,
|
||||
y: -0.3,
|
||||
z: 0
|
||||
},
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.02,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3
|
||||
});
|
||||
|
||||
mainPanel.addChild(textQuantityString);
|
||||
|
||||
var textQuantityNumber = new Text3DOverlay({
|
||||
text: availabilityNumber,
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: 0.28,
|
||||
y: -0.32,
|
||||
z: 0
|
||||
},
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.06,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3
|
||||
});
|
||||
|
||||
mainPanel.addChild(textQuantityNumber);
|
||||
|
||||
if (itemDescriptionString != null) {
|
||||
var textDescription = new Text3DOverlay({
|
||||
text: "Price: " + priceNumber + "\nAdditional information: \n" + itemDescriptionString,
|
||||
isFacingAvatar: false,
|
||||
alpha: 1.0,
|
||||
ignoreRayIntersection: true,
|
||||
offsetPosition: {
|
||||
x: -0.2,
|
||||
y: -0.3,
|
||||
z: 0
|
||||
},
|
||||
dimensions: { x: 0, y: 0 },
|
||||
backgroundColor: { red: 255, green: 255, blue: 255 },
|
||||
color: { red: 0, green: 0, blue: 0 },
|
||||
topMargin: 0.00625,
|
||||
leftMargin: 0.00625,
|
||||
bottomMargin: 0.1,
|
||||
rightMargin: 0.00625,
|
||||
lineHeight: 0.02,
|
||||
alpha: 1,
|
||||
backgroundAlpha: 0.3
|
||||
});
|
||||
|
||||
mainPanel.addChild(textDescription);
|
||||
}
|
||||
|
||||
|
||||
|
||||
print ("GOT HERE: Descrition " + itemDescriptionString + " Availability " + availabilityNumber);
|
||||
|
||||
isUIWorking = true;
|
||||
}
|
||||
},
|
||||
|
||||
//Manage the collisions and tell to the item if it is into the this inspection area
|
||||
collisionWithEntity: function(myID, otherID, collisionInfo) {
|
||||
|
||||
var itemObj = getEntityCustomData('itemKey', _this.entityID, null);
|
||||
if (itemObj != null) {
|
||||
if (itemObj.itemID == otherID) { //verify that the inspect area is colliding with the actual item which created it
|
||||
|
||||
var penetrationValue = Vec3.length(collisionInfo.penetration);
|
||||
if (penetrationValue > PENETRATION_THRESHOLD && collidedItemID === null) {
|
||||
collidedItemID = otherID;
|
||||
print("Start collision with: " + Entities.getEntityProperties(collidedItemID).name);
|
||||
Entities.callEntityMethod(otherID, 'changeOverlayColor', null);
|
||||
|
||||
} else if (penetrationValue < PENETRATION_THRESHOLD && collidedItemID !== null) {
|
||||
|
||||
print("End collision with: " + Entities.getEntityProperties(collidedItemID).name);
|
||||
collidedItemID = null;
|
||||
Entities.callEntityMethod(otherID, 'changeOverlayColor', null);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
changeModel: function(index) {
|
||||
var entityProperties = Entities.getEntityProperties(inspectedEntityID);
|
||||
if (entityProperties.modelURL != modelURLsArray[index]) {
|
||||
Entities.editEntity(inspectedEntityID, { modelURL: modelURLsArray[index] });
|
||||
}
|
||||
},
|
||||
|
||||
unload: function (entityID) {
|
||||
if(inspectingMyItem){
|
||||
print("UNLOAD INSPECT ENTITY");
|
||||
Script.update.disconnect(update);
|
||||
|
||||
// clean UI
|
||||
Entities.deleteEntity(_this.entityID);
|
||||
}
|
||||
}
|
||||
};
|
||||
return new InspectEntity();
|
||||
})
|
Loading…
Reference in a new issue