mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 01:13:32 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into hdr
This commit is contained in:
commit
11c6bb7d80
22 changed files with 566 additions and 108 deletions
Binary file not shown.
|
@ -214,7 +214,6 @@ Setting::Handle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTRE
|
|||
static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com";
|
||||
|
||||
const QHash<QString, Application::AcceptURLMethod> Application::_acceptedExtensions {
|
||||
{ SNAPSHOT_EXTENSION, &Application::acceptSnapshot },
|
||||
{ SVO_EXTENSION, &Application::importSVOFromURL },
|
||||
{ SVO_JSON_EXTENSION, &Application::importSVOFromURL },
|
||||
{ AVA_JSON_EXTENSION, &Application::askToWearAvatarAttachmentUrl },
|
||||
|
@ -2857,6 +2856,8 @@ void Application::dragEnterEvent(QDragEnterEvent* event) {
|
|||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
// This is currently not used, but could be invoked if the user wants to go to the place embedded in an
|
||||
// Interface-taken snapshot. (It was developed for drag and drop, before we had asset-server loading or in-world browsers.)
|
||||
bool Application::acceptSnapshot(const QString& urlString) {
|
||||
QUrl url(urlString);
|
||||
QString snapshotPath = url.toLocalFile();
|
||||
|
|
|
@ -182,3 +182,16 @@ ViewFrustum Camera::toViewFrustum() const {
|
|||
loadViewFrustum(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariantMap Camera::getViewFrustum() {
|
||||
ViewFrustum frustum;
|
||||
loadViewFrustum(frustum);
|
||||
|
||||
QVariantMap result;
|
||||
result["position"].setValue(frustum.getPosition());
|
||||
result["orientation"].setValue(frustum.getOrientation());
|
||||
result["projection"].setValue(frustum.getProjection());
|
||||
result["centerRadius"].setValue(frustum.getCenterRadius());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ class Camera : public QObject {
|
|||
Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation)
|
||||
Q_PROPERTY(QString mode READ getModeString WRITE setModeString)
|
||||
Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity)
|
||||
Q_PROPERTY(QVariantMap frustum READ getViewFrustum CONSTANT)
|
||||
|
||||
public:
|
||||
Camera();
|
||||
|
||||
|
@ -63,6 +65,8 @@ public:
|
|||
const glm::mat4& getProjection() const { return _projection; }
|
||||
void setProjection(const glm::mat4& projection);
|
||||
|
||||
QVariantMap getViewFrustum();
|
||||
|
||||
public slots:
|
||||
QString getModeString() const;
|
||||
void setModeString(const QString& mode);
|
||||
|
|
|
@ -1215,6 +1215,8 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceIn
|
|||
void AudioClient::outputNotify() {
|
||||
int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads();
|
||||
if (recentUnfulfilled > 0) {
|
||||
qCInfo(audioclient, "Starve detected, %d new unfulfilled reads", recentUnfulfilled);
|
||||
|
||||
if (_outputStarveDetectionEnabled.get()) {
|
||||
quint64 now = usecTimestampNow() / 1000;
|
||||
int dt = (int)(now - _outputStarveDetectionStartTimeMsec);
|
||||
|
@ -1224,14 +1226,15 @@ void AudioClient::outputNotify() {
|
|||
} else {
|
||||
_outputStarveDetectionCount += recentUnfulfilled;
|
||||
if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) {
|
||||
_outputStarveDetectionStartTimeMsec = now;
|
||||
_outputStarveDetectionCount = 0;
|
||||
|
||||
int oldOutputBufferSizeFrames = _sessionOutputBufferSizeFrames;
|
||||
int newOutputBufferSizeFrames = setOutputBufferSize(oldOutputBufferSizeFrames + 1, false);
|
||||
|
||||
if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) {
|
||||
qCDebug(audioclient) << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames;
|
||||
qCInfo(audioclient, "Starve threshold surpassed (%d starves in %d ms)", _outputStarveDetectionCount, dt);
|
||||
}
|
||||
|
||||
_outputStarveDetectionStartTimeMsec = now;
|
||||
_outputStarveDetectionCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1319,7 +1322,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDevice
|
|||
int AudioClient::setOutputBufferSize(int numFrames, bool persist) {
|
||||
numFrames = std::min(std::max(numFrames, MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES);
|
||||
if (numFrames != _sessionOutputBufferSizeFrames) {
|
||||
qCDebug(audioclient) << "Audio output buffer size (frames): " << numFrames;
|
||||
qCInfo(audioclient, "Audio output buffer set to %d frames", numFrames);
|
||||
_sessionOutputBufferSizeFrames = numFrames;
|
||||
if (persist) {
|
||||
_outputBufferSizeFrames.set(numFrames);
|
||||
|
@ -1424,24 +1427,20 @@ qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
|
|||
auto samplesRequested = maxSize / sizeof(int16_t);
|
||||
int samplesPopped;
|
||||
int bytesWritten;
|
||||
|
||||
|
||||
if ((samplesPopped = _receivedAudioStream.popSamples((int)samplesRequested, false)) > 0) {
|
||||
AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput();
|
||||
lastPopOutput.readSamples((int16_t*)data, samplesPopped);
|
||||
bytesWritten = samplesPopped * sizeof(int16_t);
|
||||
} else {
|
||||
// nothing on network, don't grab anything from injectors, and just
|
||||
// return 0s
|
||||
// nothing on network, don't grab anything from injectors, and just return 0s
|
||||
// this will flood the log: qCDebug(audioclient, "empty/partial network buffer");
|
||||
memset(data, 0, maxSize);
|
||||
bytesWritten = maxSize;
|
||||
|
||||
}
|
||||
|
||||
int bytesAudioOutputUnplayed = _audio->_audioOutput->bufferSize() - _audio->_audioOutput->bytesFree();
|
||||
if (!bytesAudioOutputUnplayed) {
|
||||
qCDebug(audioclient) << "empty audio buffer";
|
||||
}
|
||||
if (bytesAudioOutputUnplayed == 0 && bytesWritten == 0) {
|
||||
bool wasBufferStarved = _audio->_audioOutput->bufferSize() == _audio->_audioOutput->bytesFree();
|
||||
if (wasBufferStarved) {
|
||||
_unfulfilledReads++;
|
||||
}
|
||||
|
||||
|
|
|
@ -590,11 +590,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
renderInfo.setProperty("texturesSize", (int)getRenderInfoTextureSize()); // FIXME - theoretically the size of textures could be > max int
|
||||
renderInfo.setProperty("hasTransparent", getRenderInfoHasTransparent());
|
||||
renderInfo.setProperty("drawCalls", getRenderInfoDrawCalls());
|
||||
renderInfo.setProperty("texturesCount", getRenderInfoTextureCount());
|
||||
}
|
||||
|
||||
if (_type == EntityTypes::Model || _type == EntityTypes::PolyLine || _type == EntityTypes::ParticleEffect) {
|
||||
renderInfo.setProperty("texturesCount", QScriptValue(_textureNames.count()));
|
||||
}
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(renderInfo, renderInfo); // Gettable but not settable
|
||||
}
|
||||
|
||||
|
@ -771,7 +769,7 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object
|
|||
QScriptValue EntityPropertyFlagsToScriptValue(QScriptEngine* engine, const EntityPropertyFlags& flags) {
|
||||
return EntityItemProperties::entityPropertyFlagsToScriptValue(engine, flags);
|
||||
QScriptValue result = engine->newObject();
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "EntityTree.h"
|
||||
#include "LightEntityItem.h"
|
||||
#include "ModelEntityItem.h"
|
||||
#include "QVariantGLM.h"
|
||||
#include "SimulationOwner.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
|
||||
|
@ -566,6 +567,48 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corn
|
|||
return result;
|
||||
}
|
||||
|
||||
QVector<QUuid> EntityScriptingInterface::findEntitiesInFrustum(QVariantMap frustum) const {
|
||||
QVector<QUuid> result;
|
||||
|
||||
const QString POSITION_PROPERTY = "position";
|
||||
bool positionOK = frustum.contains(POSITION_PROPERTY);
|
||||
glm::vec3 position = positionOK ? qMapToGlmVec3(frustum[POSITION_PROPERTY]) : glm::vec3();
|
||||
|
||||
const QString ORIENTATION_PROPERTY = "orientation";
|
||||
bool orientationOK = frustum.contains(ORIENTATION_PROPERTY);
|
||||
glm::quat orientation = orientationOK ? qMapToGlmQuat(frustum[ORIENTATION_PROPERTY]) : glm::quat();
|
||||
|
||||
const QString PROJECTION_PROPERTY = "projection";
|
||||
bool projectionOK = frustum.contains(PROJECTION_PROPERTY);
|
||||
glm::mat4 projection = projectionOK ? qMapToGlmMat4(frustum[PROJECTION_PROPERTY]) : glm::mat4();
|
||||
|
||||
const QString CENTER_RADIUS_PROPERTY = "centerRadius";
|
||||
bool centerRadiusOK = frustum.contains(CENTER_RADIUS_PROPERTY);
|
||||
float centerRadius = centerRadiusOK ? frustum[CENTER_RADIUS_PROPERTY].toFloat() : 0.0f;
|
||||
|
||||
if (positionOK && orientationOK && projectionOK && centerRadiusOK) {
|
||||
ViewFrustum viewFrustum;
|
||||
viewFrustum.setPosition(position);
|
||||
viewFrustum.setOrientation(orientation);
|
||||
viewFrustum.setProjection(projection);
|
||||
viewFrustum.setCenterRadius(centerRadius);
|
||||
viewFrustum.calculate();
|
||||
|
||||
if (_entityTree) {
|
||||
QVector<EntityItemPointer> entities;
|
||||
_entityTree->withReadLock([&] {
|
||||
_entityTree->findEntities(viewFrustum, entities);
|
||||
});
|
||||
|
||||
foreach(EntityItemPointer entity, entities) {
|
||||
result << entity->getEntityItemID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersection(const PickRay& ray, bool precisionPicking,
|
||||
const QScriptValue& entityIdsToInclude, const QScriptValue& entityIdsToDiscard) {
|
||||
|
||||
|
|
|
@ -127,10 +127,19 @@ public slots:
|
|||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntities(const glm::vec3& center, float radius) const;
|
||||
|
||||
/// finds models within the search sphere specified by the center point and radius
|
||||
/// finds models within the box specified by the corner and dimensions
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const;
|
||||
|
||||
/// finds models within the frustum
|
||||
/// the frustum must have the following properties:
|
||||
/// - position
|
||||
/// - orientation
|
||||
/// - projection
|
||||
/// - centerRadius
|
||||
/// this function will not find any models in script engine contexts which don't have access to models
|
||||
Q_INVOKABLE QVector<QUuid> findEntitiesInFrustum(QVariantMap frustum) const;
|
||||
|
||||
/// If the scripting context has visible entities, this will determine a ray intersection, the results
|
||||
/// may be inaccurate if the engine is unable to access the visible entities, in which case result.accurate
|
||||
/// will be false.
|
||||
|
|
|
@ -688,6 +688,31 @@ void EntityTree::findEntities(const AABox& box, QVector<EntityItemPointer>& foun
|
|||
foundEntities.swap(args._foundEntities);
|
||||
}
|
||||
|
||||
class FindInFrustumArgs {
|
||||
public:
|
||||
ViewFrustum frustum;
|
||||
QVector<EntityItemPointer> entities;
|
||||
};
|
||||
|
||||
bool EntityTree::findInFrustumOperation(OctreeElementPointer element, void* extraData) {
|
||||
FindInFrustumArgs* args = static_cast<FindInFrustumArgs*>(extraData);
|
||||
if (element->isInView(args->frustum)) {
|
||||
EntityTreeElementPointer entityTreeElement = std::static_pointer_cast<EntityTreeElement>(element);
|
||||
entityTreeElement->getEntities(args->frustum, args->entities);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: assumes caller has handled locking
|
||||
void EntityTree::findEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities) {
|
||||
FindInFrustumArgs args = { frustum, QVector<EntityItemPointer>() };
|
||||
// NOTE: This should use recursion, since this is a spatial operation
|
||||
recurseTreeWithOperation(findInFrustumOperation, &args);
|
||||
// swap the two lists of entity pointers instead of copy
|
||||
foundEntities.swap(args.entities);
|
||||
}
|
||||
|
||||
EntityItemPointer EntityTree::findEntityByID(const QUuid& id) {
|
||||
EntityItemID entityID(id);
|
||||
return findEntityByEntityItemID(entityID);
|
||||
|
|
|
@ -153,6 +153,11 @@ public:
|
|||
/// \remark Side effect: any initial contents in entities will be lost
|
||||
void findEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
/// finds all entities within a frustum
|
||||
/// \parameter frustum the query frustum
|
||||
/// \param foundEntities[out] vector of EntityItemPointer
|
||||
void findEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
void addNewlyCreatedHook(NewlyCreatedEntityHook* hook);
|
||||
void removeNewlyCreatedHook(NewlyCreatedEntityHook* hook);
|
||||
|
||||
|
@ -276,6 +281,7 @@ protected:
|
|||
static bool findInSphereOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInCubeOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInBoxOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool findInFrustumOperation(OctreeElementPointer element, void* extraData);
|
||||
static bool sendEntitiesOperation(OctreeElementPointer element, void* extraData);
|
||||
|
||||
void notifyNewlyCreatedEntity(const EntityItem& newEntity, const SharedNodePointer& senderNode);
|
||||
|
|
|
@ -796,6 +796,17 @@ void EntityTreeElement::getEntities(const AABox& box, QVector<EntityItemPointer>
|
|||
});
|
||||
}
|
||||
|
||||
void EntityTreeElement::getEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities) {
|
||||
forEachEntity([&](EntityItemPointer entity) {
|
||||
bool success;
|
||||
AABox entityBox = entity->getAABox(success);
|
||||
// FIXME - See FIXMEs for similar methods above.
|
||||
if (!success || frustum.boxIntersectsFrustum(entityBox) || frustum.boxIntersectsKeyhole(entityBox)) {
|
||||
foundEntities.push_back(entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemID& id) const {
|
||||
EntityItemPointer foundEntity = NULL;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -194,6 +194,11 @@ public:
|
|||
/// \param entities[out] vector of non-const EntityItemPointer
|
||||
void getEntities(const AABox& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
/// finds all entities that touch a frustum
|
||||
/// \param frustum the query frustum
|
||||
/// \param entities[out] vector of non-const EntityItemPointer
|
||||
void getEntities(const ViewFrustum& frustum, QVector<EntityItemPointer>& foundEntities);
|
||||
|
||||
EntityItemPointer getEntityWithID(uint32_t id) const;
|
||||
EntityItemPointer getEntityWithEntityItemID(const EntityItemID& id) const;
|
||||
void getEntitiesInside(const AACube& box, QVector<EntityItemPointer>& foundEntities);
|
||||
|
|
|
@ -77,6 +77,7 @@ void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) {
|
|||
bool MeshPartPayload::calculateMaterialSize() {
|
||||
bool allTextures = true; // assume we got this...
|
||||
_materialTextureSize = 0;
|
||||
_materialTextureCount = 0;
|
||||
auto textureMaps = _drawMaterial->getTextureMaps();
|
||||
for (auto const &textureMapItem : textureMaps) {
|
||||
auto textureMap = textureMapItem.second;
|
||||
|
@ -88,6 +89,7 @@ bool MeshPartPayload::calculateMaterialSize() {
|
|||
//auto storedSize = texture->getStoredSize();
|
||||
auto size = texture->getSize();
|
||||
_materialTextureSize += size;
|
||||
_materialTextureCount++;
|
||||
} else {
|
||||
allTextures = false;
|
||||
}
|
||||
|
|
|
@ -67,10 +67,12 @@ public:
|
|||
|
||||
size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; }
|
||||
size_t getMaterialTextureSize() { return _materialTextureSize; }
|
||||
int getMaterialTextureCount() { return _materialTextureCount; }
|
||||
bool calculateMaterialSize();
|
||||
|
||||
protected:
|
||||
size_t _materialTextureSize { 0 };
|
||||
int _materialTextureCount { 0 };
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -161,22 +161,33 @@ void Model::setOffset(const glm::vec3& offset) {
|
|||
_snappedToRegistrationPoint = false;
|
||||
}
|
||||
|
||||
size_t Model::getRenderInfoTextureSize() {
|
||||
if (!_hasCalculatedTextureSize && isLoaded() && getGeometry()->areTexturesLoaded()) {
|
||||
void Model::calculateTextureInfo() {
|
||||
if (!_hasCalculatedTextureInfo && isLoaded() && getGeometry()->areTexturesLoaded() && !_modelMeshRenderItems.isEmpty()) {
|
||||
size_t textureSize = 0;
|
||||
int textureCount = 0;
|
||||
bool allTexturesLoaded = true;
|
||||
foreach(auto renderItem, _modelMeshRenderItemsSet) {
|
||||
auto meshPart = renderItem.get();
|
||||
bool allTexturesForThisMesh = meshPart->calculateMaterialSize();
|
||||
allTexturesLoaded = allTexturesLoaded & allTexturesForThisMesh;
|
||||
textureSize += meshPart->getMaterialTextureSize();
|
||||
textureCount += meshPart->getMaterialTextureCount();
|
||||
}
|
||||
_renderInfoTextureSize = textureSize;
|
||||
_hasCalculatedTextureSize = allTexturesLoaded; // only do this once
|
||||
_renderInfoTextureCount = textureCount;
|
||||
_hasCalculatedTextureInfo = allTexturesLoaded; // only do this once
|
||||
}
|
||||
}
|
||||
|
||||
size_t Model::getRenderInfoTextureSize() {
|
||||
calculateTextureInfo();
|
||||
return _renderInfoTextureSize;
|
||||
}
|
||||
|
||||
int Model::getRenderInfoTextureCount() {
|
||||
calculateTextureInfo();
|
||||
return _renderInfoTextureCount;
|
||||
}
|
||||
|
||||
void Model::updateRenderItems() {
|
||||
if (!_addedToScene) {
|
||||
|
|
|
@ -233,8 +233,8 @@ public:
|
|||
void setLoadingPriority(float priority) { _loadingPriority = priority; }
|
||||
|
||||
size_t getRenderInfoVertexCount() const { return _renderInfoVertexCount; }
|
||||
int getRenderInfoTextureCount() const { return _renderInfoTextureCount; }
|
||||
size_t getRenderInfoTextureSize();
|
||||
int getRenderInfoTextureCount();
|
||||
int getRenderInfoDrawCalls() const { return _renderInfoDrawCalls; }
|
||||
bool getRenderInfoHasTransparent() const { return _renderInfoHasTransparent; }
|
||||
|
||||
|
@ -409,13 +409,14 @@ protected:
|
|||
size_t _renderInfoVertexCount { 0 };
|
||||
int _renderInfoTextureCount { 0 };
|
||||
size_t _renderInfoTextureSize { 0 };
|
||||
bool _hasCalculatedTextureSize { false };
|
||||
bool _hasCalculatedTextureInfo { false };
|
||||
int _renderInfoDrawCalls { 0 };
|
||||
int _renderInfoHasTransparent { false };
|
||||
|
||||
private:
|
||||
float _loadingPriority { 0.0f };
|
||||
|
||||
void calculateTextureInfo();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(ModelPointer)
|
||||
|
|
|
@ -62,3 +62,48 @@ void qListtoRgbColor(const QVariant& q, rgbColor& returnValue) {
|
|||
returnValue[GREEN_INDEX] = qList[GREEN_INDEX].toInt();
|
||||
returnValue[BLUE_INDEX] = qList[BLUE_INDEX].toInt();
|
||||
}
|
||||
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("x") && qMap.contains("y") && qMap.contains("y")) {
|
||||
return glm::vec3(
|
||||
qMap["x"].toFloat(),
|
||||
qMap["y"].toFloat(),
|
||||
qMap["z"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::vec3();
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat qMapToGlmQuat(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("w") && qMap.contains("x") && qMap.contains("y") && qMap.contains("z")) {
|
||||
return glm::quat(
|
||||
qMap["w"].toFloat(),
|
||||
qMap["x"].toFloat(),
|
||||
qMap["y"].toFloat(),
|
||||
qMap["z"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::quat();
|
||||
}
|
||||
}
|
||||
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q) {
|
||||
QVariantMap qMap = q.toMap();
|
||||
if (qMap.contains("r0c0") && qMap.contains("r1c0") && qMap.contains("r2c0") && qMap.contains("r3c0")
|
||||
&& qMap.contains("r0c1") && qMap.contains("r1c1") && qMap.contains("r2c1") && qMap.contains("r3c1")
|
||||
&& qMap.contains("r0c2") && qMap.contains("r1c2") && qMap.contains("r2c2") && qMap.contains("r3c2")
|
||||
&& qMap.contains("r0c3") && qMap.contains("r1c3") && qMap.contains("r2c3") && qMap.contains("r3c3")) {
|
||||
return glm::mat4(
|
||||
qMap["r0c0"].toFloat(), qMap["r1c0"].toFloat(), qMap["r2c0"].toFloat(), qMap["r3c0"].toFloat(),
|
||||
qMap["r0c1"].toFloat(), qMap["r1c1"].toFloat(), qMap["r2c1"].toFloat(), qMap["r3c1"].toFloat(),
|
||||
qMap["r0c2"].toFloat(), qMap["r1c2"].toFloat(), qMap["r2c2"].toFloat(), qMap["r3c2"].toFloat(),
|
||||
qMap["r0c3"].toFloat(), qMap["r1c3"].toFloat(), qMap["r2c3"].toFloat(), qMap["r3c3"].toFloat()
|
||||
);
|
||||
} else {
|
||||
return glm::mat4();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,3 +27,7 @@ QVariantMap glmToQMap(const glm::quat& glmQuat);
|
|||
glm::vec3 qListToGlmVec3(const QVariant& q);
|
||||
glm::quat qListToGlmQuat(const QVariant& q);
|
||||
void qListtoRgbColor(const QVariant& q, rgbColor& returnValue);
|
||||
|
||||
glm::vec3 qMapToGlmVec3(const QVariant& q);
|
||||
glm::quat qMapToGlmQuat(const QVariant& q);
|
||||
glm::mat4 qMapToGlmMat4(const QVariant& q);
|
||||
|
|
|
@ -366,6 +366,10 @@ input[type=button]:disabled {
|
|||
background: linear-gradient(#575757 20%, #252525 100%);
|
||||
}
|
||||
|
||||
input[type=button][pressed=pressed] {
|
||||
color: #00b4ef;
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
display: none;
|
||||
}
|
||||
|
@ -861,13 +865,8 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
position: relative; /* New positioning context. */
|
||||
}
|
||||
|
||||
#entity-list .glyph {
|
||||
font-family: HiFi-Glyphs;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#search-area {
|
||||
padding-right: 148px;
|
||||
padding-right: 168px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
|
@ -875,13 +874,23 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
width: 98%;
|
||||
}
|
||||
|
||||
#in-view {
|
||||
position: absolute;
|
||||
right: 126px;
|
||||
}
|
||||
|
||||
#radius-and-unit {
|
||||
float: right;
|
||||
margin-right: -148px;
|
||||
margin-right: -168px;
|
||||
position: relative;
|
||||
top: -17px;
|
||||
}
|
||||
|
||||
#radius-and-unit label {
|
||||
margin-left: 2px;
|
||||
}
|
||||
#radius-and-unit input {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
#entity-table-scroll {
|
||||
/* Height is set by JavaScript. */
|
||||
|
@ -896,6 +905,10 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
background-color: #1c1c1c;
|
||||
}
|
||||
|
||||
#entity-table-scroll .glyph {
|
||||
font-family: HiFi-Glyphs;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
#entity-table {
|
||||
margin-top: -28px;
|
||||
|
@ -905,19 +918,6 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
background-color: #1c1c1c;
|
||||
}
|
||||
|
||||
#col-type {
|
||||
width: 16%;
|
||||
}
|
||||
#col-name {
|
||||
width: 34%;
|
||||
}
|
||||
#col-url {
|
||||
width: 34%;
|
||||
}
|
||||
#col-locked, #col-visible {
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
#entity-table thead tr, #entity-table thead tr th,
|
||||
#entity-table tfoot tr, #entity-table tfoot tr td {
|
||||
background: none;
|
||||
|
@ -938,12 +938,22 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
top: 49px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
word-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#entity-table thead th {
|
||||
.verticesCount, .texturesCount, .texturesSize, .drawCalls {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#entity-table th {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0 0 8px;
|
||||
padding: 5px 0 0 0;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#entity-table th:focus {
|
||||
|
@ -952,17 +962,54 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
|
||||
#entity-table th .glyph {
|
||||
position: relative;
|
||||
left: 0;
|
||||
left: 4px;
|
||||
}
|
||||
#entity-table th .glyph + .sort-order {
|
||||
position: relative;
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
#entity-table th#entity-hasScript {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#entity-table th#entity-hasScript .glyph {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
#entity-table thead .sort-order {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
margin: -5px 0 -3px 0;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#entity-table th #info-toggle {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: initial;
|
||||
right: 0;
|
||||
width: 11px;
|
||||
background-color: #1c1c1c;
|
||||
z-index: 100;
|
||||
}
|
||||
#entity-table th #info-toggle span {
|
||||
position: relative;
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
th#entity-hasTransparent .glyph {
|
||||
font-weight: normal;
|
||||
font-size: 24px !important;
|
||||
margin: -6px;
|
||||
position: relative;
|
||||
top: -6px;
|
||||
}
|
||||
th#entity-hasTransparent .sort-order {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
#entity-table td {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -971,6 +1018,11 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
text-align: center;
|
||||
padding: 0;
|
||||
}
|
||||
#entity-table td.hasTransparent.glyph {
|
||||
font-size: 22px;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
#entity-table tfoot {
|
||||
box-sizing: border-box;
|
||||
|
@ -984,6 +1036,82 @@ textarea:enabled[scrolling="true"]::-webkit-resizer {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
#col-type {
|
||||
width: 16%;
|
||||
}
|
||||
#col-name {
|
||||
width: 34%;
|
||||
}
|
||||
#col-url {
|
||||
width: 34%;
|
||||
}
|
||||
#col-locked, #col-visible {
|
||||
width: 9%;
|
||||
}
|
||||
#col-verticesCount, #col-texturesCount, #col-texturesSize, #col-hasTransparent, #col-drawCalls, #col-hasScript {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.showExtraInfo #col-type {
|
||||
width: 10%;
|
||||
}
|
||||
.showExtraInfo #col-name {
|
||||
width: 19%;
|
||||
}
|
||||
.showExtraInfo #col-url {
|
||||
width: 19%;
|
||||
}
|
||||
.showExtraInfo #col-locked, .showExtraInfo #col-visible {
|
||||
width: 4%;
|
||||
}
|
||||
.showExtraInfo #col-verticesCount {
|
||||
width: 8%;
|
||||
}
|
||||
.showExtraInfo #col-texturesCount {
|
||||
width: 8%;
|
||||
}
|
||||
.showExtraInfo #col-texturesSize {
|
||||
width: 10%;
|
||||
}
|
||||
.showExtraInfo #col-hasTransparent {
|
||||
width: 4%;
|
||||
}
|
||||
.showExtraInfo #col-drawCalls {
|
||||
width: 8%;
|
||||
}
|
||||
.showExtraInfo #col-hasScript {
|
||||
width: 6%;
|
||||
}
|
||||
|
||||
th#entity-verticesCount, th#entity-texturesCount, th#entity-texturesSize, th#entity-hasTransparent, th#entity-drawCalls,
|
||||
th#entity-hasScript {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.verticesCount, .texturesCount, .texturesSize, .hasTransparent, .drawCalls, .hasScript {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#entity-visible {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.showExtraInfo #entity-verticesCount, .showExtraInfo #entity-texturesCount, .showExtraInfo #entity-texturesSize,
|
||||
.showExtraInfo #entity-hasTransparent, .showExtraInfo #entity-drawCalls, .showExtraInfo #entity-hasScript {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.showExtraInfo .verticesCount, .showExtraInfo .texturesCount, .showExtraInfo .texturesSize, .showExtraInfo .hasTransparent,
|
||||
.showExtraInfo .drawCalls, .showExtraInfo .hasScript {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.showExtraInfo #entity-visible {
|
||||
border-right: 1px solid #575757;
|
||||
}
|
||||
|
||||
|
||||
#no-entities {
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
@ -1102,4 +1230,4 @@ input#reset-to-natural-dimensions {
|
|||
margin-top:5px;
|
||||
font-size:16px;
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<div id="entity-list">
|
||||
<div id="search-area">
|
||||
<span class="icon-input"><input type="text" class="search" id="filter" placeholder="Filter" /><span>Y</span></span>
|
||||
<input type="button" id="in-view" class="glyph" value="" />
|
||||
<div id="radius-and-unit" class="number">
|
||||
<label for="radius">Search radius <span class="unit">m</span></label>
|
||||
<input type="number" id="radius" value="100" />
|
||||
|
@ -37,39 +38,57 @@
|
|||
<div id="entity-table-scroll">
|
||||
<table id="entity-table">
|
||||
<colgroup>
|
||||
<col span="1" id="col-type" />
|
||||
<col span="1" id="col-name" />
|
||||
<col span="1" id="col-url" />
|
||||
<col span="1" id="col-locked" />
|
||||
<col span="1" id="col-visible" />
|
||||
<col span="1" id="col-type" />
|
||||
<col span="1" id="col-name" />
|
||||
<col span="1" id="col-url" />
|
||||
<col span="1" id="col-locked" />
|
||||
<col span="1" id="col-visible" />
|
||||
<col span="1" id="col-verticesCount" />
|
||||
<col span="1" id="col-texturesCount" />
|
||||
<col span="1" id="col-texturesSize" />
|
||||
<col span="1" id="col-hasTransparent" />
|
||||
<col span="1" id="col-drawCalls" />
|
||||
<col span="1" id="col-hasScript" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="entity-type" data-sort="type">Type<span class="sort-order"></span></th>
|
||||
<th id="entity-name" data-sort="type">Name<span class="sort-order"></span></th>
|
||||
<th id="entity-url" data-sort="url">File<span class="sort-order"></span></th>
|
||||
<th id="entity-locked" data-sort="locked"><span class="glyph"></span><span class="sort-order"></span></th>
|
||||
<th colspan="2" id="entity-visible" data-sort="visible"><span class="glyph"></span><span class="sort-order"></span></th>
|
||||
<th id="entity-type">Type<span class="sort-order"></span><span id="info-toggle"><span class="glyph">D</span></span></th>
|
||||
<th id="entity-name">Name<span class="sort-order"></span></th>
|
||||
<th id="entity-url">File<span class="sort-order"></span></th>
|
||||
<th id="entity-locked"><span class="glyph"></span><span class="sort-order"></span></th>
|
||||
<th id="entity-visible"><span class="glyph"></span><span class="sort-order"></span></th>
|
||||
<th id="entity-verticesCount">Verts<span class="sort-order"></span></th>
|
||||
<th id="entity-texturesCount">Texts<span class="sort-order"></span></th>
|
||||
<th id="entity-texturesSize">Text MB<span class="sort-order"></span></th>
|
||||
<th id="entity-hasTransparent"><span class="glyph"></span><span class="sort-order"></span></th>
|
||||
<th id="entity-drawCalls">Draws<span class="sort-order"></span></th>
|
||||
<th colspan="1" id="entity-hasScript"><span class="glyph">k</span><span class="sort-order"></span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list" id="entity-table-body">
|
||||
<tr>
|
||||
<td class="type">Type</td>
|
||||
<td class="name">Name</td>
|
||||
<td class="url"><div class='outer'><div class='inner'>URL</div></div></td>
|
||||
<td class="locked glyph">?</td>
|
||||
<td class="visible glyph">?</td>
|
||||
<td class="id" style="display: none">ID</td>
|
||||
<td class="type"></td>
|
||||
<td class="name"></td>
|
||||
<td class="url"><div class='outer'><div class='inner'></div></div></td>
|
||||
<td class="locked glyph"></td>
|
||||
<td class="visible glyph"></td>
|
||||
<td class="verticesCount"></td>
|
||||
<td class="texturesCount"></td>
|
||||
<td class="texturesSize"></td>
|
||||
<td class="hasTransparent glyph"></td>
|
||||
<td class="drawCalls"></td>
|
||||
<td class="hasScript glyph"></td>
|
||||
<td class="id" style="display: none"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td id="footer-text" colspan="5"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="footer-text" colspan="11"> </td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div id="no-entities">
|
||||
No entities found within a <span id="no-entities-radius">100</span> meter radius. Try moving to a different location and refreshing.
|
||||
No entities found <span id="no-entities-in-view">in view</span> within a <span id="no-entities-radius">100</span> meter radius. Try moving to a different location and refreshing.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,10 +12,12 @@ var currentSortColumn = 'type';
|
|||
var currentSortOrder = 'des';
|
||||
var entityList = null;
|
||||
var refreshEntityListTimer = null;
|
||||
const ASCENDING_STRING = '▾';
|
||||
const DESCENDING_STRING = '▴';
|
||||
const ASCENDING_STRING = '▴';
|
||||
const DESCENDING_STRING = '▾';
|
||||
const LOCKED_GLYPH = "";
|
||||
const VISIBLE_GLYPH = "";
|
||||
const TRANSPARENCY_GLYPH = "";
|
||||
const SCRIPT_GLYPH = "k";
|
||||
const DELETE = 46; // Key code for the delete key.
|
||||
const MAX_ITEMS = Number.MAX_VALUE; // Used to set the max length of the list of discovered entities.
|
||||
|
||||
|
@ -33,10 +35,16 @@ function loaded() {
|
|||
elToggleLocked = document.getElementById("locked");
|
||||
elToggleVisible = document.getElementById("visible");
|
||||
elDelete = document.getElementById("delete");
|
||||
elTeleport = document.getElementById("teleport");
|
||||
elFilter = document.getElementById("filter");
|
||||
elInView = document.getElementById("in-view")
|
||||
elRadius = document.getElementById("radius");
|
||||
elTeleport = document.getElementById("teleport");
|
||||
elEntityTable = document.getElementById("entity-table");
|
||||
elInfoToggle = document.getElementById("info-toggle");
|
||||
elInfoToggleGlyph = elInfoToggle.firstChild;
|
||||
elFooter = document.getElementById("footer-text");
|
||||
elNoEntitiesMessage = document.getElementById("no-entities");
|
||||
elNoEntitiesInView = document.getElementById("no-entities-in-view");
|
||||
elNoEntitiesRadius = document.getElementById("no-entities-radius");
|
||||
elEntityTableScroll = document.getElementById("entity-table-scroll");
|
||||
|
||||
|
@ -55,7 +63,25 @@ function loaded() {
|
|||
document.getElementById("entity-visible").onclick = function () {
|
||||
setSortColumn('visible');
|
||||
};
|
||||
|
||||
document.getElementById("entity-verticesCount").onclick = function () {
|
||||
setSortColumn('verticesCount');
|
||||
};
|
||||
document.getElementById("entity-texturesCount").onclick = function () {
|
||||
setSortColumn('texturesCount');
|
||||
};
|
||||
document.getElementById("entity-texturesSize").onclick = function () {
|
||||
setSortColumn('texturesSize');
|
||||
};
|
||||
document.getElementById("entity-hasTransparent").onclick = function () {
|
||||
setSortColumn('hasTransparent');
|
||||
};
|
||||
document.getElementById("entity-drawCalls").onclick = function () {
|
||||
setSortColumn('drawCalls');
|
||||
};
|
||||
document.getElementById("entity-hasScript").onclick = function () {
|
||||
setSortColumn('hasScript');
|
||||
};
|
||||
|
||||
function onRowClicked(clickEvent) {
|
||||
var id = this.dataset.entityId;
|
||||
var selection = [this.dataset.entityId];
|
||||
|
@ -106,12 +132,29 @@ function loaded() {
|
|||
}));
|
||||
}
|
||||
|
||||
function addEntity(id, name, type, url, locked, visible) {
|
||||
const BYTES_PER_MEGABYTE = 1024 * 1024;
|
||||
|
||||
function decimalMegabytes(number) {
|
||||
return number ? (number / BYTES_PER_MEGABYTE).toFixed(1) : "";
|
||||
}
|
||||
|
||||
function displayIfNonZero(number) {
|
||||
return number ? number : "";
|
||||
}
|
||||
|
||||
function addEntity(id, name, type, url, locked, visible, verticesCount, texturesCount, texturesSize, hasTransparent,
|
||||
drawCalls, hasScript) {
|
||||
|
||||
var urlParts = url.split('/');
|
||||
var filename = urlParts[urlParts.length - 1];
|
||||
|
||||
if (entities[id] === undefined) {
|
||||
entityList.add([{ id: id, name: name, type: type, url: filename, locked: locked, visible: visible }],
|
||||
entityList.add([{
|
||||
id: id, name: name, type: type, url: filename, locked: locked, visible: visible,
|
||||
verticesCount: displayIfNonZero(verticesCount), texturesCount: displayIfNonZero(texturesCount),
|
||||
texturesSize: decimalMegabytes(texturesSize), hasTransparent: hasTransparent,
|
||||
drawCalls: displayIfNonZero(drawCalls), hasScript: hasScript
|
||||
}],
|
||||
function (items) {
|
||||
var currentElement = items[0].elm;
|
||||
var id = items[0]._values.id;
|
||||
|
@ -148,7 +191,13 @@ function loaded() {
|
|||
type: document.querySelector('#entity-type .sort-order'),
|
||||
url: document.querySelector('#entity-url .sort-order'),
|
||||
locked: document.querySelector('#entity-locked .sort-order'),
|
||||
visible: document.querySelector('#entity-visible .sort-order')
|
||||
visible: document.querySelector('#entity-visible .sort-order'),
|
||||
verticesCount: document.querySelector('#entity-verticesCount .sort-order'),
|
||||
texturesCount: document.querySelector('#entity-texturesCount .sort-order'),
|
||||
texturesSize: document.querySelector('#entity-texturesSize .sort-order'),
|
||||
hasTransparent: document.querySelector('#entity-hasTransparent .sort-order'),
|
||||
drawCalls: document.querySelector('#entity-drawCalls .sort-order'),
|
||||
hasScript: document.querySelector('#entity-hasScript .sort-order'),
|
||||
}
|
||||
function setSortColumn(column) {
|
||||
if (currentSortColumn == column) {
|
||||
|
@ -168,10 +217,23 @@ function loaded() {
|
|||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||
}
|
||||
|
||||
function refreshFooter() {
|
||||
if (selectedEntities.length > 1) {
|
||||
elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected";
|
||||
} else if (selectedEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity selected";
|
||||
} else if (entityList.visibleItems.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity found";
|
||||
} else {
|
||||
elFooter.firstChild.nodeValue = entityList.visibleItems.length + " entities found";
|
||||
}
|
||||
}
|
||||
|
||||
function refreshEntityListObject() {
|
||||
refreshEntityListTimer = null;
|
||||
entityList.sort(currentSortColumn, { order: currentSortOrder });
|
||||
entityList.search(document.getElementById("filter").value);
|
||||
entityList.search(elFilter.value);
|
||||
refreshFooter();
|
||||
}
|
||||
|
||||
function updateSelectedEntities(selectedEntities) {
|
||||
|
@ -189,16 +251,6 @@ function loaded() {
|
|||
}
|
||||
}
|
||||
|
||||
if (selectedEntities.length > 1) {
|
||||
elFooter.firstChild.nodeValue = selectedEntities.length + " entities selected";
|
||||
} else if (selectedEntities.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity selected";
|
||||
} else if (entityList.visibleItems.length === 1) {
|
||||
elFooter.firstChild.nodeValue = "1 entity found";
|
||||
} else {
|
||||
elFooter.firstChild.nodeValue = entityList.visibleItems.length + " entities found";
|
||||
}
|
||||
|
||||
// HACK: Fixes the footer and header text sometimes not displaying after adding or deleting entities.
|
||||
// The problem appears to be a bug in the Qt HTML/CSS rendering (Qt 5.5).
|
||||
document.getElementById("radius").focus();
|
||||
|
@ -235,13 +287,29 @@ function loaded() {
|
|||
}
|
||||
}, false);
|
||||
|
||||
var isFilterInView = false;
|
||||
var FILTER_IN_VIEW_ATTRIBUTE = "pressed";
|
||||
elNoEntitiesInView.style.display = "none";
|
||||
elInView.onclick = function () {
|
||||
isFilterInView = !isFilterInView;
|
||||
if (isFilterInView) {
|
||||
elInView.setAttribute(FILTER_IN_VIEW_ATTRIBUTE, FILTER_IN_VIEW_ATTRIBUTE);
|
||||
elNoEntitiesInView.style.display = "inline";
|
||||
} else {
|
||||
elInView.removeAttribute(FILTER_IN_VIEW_ATTRIBUTE);
|
||||
elNoEntitiesInView.style.display = "none";
|
||||
}
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: "filterInView", filterInView: isFilterInView }));
|
||||
refreshEntities();
|
||||
}
|
||||
|
||||
elRadius.onchange = function () {
|
||||
elRadius.value = Math.max(elRadius.value, 0);
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'radius', radius: elRadius.value }));
|
||||
refreshEntities();
|
||||
elNoEntitiesRadius.firstChild.nodeValue = elRadius.value;
|
||||
}
|
||||
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
@ -264,7 +332,11 @@ function loaded() {
|
|||
var id = newEntities[i].id;
|
||||
addEntity(id, newEntities[i].name, newEntities[i].type, newEntities[i].url,
|
||||
newEntities[i].locked ? LOCKED_GLYPH : null,
|
||||
newEntities[i].visible ? VISIBLE_GLYPH : null);
|
||||
newEntities[i].visible ? VISIBLE_GLYPH : null,
|
||||
newEntities[i].verticesCount, newEntities[i].texturesCount, newEntities[i].texturesSize,
|
||||
newEntities[i].hasTransparent ? TRANSPARENCY_GLYPH : null,
|
||||
newEntities[i].drawCalls,
|
||||
newEntities[i].hasScript ? SCRIPT_GLYPH : null);
|
||||
}
|
||||
updateSelectedEntities(data.selectedIDs);
|
||||
resize();
|
||||
|
@ -278,6 +350,7 @@ function loaded() {
|
|||
// Take up available window space
|
||||
elEntityTableScroll.style.height = window.innerHeight - 207;
|
||||
|
||||
var SCROLLABAR_WIDTH = 21;
|
||||
var tds = document.querySelectorAll("#entity-table-body tr:first-child td");
|
||||
var ths = document.querySelectorAll("#entity-table thead th");
|
||||
if (tds.length >= ths.length) {
|
||||
|
@ -287,16 +360,53 @@ function loaded() {
|
|||
}
|
||||
} else {
|
||||
// Reasonable widths if nothing is displayed
|
||||
var tableWidth = document.getElementById("entity-table").offsetWidth;
|
||||
ths[0].width = 0.16 * tableWidth;
|
||||
ths[1].width = 0.34 * tableWidth;
|
||||
ths[2].width = 0.34 * tableWidth;
|
||||
ths[3].width = 0.08 * tableWidth;
|
||||
ths[4].width = 0.08 * tableWidth;
|
||||
var tableWidth = document.getElementById("entity-table").offsetWidth - SCROLLABAR_WIDTH;
|
||||
if (showExtraInfo) {
|
||||
ths[0].width = 0.10 * tableWidth;
|
||||
ths[1].width = 0.20 * tableWidth;
|
||||
ths[2].width = 0.20 * tableWidth;
|
||||
ths[3].width = 0.04 * tableWidth;
|
||||
ths[4].width = 0.04 * tableWidth;
|
||||
ths[5].width = 0.08 * tableWidth;
|
||||
ths[6].width = 0.08 * tableWidth;
|
||||
ths[7].width = 0.10 * tableWidth;
|
||||
ths[8].width = 0.04 * tableWidth;
|
||||
ths[9].width = 0.08 * tableWidth;
|
||||
ths[10].width = 0.04 * tableWidth + SCROLLABAR_WIDTH;
|
||||
} else {
|
||||
ths[0].width = 0.16 * tableWidth;
|
||||
ths[1].width = 0.34 * tableWidth;
|
||||
ths[2].width = 0.34 * tableWidth;
|
||||
ths[3].width = 0.08 * tableWidth;
|
||||
ths[4].width = 0.08 * tableWidth;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.onresize = resize;
|
||||
elFilter.onchange = resize;
|
||||
elFilter.onblur = refreshFooter;
|
||||
|
||||
|
||||
var showExtraInfo = false;
|
||||
var COLLAPSE_EXTRA_INFO = "E";
|
||||
var EXPAND_EXTRA_INFO = "D";
|
||||
|
||||
function toggleInfo(event) {
|
||||
showExtraInfo = !showExtraInfo;
|
||||
if (showExtraInfo) {
|
||||
elEntityTable.className = "showExtraInfo";
|
||||
elInfoToggleGlyph.innerHTML = COLLAPSE_EXTRA_INFO;
|
||||
} else {
|
||||
elEntityTable.className = "";
|
||||
elInfoToggleGlyph.innerHTML = EXPAND_EXTRA_INFO;
|
||||
}
|
||||
resize();
|
||||
event.stopPropagation();
|
||||
}
|
||||
elInfoToggle.addEventListener("click", toggleInfo, true);
|
||||
|
||||
|
||||
resize();
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ EntityListTool = function(opts) {
|
|||
});
|
||||
|
||||
|
||||
|
||||
var filterInView = false;
|
||||
var searchRadius = 100;
|
||||
|
||||
var visible = false;
|
||||
|
@ -48,20 +48,41 @@ EntityListTool = function(opts) {
|
|||
webView.emitScriptEvent(JSON.stringify(data));
|
||||
};
|
||||
|
||||
function valueIfDefined(value) {
|
||||
return value !== undefined ? value : "";
|
||||
}
|
||||
|
||||
that.sendUpdate = function() {
|
||||
var entities = [];
|
||||
var ids = Entities.findEntities(MyAvatar.position, searchRadius);
|
||||
|
||||
var ids;
|
||||
if (filterInView) {
|
||||
ids = Entities.findEntitiesInFrustum(Camera.frustum);
|
||||
} else {
|
||||
ids = Entities.findEntities(MyAvatar.position, searchRadius);
|
||||
}
|
||||
|
||||
var cameraPosition = Camera.position;
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var id = ids[i];
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
entities.push({
|
||||
id: id,
|
||||
name: properties.name,
|
||||
type: properties.type,
|
||||
url: properties.type == "Model" ? properties.modelURL : "",
|
||||
locked: properties.locked,
|
||||
visible: properties.visible
|
||||
});
|
||||
|
||||
if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) {
|
||||
entities.push({
|
||||
id: id,
|
||||
name: properties.name,
|
||||
type: properties.type,
|
||||
url: properties.type == "Model" ? properties.modelURL : "",
|
||||
locked: properties.locked,
|
||||
visible: properties.visible,
|
||||
verticesCount: valueIfDefined(properties.renderInfo.verticesCount),
|
||||
texturesCount: valueIfDefined(properties.renderInfo.texturesCount),
|
||||
texturesSize: valueIfDefined(properties.renderInfo.texturesSize),
|
||||
hasTransparent: valueIfDefined(properties.renderInfo.hasTransparent),
|
||||
drawCalls: valueIfDefined(properties.renderInfo.drawCalls),
|
||||
hasScript: properties.script !== ""
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var selectedIDs = [];
|
||||
|
@ -105,9 +126,10 @@ EntityListTool = function(opts) {
|
|||
toggleSelectedEntitiesLocked();
|
||||
} else if (data.type == "toggleVisible") {
|
||||
toggleSelectedEntitiesVisible();
|
||||
} else if (data.type === "filterInView") {
|
||||
filterInView = data.filterInView === true;
|
||||
} else if (data.type === "radius") {
|
||||
searchRadius = data.radius;
|
||||
that.sendUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue