mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:21:24 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into blue
This commit is contained in:
commit
363db8a834
15 changed files with 283 additions and 54 deletions
|
@ -1306,7 +1306,9 @@ function badgeSidebarForDifferences(changedElement) {
|
||||||
var isGrouped = $('#' + panelParentID).hasClass('grouped');
|
var isGrouped = $('#' + panelParentID).hasClass('grouped');
|
||||||
|
|
||||||
if (isGrouped) {
|
if (isGrouped) {
|
||||||
var initialPanelJSON = Settings.initialValues[panelParentID];
|
var initialPanelJSON = Settings.initialValues[panelParentID]
|
||||||
|
? Settings.initialValues[panelParentID]
|
||||||
|
: {};
|
||||||
|
|
||||||
// get a JSON representation of that section
|
// get a JSON representation of that section
|
||||||
var panelJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID];
|
var panelJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID];
|
||||||
|
@ -1417,7 +1419,7 @@ function addTableRow(row) {
|
||||||
|
|
||||||
input_clone.children('td').each(function () {
|
input_clone.children('td').each(function () {
|
||||||
if ($(this).attr("name") !== keepField) {
|
if ($(this).attr("name") !== keepField) {
|
||||||
$(this).find("input").val($(this).attr('data-default'));
|
$(this).find("input").val($(this).children('input').attr('data-default'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1595,7 +1597,11 @@ function updateDataChangedForSiblingRows(row, forceTrue) {
|
||||||
|
|
||||||
// get a JSON representation of that section
|
// get a JSON representation of that section
|
||||||
var panelSettingJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID][tableShortName]
|
var panelSettingJSON = form2js(panelParentID, ".", false, cleanupFormValues, true)[panelParentID][tableShortName]
|
||||||
var initialPanelSettingJSON = Settings.initialValues[panelParentID][tableShortName]
|
if (Settings.initialValues[panelParentID]) {
|
||||||
|
var initialPanelSettingJSON = Settings.initialValues[panelParentID][tableShortName]
|
||||||
|
} else {
|
||||||
|
var initialPanelSettingJSON = {};
|
||||||
|
}
|
||||||
|
|
||||||
// if they are equal, we don't need data-changed
|
// if they are equal, we don't need data-changed
|
||||||
isTrue = !_.isEqual(panelSettingJSON, initialPanelSettingJSON)
|
isTrue = !_.isEqual(panelSettingJSON, initialPanelSettingJSON)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"to": "Actions.Up",
|
"to": "Actions.Up",
|
||||||
"filters":
|
"filters":
|
||||||
[
|
[
|
||||||
{ "type": "deadZone", "min": 0.95 },
|
{ "type": "deadZone", "min": 0.6 },
|
||||||
"invert"
|
"invert"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -87,7 +87,11 @@ Item {
|
||||||
if (topMenu.objectName === "") {
|
if (topMenu.objectName === "") {
|
||||||
breadcrumbText.text = "Menu";
|
breadcrumbText.text = "Menu";
|
||||||
} else {
|
} else {
|
||||||
breadcrumbText.text = topMenu.objectName;
|
if (menuStack.length === 1) {
|
||||||
|
breadcrumbText.text = "Menu";
|
||||||
|
} else {
|
||||||
|
breadcrumbText.text = topMenu.objectName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
breadcrumbText.text = "Menu";
|
breadcrumbText.text = "Menu";
|
||||||
|
|
|
@ -74,6 +74,11 @@ int main(int argc, const char* argv[]) {
|
||||||
instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
|
instanceMightBeRunning = !sharedMemory.create(1, QSharedMemory::ReadOnly);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// allow multiple interfaces to run if this environment variable is set.
|
||||||
|
if (QProcessEnvironment::systemEnvironment().contains("HIFI_ALLOW_MULTIPLE_INSTANCES")) {
|
||||||
|
instanceMightBeRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (instanceMightBeRunning) {
|
if (instanceMightBeRunning) {
|
||||||
// Try to connect and send message to existing interface instance
|
// Try to connect and send message to existing interface instance
|
||||||
QLocalSocket socket;
|
QLocalSocket socket;
|
||||||
|
|
|
@ -25,6 +25,9 @@ void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputC
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
userInputMapper->withLock([&, this]() {
|
userInputMapper->withLock([&, this]() {
|
||||||
_inputDevice->update(deltaTime, inputCalibrationData);
|
_inputDevice->update(deltaTime, inputCalibrationData);
|
||||||
|
|
||||||
|
_inputDevice->_axisStateMap[MOUSE_AXIS_X] = _lastCursor.x();
|
||||||
|
_inputDevice->_axisStateMap[MOUSE_AXIS_Y] = _lastCursor.y();
|
||||||
});
|
});
|
||||||
|
|
||||||
// For touch event, we need to check that the last event is not too long ago
|
// For touch event, we need to check that the last event is not too long ago
|
||||||
|
@ -249,6 +252,9 @@ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInp
|
||||||
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_Y_POS), "MouseMoveUp"));
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_Y_POS), "MouseMoveUp"));
|
||||||
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_Y_NEG), "MouseMoveDown"));
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_Y_NEG), "MouseMoveDown"));
|
||||||
|
|
||||||
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_X), "MouseX"));
|
||||||
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_Y), "MouseY"));
|
||||||
|
|
||||||
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_Y_POS), "MouseWheelRight"));
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_Y_POS), "MouseWheelRight"));
|
||||||
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_Y_NEG), "MouseWheelLeft"));
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_Y_NEG), "MouseWheelLeft"));
|
||||||
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_X_POS), "MouseWheelUp"));
|
availableInputs.append(Input::NamedPair(makeInput(MOUSE_AXIS_WHEEL_X_POS), "MouseWheelUp"));
|
||||||
|
|
|
@ -47,6 +47,8 @@ public:
|
||||||
MOUSE_AXIS_X_NEG,
|
MOUSE_AXIS_X_NEG,
|
||||||
MOUSE_AXIS_Y_POS,
|
MOUSE_AXIS_Y_POS,
|
||||||
MOUSE_AXIS_Y_NEG,
|
MOUSE_AXIS_Y_NEG,
|
||||||
|
MOUSE_AXIS_X,
|
||||||
|
MOUSE_AXIS_Y,
|
||||||
MOUSE_AXIS_WHEEL_Y_POS,
|
MOUSE_AXIS_WHEEL_Y_POS,
|
||||||
MOUSE_AXIS_WHEEL_Y_NEG,
|
MOUSE_AXIS_WHEEL_Y_NEG,
|
||||||
MOUSE_AXIS_WHEEL_X_POS,
|
MOUSE_AXIS_WHEEL_X_POS,
|
||||||
|
|
|
@ -26,6 +26,10 @@ glm::mat4 Mat4::createFromScaleRotAndTrans(const glm::vec3& scale, const glm::qu
|
||||||
return createMatFromScaleQuatAndPos(scale, rot, trans);
|
return createMatFromScaleQuatAndPos(scale, rot, trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::mat4 Mat4::createFromColumns(const glm::vec4& col0, const glm::vec4& col1, const glm::vec4& col2, const glm::vec4& col3) const {
|
||||||
|
return glm::mat4(col0, col1, col2, col3);
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec3 Mat4::extractTranslation(const glm::mat4& m) const {
|
glm::vec3 Mat4::extractTranslation(const glm::mat4& m) const {
|
||||||
return ::extractTranslation(m);
|
return ::extractTranslation(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,10 @@ class Mat4 : public QObject {
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
glm::mat4 multiply(const glm::mat4& m1, const glm::mat4& m2) const;
|
glm::mat4 multiply(const glm::mat4& m1, const glm::mat4& m2) const;
|
||||||
|
|
||||||
glm::mat4 createFromRotAndTrans(const glm::quat& rot, const glm::vec3& trans) const;
|
glm::mat4 createFromRotAndTrans(const glm::quat& rot, const glm::vec3& trans) const;
|
||||||
glm::mat4 createFromScaleRotAndTrans(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) const;
|
glm::mat4 createFromScaleRotAndTrans(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) const;
|
||||||
|
glm::mat4 createFromColumns(const glm::vec4& col0, const glm::vec4& col1, const glm::vec4& col2, const glm::vec4& col3) const;
|
||||||
|
|
||||||
glm::vec3 extractTranslation(const glm::mat4& m) const;
|
glm::vec3 extractTranslation(const glm::mat4& m) const;
|
||||||
glm::quat extractRotation(const glm::mat4& m) const;
|
glm::quat extractRotation(const glm::mat4& m) const;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
var MESSAGE_CHANNEL = "io.highfidelity.summon-crowd";
|
var MESSAGE_CHANNEL = "io.highfidelity.summon-crowd";
|
||||||
|
|
||||||
print('crowd-agent version 4');
|
print('crowd-agent version 5');
|
||||||
|
|
||||||
/* Observations:
|
/* Observations:
|
||||||
- File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development.
|
- File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development.
|
||||||
|
@ -84,6 +84,9 @@ function startAgent(parameters) { // Can also be used to update.
|
||||||
clearStopper();
|
clearStopper();
|
||||||
var wasOff = !Agent.isAvatar;
|
var wasOff = !Agent.isAvatar;
|
||||||
Agent.isAvatar = true;
|
Agent.isAvatar = true;
|
||||||
|
if (parameters.displayName !== undefined) {
|
||||||
|
Avatar.displayName = parameters.displayName;
|
||||||
|
}
|
||||||
if (parameters.position) {
|
if (parameters.position) {
|
||||||
Avatar.position = parameters.position;
|
Avatar.position = parameters.position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
// See crowd-agent.js
|
// See crowd-agent.js
|
||||||
|
|
||||||
var version = 2;
|
var version = 3;
|
||||||
var label = "summon";
|
var label = "summon";
|
||||||
function debug() {
|
function debug() {
|
||||||
print.apply(null, [].concat.apply([label, version], [].map.call(arguments, JSON.stringify)));
|
print.apply(null, [].concat.apply([label, version], [].map.call(arguments, JSON.stringify)));
|
||||||
|
@ -23,6 +23,9 @@ var MINIMUM_AVATARS = 25; // We will summon agents to produce this many total. (
|
||||||
var N_LISTENING = MINIMUM_AVATARS - 1;
|
var N_LISTENING = MINIMUM_AVATARS - 1;
|
||||||
var AVATARS_CHATTERING_AT_ONCE = 4; // How many of the agents should we request to play SOUND_DATA at once.
|
var AVATARS_CHATTERING_AT_ONCE = 4; // How many of the agents should we request to play SOUND_DATA at once.
|
||||||
|
|
||||||
|
var initialBubble = Users.getIgnoreRadiusEnabled();
|
||||||
|
debug('startup seeking:', MINIMUM_AVATARS, 'listening:', N_LISTENING, 'chattering:', AVATARS_CHATTERING_AT_ONCE, 'had bubble:', initialBubble);
|
||||||
|
|
||||||
// If we add or remove things too quickly, we get problems (e.g., audio, fogbugz 2095).
|
// If we add or remove things too quickly, we get problems (e.g., audio, fogbugz 2095).
|
||||||
// For now, spread them out this timing apart.
|
// For now, spread them out this timing apart.
|
||||||
var SPREAD_TIME_MS = 500;
|
var SPREAD_TIME_MS = 500;
|
||||||
|
@ -66,7 +69,7 @@ function messageHandler(channel, messageString, senderID) {
|
||||||
if (MyAvatar.sessionUUID === senderID) { // ignore my own
|
if (MyAvatar.sessionUUID === senderID) { // ignore my own
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var message = {}, avatarIdentifiers;
|
var message = {};
|
||||||
try {
|
try {
|
||||||
message = JSON.parse(messageString);
|
message = JSON.parse(messageString);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -76,9 +79,10 @@ function messageHandler(channel, messageString, senderID) {
|
||||||
case "hello":
|
case "hello":
|
||||||
Script.setTimeout(function () {
|
Script.setTimeout(function () {
|
||||||
// There can be avatars we've summoned that do not yet appear in the AvatarList.
|
// There can be avatars we've summoned that do not yet appear in the AvatarList.
|
||||||
avatarIdentifiers = without(AvatarList.getAvatarIdentifiers(), summonedAgents);
|
var avatarIdentifiers = without(AvatarList.getAvatarIdentifiers(), summonedAgents);
|
||||||
|
var nSummoned = summonedAgents.length;
|
||||||
debug('present', avatarIdentifiers, summonedAgents);
|
debug('present', avatarIdentifiers, summonedAgents);
|
||||||
if ((summonedAgents.length + avatarIdentifiers.length) < MINIMUM_AVATARS ) {
|
if ((nSummoned + avatarIdentifiers.length) < MINIMUM_AVATARS ) {
|
||||||
var chatter = chattering.length < AVATARS_CHATTERING_AT_ONCE;
|
var chatter = chattering.length < AVATARS_CHATTERING_AT_ONCE;
|
||||||
var listen = nListening < N_LISTENING;
|
var listen = nListening < N_LISTENING;
|
||||||
if (chatter) {
|
if (chatter) {
|
||||||
|
@ -91,6 +95,7 @@ function messageHandler(channel, messageString, senderID) {
|
||||||
messageSend({
|
messageSend({
|
||||||
key: 'SUMMON',
|
key: 'SUMMON',
|
||||||
rcpt: senderID,
|
rcpt: senderID,
|
||||||
|
displayName: "crowd " + nSummoned + " " + senderID,
|
||||||
position: Vec3.sum(MyAvatar.position, {x: coord(), y: 0, z: coord()}),
|
position: Vec3.sum(MyAvatar.position, {x: coord(), y: 0, z: coord()}),
|
||||||
orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0),
|
orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0),
|
||||||
soundData: chatter && SOUND_DATA,
|
soundData: chatter && SOUND_DATA,
|
||||||
|
@ -100,7 +105,7 @@ function messageHandler(channel, messageString, senderID) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, accumulatedDelay);
|
}, accumulatedDelay);
|
||||||
accumulatedDelay += SPREAD_TIME_MS; // assume we'll get all the hello respsponses more or less together.
|
accumulatedDelay += SPREAD_TIME_MS; // assume we'll get all the hello responses more or less together.
|
||||||
break;
|
break;
|
||||||
case "finishedSound": // Give someone else a chance.
|
case "finishedSound": // Give someone else a chance.
|
||||||
chattering = without(chattering, [senderID]);
|
chattering = without(chattering, [senderID]);
|
||||||
|
@ -123,6 +128,8 @@ Messages.subscribe(MESSAGE_CHANNEL);
|
||||||
Messages.messageReceived.connect(messageHandler);
|
Messages.messageReceived.connect(messageHandler);
|
||||||
Script.scriptEnding.connect(function () {
|
Script.scriptEnding.connect(function () {
|
||||||
debug('stopping agents', summonedAgents);
|
debug('stopping agents', summonedAgents);
|
||||||
|
Users.requestsDomainListData = false;
|
||||||
|
if (initialBubble && !Users.getIgnoreRadiusEnabled()) { Users.toggleIgnoreRadius(); }
|
||||||
Messages.messageReceived.disconnect(messageHandler); // don't respond to any messages during shutdown
|
Messages.messageReceived.disconnect(messageHandler); // don't respond to any messages during shutdown
|
||||||
accumulatedDelay = 0;
|
accumulatedDelay = 0;
|
||||||
summonedAgents.forEach(function (id) {
|
summonedAgents.forEach(function (id) {
|
||||||
|
@ -134,14 +141,17 @@ Script.scriptEnding.connect(function () {
|
||||||
debug('unsubscribed');
|
debug('unsubscribed');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Users.requestsDomainListData = true; // Get avatar data for the whole domain, even if not in our view.
|
||||||
|
if (initialBubble) { Users.toggleIgnoreRadius(); }
|
||||||
messageSend({key: 'HELO'}); // Ask agents to report in now.
|
messageSend({key: 'HELO'}); // Ask agents to report in now.
|
||||||
Script.setTimeout(function () {
|
Script.setTimeout(function () {
|
||||||
var total = AvatarList.getAvatarIdentifiers().length;
|
var total = AvatarList.getAvatarIdentifiers().length;
|
||||||
if (0 === summonedAgents.length) {
|
if (0 === summonedAgents.length) {
|
||||||
Window.alert("No agents reported.\n\Please run " + MINIMUM_AVATARS + " instances of\n\
|
Window.alert("No agents reported.\n\Please run " + MINIMUM_AVATARS + " instances of\n\
|
||||||
http://hifi-content.s3.amazonaws.com/howard/scripts/tests/performance/crowd-agent.js\n\
|
http://hifi-content.s3.amazonaws.com/howard/scripts/tests/performance/crowd-agent.js?v=someDate\n\
|
||||||
on your domain server.");
|
on your domain server.");
|
||||||
} else if (total < MINIMUM_AVATARS) {
|
} else if (total < MINIMUM_AVATARS) {
|
||||||
Window.alert("Only " + summonedAgents.length + " agents reported. Now missing " + (MINIMUM_AVATARS - total) + " avatars, total.");
|
Window.alert("Only " + summonedAgents.length + " agents reported. Now missing " + (MINIMUM_AVATARS - total) + " avatars, total.");
|
||||||
}
|
}
|
||||||
|
Users.requestsDomainListData = false;
|
||||||
}, MINIMUM_AVATARS * SPREAD_TIME_MS )
|
}, MINIMUM_AVATARS * SPREAD_TIME_MS )
|
||||||
|
|
|
@ -53,6 +53,13 @@ var HAPTIC_TEXTURE_DISTANCE = 0.002;
|
||||||
var HAPTIC_DEQUIP_STRENGTH = 0.75;
|
var HAPTIC_DEQUIP_STRENGTH = 0.75;
|
||||||
var HAPTIC_DEQUIP_DURATION = 50.0;
|
var HAPTIC_DEQUIP_DURATION = 50.0;
|
||||||
|
|
||||||
|
// triggered when stylus presses a web overlay/entity
|
||||||
|
var HAPTIC_STYLUS_STRENGTH = 1.0;
|
||||||
|
var HAPTIC_STYLUS_DURATION = 20.0;
|
||||||
|
|
||||||
|
// triggerd when ui laser presses a web overlay/entity
|
||||||
|
var HAPTIC_LASER_UI_STRENGTH = 1.0;
|
||||||
|
var HAPTIC_LASER_UI_DURATION = 20.0;
|
||||||
|
|
||||||
var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move.
|
var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move.
|
||||||
|
|
||||||
|
@ -122,7 +129,6 @@ var GRAB_POINT_SPHERE_RADIUS = NEAR_GRAB_RADIUS;
|
||||||
var GRAB_POINT_SPHERE_COLOR = { red: 240, green: 240, blue: 240 };
|
var GRAB_POINT_SPHERE_COLOR = { red: 240, green: 240, blue: 240 };
|
||||||
var GRAB_POINT_SPHERE_ALPHA = 0.85;
|
var GRAB_POINT_SPHERE_ALPHA = 0.85;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// other constants
|
// other constants
|
||||||
//
|
//
|
||||||
|
@ -1248,7 +1254,7 @@ function MyController(hand) {
|
||||||
if (homeButton === hmdHomeButton) {
|
if (homeButton === hmdHomeButton) {
|
||||||
if (this.homeButtonTouched === false) {
|
if (this.homeButtonTouched === false) {
|
||||||
this.homeButtonTouched = true;
|
this.homeButtonTouched = true;
|
||||||
Controller.triggerHapticPulse(1, 20, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand);
|
||||||
Messages.sendLocalMessage("home", homeButton);
|
Messages.sendLocalMessage("home", homeButton);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1266,7 +1272,7 @@ function MyController(hand) {
|
||||||
if (homeButton === hmdHomeButton) {
|
if (homeButton === hmdHomeButton) {
|
||||||
if (this.homeButtonTouched === false) {
|
if (this.homeButtonTouched === false) {
|
||||||
this.homeButtonTouched = true;
|
this.homeButtonTouched = true;
|
||||||
Controller.triggerHapticPulse(1, 20, this.hand);
|
Controller.triggerHapticPulse(HAPTIC_LASER_UI_STRENGTH, HAPTIC_LASER_UI_DURATION, this.hand);
|
||||||
Messages.sendLocalMessage("home", homeButton);
|
Messages.sendLocalMessage("home", homeButton);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1754,7 +1760,6 @@ function MyController(hand) {
|
||||||
Entities.sendHoverOverEntity(entity, pointerEvent);
|
Entities.sendHoverOverEntity(entity, pointerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.grabbedEntity = entity;
|
this.grabbedEntity = entity;
|
||||||
this.setState(STATE_ENTITY_STYLUS_TOUCHING, "begin touching entity '" + name + "'");
|
this.setState(STATE_ENTITY_STYLUS_TOUCHING, "begin touching entity '" + name + "'");
|
||||||
return true;
|
return true;
|
||||||
|
@ -1775,11 +1780,6 @@ function MyController(hand) {
|
||||||
var pointerEvent;
|
var pointerEvent;
|
||||||
if (rayPickInfo.overlayID) {
|
if (rayPickInfo.overlayID) {
|
||||||
var overlay = rayPickInfo.overlayID;
|
var overlay = rayPickInfo.overlayID;
|
||||||
|
|
||||||
if (!this.homeButtonTouched) {
|
|
||||||
Controller.triggerHapticPulse(1, 20, this.hand);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Overlays.keyboardFocusOverlay != overlay) {
|
if (Overlays.keyboardFocusOverlay != overlay) {
|
||||||
Entities.keyboardFocusEntity = null;
|
Entities.keyboardFocusEntity = null;
|
||||||
Overlays.keyboardFocusOverlay = overlay;
|
Overlays.keyboardFocusOverlay = overlay;
|
||||||
|
@ -2710,6 +2710,12 @@ function MyController(hand) {
|
||||||
var theta = this.state === STATE_ENTITY_STYLUS_TOUCHING ? STYLUS_PRESS_TO_MOVE_DEADSPOT_ANGLE : LASER_PRESS_TO_MOVE_DEADSPOT_ANGLE;
|
var theta = this.state === STATE_ENTITY_STYLUS_TOUCHING ? STYLUS_PRESS_TO_MOVE_DEADSPOT_ANGLE : LASER_PRESS_TO_MOVE_DEADSPOT_ANGLE;
|
||||||
this.deadspotRadius = Math.tan(theta) * intersectInfo.distance; // dead spot radius in meters
|
this.deadspotRadius = Math.tan(theta) * intersectInfo.distance; // dead spot radius in meters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.state == STATE_ENTITY_STYLUS_TOUCHING) {
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand);
|
||||||
|
} else if (this.state == STATE_ENTITY_LASER_TOUCHING) {
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_LASER_UI_STRENGTH, HAPTIC_LASER_UI_DURATION, this.hand);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityTouchingExit = function() {
|
this.entityTouchingExit = function() {
|
||||||
|
@ -2829,6 +2835,12 @@ function MyController(hand) {
|
||||||
var theta = this.state === STATE_OVERLAY_STYLUS_TOUCHING ? STYLUS_PRESS_TO_MOVE_DEADSPOT_ANGLE : LASER_PRESS_TO_MOVE_DEADSPOT_ANGLE;
|
var theta = this.state === STATE_OVERLAY_STYLUS_TOUCHING ? STYLUS_PRESS_TO_MOVE_DEADSPOT_ANGLE : LASER_PRESS_TO_MOVE_DEADSPOT_ANGLE;
|
||||||
this.deadspotRadius = Math.tan(theta) * intersectInfo.distance; // dead spot radius in meters
|
this.deadspotRadius = Math.tan(theta) * intersectInfo.distance; // dead spot radius in meters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.state == STATE_OVERLAY_STYLUS_TOUCHING) {
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_STYLUS_STRENGTH, HAPTIC_STYLUS_DURATION, this.hand);
|
||||||
|
} else if (this.state == STATE_OVERLAY_LASER_TOUCHING) {
|
||||||
|
Controller.triggerHapticPulse(HAPTIC_LASER_UI_STRENGTH, HAPTIC_LASER_UI_DURATION, this.hand);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.overlayTouchingExit = function () {
|
this.overlayTouchingExit = function () {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
/* global getControllerWorldLocation, setEntityCustomData, Tablet, WebTablet:true, HMD, Settings, Script,
|
/* global getControllerWorldLocation, setEntityCustomData, Tablet, WebTablet:true, HMD, Settings, Script,
|
||||||
Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform */
|
Vec3, Quat, MyAvatar, Entities, Overlays, Camera, Messages, Xform, clamp */
|
||||||
|
|
||||||
Script.include(Script.resolvePath("../libraries/utils.js"));
|
Script.include(Script.resolvePath("../libraries/utils.js"));
|
||||||
Script.include(Script.resolvePath("../libraries/controllers.js"));
|
Script.include(Script.resolvePath("../libraries/controllers.js"));
|
||||||
|
@ -118,7 +118,7 @@ WebTablet = function (url, width, dpi, hand, clientOnly) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
this.calculateTabletAttachmentProperties(hand, tabletProperties);
|
this.calculateTabletAttachmentProperties(hand, true, tabletProperties);
|
||||||
|
|
||||||
this.cleanUpOldTablets();
|
this.cleanUpOldTablets();
|
||||||
this.tabletEntityID = Entities.addEntity(tabletProperties, clientOnly);
|
this.tabletEntityID = Entities.addEntity(tabletProperties, clientOnly);
|
||||||
|
@ -252,31 +252,78 @@ WebTablet.prototype.destroy = function () {
|
||||||
WebTablet.prototype.geometryChanged = function (geometry) {
|
WebTablet.prototype.geometryChanged = function (geometry) {
|
||||||
if (!HMD.active) {
|
if (!HMD.active) {
|
||||||
var tabletProperties = {};
|
var tabletProperties = {};
|
||||||
|
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties);
|
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
||||||
Entities.editEntity(this.tabletEntityID, tabletProperties);
|
Entities.editEntity(this.tabletEntityID, tabletProperties);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function gluPerspective(fovy, aspect, zNear, zFar) {
|
||||||
|
var cotan = 1 / Math.tan(fovy / 2);
|
||||||
|
var alpha = -(zFar + zNear) / (zFar - zNear);
|
||||||
|
var beta = -(2 * zFar * zNear) / (zFar - zNear);
|
||||||
|
var col0 = {x: cotan / aspect, y: 0, z: 0, w: 0};
|
||||||
|
var col1 = {x: 0, y: cotan, z: 0, w: 0};
|
||||||
|
var col2 = {x: 0, y: 0, z: alpha, w: -1};
|
||||||
|
var col3 = {x: 0, y: 0, z: beta, w: 0};
|
||||||
|
return Mat4.createFromColumns(col0, col1, col2, col3);
|
||||||
|
}
|
||||||
|
|
||||||
// calclulate the appropriate position of the tablet in world space, such that it fits in the center of the screen.
|
// calclulate the appropriate position of the tablet in world space, such that it fits in the center of the screen.
|
||||||
// with a bit of padding on the top and bottom.
|
// with a bit of padding on the top and bottom.
|
||||||
WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function () {
|
// windowPos is used to position the center of the tablet at the given position.
|
||||||
|
WebTablet.prototype.calculateWorldAttitudeRelativeToCamera = function (windowPos) {
|
||||||
|
|
||||||
var DEFAULT_DESKTOP_TABLET_SCALE = 75;
|
var DEFAULT_DESKTOP_TABLET_SCALE = 75;
|
||||||
var DESKTOP_TABLET_SCALE = Settings.getValue("desktopTabletScale") || DEFAULT_DESKTOP_TABLET_SCALE;
|
var DESKTOP_TABLET_SCALE = Settings.getValue("desktopTabletScale") || DEFAULT_DESKTOP_TABLET_SCALE;
|
||||||
|
|
||||||
|
// clamp window pos so 2d tablet is not off-screen.
|
||||||
|
var TABLET_TEXEL_PADDING = {x: 60, y: 90};
|
||||||
|
var X_CLAMP = (DESKTOP_TABLET_SCALE / 100) * ((TABLET_TEXTURE_RESOLUTION.x / 2) + TABLET_TEXEL_PADDING.x);
|
||||||
|
var Y_CLAMP = (DESKTOP_TABLET_SCALE / 100) * ((TABLET_TEXTURE_RESOLUTION.y / 2) + TABLET_TEXEL_PADDING.y);
|
||||||
|
windowPos.x = clamp(windowPos.x, X_CLAMP, Window.innerWidth - X_CLAMP);
|
||||||
|
windowPos.y = clamp(windowPos.y, Y_CLAMP, Window.innerHeight - Y_CLAMP);
|
||||||
|
|
||||||
var fov = (Settings.getValue('fieldOfView') || DEFAULT_VERTICAL_FIELD_OF_VIEW) * (Math.PI / 180);
|
var fov = (Settings.getValue('fieldOfView') || DEFAULT_VERTICAL_FIELD_OF_VIEW) * (Math.PI / 180);
|
||||||
var MAX_PADDING_FACTOR = 2.2;
|
var MAX_PADDING_FACTOR = 2.2;
|
||||||
var PADDING_FACTOR = Math.min(Window.innerHeight / TABLET_TEXTURE_RESOLUTION.y, MAX_PADDING_FACTOR);
|
var PADDING_FACTOR = Math.min(Window.innerHeight / TABLET_TEXTURE_RESOLUTION.y, MAX_PADDING_FACTOR);
|
||||||
var TABLET_HEIGHT = (TABLET_TEXTURE_RESOLUTION.y / this.dpi) * INCHES_TO_METERS;
|
var TABLET_HEIGHT = (TABLET_TEXTURE_RESOLUTION.y / this.dpi) * INCHES_TO_METERS;
|
||||||
var WEB_ENTITY_Z_OFFSET = (this.depth / 2);
|
var WEB_ENTITY_Z_OFFSET = (this.depth / 2);
|
||||||
|
|
||||||
|
// calcualte distance from camera
|
||||||
var dist = (PADDING_FACTOR * TABLET_HEIGHT) / (2 * Math.tan(fov / 2) * (DESKTOP_TABLET_SCALE / 100)) - WEB_ENTITY_Z_OFFSET;
|
var dist = (PADDING_FACTOR * TABLET_HEIGHT) / (2 * Math.tan(fov / 2) * (DESKTOP_TABLET_SCALE / 100)) - WEB_ENTITY_Z_OFFSET;
|
||||||
|
|
||||||
|
var Z_NEAR = 0.01;
|
||||||
|
var Z_FAR = 100.0;
|
||||||
|
|
||||||
|
// calculate mouse position in clip space
|
||||||
|
var alpha = -(Z_FAR + Z_NEAR) / (Z_FAR - Z_NEAR);
|
||||||
|
var beta = -(2 * Z_FAR * Z_NEAR) / (Z_FAR - Z_NEAR);
|
||||||
|
var clipZ = (beta / dist) - alpha;
|
||||||
|
var clipMousePosition = {x: (2 * windowPos.x / Window.innerWidth) - 1,
|
||||||
|
y: (2 * ((Window.innerHeight - windowPos.y) / Window.innerHeight)) - 1,
|
||||||
|
z: clipZ};
|
||||||
|
|
||||||
|
// calculate projection matrix
|
||||||
|
var aspect = Window.innerWidth / Window.innerHeight;
|
||||||
|
var projMatrix = gluPerspective(fov, aspect, Z_NEAR, Z_FAR);
|
||||||
|
|
||||||
|
// transform mouse clip position into view coordinates.
|
||||||
|
var viewMousePosition = Mat4.transformPoint(Mat4.inverse(projMatrix), clipMousePosition);
|
||||||
|
|
||||||
|
// transform view mouse position into world coordinates.
|
||||||
|
var viewToWorldMatrix = Mat4.createFromRotAndTrans(Camera.orientation, Camera.position);
|
||||||
|
var worldMousePosition = Mat4.transformPoint(viewToWorldMatrix, viewMousePosition);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
position: Vec3.sum(Camera.position, Vec3.multiply(dist, Quat.getFront(Camera.orientation))),
|
position: worldMousePosition,
|
||||||
rotation: Quat.multiply(Camera.orientation, ROT_Y_180)
|
rotation: Quat.multiply(Camera.orientation, ROT_Y_180)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, tabletProperties) {
|
WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, useMouse, tabletProperties) {
|
||||||
if (HMD.active) {
|
if (HMD.active) {
|
||||||
// in HMD mode, the tablet should be relative to the sensor to world matrix.
|
// in HMD mode, the tablet should be relative to the sensor to world matrix.
|
||||||
tabletProperties.parentJointIndex = SENSOR_TO_ROOM_MATRIX;
|
tabletProperties.parentJointIndex = SENSOR_TO_ROOM_MATRIX;
|
||||||
|
@ -289,8 +336,16 @@ WebTablet.prototype.calculateTabletAttachmentProperties = function (hand, tablet
|
||||||
// in desktop mode, the tablet should be relative to the camera
|
// in desktop mode, the tablet should be relative to the camera
|
||||||
tabletProperties.parentJointIndex = CAMERA_MATRIX;
|
tabletProperties.parentJointIndex = CAMERA_MATRIX;
|
||||||
|
|
||||||
// compute the appropriate postion of the tablet such that it fits in the center of the screen nicely.
|
var windowPos;
|
||||||
var attitude = this.calculateWorldAttitudeRelativeToCamera();
|
if (useMouse) {
|
||||||
|
// compute the appropriate postion of the tablet such that it fits in the center of the screen nicely.
|
||||||
|
windowPos = {x: Controller.getValue(Controller.Hardware.Keyboard.MouseX),
|
||||||
|
y: Controller.getValue(Controller.Hardware.Keyboard.MouseY)};
|
||||||
|
} else {
|
||||||
|
windowPos = {x: Window.innerWidth / 2,
|
||||||
|
y: Window.innerHeight / 2};
|
||||||
|
}
|
||||||
|
var attitude = this.calculateWorldAttitudeRelativeToCamera(windowPos);
|
||||||
tabletProperties.position = attitude.position;
|
tabletProperties.position = attitude.position;
|
||||||
tabletProperties.rotation = attitude.rotation;
|
tabletProperties.rotation = attitude.rotation;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +365,7 @@ WebTablet.prototype.onHmdChanged = function () {
|
||||||
|
|
||||||
var tabletProperties = {};
|
var tabletProperties = {};
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties);
|
this.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
||||||
Entities.editEntity(this.tabletEntityID, tabletProperties);
|
Entities.editEntity(this.tabletEntityID, tabletProperties);
|
||||||
|
|
||||||
// Full scene FXAA should be disabled on the overlay when the tablet in desktop mode.
|
// Full scene FXAA should be disabled on the overlay when the tablet in desktop mode.
|
||||||
|
@ -398,7 +453,7 @@ WebTablet.prototype.cameraModeChanged = function (newMode) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var tabletProperties = {};
|
var tabletProperties = {};
|
||||||
// compute position, rotation & parentJointIndex of the tablet
|
// compute position, rotation & parentJointIndex of the tablet
|
||||||
self.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties);
|
self.calculateTabletAttachmentProperties(NO_HANDS, false, tabletProperties);
|
||||||
Entities.editEntity(self.tabletEntityID, tabletProperties);
|
Entities.editEntity(self.tabletEntityID, tabletProperties);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
112
scripts/system/nameTag.js
Normal file
112
scripts/system/nameTag.js
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*jslint vars: true, plusplus: true*/
|
||||||
|
/*global Entities, Script, Quat, Vec3, MyAvatar, print*/
|
||||||
|
// nameTag.js
|
||||||
|
//
|
||||||
|
// Created by Triplelexx on 17/01/31
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Running the script creates a text entity that will hover over the user's head showing their display name.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
|
||||||
|
const CLIENTONLY = false;
|
||||||
|
const NULL_UUID = "{00000000-0000-0000-0000-000000000000}";
|
||||||
|
const ENTITY_CHECK_INTERVAL = 5000; // ms = 5 seconds
|
||||||
|
const STARTUP_DELAY = 2000; // ms = 2 second
|
||||||
|
const OLD_AGE = 3500; // we recreate the entity if older than this time in seconds
|
||||||
|
const TTL = 2; // time to live in seconds if script is not running
|
||||||
|
const HEIGHT_ABOVE_HEAD = 0.2;
|
||||||
|
const HEAD_OFFSET = -0.025;
|
||||||
|
const SIZE_Y = 0.075;
|
||||||
|
const LETTER_OFFSET = 0.03; // arbitrary value to dynamically change width, could be more accurate by detecting characters
|
||||||
|
const LINE_HEIGHT = 0.05;
|
||||||
|
|
||||||
|
var nameTagEntityID = NULL_UUID;
|
||||||
|
var lastCheckForEntity = 0;
|
||||||
|
|
||||||
|
// create the name tag entity after a brief delay
|
||||||
|
Script.setTimeout(function() {
|
||||||
|
addNameTag();
|
||||||
|
}, STARTUP_DELAY);
|
||||||
|
|
||||||
|
function addNameTag() {
|
||||||
|
var nameTagPosition = Vec3.sum(MyAvatar.getHeadPosition(), Vec3.multiply(HEAD_OFFSET, Quat.getFront(MyAvatar.orientation)));
|
||||||
|
nameTagPosition.y += HEIGHT_ABOVE_HEAD;
|
||||||
|
var nameTagProperties = {
|
||||||
|
name: MyAvatar.displayName + ' Name Tag',
|
||||||
|
type: 'Text',
|
||||||
|
text: MyAvatar.displayName,
|
||||||
|
lineHeight: LINE_HEIGHT,
|
||||||
|
parentID: MyAvatar.sessionUUID,
|
||||||
|
dimensions: dimensionsFromName(),
|
||||||
|
position: nameTagPosition
|
||||||
|
}
|
||||||
|
nameTagEntityID = Entities.addEntity(nameTagProperties, CLIENTONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateNameTag() {
|
||||||
|
var nameTagProps = Entities.getEntityProperties(nameTagEntityID);
|
||||||
|
var nameTagPosition = Vec3.sum(MyAvatar.getHeadPosition(), Vec3.multiply(HEAD_OFFSET, Quat.getFront(MyAvatar.orientation)));
|
||||||
|
nameTagPosition.y += HEIGHT_ABOVE_HEAD;
|
||||||
|
|
||||||
|
Entities.editEntity(nameTagEntityID, {
|
||||||
|
position: nameTagPosition,
|
||||||
|
dimensions: dimensionsFromName(),
|
||||||
|
// lifetime is in seconds we add TTL on top of the next poll time
|
||||||
|
lifetime: Math.round(nameTagProps.age) + (ENTITY_CHECK_INTERVAL / 1000) + TTL,
|
||||||
|
text: MyAvatar.displayName
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function deleteNameTag() {
|
||||||
|
if(nameTagEntityID !== NULL_UUID) {
|
||||||
|
Entities.deleteEntity(nameTagEntityID);
|
||||||
|
nameTagEntityID = NULL_UUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dimensionsFromName() {
|
||||||
|
return {
|
||||||
|
x: LETTER_OFFSET * MyAvatar.displayName.length,
|
||||||
|
y: SIZE_Y,
|
||||||
|
z: 0.0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// cleanup on ending
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
||||||
|
function cleanup() {
|
||||||
|
deleteNameTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(update);
|
||||||
|
function update() {
|
||||||
|
// if no entity we return
|
||||||
|
if(nameTagEntityID == NULL_UUID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Date.now() - lastCheckForEntity > ENTITY_CHECK_INTERVAL) {
|
||||||
|
checkForEntity();
|
||||||
|
lastCheckForEntity = Date.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForEntity() {
|
||||||
|
var nameTagProps = Entities.getEntityProperties(nameTagEntityID);
|
||||||
|
// it is possible for the age to not be a valid number, we check for this and return accordingly
|
||||||
|
if(nameTagProps.age == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's too old or we receive undefined make a new one, otherwise update
|
||||||
|
if(nameTagProps.age > OLD_AGE || nameTagProps.age == undefined) {
|
||||||
|
deleteNameTag();
|
||||||
|
addNameTag();
|
||||||
|
} else {
|
||||||
|
updateNameTag();
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
|
|
||||||
// hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed
|
// hardcoding these as it appears we cannot traverse the originalTextures in overlays??? Maybe I've missed
|
||||||
// something, will revisit as this is sorta horrible.
|
// something, will revisit as this is sorta horrible.
|
||||||
const UNSELECTED_TEXTURES = {"idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"),
|
const UNSELECTED_TEXTURES = {"idle-D": Script.resolvePath("./assets/models/Avatar-Overlay-v1.fbx/Avatar-Overlay-v1.fbm/avatar-overlay-idle.png"),
|
||||||
|
@ -27,7 +29,7 @@ const UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
|
||||||
const SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
const SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
||||||
const HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
const HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
||||||
|
|
||||||
(function() { // BEGIN LOCAL_SCOPE
|
var conserveResources = true;
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllers.js");
|
Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
||||||
|
@ -265,15 +267,16 @@ pal.fromQml.connect(function (message) { // messages are {method, params}, like
|
||||||
function addAvatarNode(id) {
|
function addAvatarNode(id) {
|
||||||
var selected = ExtendedOverlay.isSelected(id);
|
var selected = ExtendedOverlay.isSelected(id);
|
||||||
return new ExtendedOverlay(id, "sphere", {
|
return new ExtendedOverlay(id, "sphere", {
|
||||||
drawInFront: true,
|
drawInFront: true,
|
||||||
solid: true,
|
solid: true,
|
||||||
alpha: 0.8,
|
alpha: 0.8,
|
||||||
color: color(selected, false, 0.0),
|
color: color(selected, false, 0.0),
|
||||||
ignoreRayIntersection: false}, selected, true);
|
ignoreRayIntersection: false}, selected, !conserveResources);
|
||||||
}
|
}
|
||||||
function populateUserList(selectData) {
|
function populateUserList(selectData) {
|
||||||
var data = [];
|
var data = [], avatars = AvatarList.getAvatarIdentifiers();
|
||||||
AvatarList.getAvatarIdentifiers().sort().forEach(function (id) { // sorting the identifiers is just an aid for debugging
|
conserveResources = avatars.length > 20;
|
||||||
|
avatars.forEach(function (id) { // sorting the identifiers is just an aid for debugging
|
||||||
var avatar = AvatarList.getAvatar(id);
|
var avatar = AvatarList.getAvatar(id);
|
||||||
var avatarPalDatum = {
|
var avatarPalDatum = {
|
||||||
displayName: avatar.sessionDisplayName,
|
displayName: avatar.sessionDisplayName,
|
||||||
|
@ -498,6 +501,9 @@ if (Settings.getValue("HUDUIEnabled")) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var isWired = false;
|
var isWired = false;
|
||||||
|
var audioTimer;
|
||||||
|
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
|
||||||
|
var AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS = 300;
|
||||||
function off() {
|
function off() {
|
||||||
if (isWired) { // It is not ok to disconnect these twice, hence guard.
|
if (isWired) { // It is not ok to disconnect these twice, hence guard.
|
||||||
Script.update.disconnect(updateOverlays);
|
Script.update.disconnect(updateOverlays);
|
||||||
|
@ -505,6 +511,7 @@ function off() {
|
||||||
Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent);
|
Controller.mouseMoveEvent.disconnect(handleMouseMoveEvent);
|
||||||
isWired = false;
|
isWired = false;
|
||||||
}
|
}
|
||||||
|
if (audioTimer) { Script.clearInterval(audioTimer); }
|
||||||
triggerMapping.disable(); // It's ok if we disable twice.
|
triggerMapping.disable(); // It's ok if we disable twice.
|
||||||
triggerPressMapping.disable(); // see above
|
triggerPressMapping.disable(); // see above
|
||||||
removeOverlays();
|
removeOverlays();
|
||||||
|
@ -521,7 +528,7 @@ function onClicked() {
|
||||||
Controller.mouseMoveEvent.connect(handleMouseMoveEvent);
|
Controller.mouseMoveEvent.connect(handleMouseMoveEvent);
|
||||||
triggerMapping.enable();
|
triggerMapping.enable();
|
||||||
triggerPressMapping.enable();
|
triggerPressMapping.enable();
|
||||||
createAudioInterval();
|
audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS);
|
||||||
} else {
|
} else {
|
||||||
off();
|
off();
|
||||||
}
|
}
|
||||||
|
@ -557,9 +564,7 @@ var AVERAGING_RATIO = 0.05;
|
||||||
var LOUDNESS_FLOOR = 11.0;
|
var LOUDNESS_FLOOR = 11.0;
|
||||||
var LOUDNESS_SCALE = 2.8 / 5.0;
|
var LOUDNESS_SCALE = 2.8 / 5.0;
|
||||||
var LOG2 = Math.log(2.0);
|
var LOG2 = Math.log(2.0);
|
||||||
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
|
|
||||||
var myData = {}; // we're not includied in ExtendedOverlay.get.
|
var myData = {}; // we're not includied in ExtendedOverlay.get.
|
||||||
var audioInterval;
|
|
||||||
|
|
||||||
function getAudioLevel(id) {
|
function getAudioLevel(id) {
|
||||||
// the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged
|
// the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged
|
||||||
|
@ -591,21 +596,19 @@ function getAudioLevel(id) {
|
||||||
return audioLevel;
|
return audioLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAudioInterval() {
|
function createAudioInterval(interval) {
|
||||||
// we will update the audioLevels periodically
|
// we will update the audioLevels periodically
|
||||||
// TODO: tune for efficiency - expecially with large numbers of avatars
|
// TODO: tune for efficiency - expecially with large numbers of avatars
|
||||||
return Script.setInterval(function () {
|
return Script.setInterval(function () {
|
||||||
if (pal.visible) {
|
var param = {};
|
||||||
var param = {};
|
AvatarList.getAvatarIdentifiers().forEach(function (id) {
|
||||||
AvatarList.getAvatarIdentifiers().forEach(function (id) {
|
var level = getAudioLevel(id);
|
||||||
var level = getAudioLevel(id);
|
// qml didn't like an object with null/empty string for a key, so...
|
||||||
// qml didn't like an object with null/empty string for a key, so...
|
var userId = id || 0;
|
||||||
var userId = id || 0;
|
param[userId] = level;
|
||||||
param[userId] = level;
|
});
|
||||||
});
|
pal.sendToQml({method: 'updateAudioLevel', params: param});
|
||||||
pal.sendToQml({method: 'updateAudioLevel', params: param});
|
}, interval);
|
||||||
}
|
|
||||||
}, AUDIO_LEVEL_UPDATE_INTERVAL_MS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function avatarDisconnected(nodeID) {
|
function avatarDisconnected(nodeID) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
(function() { // BEGIN LOCAL_SCOPE
|
(function() { // BEGIN LOCAL_SCOPE
|
||||||
var USERS_URL = "https://hifi-content.s3.amazonaws.com/faye/tablet-dev/users.html";
|
var USERS_URL = "https://hifi-content.s3.amazonaws.com/faye/tablet-dev/users.html";
|
||||||
|
var HOME_BUTTON_TEXTURE = Script.resourcesPath() + "meshes/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
||||||
|
|
||||||
var FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends";
|
var FRIENDS_WINDOW_URL = "https://metaverse.highfidelity.com/user/friends";
|
||||||
var FRIENDS_WINDOW_WIDTH = 290;
|
var FRIENDS_WINDOW_WIDTH = 290;
|
||||||
|
@ -40,6 +41,10 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
function onClicked() {
|
function onClicked() {
|
||||||
|
var tabletEntity = HMD.tabletID;
|
||||||
|
if (tabletEntity) {
|
||||||
|
Entities.editEntity(tabletEntity, {textures: JSON.stringify({"tex.close" : HOME_BUTTON_TEXTURE})});
|
||||||
|
}
|
||||||
tablet.gotoWebScreen(USERS_URL);
|
tablet.gotoWebScreen(USERS_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue