mirror of
https://github.com/overte-org/overte.git
synced 2025-08-13 19:19:42 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into orange
This commit is contained in:
commit
07a36158e6
10 changed files with 191 additions and 103 deletions
|
@ -210,6 +210,9 @@
|
|||
|
||||
disableChildren(document.getElementById("properties-list"), 'input');
|
||||
} else {
|
||||
var activeElement = document.activeElement;
|
||||
var selected = activeElement.selectionStart == 0 && activeElement.selectionEnd == activeElement.value.length;
|
||||
|
||||
var properties = data.selections[0].properties;
|
||||
|
||||
elID.innerHTML = properties.id;
|
||||
|
@ -335,6 +338,11 @@
|
|||
elLightExponent.value = properties.exponent;
|
||||
elLightCutoff.value = properties.cutoff;
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
activeElement.focus();
|
||||
activeElement.select();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,8 +11,11 @@
|
|||
|
||||
var usersWindow = (function () {
|
||||
|
||||
var WINDOW_WIDTH_2D = 160,
|
||||
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/",
|
||||
|
||||
WINDOW_WIDTH_2D = 160,
|
||||
WINDOW_MARGIN_2D = 12,
|
||||
WINDOW_BASE_MARGIN_2D = 6, // A little less is needed in order look correct
|
||||
WINDOW_FONT_2D = { size: 12 },
|
||||
WINDOW_FOREGROUND_COLOR_2D = { red: 240, green: 240, blue: 240 },
|
||||
WINDOW_FOREGROUND_ALPHA_2D = 0.9,
|
||||
|
@ -22,6 +25,14 @@ var usersWindow = (function () {
|
|||
WINDOW_BACKGROUND_ALPHA_2D = 0.7,
|
||||
windowPane2D,
|
||||
windowHeading2D,
|
||||
MINIMIZE_BUTTON_SVG = HIFI_PUBLIC_BUCKET + "images/tools/min-max-toggle.svg",
|
||||
MINIMIZE_BUTTON_SVG_WIDTH = 17.1,
|
||||
MINIMIZE_BUTTON_SVG_HEIGHT = 32.5,
|
||||
MINIMIZE_BUTTON_WIDTH_2D = 14,
|
||||
MINIMIZE_BUTTON_HEIGHT_2D = MINIMIZE_BUTTON_WIDTH_2D,
|
||||
MINIMIZE_BUTTON_COLOR_2D = { red: 255, green: 255, blue: 255 },
|
||||
MINIMIZE_BUTTON_ALPHA_2D = 0.9,
|
||||
minimizeButton2D,
|
||||
SCROLLBAR_BACKGROUND_WIDTH_2D = 12,
|
||||
SCROLLBAR_BACKGROUND_COLOR_2D = { red: 80, green: 80, blue: 80 },
|
||||
SCROLLBAR_BACKGROUND_ALPHA_2D = 0.8,
|
||||
|
@ -65,6 +76,7 @@ var usersWindow = (function () {
|
|||
MENU_ITEM_AFTER = "Chat...",
|
||||
|
||||
isVisible = true,
|
||||
isMinimized = false,
|
||||
|
||||
viewportHeight,
|
||||
isMirrorDisplay = false,
|
||||
|
@ -77,7 +89,6 @@ var usersWindow = (function () {
|
|||
scrollbarBarClickedAt, // 0.0 .. 1.0
|
||||
scrollbarValue = 0.0, // 0.0 .. 1.0
|
||||
|
||||
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/",
|
||||
RADIO_BUTTON_SVG = HIFI_PUBLIC_BUCKET + "images/radio-button.svg",
|
||||
RADIO_BUTTON_SVG_DIAMETER = 14,
|
||||
RADIO_BUTTON_DISPLAY_SCALE = 0.7, // 1.0 = windowTextHeight
|
||||
|
@ -89,9 +100,15 @@ var usersWindow = (function () {
|
|||
nonUsersHeight,
|
||||
maxWindowHeight;
|
||||
|
||||
if (isMinimized) {
|
||||
windowHeight = windowTextHeight + WINDOW_MARGIN_2D + WINDOW_BASE_MARGIN_2D;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserve 5 lines for window heading plus visibility heading and controls
|
||||
// Subtract windowLineSpacing for both end of user list and end of controls
|
||||
nonUsersHeight = 5 * windowLineHeight - 2 * windowLineSpacing + VISIBILITY_SPACER_2D + 2 * WINDOW_MARGIN_2D;
|
||||
nonUsersHeight = 5 * windowLineHeight - 2 * windowLineSpacing + VISIBILITY_SPACER_2D + WINDOW_MARGIN_2D
|
||||
+ WINDOW_BASE_MARGIN_2D;
|
||||
|
||||
// Limit window to height of viewport minus VU meter and mirror if displayed
|
||||
windowHeight = linesOfUsers.length * windowLineHeight + nonUsersHeight;
|
||||
|
@ -102,7 +119,7 @@ var usersWindow = (function () {
|
|||
windowHeight = Math.max(Math.min(windowHeight, maxWindowHeight), nonUsersHeight);
|
||||
|
||||
// Corresponding number of users to actually display
|
||||
numUsersToDisplay = Math.max(Math.round((windowHeight - nonUsersHeight) / windowLineHeight), 0);
|
||||
numUsersToDisplay = Math.max(Math.floor((windowHeight - nonUsersHeight) / windowLineHeight), 0);
|
||||
isUsingScrollbars = 0 < numUsersToDisplay && numUsersToDisplay < linesOfUsers.length;
|
||||
if (isUsingScrollbars) {
|
||||
firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay));
|
||||
|
@ -123,6 +140,10 @@ var usersWindow = (function () {
|
|||
y: viewportHeight - windowHeight + WINDOW_MARGIN_2D
|
||||
});
|
||||
|
||||
Overlays.editOverlay(minimizeButton2D, {
|
||||
y: viewportHeight - windowHeight + WINDOW_MARGIN_2D / 2
|
||||
});
|
||||
|
||||
scrollbarBackgroundPosition.y = viewportHeight - windowHeight + WINDOW_MARGIN_2D + windowTextHeight;
|
||||
Overlays.editOverlay(scrollbarBackground2D, {
|
||||
y: scrollbarBackgroundPosition.y
|
||||
|
@ -133,10 +154,10 @@ var usersWindow = (function () {
|
|||
y: scrollbarBarPosition.y
|
||||
});
|
||||
Overlays.editOverlay(visibilityHeading2D, {
|
||||
y: viewportHeight - 4 * windowLineHeight + windowLineSpacing - WINDOW_MARGIN_2D
|
||||
y: viewportHeight - 4 * windowLineHeight + windowLineSpacing - WINDOW_BASE_MARGIN_2D
|
||||
});
|
||||
for (i = 0; i < visibilityControls2D.length; i += 1) {
|
||||
y = viewportHeight - (3 - i) * windowLineHeight + windowLineSpacing - WINDOW_MARGIN_2D;
|
||||
y = viewportHeight - (3 - i) * windowLineHeight + windowLineSpacing - WINDOW_BASE_MARGIN_2D;
|
||||
Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { y: y });
|
||||
Overlays.editOverlay(visibilityControls2D[i].textOverlay, { y: y });
|
||||
}
|
||||
|
@ -166,29 +187,43 @@ var usersWindow = (function () {
|
|||
reducedTextWidth,
|
||||
i;
|
||||
|
||||
maxTextWidth = WINDOW_WIDTH_2D - (isUsingScrollbars ? SCROLLBAR_BACKGROUND_WIDTH_2D : 0) - 2 * WINDOW_MARGIN_2D;
|
||||
ellipsisWidth = Overlays.textSize(windowPane2D, "...").width;
|
||||
reducedTextWidth = maxTextWidth - ellipsisWidth;
|
||||
if (!isMinimized) {
|
||||
maxTextWidth = WINDOW_WIDTH_2D - (isUsingScrollbars ? SCROLLBAR_BACKGROUND_WIDTH_2D : 0) - 2 * WINDOW_MARGIN_2D;
|
||||
ellipsisWidth = Overlays.textSize(windowPane2D, "...").width;
|
||||
reducedTextWidth = maxTextWidth - ellipsisWidth;
|
||||
|
||||
for (i = 0; i < numUsersToDisplay; i += 1) {
|
||||
user = usersOnline[linesOfUsers[firstUserToDisplay + i]];
|
||||
userText = user.text;
|
||||
textWidth = user.textWidth;
|
||||
for (i = 0; i < numUsersToDisplay; i += 1) {
|
||||
user = usersOnline[linesOfUsers[firstUserToDisplay + i]];
|
||||
userText = user.text;
|
||||
textWidth = user.textWidth;
|
||||
|
||||
if (textWidth > maxTextWidth) {
|
||||
// Trim and append "..." to fit window width
|
||||
maxTextWidth = maxTextWidth - Overlays.textSize(windowPane2D, "...").width;
|
||||
while (textWidth > reducedTextWidth) {
|
||||
userText = userText.slice(0, -1);
|
||||
textWidth = Overlays.textSize(windowPane2D, userText).width;
|
||||
if (textWidth > maxTextWidth) {
|
||||
// Trim and append "..." to fit window width
|
||||
maxTextWidth = maxTextWidth - Overlays.textSize(windowPane2D, "...").width;
|
||||
while (textWidth > reducedTextWidth) {
|
||||
userText = userText.slice(0, -1);
|
||||
textWidth = Overlays.textSize(windowPane2D, userText).width;
|
||||
}
|
||||
userText += "...";
|
||||
}
|
||||
userText += "...";
|
||||
|
||||
displayText += "\n" + userText;
|
||||
}
|
||||
|
||||
displayText += "\n" + userText;
|
||||
}
|
||||
displayText = displayText.slice(1); // Remove leading "\n".
|
||||
|
||||
displayText = displayText.slice(1); // Remove leading "\n".
|
||||
scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2;
|
||||
Overlays.editOverlay(scrollbarBackground2D, {
|
||||
height: scrollbarBackgroundHeight,
|
||||
visible: isUsingScrollbars
|
||||
});
|
||||
scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight,
|
||||
SCROLLBAR_BAR_MIN_HEIGHT);
|
||||
Overlays.editOverlay(scrollbarBar2D, {
|
||||
height: scrollbarBarHeight,
|
||||
visible: isUsingScrollbars
|
||||
});
|
||||
}
|
||||
|
||||
Overlays.editOverlay(windowPane2D, {
|
||||
height: windowHeight,
|
||||
|
@ -198,20 +233,6 @@ var usersWindow = (function () {
|
|||
Overlays.editOverlay(windowHeading2D, {
|
||||
text: linesOfUsers.length > 0 ? "Users online" : "No users online"
|
||||
});
|
||||
|
||||
scrollbarBackgroundHeight = numUsersToDisplay * windowLineHeight - windowLineSpacing / 2;
|
||||
Overlays.editOverlay(scrollbarBackground2D, {
|
||||
height: scrollbarBackgroundHeight,
|
||||
visible: isUsingScrollbars
|
||||
});
|
||||
scrollbarBarHeight = Math.max(numUsersToDisplay / linesOfUsers.length * scrollbarBackgroundHeight,
|
||||
SCROLLBAR_BAR_MIN_HEIGHT);
|
||||
Overlays.editOverlay(scrollbarBar2D, {
|
||||
height: scrollbarBarHeight,
|
||||
visible: isUsingScrollbars
|
||||
});
|
||||
|
||||
updateOverlayPositions();
|
||||
}
|
||||
|
||||
function pollUsers() {
|
||||
|
@ -264,6 +285,7 @@ var usersWindow = (function () {
|
|||
|
||||
calculateWindowHeight();
|
||||
updateUsersDisplay();
|
||||
updateOverlayPositions();
|
||||
|
||||
} else {
|
||||
print("Error: Request for users status returned " + usersRequest.status + " " + usersRequest.statusText);
|
||||
|
@ -289,9 +311,22 @@ var usersWindow = (function () {
|
|||
}
|
||||
}
|
||||
|
||||
function setVisible(visible) {
|
||||
function updateOverlayVisibility() {
|
||||
var i;
|
||||
|
||||
Overlays.editOverlay(windowPane2D, { visible: isVisible });
|
||||
Overlays.editOverlay(windowHeading2D, { visible: isVisible });
|
||||
Overlays.editOverlay(minimizeButton2D, { visible: isVisible });
|
||||
Overlays.editOverlay(scrollbarBackground2D, { visible: isVisible && isUsingScrollbars && !isMinimized });
|
||||
Overlays.editOverlay(scrollbarBar2D, { visible: isVisible && isUsingScrollbars && !isMinimized });
|
||||
Overlays.editOverlay(visibilityHeading2D, { visible: isVisible && !isMinimized });
|
||||
for (i = 0; i < visibilityControls2D.length; i += 1) {
|
||||
Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { visible: isVisible && !isMinimized });
|
||||
Overlays.editOverlay(visibilityControls2D[i].textOverlay, { visible: isVisible && !isMinimized });
|
||||
}
|
||||
}
|
||||
|
||||
function setVisible(visible) {
|
||||
isVisible = visible;
|
||||
|
||||
if (isVisible) {
|
||||
|
@ -303,15 +338,15 @@ var usersWindow = (function () {
|
|||
usersTimer = null;
|
||||
}
|
||||
|
||||
Overlays.editOverlay(windowPane2D, { visible: isVisible });
|
||||
Overlays.editOverlay(windowHeading2D, { visible: isVisible });
|
||||
Overlays.editOverlay(scrollbarBackground2D, { visible: isVisible && isUsingScrollbars });
|
||||
Overlays.editOverlay(scrollbarBar2D, { visible: isVisible && isUsingScrollbars });
|
||||
Overlays.editOverlay(visibilityHeading2D, { visible: isVisible });
|
||||
for (i = 0; i < visibilityControls2D.length; i += 1) {
|
||||
Overlays.editOverlay(visibilityControls2D[i].radioOverlay, { visible: isVisible });
|
||||
Overlays.editOverlay(visibilityControls2D[i].textOverlay, { visible: isVisible });
|
||||
}
|
||||
updateOverlayVisibility();
|
||||
}
|
||||
|
||||
function setMinimized(minimized) {
|
||||
isMinimized = minimized;
|
||||
Overlays.editOverlay(minimizeButton2D, {
|
||||
subImage: { y: isMinimized ? MINIMIZE_BUTTON_SVG_HEIGHT / 2 : 0 }
|
||||
});
|
||||
updateOverlayVisibility();
|
||||
}
|
||||
|
||||
function onMenuItemEvent(event) {
|
||||
|
@ -360,6 +395,8 @@ var usersWindow = (function () {
|
|||
//print("Go to " + usersOnline[linesOfUsers[userClicked]].username);
|
||||
location.goToUser(usersOnline[linesOfUsers[userClicked]].username);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
visibilityChanged = false;
|
||||
|
@ -376,6 +413,15 @@ var usersWindow = (function () {
|
|||
visibilityControls2D[i].selected = clickedOverlay === visibilityControls2D[i].textOverlay;
|
||||
}
|
||||
updateVisibilityControls();
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickedOverlay === minimizeButton2D) {
|
||||
setMinimized(!isMinimized);
|
||||
calculateWindowHeight();
|
||||
updateOverlayPositions();
|
||||
updateUsersDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickedOverlay === scrollbarBar2D) {
|
||||
|
@ -384,6 +430,7 @@ var usersWindow = (function () {
|
|||
backgroundAlpha: SCROLLBAR_BAR_SELECTED_ALPHA_2D
|
||||
});
|
||||
isMovingScrollbar = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickedOverlay === scrollbarBackground2D) {
|
||||
|
@ -398,6 +445,7 @@ var usersWindow = (function () {
|
|||
firstUserToDisplay = Math.floor(scrollbarValue * (linesOfUsers.length - numUsersToDisplay));
|
||||
updateOverlayPositions();
|
||||
updateUsersDisplay();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,7 +540,19 @@ var usersWindow = (function () {
|
|||
backgroundAlpha: 0.0,
|
||||
text: "No users online",
|
||||
font: WINDOW_FONT_2D,
|
||||
visible: isVisible
|
||||
visible: isVisible && !isMinimized
|
||||
});
|
||||
|
||||
minimizeButton2D = Overlays.addOverlay("image", {
|
||||
x: WINDOW_WIDTH_2D - WINDOW_MARGIN_2D / 2 - MINIMIZE_BUTTON_WIDTH_2D,
|
||||
y: viewportHeight,
|
||||
width: MINIMIZE_BUTTON_WIDTH_2D,
|
||||
height: MINIMIZE_BUTTON_HEIGHT_2D,
|
||||
imageURL: MINIMIZE_BUTTON_SVG,
|
||||
subImage: { x: 0, y: 0, width: MINIMIZE_BUTTON_SVG_WIDTH, height: MINIMIZE_BUTTON_SVG_HEIGHT / 2 },
|
||||
color: MINIMIZE_BUTTON_COLOR_2D,
|
||||
alpha: MINIMIZE_BUTTON_ALPHA_2D,
|
||||
visible: isVisible && !isMinimized
|
||||
});
|
||||
|
||||
scrollbarBackgroundPosition = {
|
||||
|
@ -507,7 +567,7 @@ var usersWindow = (function () {
|
|||
backgroundColor: SCROLLBAR_BACKGROUND_COLOR_2D,
|
||||
backgroundAlpha: SCROLLBAR_BACKGROUND_ALPHA_2D,
|
||||
text: "",
|
||||
visible: isVisible && isUsingScrollbars
|
||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
||||
});
|
||||
|
||||
scrollbarBarPosition = {
|
||||
|
@ -522,7 +582,7 @@ var usersWindow = (function () {
|
|||
backgroundColor: SCROLLBAR_BAR_COLOR_2D,
|
||||
backgroundAlpha: SCROLLBAR_BAR_ALPHA_2D,
|
||||
text: "",
|
||||
visible: isVisible && isUsingScrollbars
|
||||
visible: isVisible && isUsingScrollbars && !isMinimized
|
||||
});
|
||||
|
||||
visibilityHeading2D = Overlays.addOverlay("text", {
|
||||
|
@ -537,7 +597,7 @@ var usersWindow = (function () {
|
|||
backgroundAlpha: 0.0,
|
||||
text: "I am visible to:",
|
||||
font: WINDOW_FONT_2D,
|
||||
visible: isVisible
|
||||
visible: isVisible && !isMinimized
|
||||
});
|
||||
|
||||
myVisibility = GlobalServices.findableBy;
|
||||
|
@ -561,7 +621,8 @@ var usersWindow = (function () {
|
|||
height: RADIO_BUTTON_SVG_DIAMETER
|
||||
},
|
||||
color: WINDOW_HEADING_COLOR_2D,
|
||||
alpha: WINDOW_FOREGROUND_ALPHA_2D
|
||||
alpha: WINDOW_FOREGROUND_ALPHA_2D,
|
||||
visible: isVisible && !isMinimized
|
||||
}),
|
||||
textOverlay: Overlays.addOverlay("text", {
|
||||
x: WINDOW_MARGIN_2D,
|
||||
|
@ -575,7 +636,7 @@ var usersWindow = (function () {
|
|||
backgroundAlpha: 0.0,
|
||||
text: optionText,
|
||||
font: WINDOW_FONT_2D,
|
||||
visible: isVisible
|
||||
visible: isVisible && !isMinimized
|
||||
}),
|
||||
selected: myVisibility === VISIBILITY_VALUES[0]
|
||||
}];
|
||||
|
@ -634,6 +695,7 @@ var usersWindow = (function () {
|
|||
Script.clearTimeout(usersTimer);
|
||||
Overlays.deleteOverlay(windowPane2D);
|
||||
Overlays.deleteOverlay(windowHeading2D);
|
||||
Overlays.deleteOverlay(minimizeButton2D);
|
||||
Overlays.deleteOverlay(scrollbarBackground2D);
|
||||
Overlays.deleteOverlay(scrollbarBar2D);
|
||||
Overlays.deleteOverlay(visibilityHeading2D);
|
||||
|
|
|
@ -101,7 +101,7 @@ void EntityTreeRenderer::init() {
|
|||
_lastAvatarPosition = _viewState->getAvatarPosition() + glm::vec3((float)TREE_SCALE);
|
||||
|
||||
connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity);
|
||||
connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload);
|
||||
connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::addingEntity);
|
||||
connect(entityTree, &EntityTree::entityScriptChanging, this, &EntityTreeRenderer::entitySciptChanging);
|
||||
connect(entityTree, &EntityTree::changingEntityID, this, &EntityTreeRenderer::changingEntityID);
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity, bool isPre
|
|||
// can accomplish all we need to here with just the script "text" and the ID.
|
||||
EntityItemID entityID = entity->getEntityItemID();
|
||||
QString entityScript = entity->getScript();
|
||||
|
||||
|
||||
if (_entityScripts.contains(entityID)) {
|
||||
EntityScriptDetails details = _entityScripts[entityID];
|
||||
|
||||
|
@ -217,7 +217,6 @@ QScriptValue EntityTreeRenderer::loadEntityScript(EntityItem* entity, bool isPre
|
|||
|
||||
if (isPending && isPreload && isURL) {
|
||||
_waitingOnPreload.insert(url, entityID);
|
||||
|
||||
}
|
||||
|
||||
auto scriptCache = DependencyManager::get<ScriptCache>();
|
||||
|
@ -941,6 +940,10 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) {
|
|||
_entityScripts.remove(entityID);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::addingEntity(const EntityItemID& entityID) {
|
||||
checkAndCallPreload(entityID);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::entitySciptChanging(const EntityItemID& entityID) {
|
||||
if (_tree && !_shuttingDown) {
|
||||
checkAndCallUnload(entityID);
|
||||
|
|
|
@ -105,6 +105,7 @@ signals:
|
|||
void leaveEntity(const EntityItemID& entityItemID);
|
||||
|
||||
public slots:
|
||||
void addingEntity(const EntityItemID& entityID);
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
|
||||
void entitySciptChanging(const EntityItemID& entityID);
|
||||
|
|
|
@ -404,7 +404,8 @@ void EntityTree::handleAddEntityResponse(const QByteArray& packet) {
|
|||
EntityItem* foundEntity = NULL;
|
||||
EntityItemID creatorTokenVersion = searchEntityID.convertToCreatorTokenVersion();
|
||||
EntityItemID knownIDVersion = searchEntityID.convertToKnownIDVersion();
|
||||
|
||||
|
||||
_changedEntityIDs[creatorTokenVersion] = knownIDVersion;
|
||||
|
||||
// First look for and find the "viewed version" of this entity... it's possible we got
|
||||
// the known ID version sent to us between us creating our local version, and getting this
|
||||
|
@ -592,6 +593,9 @@ EntityItem* EntityTree::findEntityByEntityItemID(const EntityItemID& entityID) /
|
|||
EntityTreeElement* containingElement = getContainingElement(entityID);
|
||||
if (containingElement) {
|
||||
foundEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||
if (!foundEntity && _changedEntityIDs.contains(entityID)) {
|
||||
foundEntity = containingElement->getEntityWithEntityItemID(_changedEntityIDs[entityID]);
|
||||
}
|
||||
}
|
||||
return foundEntity;
|
||||
}
|
||||
|
@ -958,6 +962,12 @@ EntityTreeElement* EntityTree::getContainingElement(const EntityItemID& entityIt
|
|||
creatorTokenOnly.isKnownID = false;
|
||||
element = _entityToElementMap.value(creatorTokenOnly);
|
||||
}
|
||||
|
||||
// If we still didn't find the entity, but the ID was in our changed entityIDs, search for the new ID version
|
||||
if (!element && _changedEntityIDs.contains(entityItemID)) {
|
||||
element = getContainingElement(_changedEntityIDs[entityItemID]);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
|
|
@ -195,6 +195,7 @@ private:
|
|||
EntityItemFBXService* _fbxService;
|
||||
|
||||
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
|
||||
QHash<EntityItemID, EntityItemID> _changedEntityIDs;
|
||||
|
||||
EntitySimulation* _simulation;
|
||||
|
||||
|
|
48
libraries/physics/src/CharacterController.cpp
Normal file → Executable file
48
libraries/physics/src/CharacterController.cpp
Normal file → Executable file
|
@ -274,7 +274,6 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl
|
|||
collisionWorld->getDispatcher()->dispatchAllCollisionPairs(_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
|
||||
|
||||
_currentPosition = _ghostObject->getWorldTransform().getOrigin();
|
||||
btVector3 up = quatRotate(_currentRotation, LOCAL_UP_AXIS);
|
||||
|
||||
btVector3 currentPosition = _currentPosition;
|
||||
|
||||
|
@ -308,7 +307,7 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl
|
|||
btVector3 normal = pt.m_normalWorldOnB;
|
||||
normal *= directionSign; // always points from object to character
|
||||
|
||||
btScalar normalDotUp = normal.dot(up);
|
||||
btScalar normalDotUp = normal.dot(_currentUp);
|
||||
if (normalDotUp < _maxSlopeCosine) {
|
||||
// this contact has a non-vertical normal... might need to ignored
|
||||
btVector3 collisionPoint;
|
||||
|
@ -319,9 +318,9 @@ bool CharacterController::recoverFromPenetration(btCollisionWorld* collisionWorl
|
|||
}
|
||||
|
||||
// we do math in frame where character base is origin
|
||||
btVector3 characterBase = currentPosition - (_radius + _halfHeight) * up;
|
||||
btVector3 characterBase = currentPosition - (_radius + _halfHeight) * _currentUp;
|
||||
collisionPoint -= characterBase;
|
||||
btScalar collisionHeight = collisionPoint.dot(up);
|
||||
btScalar collisionHeight = collisionPoint.dot(_currentUp);
|
||||
|
||||
if (collisionHeight < _lastStepUp) {
|
||||
// This contact is below the lastStepUp, so we ignore it for penetration resolution,
|
||||
|
@ -357,11 +356,10 @@ void CharacterController::scanDown(btCollisionWorld* world) {
|
|||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
btVector3 up = quatRotate(_currentRotation, LOCAL_UP_AXIS);
|
||||
btVector3 start = _currentPosition;
|
||||
const btScalar MAX_SCAN_HEIGHT = 20.0f + _halfHeight + _radius; // closest possible floor for disabling hover
|
||||
const btScalar MIN_HOVER_HEIGHT = 3.0f + _halfHeight + _radius; // distance to floor for enabling hover
|
||||
btVector3 end = start - MAX_SCAN_HEIGHT * up;
|
||||
btVector3 end = start - MAX_SCAN_HEIGHT * _currentUp;
|
||||
|
||||
world->rayTest(start, end, callback);
|
||||
if (!callback.hasHit()) {
|
||||
|
@ -377,15 +375,14 @@ void CharacterController::stepUp(btCollisionWorld* world) {
|
|||
// compute start and end
|
||||
btTransform start, end;
|
||||
start.setIdentity();
|
||||
btVector3 up = quatRotate(_currentRotation, LOCAL_UP_AXIS);
|
||||
start.setOrigin(_currentPosition + up * (_convexShape->getMargin() + _addedMargin));
|
||||
start.setOrigin(_currentPosition + _currentUp * (_convexShape->getMargin() + _addedMargin));
|
||||
|
||||
_targetPosition = _currentPosition + up * _stepUpHeight;
|
||||
_targetPosition = _currentPosition + _currentUp * _stepUpHeight;
|
||||
end.setIdentity();
|
||||
end.setOrigin(_targetPosition);
|
||||
|
||||
// sweep up
|
||||
btVector3 sweepDirNegative = - up;
|
||||
btVector3 sweepDirNegative = - _currentUp;
|
||||
btKinematicClosestNotMeConvexResultCallback callback(_ghostObject, sweepDirNegative, btScalar(0.7071));
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
@ -397,7 +394,7 @@ void CharacterController::stepUp(btCollisionWorld* world) {
|
|||
_verticalOffset = 0.0f;
|
||||
|
||||
// Only modify the position if the hit was a slope and not a wall or ceiling.
|
||||
if (callback.m_hitNormalWorld.dot(up) > 0.0f) {
|
||||
if (callback.m_hitNormalWorld.dot(_currentUp) > 0.0f) {
|
||||
_lastStepUp = _stepUpHeight * callback.m_closestHitFraction;
|
||||
_currentPosition.setInterpolate3(_currentPosition, _targetPosition, callback.m_closestHitFraction);
|
||||
} else {
|
||||
|
@ -469,8 +466,8 @@ void CharacterController::stepForward(btCollisionWorld* collisionWorld, const bt
|
|||
// sweep forward
|
||||
btVector3 sweepDirNegative(_currentPosition - _targetPosition);
|
||||
btKinematicClosestNotMeConvexResultCallback callback(_ghostObject, sweepDirNegative, btScalar(0.0));
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
_ghostObject->convexSweepTest(_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
|
||||
|
||||
if (callback.hasHit()) {
|
||||
|
@ -502,17 +499,16 @@ void CharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt
|
|||
// reach of the character's feet.
|
||||
|
||||
// first sweep for ledge
|
||||
btVector3 up = quatRotate(_currentRotation, LOCAL_UP_AXIS);
|
||||
btVector3 step = (_verticalVelocity * dt - _lastStepUp) * up;
|
||||
btVector3 step = (_verticalVelocity * dt - _lastStepUp) * _currentUp;
|
||||
|
||||
StepDownConvexResultCallback callback(_ghostObject,
|
||||
up,
|
||||
_currentUp,
|
||||
_currentPosition, step,
|
||||
_walkDirection,
|
||||
_maxSlopeCosine,
|
||||
_radius, _halfHeight);
|
||||
callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
callback.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
btTransform start, end;
|
||||
start.setIdentity();
|
||||
|
@ -532,16 +528,16 @@ void CharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt
|
|||
_isOnGround = true;
|
||||
} else if (!_isJumping) {
|
||||
// sweep again for floor within downStep threshold
|
||||
step = -_stepDownHeight * up;
|
||||
step = -_stepDownHeight * _currentUp;
|
||||
StepDownConvexResultCallback callback2 (_ghostObject,
|
||||
up,
|
||||
_currentUp,
|
||||
_currentPosition, step,
|
||||
_walkDirection,
|
||||
_maxSlopeCosine,
|
||||
_radius, _halfHeight);
|
||||
|
||||
callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
callback2.m_collisionFilterGroup = _ghostObject->getBroadphaseHandle()->m_collisionFilterGroup;
|
||||
callback2.m_collisionFilterMask = _ghostObject->getBroadphaseHandle()->m_collisionFilterMask;
|
||||
|
||||
_currentPosition = _targetPosition;
|
||||
_targetPosition = _currentPosition + step;
|
||||
|
@ -617,10 +613,10 @@ void CharacterController::preStep(btCollisionWorld* collisionWorld) {
|
|||
}
|
||||
}
|
||||
|
||||
// the CharacterController algorithm can only change the position,
|
||||
// so we don't bother to pull the rotation out of the transform
|
||||
const btTransform& transform = _ghostObject->getWorldTransform();
|
||||
_currentRotation = transform.getRotation();
|
||||
_currentPosition = transform.getOrigin();
|
||||
_targetPosition = _currentPosition;
|
||||
}
|
||||
|
||||
void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt) {
|
||||
|
@ -868,6 +864,7 @@ void CharacterController::updateShapeIfNecessary() {
|
|||
void CharacterController::preSimulation(btScalar timeStep) {
|
||||
if (_enabled && _dynamicsWorld) {
|
||||
glm::quat rotation = _avatarData->getOrientation();
|
||||
_currentUp = quatRotate(glmToBullet(rotation), LOCAL_UP_AXIS);
|
||||
glm::vec3 position = _avatarData->getPosition() + rotation * _shapeLocalOffset;
|
||||
btVector3 walkVelocity = glmToBullet(_avatarData->getVelocity());
|
||||
|
||||
|
@ -895,8 +892,7 @@ void CharacterController::postSimulation() {
|
|||
// cap the velocity of the step so that the character doesn't POP! so hard on steps
|
||||
glm::vec3 finalStep = position - _lastPosition;
|
||||
btVector3 finalVelocity = _walkDirection;
|
||||
btVector3 up = quatRotate(_currentRotation, LOCAL_UP_AXIS);
|
||||
finalVelocity += _verticalVelocity * up;
|
||||
finalVelocity += _verticalVelocity * _currentUp;
|
||||
const btScalar MAX_RESOLUTION_SPEED = 5.0f; // m/sec
|
||||
btScalar maxStepLength = glm::max(MAX_RESOLUTION_SPEED, 2.0f * finalVelocity.length()) * _stepDt;
|
||||
btScalar stepLength = glm::length(finalStep);
|
||||
|
|
|
@ -42,9 +42,22 @@ class btPairCachingGhostObject;
|
|||
ATTRIBUTE_ALIGNED16(class) CharacterController : public btCharacterControllerInterface
|
||||
{
|
||||
protected:
|
||||
///this is the desired walk direction, set by the user
|
||||
btVector3 _walkDirection;
|
||||
btVector3 _normalizedDirection;
|
||||
|
||||
//some internal variables
|
||||
btVector3 _currentPosition;
|
||||
btVector3 _currentUp;
|
||||
btVector3 _targetPosition;
|
||||
glm::vec3 _lastPosition;
|
||||
btVector3 _floorNormal; // points from object to character
|
||||
|
||||
glm::vec3 _shapeLocalOffset;
|
||||
glm::vec3 _boxScale; // used to compute capsule shape
|
||||
|
||||
AvatarData* _avatarData = NULL;
|
||||
btPairCachingGhostObject* _ghostObject;
|
||||
btPairCachingGhostObject* _ghostObject = NULL;
|
||||
|
||||
btConvexShape* _convexShape;//is also in _ghostObject, but it needs to be convex, so we store it here to avoid upcast
|
||||
btScalar _radius;
|
||||
|
@ -64,22 +77,12 @@ protected:
|
|||
|
||||
btScalar _addedMargin;//@todo: remove this and fix the code
|
||||
|
||||
///this is the desired walk direction, set by the user
|
||||
btVector3 _walkDirection;
|
||||
btVector3 _normalizedDirection;
|
||||
|
||||
//some internal variables
|
||||
btVector3 _currentPosition;
|
||||
btQuaternion _currentRotation;
|
||||
btVector3 _targetPosition;
|
||||
glm::vec3 _lastPosition;
|
||||
btScalar _lastStepUp;
|
||||
|
||||
///keep track of the contact manifolds
|
||||
btManifoldArray _manifoldArray;
|
||||
|
||||
bool _touchingContact;
|
||||
btVector3 _floorNormal; // points from object to character
|
||||
|
||||
bool _enabled;
|
||||
bool _isOnGround;
|
||||
|
@ -90,9 +93,6 @@ protected:
|
|||
btScalar _stepDt;
|
||||
uint32_t _pendingFlags;
|
||||
|
||||
glm::vec3 _shapeLocalOffset;
|
||||
glm::vec3 _boxScale; // used to compute capsule shape
|
||||
|
||||
btDynamicsWorld* _dynamicsWorld = NULL;
|
||||
|
||||
btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
|
||||
|
|
|
@ -36,8 +36,8 @@ PhysicsEngine::~PhysicsEngine() {
|
|||
delete _collisionDispatcher;
|
||||
delete _broadphaseFilter;
|
||||
delete _constraintSolver;
|
||||
// delete _dynamicsWorld;
|
||||
// delete _ghostPairCallback;
|
||||
delete _dynamicsWorld;
|
||||
delete _ghostPairCallback;
|
||||
}
|
||||
|
||||
// begin EntitySimulation overrides
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// SettingInterface.cpp
|
||||
//
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Clement on 2/2/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
|
@ -9,7 +9,6 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
@ -23,8 +22,16 @@ namespace Setting {
|
|||
|
||||
// cleans up the settings private instance. Should only be run once at closing down.
|
||||
void cleanupPrivateInstance() {
|
||||
delete privateInstance;
|
||||
privateInstance = nullptr;
|
||||
// grab the thread before we nuke the instance
|
||||
QThread* settingsManagerThread = privateInstance->thread();
|
||||
|
||||
// tell the private instance to clean itself up on its thread
|
||||
privateInstance->deleteLater();
|
||||
privateInstance = NULL;
|
||||
|
||||
// quit the settings manager thread and wait on it to make sure it's gone
|
||||
settingsManagerThread->quit();
|
||||
settingsManagerThread->wait();
|
||||
}
|
||||
|
||||
// Sets up the settings private instance. Should only be run once at startup
|
||||
|
|
Loading…
Reference in a new issue