mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 04:23:56 +02:00
code) and into shared.js (for JS code). Modify references to the metaverse server from constants to references to the new central definitions.
398 lines
12 KiB
JavaScript
398 lines
12 KiB
JavaScript
//
|
|
// lobby.js
|
|
// examples
|
|
//
|
|
// Created by Stephen Birarda on October 17, 2014
|
|
// Copyright 2014 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
|
|
//
|
|
|
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
|
|
|
var panelWall = false;
|
|
var orbShell = false;
|
|
var descriptionText = false;
|
|
var showText = false;
|
|
|
|
// used for formating the description text, in meters
|
|
var textWidth = 4;
|
|
var textHeight = .5;
|
|
var numberOfLines = 2;
|
|
var textMargin = 0.0625;
|
|
var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines;
|
|
|
|
var avatarStickPosition = {};
|
|
|
|
var orbNaturalExtentsMin = { x: -1.230354, y: -1.22077, z: -1.210487 };
|
|
var orbNaturalExtentsMax = { x: 1.230353, y: 1.229819, z: 1.210487 };
|
|
var panelsNaturalExtentsMin = { x: -1.223182, y: -0.348487, z: 0.0451369 };
|
|
var panelsNaturalExtentsMax = { x: 1.223039, y: 0.602978, z: 1.224298 };
|
|
|
|
var orbNaturalDimensions = Vec3.subtract(orbNaturalExtentsMax, orbNaturalExtentsMin);
|
|
var panelsNaturalDimensions = Vec3.subtract(panelsNaturalExtentsMax, panelsNaturalExtentsMin);
|
|
|
|
var SCALING_FACTOR = 10;
|
|
var orbDimensions = Vec3.multiply(orbNaturalDimensions, SCALING_FACTOR);
|
|
var panelsDimensions = Vec3.multiply(panelsNaturalDimensions, SCALING_FACTOR);
|
|
|
|
var orbNaturalCenter = Vec3.sum(orbNaturalExtentsMin, Vec3.multiply(orbNaturalDimensions, 0.5));
|
|
var panelsNaturalCenter = Vec3.sum(panelsNaturalExtentsMin, Vec3.multiply(panelsNaturalDimensions, 0.5));
|
|
var orbCenter = Vec3.multiply(orbNaturalCenter, SCALING_FACTOR);
|
|
var panelsCenter = Vec3.multiply(panelsNaturalCenter, SCALING_FACTOR);
|
|
var panelsCenterShift = Vec3.subtract(panelsCenter, orbCenter);
|
|
|
|
var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8};
|
|
|
|
var LOBBY_PANEL_WALL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/PanelWallForInterface.fbx";
|
|
var LOBBY_BLANK_PANEL_TEXTURE_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/Texture.jpg";
|
|
var LOBBY_SHELL_URL = HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyShellForInterface.fbx";
|
|
|
|
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.stereo.raw")
|
|
var currentDrone = null;
|
|
|
|
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.stereo.raw")
|
|
var latinInjector = null;
|
|
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.stereo.raw")
|
|
var elevatorInjector = null;
|
|
var currentMuzakInjector = null;
|
|
var currentSound = null;
|
|
|
|
function textOverlayPosition() {
|
|
var TEXT_DISTANCE_OUT = 6;
|
|
var TEXT_DISTANCE_DOWN = -2;
|
|
return Vec3.sum(Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), TEXT_DISTANCE_OUT)),
|
|
Vec3.multiply(Quat.getUp(Camera.orientation), TEXT_DISTANCE_DOWN));
|
|
}
|
|
|
|
var panelPlaceOrder = [
|
|
7, 8, 9, 10, 11, 12, 13,
|
|
0, 1, 2, 3, 4, 5, 6,
|
|
14, 15, 16, 17, 18, 19, 20
|
|
];
|
|
|
|
// place index is 0-based
|
|
function placeIndexToPanelIndex(placeIndex) {
|
|
return panelPlaceOrder.indexOf(placeIndex) + 1;
|
|
}
|
|
|
|
// Panel index is 1-based
|
|
function panelIndexToPlaceIndex(panelIndex) {
|
|
return panelPlaceOrder[panelIndex - 1];
|
|
}
|
|
|
|
var MAX_NUM_PANELS = 21;
|
|
var DRONE_VOLUME = 0.3;
|
|
|
|
function drawLobby() {
|
|
if (!panelWall) {
|
|
print("Adding overlays for the lobby panel wall and orb shell.");
|
|
|
|
var cameraEuler = Quat.safeEulerAngles(Camera.orientation);
|
|
var towardsMe = Quat.angleAxis(cameraEuler.y + 180, { x: 0, y: 1, z: 0});
|
|
|
|
var orbPosition = Vec3.sum(Camera.position, Vec3.multiplyQbyV(towardsMe, ORB_SHIFT));
|
|
|
|
var panelWallProps = {
|
|
url: LOBBY_PANEL_WALL_URL,
|
|
position: Vec3.sum(orbPosition, Vec3.multiplyQbyV(towardsMe, panelsCenterShift)),
|
|
rotation: towardsMe,
|
|
dimensions: panelsDimensions
|
|
};
|
|
|
|
var orbShellProps = {
|
|
url: LOBBY_SHELL_URL,
|
|
position: orbPosition,
|
|
rotation: towardsMe,
|
|
dimensions: orbDimensions,
|
|
ignoreRayIntersection: true
|
|
};
|
|
|
|
var windowDimensions = Controller.getViewportDimensions();
|
|
|
|
var descriptionTextProps = {
|
|
position: textOverlayPosition(),
|
|
dimensions: { x: textWidth, y: textHeight },
|
|
backgroundColor: { red: 0, green: 0, blue: 0},
|
|
color: { red: 255, green: 255, blue: 255},
|
|
topMargin: textMargin,
|
|
leftMargin: textMargin,
|
|
bottomMargin: textMargin,
|
|
rightMargin: textMargin,
|
|
text: "",
|
|
lineHeight: lineHeight,
|
|
alpha: 0.9,
|
|
backgroundAlpha: 0.9,
|
|
ignoreRayIntersection: true,
|
|
visible: false,
|
|
isFacingAvatar: true
|
|
};
|
|
|
|
avatarStickPosition = MyAvatar.position;
|
|
|
|
panelWall = Overlays.addOverlay("model", panelWallProps);
|
|
orbShell = Overlays.addOverlay("model", orbShellProps);
|
|
descriptionText = Overlays.addOverlay("text3d", descriptionTextProps);
|
|
|
|
if (droneSound.downloaded) {
|
|
// start the drone sound
|
|
if (!currentDrone) {
|
|
currentDrone = Audio.playSound(droneSound, { stereo: true, loop: true, localOnly: true, volume: DRONE_VOLUME });
|
|
} else {
|
|
currentDrone.restart();
|
|
}
|
|
}
|
|
|
|
// start one of our muzak sounds
|
|
playRandomMuzak();
|
|
}
|
|
}
|
|
|
|
var places = {};
|
|
|
|
function changeLobbyTextures() {
|
|
var req = new XMLHttpRequest();
|
|
req.open("GET", URLs.METAVERSE_URL + "/api/v1/places?limit=21", false);
|
|
req.send();
|
|
|
|
places = JSON.parse(req.responseText).data.places;
|
|
|
|
var NUM_PANELS = places.length;
|
|
|
|
var textureProp = {
|
|
textures: {}
|
|
};
|
|
|
|
for (var j = 0; j < NUM_PANELS; j++) {
|
|
var panelIndex = placeIndexToPanelIndex(j);
|
|
textureProp["textures"]["file" + panelIndex] = places[j].previews.lobby;
|
|
};
|
|
|
|
Overlays.editOverlay(panelWall, textureProp);
|
|
}
|
|
|
|
var MUZAK_VOLUME = 0.1;
|
|
|
|
function playCurrentSound(secondOffset) {
|
|
if (currentSound == latinSound) {
|
|
if (!latinInjector) {
|
|
latinInjector = Audio.playSound(latinSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME });
|
|
} else {
|
|
latinInjector.restart();
|
|
}
|
|
|
|
currentMuzakInjector = latinInjector;
|
|
} else if (currentSound == elevatorSound) {
|
|
if (!elevatorInjector) {
|
|
elevatorInjector = Audio.playSound(elevatorSound, { localOnly: true, secondOffset: secondOffset, volume: MUZAK_VOLUME });
|
|
} else {
|
|
elevatorInjector.restart();
|
|
}
|
|
|
|
currentMuzakInjector = elevatorInjector;
|
|
}
|
|
}
|
|
|
|
function playNextMuzak() {
|
|
if (panelWall) {
|
|
if (currentSound == latinSound) {
|
|
if (elevatorSound.downloaded) {
|
|
currentSound = elevatorSound;
|
|
}
|
|
} else if (currentSound == elevatorSound) {
|
|
if (latinSound.downloaded) {
|
|
currentSound = latinSound;
|
|
}
|
|
}
|
|
|
|
playCurrentSound(0);
|
|
}
|
|
}
|
|
|
|
function playRandomMuzak() {
|
|
currentSound = null;
|
|
|
|
if (latinSound.downloaded && elevatorSound.downloaded) {
|
|
currentSound = Math.random() < 0.5 ? latinSound : elevatorSound;
|
|
} else if (latinSound.downloaded) {
|
|
currentSound = latinSound;
|
|
} else if (elevatorSound.downloaded) {
|
|
currentSound = elevatorSound;
|
|
}
|
|
|
|
if (currentSound) {
|
|
// pick a random number of seconds from 0-10 to offset the muzak
|
|
var secondOffset = Math.random() * 10;
|
|
|
|
playCurrentSound(secondOffset);
|
|
} else {
|
|
currentMuzakInjector = null;
|
|
}
|
|
}
|
|
|
|
function cleanupLobby() {
|
|
toggleEnvironmentRendering(true);
|
|
|
|
// for each of the 21 placeholder textures, set them back to default so the cached model doesn't have changed textures
|
|
var panelTexturesReset = {};
|
|
panelTexturesReset["textures"] = {};
|
|
|
|
for (var j = 0; j < MAX_NUM_PANELS; j++) {
|
|
panelTexturesReset["textures"]["file" + (j + 1)] = LOBBY_BLANK_PANEL_TEXTURE_URL;
|
|
};
|
|
|
|
Overlays.editOverlay(panelWall, panelTexturesReset);
|
|
|
|
Overlays.deleteOverlay(panelWall);
|
|
Overlays.deleteOverlay(orbShell);
|
|
Overlays.deleteOverlay(descriptionText);
|
|
|
|
panelWall = false;
|
|
orbShell = false;
|
|
|
|
if (currentDrone) {
|
|
currentDrone.stop();
|
|
currentDrone = null
|
|
}
|
|
|
|
if (currentMuzakInjector) {
|
|
currentMuzakInjector.stop();
|
|
currentMuzakInjector = null;
|
|
}
|
|
|
|
places = {};
|
|
|
|
}
|
|
|
|
function actionStartEvent(event) {
|
|
if (panelWall) {
|
|
// we've got an action event and our panel wall is up
|
|
// check if we hit a panel and if we should jump there
|
|
var result = Overlays.findRayIntersection(event.actionRay);
|
|
if (result.intersects && result.overlayID == panelWall) {
|
|
|
|
var panelName = result.extraInfo.subMeshName + '';
|
|
|
|
var panelStringIndex = panelName.indexOf("Panel");
|
|
if (panelStringIndex != -1) {
|
|
var panelIndex = parseInt(panelName.slice(5));
|
|
var placeIndex = panelIndexToPlaceIndex(panelIndex);
|
|
if (placeIndex < places.length) {
|
|
var actionPlace = places[placeIndex];
|
|
|
|
print("Jumping to " + actionPlace.name + " at " + actionPlace.address
|
|
+ " after click on panel " + panelIndex + " with place index " + placeIndex);
|
|
|
|
Window.location = actionPlace.address;
|
|
maybeCleanupLobby();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function backStartEvent() {
|
|
if (!panelWall) {
|
|
toggleEnvironmentRendering(false);
|
|
drawLobby();
|
|
changeLobbyTextures();
|
|
} else {
|
|
cleanupLobby();
|
|
}
|
|
}
|
|
|
|
var CLEANUP_EPSILON_DISTANCE = 0.05;
|
|
|
|
function maybeCleanupLobby() {
|
|
if (panelWall && Vec3.length(Vec3.subtract(avatarStickPosition, MyAvatar.position)) > CLEANUP_EPSILON_DISTANCE) {
|
|
cleanupLobby();
|
|
}
|
|
}
|
|
|
|
function toggleEnvironmentRendering(shouldRender) {
|
|
Scene.shouldRenderAvatars = shouldRender;
|
|
Scene.shouldRenderEntities = shouldRender;
|
|
}
|
|
|
|
function handleLookAt(pickRay) {
|
|
if (panelWall && descriptionText) {
|
|
// we've got an action event and our panel wall is up
|
|
// check if we hit a panel and if we should jump there
|
|
var result = Overlays.findRayIntersection(pickRay);
|
|
if (result.intersects && result.overlayID == panelWall) {
|
|
var panelName = result.extraInfo.subMeshName + '';
|
|
var panelStringIndex = panelName.indexOf("Panel");
|
|
if (panelStringIndex != -1) {
|
|
var panelIndex = parseInt(panelName.slice(5));
|
|
var placeIndex = panelIndexToPlaceIndex(panelIndex);
|
|
if (placeIndex < places.length) {
|
|
var actionPlace = places[placeIndex];
|
|
|
|
if (actionPlace.description == "") {
|
|
Overlays.editOverlay(descriptionText, { text: actionPlace.name, visible: showText });
|
|
} else {
|
|
// handle line wrapping
|
|
var allWords = actionPlace.description.split(" ");
|
|
var currentGoodLine = "";
|
|
var currentTestLine = "";
|
|
var formatedDescription = "";
|
|
var wordsFormated = 0;
|
|
var currentTestWord = 0;
|
|
var wordsOnLine = 0;
|
|
while (wordsFormated < allWords.length) {
|
|
// first add the "next word" to the line and test it.
|
|
currentTestLine = currentGoodLine;
|
|
if (wordsOnLine > 0) {
|
|
currentTestLine += " " + allWords[currentTestWord];
|
|
} else {
|
|
currentTestLine = allWords[currentTestWord];
|
|
}
|
|
var lineLength = Overlays.textSize(descriptionText, currentTestLine).width;
|
|
if (lineLength < textWidth || wordsOnLine == 0) {
|
|
wordsFormated++;
|
|
currentTestWord++;
|
|
wordsOnLine++;
|
|
currentGoodLine = currentTestLine;
|
|
} else {
|
|
formatedDescription += currentGoodLine + "\n";
|
|
wordsOnLine = 0;
|
|
currentGoodLine = "";
|
|
currentTestLine = "";
|
|
}
|
|
}
|
|
formatedDescription += currentGoodLine;
|
|
Overlays.editOverlay(descriptionText, { text: formatedDescription, visible: showText });
|
|
}
|
|
} else {
|
|
Overlays.editOverlay(descriptionText, { text: "", visible: false });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function update(deltaTime) {
|
|
maybeCleanupLobby();
|
|
if (panelWall) {
|
|
Overlays.editOverlay(descriptionText, { position: textOverlayPosition() });
|
|
|
|
// if the reticle is up then we may need to play the next muzak
|
|
if (currentMuzakInjector && !currentMuzakInjector.playing) {
|
|
playNextMuzak();
|
|
}
|
|
}
|
|
}
|
|
|
|
function mouseMoveEvent(event) {
|
|
if (panelWall) {
|
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
|
handleLookAt(pickRay);
|
|
}
|
|
}
|
|
|
|
Controller.actionStartEvent.connect(actionStartEvent);
|
|
Controller.backStartEvent.connect(backStartEvent);
|
|
Script.update.connect(update);
|
|
Script.scriptEnding.connect(maybeCleanupLobby);
|
|
Controller.mouseMoveEvent.connect(mouseMoveEvent);
|