Needs a lot of cleanup. Data has been de-duplicated, and where identical copies existed, one of them has been replaced with a symlink. Some files have been excluded, such as binaries, installers and debug dumps. Some of that may still be present.
858 lines
No EOL
36 KiB
JavaScript
858 lines
No EOL
36 KiB
JavaScript
// 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();
|
|
}) |