mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Merge pull request #13 from kasenvr/revert-12-features/default-scripts
Revert "Adds community script directory, adds chat as default app."
This commit is contained in:
commit
7f56c090f8
2 changed files with 2 additions and 997 deletions
|
@ -1,995 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
// Chat.js
|
||||
// By Don Hopkins (dhopkins@donhopkins.com)
|
||||
//
|
||||
// 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 webPageURL = Script.resolvePath("html/ChatPage.html"); // URL of tablet web page.
|
||||
var randomizeWebPageURL = true; // Set to true for debugging.
|
||||
var lastWebPageURL = ""; // Last random URL of tablet web page.
|
||||
var onChatPage = false; // True when chat web page is opened.
|
||||
var webHandlerConnected = false; // True when the web handler has been connected.
|
||||
var channelName = "Chat"; // Unique name for channel that we listen to.
|
||||
var tabletButtonName = "CHAT"; // Tablet button label.
|
||||
var tabletButtonIcon = "icons/tablet-icons/menu-i.svg"; // Icon for chat button.
|
||||
var tabletButtonActiveIcon = "icons/tablet-icons/menu-a.svg"; // Active icon for chat button.
|
||||
var tabletButton = null; // The button we create in the tablet.
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); // The awesome tablet.
|
||||
var chatLog = []; // Array of chat messages in the form of [avatarID, displayName, message, data].
|
||||
var avatarIdentifiers = {}; // Map of avatar ids to dict of identifierParams.
|
||||
var speechBubbleShowing = false; // Is the speech bubble visible?
|
||||
var speechBubbleMessage = null; // The message shown in the speech bubble.
|
||||
var speechBubbleData = null; // The data of the speech bubble message.
|
||||
var speechBubbleTextID = null; // The id of the speech bubble local text entity.
|
||||
var speechBubbleTimer = null; // The timer to pop down the speech bubble.
|
||||
var speechBubbleParams = null; // The params used to create or edit the speech bubble.
|
||||
|
||||
// Persistent variables saved in the Settings.
|
||||
var chatName = ''; // The user's name shown in chat.
|
||||
var chatLogMaxSize = 100; // The maximum number of chat messages we remember.
|
||||
var sendTyping = true; // Send typing begin and end notification.
|
||||
var identifyAvatarDuration = 10; // How long to leave the avatar identity line up, in seconds.
|
||||
var identifyAvatarLineColor = { red: 0, green: 255, blue: 0 }; // The color of the avatar identity line.
|
||||
var identifyAvatarMyJointName = 'Head'; // My bone from which to draw the avatar identity line.
|
||||
var identifyAvatarYourJointName = 'Head'; // Your bone to which to draw the avatar identity line.
|
||||
var speechBubbleDuration = 10; // How long to leave the speech bubble up, in seconds.
|
||||
var speechBubbleTextColor = {red: 255, green: 255, blue: 255}; // The text color of the speech bubble.
|
||||
var speechBubbleBackgroundColor = {red: 0, green: 0, blue: 0}; // The background color of the speech bubble.
|
||||
var speechBubbleOffset = {x: 0, y: 0.3, z: 0.0}; // The offset from the joint to whic the speech bubble is attached.
|
||||
var speechBubbleJointName = 'Head'; // The name of the joint to which the speech bubble is attached.
|
||||
var speechBubbleLineHeight = 0.05; // The height of a line of text in the speech bubble.
|
||||
var SPEECH_BUBBLE_MAX_WIDTH = 1; // meters
|
||||
|
||||
// Load the persistent variables from the Settings, with defaults.
|
||||
function loadSettings() {
|
||||
chatName = Settings.getValue('Chat_chatName', MyAvatar.displayName);
|
||||
if (!chatName) {
|
||||
chatName = randomAvatarName();
|
||||
}
|
||||
chatLogMaxSize = Settings.getValue('Chat_chatLogMaxSize', 100);
|
||||
sendTyping = Settings.getValue('Chat_sendTyping', true);
|
||||
identifyAvatarDuration = Settings.getValue('Chat_identifyAvatarDuration', 10);
|
||||
identifyAvatarLineColor = Settings.getValue('Chat_identifyAvatarLineColor', { red: 0, green: 255, blue: 0 });
|
||||
identifyAvatarMyJointName = Settings.getValue('Chat_identifyAvatarMyJointName', 'Head');
|
||||
identifyAvatarYourJointName = Settings.getValue('Chat_identifyAvatarYourJointName', 'Head');
|
||||
speechBubbleDuration = Settings.getValue('Chat_speechBubbleDuration', 10);
|
||||
speechBubbleTextColor = Settings.getValue('Chat_speechBubbleTextColor', {red: 255, green: 255, blue: 255});
|
||||
speechBubbleBackgroundColor = Settings.getValue('Chat_speechBubbleBackgroundColor', {red: 0, green: 0, blue: 0});
|
||||
speechBubbleOffset = Settings.getValue('Chat_speechBubbleOffset', {x: 0.0, y: 0.3, z:0.0});
|
||||
speechBubbleJointName = Settings.getValue('Chat_speechBubbleJointName', 'Head');
|
||||
speechBubbleLineHeight = Settings.getValue('Chat_speechBubbleLineHeight', 0.05);
|
||||
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
// Save the persistent variables to the Settings.
|
||||
function saveSettings() {
|
||||
Settings.setValue('Chat_chatName', chatName);
|
||||
Settings.setValue('Chat_chatLogMaxSize', chatLogMaxSize);
|
||||
Settings.setValue('Chat_sendTyping', sendTyping);
|
||||
Settings.setValue('Chat_identifyAvatarDuration', identifyAvatarDuration);
|
||||
Settings.setValue('Chat_identifyAvatarLineColor', identifyAvatarLineColor);
|
||||
Settings.setValue('Chat_identifyAvatarMyJointName', identifyAvatarMyJointName);
|
||||
Settings.setValue('Chat_identifyAvatarYourJointName', identifyAvatarYourJointName);
|
||||
Settings.setValue('Chat_speechBubbleDuration', speechBubbleDuration);
|
||||
Settings.setValue('Chat_speechBubbleTextColor', speechBubbleTextColor);
|
||||
Settings.setValue('Chat_speechBubbleBackgroundColor', speechBubbleBackgroundColor);
|
||||
Settings.setValue('Chat_speechBubbleOffset', speechBubbleOffset);
|
||||
Settings.setValue('Chat_speechBubbleJointName', speechBubbleJointName);
|
||||
Settings.setValue('Chat_speechBubbleLineHeight', speechBubbleLineHeight);
|
||||
}
|
||||
|
||||
// Reset the Settings and persistent variables to the defaults.
|
||||
function resetSettings() {
|
||||
Settings.setValue('Chat_chatName', null);
|
||||
Settings.setValue('Chat_chatLogMaxSize', null);
|
||||
Settings.setValue('Chat_sendTyping', null);
|
||||
Settings.setValue('Chat_identifyAvatarDuration', null);
|
||||
Settings.setValue('Chat_identifyAvatarLineColor', null);
|
||||
Settings.setValue('Chat_identifyAvatarMyJointName', null);
|
||||
Settings.setValue('Chat_identifyAvatarYourJointName', null);
|
||||
Settings.setValue('Chat_speechBubbleDuration', null);
|
||||
Settings.setValue('Chat_speechBubbleTextColor', null);
|
||||
Settings.setValue('Chat_speechBubbleBackgroundColor', null);
|
||||
Settings.setValue('Chat_speechBubbleOffset', null);
|
||||
Settings.setValue('Chat_speechBubbleJointName', null);
|
||||
Settings.setValue('Chat_speechBubbleLineHeight', null);
|
||||
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
// Update anything that might depend on the settings.
|
||||
function updateSettings() {
|
||||
updateSpeechBubble();
|
||||
trimChatLog();
|
||||
updateChatPage();
|
||||
}
|
||||
|
||||
// Trim the chat log so it is no longer than chatLogMaxSize lines.
|
||||
function trimChatLog() {
|
||||
if (chatLog.length > chatLogMaxSize) {
|
||||
chatLog.splice(0, chatLogMaxSize - chatLog.length);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the local chat log.
|
||||
function clearChatLog() {
|
||||
//print("clearChatLog");
|
||||
chatLog = [];
|
||||
updateChatPage();
|
||||
}
|
||||
|
||||
// We got a chat message from the channel.
|
||||
// Trim the chat log, save the latest message in the chat log,
|
||||
// and show the message on the tablet, if the chat page is showing.
|
||||
function handleTransmitChatMessage(avatarID, displayName, message, data) {
|
||||
//print("receiveChat", "avatarID", avatarID, "displayName", displayName, "message", message, "data", data);
|
||||
|
||||
trimChatLog();
|
||||
chatLog.push([avatarID, displayName, message, data]);
|
||||
|
||||
if (onChatPage) {
|
||||
tablet.emitScriptEvent(
|
||||
JSON.stringify({
|
||||
type: "ReceiveChatMessage",
|
||||
avatarID: avatarID,
|
||||
displayName: displayName,
|
||||
message: message,
|
||||
data: data
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the chat log, save the latest log message in the chat log,
|
||||
// and show the message on the tablet, if the chat page is showing.
|
||||
function logMessage(message, data) {
|
||||
//print("logMessage", message, data);
|
||||
|
||||
trimChatLog();
|
||||
chatLog.push([null, null, message, data]);
|
||||
|
||||
if (onChatPage) {
|
||||
tablet.emitScriptEvent(
|
||||
JSON.stringify({
|
||||
type: "LogMessage",
|
||||
message: message,
|
||||
data: data
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// An empty chat message was entered.
|
||||
// Hide our speech bubble.
|
||||
function emptyChatMessage(data) {
|
||||
popDownSpeechBubble();
|
||||
}
|
||||
|
||||
// Notification that we typed a keystroke.
|
||||
function type() {
|
||||
//print("type");
|
||||
}
|
||||
|
||||
// Notification that we began typing.
|
||||
// Notify everyone that we started typing.
|
||||
function beginTyping() {
|
||||
//print("beginTyping");
|
||||
if (!sendTyping) {
|
||||
return;
|
||||
}
|
||||
|
||||
Messages.sendMessage(
|
||||
channelName,
|
||||
JSON.stringify({
|
||||
type: 'AvatarBeginTyping',
|
||||
avatarID: MyAvatar.sessionUUID,
|
||||
displayName: chatName
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
// Notification that somebody started typing.
|
||||
function handleAvatarBeginTyping(avatarID, displayName) {
|
||||
//print("handleAvatarBeginTyping:", "avatarID", avatarID, displayName);
|
||||
}
|
||||
|
||||
// Notification that we stopped typing.
|
||||
// Notify everyone that we stopped typing.
|
||||
function endTyping() {
|
||||
//print("endTyping");
|
||||
if (!sendTyping) {
|
||||
return;
|
||||
}
|
||||
|
||||
Messages.sendMessage(
|
||||
channelName,
|
||||
JSON.stringify({
|
||||
type: 'AvatarEndTyping',
|
||||
avatarID: MyAvatar.sessionUUID,
|
||||
displayName: chatName
|
||||
}));
|
||||
}
|
||||
|
||||
// Notification that somebody stopped typing.
|
||||
function handleAvatarEndTyping(avatarID, displayName) {
|
||||
//print("handleAvatarEndTyping:", "avatarID", avatarID, displayName);
|
||||
}
|
||||
|
||||
// Identify an avatar by drawing a line from our head to their head.
|
||||
// If the avatar is our own, then just draw a line up into the sky.
|
||||
function identifyAvatar(yourAvatarID) {
|
||||
//print("identifyAvatar", yourAvatarID);
|
||||
|
||||
unidentifyAvatars();
|
||||
|
||||
var myAvatarID = MyAvatar.sessionUUID;
|
||||
var myJointIndex = MyAvatar.getJointIndex(identifyAvatarMyJointName);
|
||||
var myJointRotation =
|
||||
Quat.multiply(
|
||||
MyAvatar.orientation,
|
||||
MyAvatar.getAbsoluteJointRotationInObjectFrame(myJointIndex));
|
||||
var myJointPosition =
|
||||
Vec3.sum(
|
||||
MyAvatar.position,
|
||||
Vec3.multiplyQbyV(
|
||||
MyAvatar.orientation,
|
||||
MyAvatar.getAbsoluteJointTranslationInObjectFrame(myJointIndex)));
|
||||
|
||||
var yourJointIndex = -1;
|
||||
var yourJointPosition;
|
||||
|
||||
if (yourAvatarID == myAvatarID) {
|
||||
|
||||
// You pointed at your own name, so draw a line up from your head.
|
||||
|
||||
yourJointPosition = {
|
||||
x: myJointPosition.x,
|
||||
y: myJointPosition.y + 1000.0,
|
||||
z: myJointPosition.z
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
// You pointed at somebody else's name, so draw a line from your head to their head.
|
||||
|
||||
var yourAvatar = AvatarList.getAvatar(yourAvatarID);
|
||||
if (!yourAvatar) {
|
||||
return;
|
||||
}
|
||||
|
||||
yourJointIndex = yourAvatar.getJointIndex(identifyAvatarMyJointName)
|
||||
|
||||
var yourJointRotation =
|
||||
Quat.multiply(
|
||||
yourAvatar.orientation,
|
||||
yourAvatar.getAbsoluteJointRotationInObjectFrame(yourJointIndex));
|
||||
yourJointPosition =
|
||||
Vec3.sum(
|
||||
yourAvatar.position,
|
||||
Vec3.multiplyQbyV(
|
||||
yourAvatar.orientation,
|
||||
yourAvatar.getAbsoluteJointTranslationInObjectFrame(yourJointIndex)));
|
||||
|
||||
}
|
||||
|
||||
var identifierParams = {
|
||||
parentID: myAvatarID,
|
||||
parentJointIndex: myJointIndex,
|
||||
lifetime: identifyAvatarDuration,
|
||||
start: myJointPosition,
|
||||
endParentID: yourAvatarID,
|
||||
endParentJointIndex: yourJointIndex,
|
||||
end: yourJointPosition,
|
||||
color: identifyAvatarLineColor,
|
||||
alpha: 1
|
||||
};
|
||||
|
||||
avatarIdentifiers[yourAvatarID] = identifierParams;
|
||||
|
||||
identifierParams.lineID = Overlays.addOverlay("line3d", identifierParams);
|
||||
|
||||
//print("ADDOVERLAY lineID", lineID, "myJointPosition", JSON.stringify(myJointPosition), "yourJointPosition", JSON.stringify(yourJointPosition), "lineData", JSON.stringify(lineData));
|
||||
|
||||
identifierParams.timer =
|
||||
Script.setTimeout(function() {
|
||||
//print("DELETEOVERLAY lineID");
|
||||
unidentifyAvatar(yourAvatarID);
|
||||
}, identifyAvatarDuration * 1000);
|
||||
|
||||
}
|
||||
|
||||
// Stop identifying an avatar.
|
||||
function unidentifyAvatar(yourAvatarID) {
|
||||
//print("unidentifyAvatar", yourAvatarID);
|
||||
|
||||
var identifierParams = avatarIdentifiers[yourAvatarID];
|
||||
if (!identifierParams) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (identifierParams.timer) {
|
||||
Script.clearTimeout(identifierParams.timer);
|
||||
}
|
||||
|
||||
if (identifierParams.lineID) {
|
||||
Overlays.deleteOverlay(identifierParams.lineID);
|
||||
}
|
||||
|
||||
delete avatarIdentifiers[yourAvatarID];
|
||||
}
|
||||
|
||||
// Stop identifying all avatars.
|
||||
function unidentifyAvatars() {
|
||||
var ids = [];
|
||||
|
||||
for (var avatarID in avatarIdentifiers) {
|
||||
ids.push(avatarID);
|
||||
}
|
||||
|
||||
for (var i = 0, n = ids.length; i < n; i++) {
|
||||
var avatarID = ids[i];
|
||||
unidentifyAvatar(avatarID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Turn to face another avatar.
|
||||
function faceAvatar(yourAvatarID, displayName) {
|
||||
//print("faceAvatar:", yourAvatarID, displayName);
|
||||
|
||||
var myAvatarID = MyAvatar.sessionUUID;
|
||||
if (yourAvatarID == myAvatarID) {
|
||||
// You clicked on yourself.
|
||||
return;
|
||||
}
|
||||
|
||||
var yourAvatar = AvatarList.getAvatar(yourAvatarID);
|
||||
if (!yourAvatar) {
|
||||
logMessage(displayName + ' is not here!', null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Project avatar positions to the floor and get the direction between those points,
|
||||
// then face my avatar towards your avatar.
|
||||
var yourPosition = yourAvatar.position;
|
||||
yourPosition.y = 0;
|
||||
var myPosition = MyAvatar.position;
|
||||
myPosition.y = 0;
|
||||
var myOrientation = Quat.lookAtSimple(myPosition, yourPosition);
|
||||
MyAvatar.orientation = myOrientation;
|
||||
}
|
||||
|
||||
// Make a hopefully unique random anonymous avatar name.
|
||||
function randomAvatarName() {
|
||||
return 'Anon_' + Math.floor(Math.random() * 1000000);
|
||||
}
|
||||
|
||||
// Change the avatar size to bigger.
|
||||
function biggerSize() {
|
||||
//print("biggerSize");
|
||||
logMessage("Increasing avatar size", null);
|
||||
MyAvatar.increaseSize();
|
||||
}
|
||||
|
||||
// Change the avatar size to smaller.
|
||||
function smallerSize() {
|
||||
//print("smallerSize");
|
||||
logMessage("Decreasing avatar size", null);
|
||||
MyAvatar.decreaseSize();
|
||||
}
|
||||
|
||||
// Set the avatar size to normal.
|
||||
function normalSize() {
|
||||
//print("normalSize");
|
||||
logMessage("Resetting avatar size to normal!", null);
|
||||
MyAvatar.resetSize();
|
||||
}
|
||||
|
||||
// Send out a "Who" message, including our avatarID as myAvatarID,
|
||||
// which will be sent in the response, so we can tell the reply
|
||||
// is to our request.
|
||||
function transmitWho() {
|
||||
//print("transmitWho");
|
||||
logMessage("Who is here?", null);
|
||||
Messages.sendMessage(
|
||||
channelName,
|
||||
JSON.stringify({
|
||||
type: 'Who',
|
||||
myAvatarID: MyAvatar.sessionUUID
|
||||
}));
|
||||
}
|
||||
|
||||
// Send a reply to a "Who" message, with a friendly message,
|
||||
// our avatarID and our displayName. myAvatarID is the id
|
||||
// of the avatar who send the Who message, to whom we're
|
||||
// responding.
|
||||
function handleWho(myAvatarID) {
|
||||
var avatarID = MyAvatar.sessionUUID;
|
||||
if (myAvatarID == avatarID) {
|
||||
// Don't reply to myself.
|
||||
return;
|
||||
}
|
||||
|
||||
var message = "I'm here!";
|
||||
var data = {};
|
||||
|
||||
Messages.sendMessage(
|
||||
channelName,
|
||||
JSON.stringify({
|
||||
type: 'ReplyWho',
|
||||
myAvatarID: myAvatarID,
|
||||
avatarID: avatarID,
|
||||
displayName: chatName,
|
||||
message: message,
|
||||
data: data
|
||||
}));
|
||||
}
|
||||
|
||||
// Receive the reply to a "Who" message. Ignore it unless we were the one
|
||||
// who sent it out (if myAvatarIS is our avatar's id).
|
||||
function handleReplyWho(myAvatarID, avatarID, displayName, message, data) {
|
||||
if (myAvatarID != MyAvatar.sessionUUID) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleTransmitChatMessage(avatarID, displayName, message, data);
|
||||
}
|
||||
|
||||
// Handle input form the user, possibly multiple lines separated by newlines.
|
||||
// Each line may be a chat command starting with "/", or a chat message.
|
||||
function handleChatMessage(message, data) {
|
||||
|
||||
var messageLines = message.trim().split('\n');
|
||||
|
||||
for (var i = 0, n = messageLines.length; i < n; i++) {
|
||||
var messageLine = messageLines[i];
|
||||
|
||||
if (messageLine.substr(0, 1) == '/') {
|
||||
handleChatCommand(messageLine, data);
|
||||
} else {
|
||||
transmitChatMessage(messageLine, data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle a chat command prefixed by "/".
|
||||
function handleChatCommand(message, data) {
|
||||
|
||||
var commandLine = message.substr(1);
|
||||
var tokens = commandLine.trim().split(' ');
|
||||
var command = tokens[0];
|
||||
var rest = commandLine.substr(command.length + 1).trim();
|
||||
|
||||
//print("commandLine", commandLine, "command", command, "tokens", tokens, "rest", rest);
|
||||
|
||||
switch (command) {
|
||||
|
||||
case '?':
|
||||
case 'help':
|
||||
logMessage('Type "/?" or "/help" for help', null);
|
||||
logMessage('Type "/name <name>" to set your chat name, or "/name" to use your display name. If your display name is not defined, a random name will be used.', null);
|
||||
logMessage('Type "/close" to close your overhead chat message.', null);
|
||||
logMessage('Type "/say <something>" to display a new message.', null);
|
||||
logMessage('Type "/clear" to clear your chat log.', null);
|
||||
logMessage('Type "/who" to ask who is in the chat session.', null);
|
||||
logMessage('Type "/bigger", "/smaller" or "/normal" to change your avatar size.', null);
|
||||
break;
|
||||
|
||||
case 'name':
|
||||
if (rest == '') {
|
||||
if (MyAvatar.displayName) {
|
||||
chatName = MyAvatar.displayName;
|
||||
saveSettings();
|
||||
logMessage('Your chat name has been set to your display name "' + chatName + '".', null);
|
||||
} else {
|
||||
chatName = randomAvatarName();
|
||||
saveSettings();
|
||||
logMessage('Your avatar\'s display name is not defined, so your chat name has been set to "' + chatName + '".', null);
|
||||
}
|
||||
} else {
|
||||
chatName = rest;
|
||||
saveSettings();
|
||||
logMessage('Your chat name has been set to "' + chatName + '".', null);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'close':
|
||||
popDownSpeechBubble();
|
||||
logMessage('Overhead chat message closed.', null);
|
||||
break;
|
||||
|
||||
case 'say':
|
||||
if (rest == '') {
|
||||
emptyChatMessage(data);
|
||||
} else {
|
||||
transmitChatMessage(rest, data);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'who':
|
||||
transmitWho();
|
||||
break;
|
||||
|
||||
case 'clear':
|
||||
clearChatLog();
|
||||
break;
|
||||
|
||||
case 'bigger':
|
||||
biggerSize();
|
||||
break;
|
||||
|
||||
case 'smaller':
|
||||
smallerSize();
|
||||
break;
|
||||
|
||||
case 'normal':
|
||||
normalSize();
|
||||
break;
|
||||
|
||||
case 'resetsettings':
|
||||
resetSettings();
|
||||
updateSettings();
|
||||
break;
|
||||
|
||||
case 'speechbubbleheight':
|
||||
var y = parseInt(rest);
|
||||
if (!isNaN(y)) {
|
||||
speechBubbleOffset.y = y;
|
||||
}
|
||||
saveSettings();
|
||||
updateSettings();
|
||||
break;
|
||||
|
||||
case 'speechbubbleduration':
|
||||
var duration = parseFloat(rest);
|
||||
if (!isNaN(duration)) {
|
||||
speechBubbleDuration = duration;
|
||||
}
|
||||
saveSettings();
|
||||
updateSettings();
|
||||
break;
|
||||
|
||||
default:
|
||||
logMessage('Unknown chat command. Type "/help" or "/?" for help.', null);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Send out a chat message to everyone.
|
||||
function transmitChatMessage(message, data) {
|
||||
//print("transmitChatMessage", 'avatarID', avatarID, 'displayName', displayName, 'message', message, 'data', data);
|
||||
|
||||
popUpSpeechBubble(message, data);
|
||||
|
||||
Messages.sendMessage(
|
||||
channelName,
|
||||
JSON.stringify({
|
||||
type: 'TransmitChatMessage',
|
||||
avatarID: MyAvatar.sessionUUID,
|
||||
displayName: chatName,
|
||||
message: message,
|
||||
data: data
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
// Show the speech bubble.
|
||||
function popUpSpeechBubble(message, data) {
|
||||
//print("popUpSpeechBubble", message, data);
|
||||
|
||||
popDownSpeechBubble();
|
||||
|
||||
speechBubbleShowing = true;
|
||||
speechBubbleMessage = message;
|
||||
speechBubbleData = data;
|
||||
|
||||
updateSpeechBubble();
|
||||
|
||||
if (speechBubbleDuration > 0) {
|
||||
speechBubbleTimer = Script.setTimeout(
|
||||
function () {
|
||||
popDownSpeechBubble();
|
||||
},
|
||||
speechBubbleDuration * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the speech bubble.
|
||||
// This is factored out so we can update an existing speech bubble if any settings change.
|
||||
function updateSpeechBubble() {
|
||||
if (!speechBubbleShowing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var jointIndex = MyAvatar.getJointIndex(speechBubbleJointName);
|
||||
var dimensions = {
|
||||
x: 100.0,
|
||||
y: 100.0,
|
||||
z: 0.1
|
||||
};
|
||||
|
||||
speechBubbleParams = {
|
||||
type: "Text",
|
||||
lifetime: speechBubbleDuration,
|
||||
parentID: MyAvatar.sessionUUID,
|
||||
jointIndex: jointIndex,
|
||||
dimensions: dimensions,
|
||||
lineHeight: speechBubbleLineHeight,
|
||||
leftMargin: 0,
|
||||
topMargin: 0,
|
||||
rightMargin: 0,
|
||||
bottomMargin: 0,
|
||||
faceCamera: true,
|
||||
drawInFront: true,
|
||||
ignoreRayIntersection: true,
|
||||
text: speechBubbleMessage,
|
||||
textColor: speechBubbleTextColor,
|
||||
color: speechBubbleTextColor,
|
||||
backgroundColor: speechBubbleBackgroundColor
|
||||
};
|
||||
|
||||
// Only overlay text3d has a way to measure the text, not entities.
|
||||
// So we make a temporary one just for measuring text, then delete it.
|
||||
var speechBubbleTextOverlayID = Overlays.addOverlay("text3d", speechBubbleParams);
|
||||
var textSize = Overlays.textSize(speechBubbleTextOverlayID, speechBubbleMessage);
|
||||
try {
|
||||
Overlays.deleteOverlay(speechBubbleTextOverlayID);
|
||||
} catch (e) {}
|
||||
|
||||
//print("updateSpeechBubble:", "speechBubbleMessage", speechBubbleMessage, "textSize", textSize.width, textSize.height);
|
||||
|
||||
var fudge = 0.02;
|
||||
|
||||
var width = textSize.width + fudge;
|
||||
var height = speechBubbleLineHeight + fudge;
|
||||
|
||||
if (textSize.width >= SPEECH_BUBBLE_MAX_WIDTH) {
|
||||
var numLines = Math.ceil(width);
|
||||
height = speechBubbleLineHeight * numLines + fudge;
|
||||
width = SPEECH_BUBBLE_MAX_WIDTH;
|
||||
}
|
||||
|
||||
dimensions = {
|
||||
x: width,
|
||||
y: height,
|
||||
z: 0.1
|
||||
};
|
||||
speechBubbleParams.dimensions = dimensions;
|
||||
|
||||
var headRotation =
|
||||
Quat.multiply(
|
||||
MyAvatar.orientation,
|
||||
MyAvatar.getAbsoluteJointRotationInObjectFrame(jointIndex));
|
||||
var headPosition =
|
||||
Vec3.sum(
|
||||
MyAvatar.position,
|
||||
Vec3.multiplyQbyV(
|
||||
MyAvatar.orientation,
|
||||
MyAvatar.getAbsoluteJointTranslationInObjectFrame(jointIndex)));
|
||||
var rotatedOffset =
|
||||
Vec3.multiplyQbyV(
|
||||
headRotation,
|
||||
speechBubbleOffset);
|
||||
var position =
|
||||
Vec3.sum(
|
||||
headPosition,
|
||||
rotatedOffset);
|
||||
position.y += height / 2; // offset based on half of bubble height
|
||||
speechBubbleParams.position = position;
|
||||
|
||||
if (!speechBubbleTextID) {
|
||||
speechBubbleTextID =
|
||||
Entities.addEntity(speechBubbleParams, true);
|
||||
} else {
|
||||
Entities.editEntity(speechBubbleTextID, speechBubbleParams);
|
||||
}
|
||||
|
||||
//print("speechBubbleTextID:", speechBubbleTextID, "speechBubbleParams", JSON.stringify(speechBubbleParams));
|
||||
}
|
||||
|
||||
// Hide the speech bubble.
|
||||
function popDownSpeechBubble() {
|
||||
cancelSpeechBubbleTimer();
|
||||
|
||||
speechBubbleShowing = false;
|
||||
|
||||
//print("popDownSpeechBubble speechBubbleTextID", speechBubbleTextID);
|
||||
|
||||
if (speechBubbleTextID) {
|
||||
try {
|
||||
Entities.deleteEntity(speechBubbleTextID);
|
||||
} catch (e) {}
|
||||
speechBubbleTextID = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the speech bubble popup timer.
|
||||
function cancelSpeechBubbleTimer() {
|
||||
if (speechBubbleTimer) {
|
||||
Script.clearTimeout(speechBubbleTimer);
|
||||
speechBubbleTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Show the tablet web page and connect the web handler.
|
||||
function showTabletWebPage() {
|
||||
var url = Script.resolvePath(webPageURL);
|
||||
if (randomizeWebPageURL) {
|
||||
url += '?rand=' + Math.random();
|
||||
}
|
||||
lastWebPageURL = url;
|
||||
onChatPage = true;
|
||||
tablet.gotoWebScreen(lastWebPageURL);
|
||||
// Connect immediately so we don't miss anything.
|
||||
connectWebHandler();
|
||||
}
|
||||
|
||||
// Update the tablet web page with the chat log.
|
||||
function updateChatPage() {
|
||||
if (!onChatPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
tablet.emitScriptEvent(
|
||||
JSON.stringify({
|
||||
type: "Update",
|
||||
chatLog: chatLog
|
||||
}));
|
||||
}
|
||||
|
||||
function onChatMessageReceived(channel, message, senderID) {
|
||||
|
||||
// Ignore messages to any other channel than mine.
|
||||
if (channel != channelName) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the message and pull out the message parameters.
|
||||
var messageData = JSON.parse(message);
|
||||
var messageType = messageData.type;
|
||||
|
||||
//print("MESSAGE", message);
|
||||
//print("MESSAGEDATA", messageData, JSON.stringify(messageData));
|
||||
|
||||
switch (messageType) {
|
||||
|
||||
case 'TransmitChatMessage':
|
||||
handleTransmitChatMessage(messageData.avatarID, messageData.displayName, messageData.message, messageData.data);
|
||||
break;
|
||||
|
||||
case 'AvatarBeginTyping':
|
||||
handleAvatarBeginTyping(messageData.avatarID, messageData.displayName);
|
||||
break;
|
||||
|
||||
case 'AvatarEndTyping':
|
||||
handleAvatarEndTyping(messageData.avatarID, messageData.displayName);
|
||||
break;
|
||||
|
||||
case 'Who':
|
||||
handleWho(messageData.myAvatarID);
|
||||
break;
|
||||
|
||||
case 'ReplyWho':
|
||||
handleReplyWho(messageData.myAvatarID, messageData.avatarID, messageData.displayName, messageData.message, messageData.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
print("onChatMessageReceived: unknown messageType", messageType, "message", message);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Handle events from the tablet web page.
|
||||
function onWebEventReceived(event) {
|
||||
if (!onChatPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
//print("onWebEventReceived: event", event);
|
||||
|
||||
var eventData = JSON.parse(event);
|
||||
var eventType = eventData.type;
|
||||
|
||||
switch (eventType) {
|
||||
|
||||
case 'Ready':
|
||||
updateChatPage();
|
||||
break;
|
||||
|
||||
case 'Update':
|
||||
updateChatPage();
|
||||
break;
|
||||
|
||||
case 'HandleChatMessage':
|
||||
var message = eventData.message;
|
||||
var data = eventData.data;
|
||||
//print("onWebEventReceived: HandleChatMessage:", 'message', message, 'data', data);
|
||||
handleChatMessage(message, data);
|
||||
break;
|
||||
|
||||
case 'PopDownSpeechBubble':
|
||||
popDownSpeechBubble();
|
||||
break;
|
||||
|
||||
case 'EmptyChatMessage':
|
||||
emptyChatMessage();
|
||||
break;
|
||||
|
||||
case 'Type':
|
||||
type();
|
||||
break;
|
||||
|
||||
case 'BeginTyping':
|
||||
beginTyping();
|
||||
break;
|
||||
|
||||
case 'EndTyping':
|
||||
endTyping();
|
||||
break;
|
||||
|
||||
case 'IdentifyAvatar':
|
||||
identifyAvatar(eventData.avatarID);
|
||||
break;
|
||||
|
||||
case 'UnidentifyAvatar':
|
||||
unidentifyAvatar(eventData.avatarID);
|
||||
break;
|
||||
|
||||
case 'FaceAvatar':
|
||||
faceAvatar(eventData.avatarID, eventData.displayName);
|
||||
break;
|
||||
|
||||
case 'ClearChatLog':
|
||||
clearChatLog();
|
||||
break;
|
||||
|
||||
case 'Who':
|
||||
transmitWho();
|
||||
break;
|
||||
|
||||
case 'Bigger':
|
||||
biggerSize();
|
||||
break;
|
||||
|
||||
case 'Smaller':
|
||||
smallerSize();
|
||||
break;
|
||||
|
||||
case 'Normal':
|
||||
normalSize();
|
||||
break;
|
||||
|
||||
default:
|
||||
print("onWebEventReceived: unexpected eventType", eventType);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function onScreenChanged(type, url) {
|
||||
//print("onScreenChanged", "type", type, "url", url, "lastWebPageURL", lastWebPageURL);
|
||||
|
||||
if ((type === "Web") &&
|
||||
(url === lastWebPageURL)) {
|
||||
if (!onChatPage) {
|
||||
onChatPage = true;
|
||||
connectWebHandler();
|
||||
}
|
||||
} else {
|
||||
if (onChatPage) {
|
||||
onChatPage = false;
|
||||
disconnectWebHandler();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function connectWebHandler() {
|
||||
if (webHandlerConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
tablet.webEventReceived.connect(onWebEventReceived);
|
||||
} catch (e) {
|
||||
print("connectWebHandler: error connecting: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
webHandlerConnected = true;
|
||||
//print("connectWebHandler connected");
|
||||
|
||||
updateChatPage();
|
||||
}
|
||||
|
||||
function disconnectWebHandler() {
|
||||
if (!webHandlerConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
tablet.webEventReceived.disconnect(onWebEventReceived);
|
||||
} catch (e) {
|
||||
print("disconnectWebHandler: error disconnecting web handler: " + e);
|
||||
return;
|
||||
}
|
||||
webHandlerConnected = false;
|
||||
|
||||
//print("disconnectWebHandler: disconnected");
|
||||
}
|
||||
|
||||
// Show the tablet web page when the chat button on the tablet is clicked.
|
||||
function onTabletButtonClicked() {
|
||||
showTabletWebPage();
|
||||
}
|
||||
|
||||
// Shut down the chat application when the tablet button is destroyed.
|
||||
function onTabletButtonDestroyed() {
|
||||
shutDown();
|
||||
}
|
||||
|
||||
// Start up the chat application.
|
||||
function startUp() {
|
||||
//print("startUp");
|
||||
|
||||
loadSettings();
|
||||
|
||||
tabletButton = tablet.addButton({
|
||||
icon: tabletButtonIcon,
|
||||
activeIcon: tabletButtonActiveIcon,
|
||||
text: tabletButtonName
|
||||
});
|
||||
|
||||
Messages.subscribe(channelName);
|
||||
|
||||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
Messages.messageReceived.connect(onChatMessageReceived);
|
||||
|
||||
tabletButton.clicked.connect(onTabletButtonClicked);
|
||||
|
||||
Script.scriptEnding.connect(onTabletButtonDestroyed);
|
||||
|
||||
logMessage('Type "/?" or "/help" for help with chat.', null);
|
||||
|
||||
//print("Added chat button to tablet.");
|
||||
}
|
||||
|
||||
// Shut down the chat application.
|
||||
function shutDown() {
|
||||
//print("shutDown");
|
||||
|
||||
popDownSpeechBubble();
|
||||
unidentifyAvatars();
|
||||
disconnectWebHandler();
|
||||
|
||||
if (onChatPage) {
|
||||
tablet.gotoHomeScreen();
|
||||
onChatPage = false;
|
||||
}
|
||||
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
|
||||
Messages.messageReceived.disconnect(onChatMessageReceived);
|
||||
|
||||
// Clean up the tablet button we made.
|
||||
tabletButton.clicked.disconnect(onTabletButtonClicked);
|
||||
tablet.removeButton(tabletButton);
|
||||
tabletButton = null;
|
||||
|
||||
//print("Removed chat button from tablet.");
|
||||
}
|
||||
|
||||
// Kick off the chat application!
|
||||
startUp();
|
||||
|
||||
}());
|
|
@ -34,11 +34,11 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
|||
"system/emote.js",
|
||||
"system/miniTablet.js",
|
||||
"system/audioMuteOverlay.js",
|
||||
"system/keyboardShortcuts/keyboardShortcuts.js",
|
||||
"community/chat.js"
|
||||
"system/keyboardShortcuts/keyboardShortcuts.js"
|
||||
];
|
||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||
"system/controllers/controllerScripts.js"
|
||||
//"system/chat.js"
|
||||
];
|
||||
|
||||
if (Window.interstitialModeEnabled) {
|
||||
|
|
Loading…
Reference in a new issue