mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 05:58:35 +02:00
Merge remote-tracking branch 'upstream/master' into android_goto_splash
This commit is contained in:
commit
ddbf4417ff
22 changed files with 218 additions and 219 deletions
|
@ -105,8 +105,6 @@ EntityScriptServer::~EntityScriptServer() {
|
||||||
static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server";
|
static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server";
|
||||||
|
|
||||||
void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
|
||||||
// about each other.
|
|
||||||
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
||||||
auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID));
|
auto entityID = QUuid::fromRfc4122(message->read(NUM_BYTES_RFC4122_UUID));
|
||||||
|
|
||||||
|
@ -119,8 +117,6 @@ void EntityScriptServer::handleReloadEntityServerScriptPacket(QSharedPointer<Rec
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
void EntityScriptServer::handleEntityScriptGetStatusPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
|
||||||
// about each other.
|
|
||||||
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
if (senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified()) {
|
||||||
MessageID messageID;
|
MessageID messageID;
|
||||||
message->readPrimitive(&messageID);
|
message->readPrimitive(&messageID);
|
||||||
|
@ -190,15 +186,14 @@ void EntityScriptServer::updateEntityPPS() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityScriptServer::handleEntityServerScriptLogPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
void EntityScriptServer::handleEntityServerScriptLogPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
// These are temporary checks until we can ensure that nodes eventually disconnect if the Domain Server stops telling them
|
bool canRezAny = senderNode->getCanRez() || senderNode->getCanRezTmp() || senderNode->getCanRezCertified() || senderNode->getCanRezTmpCertified();
|
||||||
// about each other.
|
|
||||||
bool enable = false;
|
bool enable = false;
|
||||||
message->readPrimitive(&enable);
|
message->readPrimitive(&enable);
|
||||||
|
|
||||||
auto senderUUID = senderNode->getUUID();
|
auto senderUUID = senderNode->getUUID();
|
||||||
auto it = _logListeners.find(senderUUID);
|
auto it = _logListeners.find(senderUUID);
|
||||||
|
|
||||||
if (enable && senderNode->getCanRez()) {
|
if (enable && canRezAny) {
|
||||||
if (it == std::end(_logListeners)) {
|
if (it == std::end(_logListeners)) {
|
||||||
_logListeners.insert(senderUUID);
|
_logListeners.insert(senderUUID);
|
||||||
qCInfo(entity_script_server) << "Node" << senderUUID << "subscribed to log stream";
|
qCInfo(entity_script_server) << "Node" << senderUUID << "subscribed to log stream";
|
||||||
|
|
|
@ -1042,41 +1042,7 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
|
||||||
|
|
||||||
bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB) {
|
||||||
auto nodeAData = static_cast<DomainServerNodeData*>(nodeA->getLinkedData());
|
auto nodeAData = static_cast<DomainServerNodeData*>(nodeA->getLinkedData());
|
||||||
auto nodeBData = static_cast<DomainServerNodeData*>(nodeB->getLinkedData());
|
return nodeAData && nodeAData->getNodeInterestSet().contains(nodeB->getType());
|
||||||
|
|
||||||
// if we have no linked data for node A then B can't possibly be in the interest set
|
|
||||||
if (!nodeAData) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first check if the general interest set A contains the type for B
|
|
||||||
if (nodeAData->getNodeInterestSet().contains(nodeB->getType())) {
|
|
||||||
// given that there is a match in the general interest set, do any special checks
|
|
||||||
|
|
||||||
// (1/19/17) Agents only need to connect to Entity Script Servers to perform administrative tasks
|
|
||||||
// related to entity server scripts. Only agents with rez permissions should be doing that, so
|
|
||||||
// if the agent does not have those permissions, we do not want them and the server to incur the
|
|
||||||
// overhead of connecting to one another. Additionally we exclude agents that do not care about the
|
|
||||||
// Entity Script Server and won't attempt to connect to it.
|
|
||||||
|
|
||||||
bool isAgentWithoutRights = nodeA->getType() == NodeType::Agent
|
|
||||||
&& nodeB->getType() == NodeType::EntityScriptServer
|
|
||||||
&& !nodeA->getCanRez() && !nodeA->getCanRezTmp()
|
|
||||||
&& !nodeA->getCanRezCertified() && !nodeA->getCanRezTmpCertified();
|
|
||||||
|
|
||||||
if (isAgentWithoutRights) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isScriptServerForIneffectiveAgent =
|
|
||||||
(nodeA->getType() == NodeType::EntityScriptServer && nodeB->getType() == NodeType::Agent)
|
|
||||||
&& ((nodeBData && !nodeBData->getNodeInterestSet().contains(NodeType::EntityScriptServer))
|
|
||||||
|| (!nodeB->getCanRez() && !nodeB->getCanRezTmp() && !nodeB->getCanRezCertified() && !nodeB->getCanRezTmpCertified()));
|
|
||||||
|
|
||||||
return !isScriptServerForIneffectiveAgent;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DomainServer::countConnectedUsers() {
|
unsigned int DomainServer::countConnectedUsers() {
|
||||||
|
@ -3476,4 +3442,4 @@ void DomainServer::handleOctreeFileReplacementRequest(QSharedPointer<ReceivedMes
|
||||||
if (node->getCanReplaceContent()) {
|
if (node->getCanReplaceContent()) {
|
||||||
handleOctreeFileReplacement(message->readAll());
|
handleOctreeFileReplacement(message->readAll());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
{ "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||||
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
{ "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" },
|
||||||
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
{ "from": "Keyboard.Shift", "when": ["!Keyboard.Left", "!Keyboard.Right"], "to": "Actions.SPRINT" },
|
||||||
{ "from": "Keyboard.Control", "to": "Actions.VERTICAL_DOWN" },
|
{ "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" },
|
||||||
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
{ "from": "Keyboard.Left", "when": "Keyboard.Shift", "to": "Actions.LATERAL_LEFT" },
|
||||||
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
{ "from": "Keyboard.Right", "when": "Keyboard.Shift", "to": "Actions.LATERAL_RIGHT" },
|
||||||
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
{ "from": "Keyboard.Up", "when": "Application.CameraFirstPerson", "to": "Actions.LONGITUDINAL_FORWARD" },
|
||||||
|
|
|
@ -163,10 +163,18 @@ TextField {
|
||||||
text: textField.label
|
text: textField.label
|
||||||
colorScheme: textField.colorScheme
|
colorScheme: textField.colorScheme
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
|
||||||
|
Binding on anchors.right {
|
||||||
|
when: parent.right
|
||||||
|
value: parent.right
|
||||||
|
}
|
||||||
|
Binding on wrapMode {
|
||||||
|
when: parent.right
|
||||||
|
value: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
anchors.bottom: parent.top
|
anchors.bottom: parent.top
|
||||||
anchors.bottomMargin: 3
|
anchors.bottomMargin: 3
|
||||||
wrapMode: Text.WordWrap
|
|
||||||
visible: label != ""
|
visible: label != ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6247,8 +6247,9 @@ bool Application::canAcceptURL(const QString& urlString) const {
|
||||||
|
|
||||||
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
|
||||||
QUrl url(urlString);
|
QUrl url(urlString);
|
||||||
if (isDomainURL(url)) {
|
|
||||||
// this is a URL for a domain, either hifi:// or serverless - have the AddressManager handle it
|
if (url.scheme() == URL_SCHEME_HIFI) {
|
||||||
|
// this is a hifi URL - have the AddressManager handle it
|
||||||
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
QMetaObject::invokeMethod(DependencyManager::get<AddressManager>().data(), "handleLookupString",
|
||||||
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
Qt::AutoConnection, Q_ARG(const QString&, urlString));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -81,26 +81,14 @@ void LaserPointer::editRenderState(const std::string& state, const QVariant& sta
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
|
PickResultPointer LaserPointer::getVisualPickResult(const PickResultPointer& pickResult) {
|
||||||
if (!id.isNull() && props.isValid()) {
|
PickResultPointer visualPickResult = pickResult;
|
||||||
QVariantMap propMap = props.toMap();
|
auto rayPickResult = std::static_pointer_cast<RayPickResult>(visualPickResult);
|
||||||
propMap.remove("visible");
|
IntersectionType type = rayPickResult ? rayPickResult->type : IntersectionType::NONE;
|
||||||
qApp->getOverlays().editOverlay(id, propMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay, bool defaultState) {
|
if (type != IntersectionType::HUD) {
|
||||||
if (!renderState.getStartID().isNull()) {
|
glm::vec3 endVec;
|
||||||
QVariantMap startProps;
|
PickRay pickRay = rayPickResult ? PickRay(rayPickResult->pickVariant) : PickRay();
|
||||||
startProps.insert("position", vec3toVariant(pickRay.origin));
|
|
||||||
startProps.insert("visible", true);
|
|
||||||
startProps.insert("ignoreRayIntersection", renderState.doesStartIgnoreRays());
|
|
||||||
qApp->getOverlays().editOverlay(renderState.getStartID(), startProps);
|
|
||||||
}
|
|
||||||
glm::vec3 endVec;
|
|
||||||
if (((defaultState || !_lockEnd) && _lockEndObject.id.isNull()) || type == IntersectionType::HUD) {
|
|
||||||
endVec = pickRay.origin + pickRay.direction * distance;
|
|
||||||
} else {
|
|
||||||
if (!_lockEndObject.id.isNull()) {
|
if (!_lockEndObject.id.isNull()) {
|
||||||
glm::vec3 pos;
|
glm::vec3 pos;
|
||||||
glm::quat rot;
|
glm::quat rot;
|
||||||
|
@ -122,17 +110,54 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter
|
||||||
}
|
}
|
||||||
const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f);
|
const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f);
|
||||||
endVec = pos + rot * (dim * (DEFAULT_REGISTRATION_POINT - registrationPoint));
|
endVec = pos + rot * (dim * (DEFAULT_REGISTRATION_POINT - registrationPoint));
|
||||||
} else {
|
glm::vec3 direction = endVec - pickRay.origin;
|
||||||
|
float distance = glm::distance(pickRay.origin, endVec);
|
||||||
|
glm::vec3 normalizedDirection = glm::normalize(direction);
|
||||||
|
|
||||||
|
rayPickResult->type = _lockEndObject.isOverlay ? IntersectionType::OVERLAY : IntersectionType::ENTITY;
|
||||||
|
rayPickResult->objectID = _lockEndObject.id;
|
||||||
|
rayPickResult->intersection = endVec;
|
||||||
|
rayPickResult->distance = distance;
|
||||||
|
rayPickResult->surfaceNormal = -normalizedDirection;
|
||||||
|
rayPickResult->pickVariant["direction"] = vec3toVariant(normalizedDirection);
|
||||||
|
} else if (type != IntersectionType::NONE && _lockEnd) {
|
||||||
if (type == IntersectionType::ENTITY) {
|
if (type == IntersectionType::ENTITY) {
|
||||||
endVec = DependencyManager::get<EntityScriptingInterface>()->getEntityTransform(objectID)[3];
|
endVec = DependencyManager::get<EntityScriptingInterface>()->getEntityTransform(rayPickResult->objectID)[3];
|
||||||
} else if (type == IntersectionType::OVERLAY) {
|
} else if (type == IntersectionType::OVERLAY) {
|
||||||
endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value);
|
endVec = vec3FromVariant(qApp->getOverlays().getProperty(rayPickResult->objectID, "position").value);
|
||||||
} else if (type == IntersectionType::AVATAR) {
|
} else if (type == IntersectionType::AVATAR) {
|
||||||
endVec = DependencyManager::get<AvatarHashMap>()->getAvatar(objectID)->getPosition();
|
endVec = DependencyManager::get<AvatarHashMap>()->getAvatar(rayPickResult->objectID)->getPosition();
|
||||||
}
|
}
|
||||||
|
glm::vec3 direction = endVec - pickRay.origin;
|
||||||
|
float distance = glm::distance(pickRay.origin, endVec);
|
||||||
|
glm::vec3 normalizedDirection = glm::normalize(direction);
|
||||||
|
rayPickResult->intersection = endVec;
|
||||||
|
rayPickResult->distance = distance;
|
||||||
|
rayPickResult->surfaceNormal = -normalizedDirection;
|
||||||
|
rayPickResult->pickVariant["direction"] = vec3toVariant(normalizedDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return visualPickResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& props) {
|
||||||
|
if (!id.isNull() && props.isValid()) {
|
||||||
|
QVariantMap propMap = props.toMap();
|
||||||
|
propMap.remove("visible");
|
||||||
|
qApp->getOverlays().editOverlay(id, propMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay) {
|
||||||
|
if (!renderState.getStartID().isNull()) {
|
||||||
|
QVariantMap startProps;
|
||||||
|
startProps.insert("position", vec3toVariant(pickRay.origin));
|
||||||
|
startProps.insert("visible", true);
|
||||||
|
startProps.insert("ignoreRayIntersection", renderState.doesStartIgnoreRays());
|
||||||
|
qApp->getOverlays().editOverlay(renderState.getStartID(), startProps);
|
||||||
|
}
|
||||||
|
glm::vec3 endVec = pickRay.origin + pickRay.direction * distance;
|
||||||
|
|
||||||
QVariant end = vec3toVariant(endVec);
|
QVariant end = vec3toVariant(endVec);
|
||||||
if (!renderState.getPathID().isNull()) {
|
if (!renderState.getPathID().isNull()) {
|
||||||
QVariantMap pathProps;
|
QVariantMap pathProps;
|
||||||
|
@ -195,15 +220,15 @@ void LaserPointer::updateVisuals(const PickResultPointer& pickResult) {
|
||||||
IntersectionType type = rayPickResult ? rayPickResult->type : IntersectionType::NONE;
|
IntersectionType type = rayPickResult ? rayPickResult->type : IntersectionType::NONE;
|
||||||
if (_enabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
if (_enabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||||
(type != IntersectionType::NONE || _laserLength > 0.0f || !_lockEndObject.id.isNull())) {
|
(type != IntersectionType::NONE || _laserLength > 0.0f || !_lockEndObject.id.isNull())) {
|
||||||
PickRay pickRay(rayPickResult->pickVariant);
|
PickRay pickRay = rayPickResult ? PickRay(rayPickResult->pickVariant): PickRay();
|
||||||
QUuid uid = rayPickResult->objectID;
|
QUuid uid = rayPickResult->objectID;
|
||||||
float distance = _laserLength > 0.0f ? _laserLength : rayPickResult->distance;
|
float distance = _laserLength > 0.0f ? _laserLength : rayPickResult->distance;
|
||||||
updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay, false);
|
updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay);
|
||||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||||
} else if (_enabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
} else if (_enabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||||
disableRenderState(_renderStates[_currentRenderState]);
|
disableRenderState(_renderStates[_currentRenderState]);
|
||||||
PickRay pickRay = rayPickResult ? PickRay(rayPickResult->pickVariant) : PickRay();
|
PickRay pickRay = rayPickResult ? PickRay(rayPickResult->pickVariant) : PickRay();
|
||||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay, true);
|
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay);
|
||||||
} else if (!_currentRenderState.empty()) {
|
} else if (!_currentRenderState.empty()) {
|
||||||
disableRenderState(_renderStates[_currentRenderState]);
|
disableRenderState(_renderStates[_currentRenderState]);
|
||||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||||
|
@ -386,4 +411,4 @@ glm::vec2 LaserPointer::findPos2D(const PickedObject& pickedObject, const glm::v
|
||||||
default:
|
default:
|
||||||
return glm::vec2(NAN);
|
return glm::vec2(NAN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button = "", bool hover = true) override;
|
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button = "", bool hover = true) override;
|
||||||
|
|
||||||
|
PickResultPointer getVisualPickResult(const PickResultPointer& pickResult) override;
|
||||||
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
||||||
Pointer::Buttons getPressedButtons(const PickResultPointer& pickResult) override;
|
Pointer::Buttons getPressedButtons(const PickResultPointer& pickResult) override;
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ private:
|
||||||
LockEndObject _lockEndObject;
|
LockEndObject _lockEndObject;
|
||||||
|
|
||||||
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
|
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
|
||||||
void updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay, bool defaultState);
|
void updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay);
|
||||||
void disableRenderState(const RenderState& renderState);
|
void disableRenderState(const RenderState& renderState);
|
||||||
|
|
||||||
struct TriggerState {
|
struct TriggerState {
|
||||||
|
|
|
@ -6,10 +6,43 @@
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
|
||||||
// NOTE: we don't need to include this header unless/until we add additional symbols.
|
#include "JSEndpoint.h"
|
||||||
// By removing this header we prevent these warnings on windows:
|
#include "../../Logging.h"
|
||||||
//
|
|
||||||
// warning LNK4221: This object file does not define any previously undefined public symbols,
|
using namespace controller;
|
||||||
// so it will not be used by any link operation that consumes this library
|
|
||||||
//
|
QString formatException(const QJSValue& exception) {
|
||||||
//#include "JSEndpoint.h"
|
QString note { "UncaughtException" };
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
const auto message = exception.toString();
|
||||||
|
const auto fileName = exception.property("fileName").toString();
|
||||||
|
const auto lineNumber = exception.property("lineNumber").toString();
|
||||||
|
const auto stacktrace = exception.property("stack").toString();
|
||||||
|
|
||||||
|
const QString SCRIPT_EXCEPTION_FORMAT = "[%0] %1 in %2:%3";
|
||||||
|
const QString SCRIPT_BACKTRACE_SEP = "\n ";
|
||||||
|
|
||||||
|
result = QString(SCRIPT_EXCEPTION_FORMAT).arg(note, message, fileName, lineNumber);
|
||||||
|
if (!stacktrace.isEmpty()) {
|
||||||
|
result += QString("\n[Backtrace]%1%2").arg(SCRIPT_BACKTRACE_SEP).arg(stacktrace);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float JSEndpoint::peek() const {
|
||||||
|
QJSValue result = _callable.call();
|
||||||
|
if (result.isError()) {
|
||||||
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
|
return 0.0f;
|
||||||
|
} else {
|
||||||
|
return (float)result.toNumber();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JSEndpoint::apply(float newValue, const Pointer& source) {
|
||||||
|
QJSValue result = _callable.call(QJSValueList({ QJSValue(newValue) }));
|
||||||
|
if (result.isError()) {
|
||||||
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,16 +24,11 @@ public:
|
||||||
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
: Endpoint(Input::INVALID_INPUT), _callable(callable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual float peek() const override {
|
virtual float peek() const override;
|
||||||
return (float)const_cast<JSEndpoint*>(this)->_callable.call().toNumber();
|
virtual void apply(float newValue, const Pointer& source) override;
|
||||||
}
|
|
||||||
|
|
||||||
virtual void apply(float newValue, const Pointer& source) override {
|
|
||||||
_callable.call(QJSValueList({ QJSValue(newValue) }));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJSValue _callable;
|
mutable QJSValue _callable;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "ScriptEndpoint.h"
|
#include "ScriptEndpoint.h"
|
||||||
|
#include "../../Logging.h"
|
||||||
|
|
||||||
#include <QtCore/QThread>
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
|
@ -14,6 +15,25 @@
|
||||||
|
|
||||||
using namespace controller;
|
using namespace controller;
|
||||||
|
|
||||||
|
QString formatException(const QScriptValue& exception) {
|
||||||
|
QString note { "UncaughtException" };
|
||||||
|
QString result;
|
||||||
|
|
||||||
|
const auto message = exception.toString();
|
||||||
|
const auto fileName = exception.property("fileName").toString();
|
||||||
|
const auto lineNumber = exception.property("lineNumber").toString();
|
||||||
|
const auto stacktrace = exception.property("stack").toString();
|
||||||
|
|
||||||
|
const QString SCRIPT_EXCEPTION_FORMAT = "[%0] %1 in %2:%3";
|
||||||
|
const QString SCRIPT_BACKTRACE_SEP = "\n ";
|
||||||
|
|
||||||
|
result = QString(SCRIPT_EXCEPTION_FORMAT).arg(note, message, fileName, lineNumber);
|
||||||
|
if (!stacktrace.isEmpty()) {
|
||||||
|
result += QString("\n[Backtrace]%1%2").arg(SCRIPT_BACKTRACE_SEP).arg(stacktrace);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
float ScriptEndpoint::peek() const {
|
float ScriptEndpoint::peek() const {
|
||||||
const_cast<ScriptEndpoint*>(this)->updateValue();
|
const_cast<ScriptEndpoint*>(this)->updateValue();
|
||||||
return _lastValueRead;
|
return _lastValueRead;
|
||||||
|
@ -26,10 +46,11 @@ void ScriptEndpoint::updateValue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QScriptValue result = _callable.call();
|
QScriptValue result = _callable.call();
|
||||||
|
if (result.isError()) {
|
||||||
// If the callable ever returns a non-number, we assume it's a pose
|
// print JavaScript exception
|
||||||
// and start reporting ourselves as a pose.
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
if (result.isNumber()) {
|
_lastValueRead = 0.0f;
|
||||||
|
} else if (result.isNumber()) {
|
||||||
_lastValueRead = (float)_callable.call().toNumber();
|
_lastValueRead = (float)_callable.call().toNumber();
|
||||||
} else {
|
} else {
|
||||||
Pose::fromScriptValue(result, _lastPoseRead);
|
Pose::fromScriptValue(result, _lastPoseRead);
|
||||||
|
@ -52,8 +73,12 @@ void ScriptEndpoint::internalApply(float value, int sourceID) {
|
||||||
Q_ARG(int, sourceID));
|
Q_ARG(int, sourceID));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_callable.call(QScriptValue(),
|
QScriptValue result = _callable.call(QScriptValue(),
|
||||||
QScriptValueList({ QScriptValue(value), QScriptValue(sourceID) }));
|
QScriptValueList({ QScriptValue(value), QScriptValue(sourceID) }));
|
||||||
|
if (result.isError()) {
|
||||||
|
// print JavaScript exception
|
||||||
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pose ScriptEndpoint::peekPose() const {
|
Pose ScriptEndpoint::peekPose() const {
|
||||||
|
@ -67,6 +92,10 @@ void ScriptEndpoint::updatePose() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QScriptValue result = _callable.call();
|
QScriptValue result = _callable.call();
|
||||||
|
if (result.isError()) {
|
||||||
|
// print JavaScript exception
|
||||||
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
|
}
|
||||||
Pose::fromScriptValue(result, _lastPoseRead);
|
Pose::fromScriptValue(result, _lastPoseRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +114,10 @@ void ScriptEndpoint::internalApply(const Pose& newPose, int sourceID) {
|
||||||
Q_ARG(int, sourceID));
|
Q_ARG(int, sourceID));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_callable.call(QScriptValue(),
|
QScriptValue result = _callable.call(QScriptValue(),
|
||||||
QScriptValueList({ Pose::toScriptValue(_callable.engine(), newPose), QScriptValue(sourceID) }));
|
QScriptValueList({ Pose::toScriptValue(_callable.engine(), newPose), QScriptValue(sourceID) }));
|
||||||
|
if (result.isError()) {
|
||||||
|
// print JavaScript exception
|
||||||
|
qCDebug(controllers).noquote() << formatException(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,8 @@ ItemKey ShapeEntityRenderer::getKey() {
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
if (isTransparent()) {
|
if (isTransparent()) {
|
||||||
builder.withTransparent();
|
builder.withTransparent();
|
||||||
|
} else if (_canCastShadow) {
|
||||||
|
builder.withShadowCaster();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -254,17 +254,6 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
||||||
propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent);
|
propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent);
|
||||||
propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged());
|
propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged());
|
||||||
|
|
||||||
auto dimensions = propertiesWithSimID.getDimensions();
|
|
||||||
float volume = dimensions.x * dimensions.y * dimensions.z;
|
|
||||||
auto density = propertiesWithSimID.getDensity();
|
|
||||||
auto newVelocity = propertiesWithSimID.getVelocity().length();
|
|
||||||
float cost = calculateCost(density * volume, 0, newVelocity);
|
|
||||||
cost *= costMultiplier;
|
|
||||||
|
|
||||||
if (cost > _currentAvatarEnergy) {
|
|
||||||
return QUuid();
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityItemID id = EntityItemID(QUuid::createUuid());
|
EntityItemID id = EntityItemID(QUuid::createUuid());
|
||||||
|
|
||||||
// If we have a local entity tree set, then also update it.
|
// If we have a local entity tree set, then also update it.
|
||||||
|
@ -295,9 +284,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
|
||||||
|
|
||||||
// queue the packet
|
// queue the packet
|
||||||
if (success) {
|
if (success) {
|
||||||
emit debitEnergySource(cost);
|
|
||||||
queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID);
|
queueEntityMessage(PacketType::EntityAdd, id, propertiesWithSimID);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
} else {
|
} else {
|
||||||
return QUuid();
|
return QUuid();
|
||||||
|
@ -378,27 +365,9 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
||||||
|
|
||||||
EntityItemProperties properties = scriptSideProperties;
|
EntityItemProperties properties = scriptSideProperties;
|
||||||
|
|
||||||
auto dimensions = properties.getDimensions();
|
|
||||||
float volume = dimensions.x * dimensions.y * dimensions.z;
|
|
||||||
auto density = properties.getDensity();
|
|
||||||
auto newVelocity = properties.getVelocity().length();
|
|
||||||
float oldVelocity = { 0.0f };
|
|
||||||
|
|
||||||
EntityItemID entityID(id);
|
EntityItemID entityID(id);
|
||||||
if (!_entityTree) {
|
if (!_entityTree) {
|
||||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||||
|
|
||||||
//if there is no local entity entity tree, no existing velocity, use 0.
|
|
||||||
float cost = calculateCost(density * volume, oldVelocity, newVelocity);
|
|
||||||
cost *= costMultiplier;
|
|
||||||
|
|
||||||
if (cost > _currentAvatarEnergy) {
|
|
||||||
return QUuid();
|
|
||||||
} else {
|
|
||||||
//debit the avatar energy and continue
|
|
||||||
emit debitEnergySource(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
// If we have a local entity tree set, then also update it.
|
// If we have a local entity tree set, then also update it.
|
||||||
|
@ -420,9 +389,6 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
||||||
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
|
// All of parentID, parentJointIndex, position, rotation are needed to make sense of any of them.
|
||||||
// If any of these changed, pull any missing properties from the entity.
|
// If any of these changed, pull any missing properties from the entity.
|
||||||
|
|
||||||
//existing entity, retrieve old velocity for check down below
|
|
||||||
oldVelocity = entity->getWorldVelocity().length();
|
|
||||||
|
|
||||||
if (!scriptSideProperties.parentIDChanged()) {
|
if (!scriptSideProperties.parentIDChanged()) {
|
||||||
properties.setParentID(entity->getParentID());
|
properties.setParentID(entity->getParentID());
|
||||||
}
|
}
|
||||||
|
@ -442,23 +408,11 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
||||||
properties.setClientOnly(entity->getClientOnly());
|
properties.setClientOnly(entity->getClientOnly());
|
||||||
properties.setOwningAvatarID(entity->getOwningAvatarID());
|
properties.setOwningAvatarID(entity->getOwningAvatarID());
|
||||||
properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent());
|
properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent());
|
||||||
|
updatedEntity = _entityTree->updateEntity(entityID, properties);
|
||||||
float cost = calculateCost(density * volume, oldVelocity, newVelocity);
|
|
||||||
cost *= costMultiplier;
|
|
||||||
|
|
||||||
if (cost > _currentAvatarEnergy) {
|
|
||||||
updatedEntity = false;
|
|
||||||
} else {
|
|
||||||
//debit the avatar energy and continue
|
|
||||||
updatedEntity = _entityTree->updateEntity(entityID, properties);
|
|
||||||
if (updatedEntity) {
|
|
||||||
emit debitEnergySource(cost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: We need to figure out a better way to handle this. Allowing these edits to go through potentially
|
// FIXME: We need to figure out a better way to handle this. Allowing these edits to go through potentially
|
||||||
// breaks avatar energy and entities that are parented.
|
// breaks entities that are parented.
|
||||||
//
|
//
|
||||||
// To handle cases where a script needs to edit an entity with a _known_ entity id but doesn't exist
|
// To handle cases where a script needs to edit an entity with a _known_ entity id but doesn't exist
|
||||||
// in the local entity tree, we need to allow those edits to go through to the server.
|
// in the local entity tree, we need to allow those edits to go through to the server.
|
||||||
|
@ -577,21 +531,6 @@ void EntityScriptingInterface::deleteEntity(QUuid id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dimensions = entity->getScaledDimensions();
|
|
||||||
float volume = dimensions.x * dimensions.y * dimensions.z;
|
|
||||||
auto density = entity->getDensity();
|
|
||||||
auto velocity = entity->getWorldVelocity().length();
|
|
||||||
float cost = calculateCost(density * volume, velocity, 0);
|
|
||||||
cost *= costMultiplier;
|
|
||||||
|
|
||||||
if (cost > _currentAvatarEnergy) {
|
|
||||||
shouldDelete = false;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
//debit the avatar energy and continue
|
|
||||||
emit debitEnergySource(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entity->getLocked()) {
|
if (entity->getLocked()) {
|
||||||
shouldDelete = false;
|
shouldDelete = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1812,23 +1751,6 @@ void EntityScriptingInterface::emitScriptEvent(const EntityItemID& entityID, con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float EntityScriptingInterface::calculateCost(float mass, float oldVelocity, float newVelocity) {
|
|
||||||
return std::abs(mass * (newVelocity - oldVelocity));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityScriptingInterface::setCurrentAvatarEnergy(float energy) {
|
|
||||||
// qCDebug(entities) << "NEW AVATAR ENERGY IN ENTITY SCRIPTING INTERFACE: " << energy;
|
|
||||||
_currentAvatarEnergy = energy;
|
|
||||||
}
|
|
||||||
|
|
||||||
float EntityScriptingInterface::getCostMultiplier() {
|
|
||||||
return costMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityScriptingInterface::setCostMultiplier(float value) {
|
|
||||||
costMultiplier = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move this someplace that makes more sense...
|
// TODO move this someplace that makes more sense...
|
||||||
bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions,
|
bool EntityScriptingInterface::AABoxIntersectsCapsule(const glm::vec3& low, const glm::vec3& dimensions,
|
||||||
const glm::vec3& start, const glm::vec3& end, float radius) {
|
const glm::vec3& start, const glm::vec3& end, float radius) {
|
||||||
|
|
|
@ -94,8 +94,6 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
|
||||||
* Interface has displayed and so knows about.
|
* Interface has displayed and so knows about.
|
||||||
*
|
*
|
||||||
* @namespace Entities
|
* @namespace Entities
|
||||||
* @property {number} currentAvatarEnergy - <strong>Deprecated</strong>
|
|
||||||
* @property {number} costMultiplier - <strong>Deprecated</strong>
|
|
||||||
* @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus.
|
* @property {Uuid} keyboardFocusEntity - Get or set the {@link Entities.EntityType|Web} entity that has keyboard focus.
|
||||||
* If no entity has keyboard focus, get returns <code>null</code>; set to <code>null</code> or {@link Uuid|Uuid.NULL} to
|
* If no entity has keyboard focus, get returns <code>null</code>; set to <code>null</code> or {@link Uuid|Uuid.NULL} to
|
||||||
* clear keyboard focus.
|
* clear keyboard focus.
|
||||||
|
@ -104,8 +102,6 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
|
||||||
class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency {
|
class EntityScriptingInterface : public OctreeScriptingInterface, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
Q_PROPERTY(float currentAvatarEnergy READ getCurrentAvatarEnergy WRITE setCurrentAvatarEnergy)
|
|
||||||
Q_PROPERTY(float costMultiplier READ getCostMultiplier WRITE setCostMultiplier)
|
|
||||||
Q_PROPERTY(QUuid keyboardFocusEntity READ getKeyboardFocusEntity WRITE setKeyboardFocusEntity)
|
Q_PROPERTY(QUuid keyboardFocusEntity READ getKeyboardFocusEntity WRITE setKeyboardFocusEntity)
|
||||||
|
|
||||||
friend EntityPropertyMetadataRequest;
|
friend EntityPropertyMetadataRequest;
|
||||||
|
@ -126,7 +122,6 @@ public:
|
||||||
void setEntityTree(EntityTreePointer modelTree);
|
void setEntityTree(EntityTreePointer modelTree);
|
||||||
EntityTreePointer getEntityTree() { return _entityTree; }
|
EntityTreePointer getEntityTree() { return _entityTree; }
|
||||||
void setEntitiesScriptEngine(QSharedPointer<EntitiesScriptEngineProvider> engine);
|
void setEntitiesScriptEngine(QSharedPointer<EntitiesScriptEngineProvider> engine);
|
||||||
float calculateCost(float mass, float oldVelocity, float newVelocity);
|
|
||||||
|
|
||||||
void resetActivityTracking();
|
void resetActivityTracking();
|
||||||
ActivityTracking getActivityTracking() const { return _activityTracking; }
|
ActivityTracking getActivityTracking() const { return _activityTracking; }
|
||||||
|
@ -1834,14 +1829,6 @@ signals:
|
||||||
*/
|
*/
|
||||||
void clearingEntities();
|
void clearingEntities();
|
||||||
|
|
||||||
/**jsdoc
|
|
||||||
* @function Entities.debitEnergySource
|
|
||||||
* @param {number} value - The amount to debit.
|
|
||||||
* @returns {Signal}
|
|
||||||
* @deprecated This function is deprecated and will soon be removed.
|
|
||||||
*/
|
|
||||||
void debitEnergySource(float value);
|
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Triggered in when a script in a {@link Entities.EntityType|Web} entity's Web page script sends an event over the
|
* Triggered in when a script in a {@link Entities.EntityType|Web} entity's Web page script sends an event over the
|
||||||
* script's <code>EventBridge</code>.
|
* script's <code>EventBridge</code>.
|
||||||
|
@ -1882,14 +1869,8 @@ private:
|
||||||
QSharedPointer<EntitiesScriptEngineProvider> _entitiesScriptEngine;
|
QSharedPointer<EntitiesScriptEngineProvider> _entitiesScriptEngine;
|
||||||
|
|
||||||
bool _bidOnSimulationOwnership { false };
|
bool _bidOnSimulationOwnership { false };
|
||||||
float _currentAvatarEnergy = { FLT_MAX };
|
|
||||||
float getCurrentAvatarEnergy() { return _currentAvatarEnergy; }
|
|
||||||
void setCurrentAvatarEnergy(float energy);
|
|
||||||
|
|
||||||
ActivityTracking _activityTracking;
|
ActivityTracking _activityTracking;
|
||||||
float costMultiplier = { 0.01f };
|
|
||||||
float getCostMultiplier();
|
|
||||||
void setCostMultiplier(float value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityScriptingInterface_h
|
#endif // hifi_EntityScriptingInterface_h
|
||||||
|
|
|
@ -425,8 +425,8 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
|
||||||
if (!childEntity) {
|
if (!childEntity) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
EntityTreeElementPointer containingElement = childEntity->getElement();
|
EntityTreeElementPointer childContainingElement = childEntity->getElement();
|
||||||
if (!containingElement) {
|
if (!childContainingElement) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperti
|
||||||
addToNeedsParentFixupList(childEntity);
|
addToNeedsParentFixupList(childEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateEntityOperator theChildOperator(getThisPointer(), containingElement, childEntity, queryCube);
|
UpdateEntityOperator theChildOperator(getThisPointer(), childContainingElement, childEntity, queryCube);
|
||||||
recurseTreeWithOperator(&theChildOperator);
|
recurseTreeWithOperator(&theChildOperator);
|
||||||
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
|
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
|
||||||
if (childChild && childChild->getNestableType() == NestableType::Entity) {
|
if (childChild && childChild->getNestableType() == NestableType::Entity) {
|
||||||
|
|
|
@ -288,7 +288,7 @@ OctreeElementPointer UpdateEntityOperator::possiblyCreateChildAt(const OctreeEle
|
||||||
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityBox);
|
int indexOfChildContainingNewEntity = element->getMyChildContaining(_newEntityBox);
|
||||||
|
|
||||||
if (childIndex == indexOfChildContainingNewEntity) {
|
if (childIndex == indexOfChildContainingNewEntity) {
|
||||||
return element->addChildAtIndex(childIndex);;
|
return element->addChildAtIndex(childIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,9 @@ void Pointer::update(unsigned int pointerID) {
|
||||||
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
auto pickResult = getPrevPickResult();
|
auto pickResult = getPrevPickResult();
|
||||||
updateVisuals(pickResult);
|
auto visualPickResult = getVisualPickResult(pickResult);
|
||||||
generatePointerEvents(pointerID, pickResult);
|
updateVisuals(visualPickResult);
|
||||||
|
generatePointerEvents(pointerID, visualPickResult);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ protected:
|
||||||
|
|
||||||
virtual bool shouldHover(const PickResultPointer& pickResult) { return true; }
|
virtual bool shouldHover(const PickResultPointer& pickResult) { return true; }
|
||||||
virtual bool shouldTrigger(const PickResultPointer& pickResult) { return true; }
|
virtual bool shouldTrigger(const PickResultPointer& pickResult) { return true; }
|
||||||
|
virtual PickResultPointer getVisualPickResult(const PickResultPointer& pickResult) { return pickResult; };
|
||||||
|
|
||||||
static const float POINTER_MOVE_DELAY;
|
static const float POINTER_MOVE_DELAY;
|
||||||
static const float TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED;
|
static const float TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED;
|
||||||
|
|
|
@ -380,6 +380,8 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const
|
||||||
batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, nullptr);
|
batch.setResourceTexture(AntialiasingPass_VelocityMapSlot, nullptr);
|
||||||
batch.setResourceTexture(AntialiasingPass_NextMapSlot, nullptr);
|
batch.setResourceTexture(AntialiasingPass_NextMapSlot, nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
args->popViewFrustum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -520,7 +522,7 @@ void JitterSample::run(const render::RenderContextPointer& renderContext) {
|
||||||
|
|
||||||
viewFrustum.setProjection(projMat);
|
viewFrustum.setProjection(projMat);
|
||||||
viewFrustum.calculate();
|
viewFrustum.calculate();
|
||||||
args->setViewFrustum(viewFrustum);
|
args->pushViewFrustum(viewFrustum);
|
||||||
} else {
|
} else {
|
||||||
mat4 projMats[2];
|
mat4 projMats[2];
|
||||||
args->_context->getStereoProjections(projMats);
|
args->_context->getStereoProjections(projMats);
|
||||||
|
@ -538,4 +540,4 @@ void JitterSample::run(const render::RenderContextPointer& renderContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,7 +46,7 @@ void printOctalCode(const unsigned char* octalCode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char sectionValue(const unsigned char* startByte, char startIndexInByte) {
|
char sectionValue(const unsigned char* startByte, char startIndexInByte) {
|
||||||
char rightShift = 8 - startIndexInByte - 3;
|
int8_t rightShift = 8 - startIndexInByte - 3;
|
||||||
|
|
||||||
if (rightShift < 0) {
|
if (rightShift < 0) {
|
||||||
return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> (8 + rightShift));
|
return ((startByte[0] << -rightShift) & 7) + (startByte[1] >> (8 + rightShift));
|
||||||
|
@ -73,7 +73,7 @@ int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsi
|
||||||
return sectionValue(descendantOctalCode + 1 + (branchStartBit / 8), branchStartBit % 8);
|
return sectionValue(descendantOctalCode + 1 + (branchStartBit / 8), branchStartBit % 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNumber) {
|
unsigned char* childOctalCode(const unsigned char* parentOctalCode, int childNumber) {
|
||||||
|
|
||||||
// find the length (in number of three bit code sequences)
|
// find the length (in number of three bit code sequences)
|
||||||
// in the parent
|
// in the parent
|
||||||
|
@ -111,7 +111,7 @@ unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNu
|
||||||
|
|
||||||
// calculate the amount of left shift required
|
// calculate the amount of left shift required
|
||||||
// this will be -1 or -2 if there's wrap
|
// this will be -1 or -2 if there's wrap
|
||||||
char leftShift = 8 - (startBit % 8) - 3;
|
int8_t leftShift = 8 - (startBit % 8) - 3;
|
||||||
|
|
||||||
if (leftShift < 0) {
|
if (leftShift < 0) {
|
||||||
// we have a wrap-around to accomodate
|
// we have a wrap-around to accomodate
|
||||||
|
|
|
@ -30,7 +30,7 @@ using OctalCodePtrList = std::vector<OctalCodePtr>;
|
||||||
void printOctalCode(const unsigned char* octalCode);
|
void printOctalCode(const unsigned char* octalCode);
|
||||||
size_t bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
size_t bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
||||||
int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsigned char* descendantOctalCode);
|
int branchIndexWithDescendant(const unsigned char* ancestorOctalCode, const unsigned char* descendantOctalCode);
|
||||||
unsigned char* childOctalCode(const unsigned char* parentOctalCode, char childNumber);
|
unsigned char* childOctalCode(const unsigned char* parentOctalCode, int childNumber);
|
||||||
|
|
||||||
const int OVERFLOWED_OCTCODE_BUFFER = -1;
|
const int OVERFLOWED_OCTCODE_BUFFER = -1;
|
||||||
const int UNKNOWN_OCTCODE_LENGTH = -2;
|
const int UNKNOWN_OCTCODE_LENGTH = -2;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
||||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
||||||
Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents
|
Picks, makeLaserLockInfo Xform, makeLaserParams, AddressManager, getEntityParents, Selection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||||
|
@ -467,8 +467,10 @@ Script.include("/~/system/libraries/Xform.js");
|
||||||
Script.clearTimeout(this.contextOverlayTimer);
|
Script.clearTimeout(this.contextOverlayTimer);
|
||||||
}
|
}
|
||||||
this.contextOverlayTimer = false;
|
this.contextOverlayTimer = false;
|
||||||
if (entityID !== this.entityWithContextOverlay) {
|
if (entityID === this.entityWithContextOverlay) {
|
||||||
this.destroyContextOverlay();
|
this.destroyContextOverlay();
|
||||||
|
} else {
|
||||||
|
Selection.removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetEntity = this.targetObject.getTargetEntity();
|
var targetEntity = this.targetObject.getTargetEntity();
|
||||||
|
|
|
@ -1618,8 +1618,18 @@ SelectionDisplay = (function() {
|
||||||
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
||||||
cornerPosition);
|
cornerPosition);
|
||||||
|
|
||||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
// editing a parent will cause all the children to automatically follow along, so don't
|
||||||
var properties = SelectionManager.savedProperties[SelectionManager.selections[i]];
|
// edit any entity who has an ancestor in SelectionManager.selections
|
||||||
|
var toMove = SelectionManager.selections.filter(function (selection) {
|
||||||
|
if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
|
||||||
|
return false; // a parent is also being moved, so don't issue an edit for this entity
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < toMove.length; i++) {
|
||||||
|
var properties = SelectionManager.savedProperties[toMove[i]];
|
||||||
if (!properties) {
|
if (!properties) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1628,7 +1638,7 @@ SelectionDisplay = (function() {
|
||||||
y: 0,
|
y: 0,
|
||||||
z: vector.z
|
z: vector.z
|
||||||
});
|
});
|
||||||
Entities.editEntity(SelectionManager.selections[i], {
|
Entities.editEntity(toMove[i], {
|
||||||
position: newPosition
|
position: newPosition
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1727,9 +1737,19 @@ SelectionDisplay = (function() {
|
||||||
Vec3.print(" newIntersection:", newIntersection);
|
Vec3.print(" newIntersection:", newIntersection);
|
||||||
Vec3.print(" vector:", vector);
|
Vec3.print(" vector:", vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
// editing a parent will cause all the children to automatically follow along, so don't
|
||||||
var id = SelectionManager.selections[i];
|
// edit any entity who has an ancestor in SelectionManager.selections
|
||||||
|
var toMove = SelectionManager.selections.filter(function (selection) {
|
||||||
|
if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
|
||||||
|
return false; // a parent is also being moved, so don't issue an edit for this entity
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < toMove.length; i++) {
|
||||||
|
var id = toMove[i];
|
||||||
var properties = SelectionManager.savedProperties[id];
|
var properties = SelectionManager.savedProperties[id];
|
||||||
var newPosition = Vec3.sum(properties.position, vector);
|
var newPosition = Vec3.sum(properties.position, vector);
|
||||||
Entities.editEntity(id, { position: newPosition });
|
Entities.editEntity(id, { position: newPosition });
|
||||||
|
@ -2166,8 +2186,19 @@ SelectionDisplay = (function() {
|
||||||
// the selections center point. Otherwise, the rotation will be around the entities
|
// the selections center point. Otherwise, the rotation will be around the entities
|
||||||
// registration point which does not need repositioning.
|
// registration point which does not need repositioning.
|
||||||
var reposition = (SelectionManager.selections.length > 1);
|
var reposition = (SelectionManager.selections.length > 1);
|
||||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
|
||||||
var entityID = SelectionManager.selections[i];
|
// editing a parent will cause all the children to automatically follow along, so don't
|
||||||
|
// edit any entity who has an ancestor in SelectionManager.selections
|
||||||
|
var toRotate = SelectionManager.selections.filter(function (selection) {
|
||||||
|
if (SelectionManager.selections.indexOf(SelectionManager.savedProperties[selection].parentID) >= 0) {
|
||||||
|
return false; // a parent is also being moved, so don't issue an edit for this entity
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < toRotate.length; i++) {
|
||||||
|
var entityID = toRotate[i];
|
||||||
var initialProperties = SelectionManager.savedProperties[entityID];
|
var initialProperties = SelectionManager.savedProperties[entityID];
|
||||||
|
|
||||||
var newProperties = {
|
var newProperties = {
|
||||||
|
|
Loading…
Reference in a new issue