mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 21:36:47 +02:00
working it seems
But, AABox for zones isn't very helpful (box is _small). Time to use the shape of the zone.
This commit is contained in:
parent
ff7c9d3546
commit
8d666854c7
8 changed files with 125 additions and 49 deletions
|
@ -294,16 +294,15 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
|
||||||
tree->setEntityScriptSourceWhitelist("");
|
tree->setEntityScriptSourceWhitelist("");
|
||||||
}
|
}
|
||||||
|
|
||||||
_entityEditFilters = new EntityEditFilters();
|
auto entityEditFilters = tree->createEntityEditFilters();
|
||||||
|
|
||||||
std::static_pointer_cast<EntityTree>(tree)->setEntityEditFilters(_entityEditFilters);
|
|
||||||
QString filterURL;
|
QString filterURL;
|
||||||
if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) {
|
if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) {
|
||||||
// connect the filterAdded signal, and block edits until you hear back
|
// connect the filterAdded signal, and block edits until you hear back
|
||||||
connect(_entityEditFilters, &EntityEditFilters::filterAdded, this, &EntityServer::entityFilterAdded);
|
connect(entityEditFilters, &EntityEditFilters::filterAdded, this, &EntityServer::entityFilterAdded);
|
||||||
|
|
||||||
_entityEditFilters->rejectAll(true);
|
entityEditFilters->rejectAll(true);
|
||||||
_entityEditFilters->addFilter(EntityItemID(), filterURL);
|
entityEditFilters->addFilter(EntityItemID(), filterURL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,8 +310,10 @@ void EntityServer::entityFilterAdded(EntityItemID id, bool success) {
|
||||||
if(id.isInvalidID()) {
|
if(id.isInvalidID()) {
|
||||||
// this is the domain-wide entity filter, which we want to stop
|
// this is the domain-wide entity filter, which we want to stop
|
||||||
// the world for
|
// the world for
|
||||||
|
auto entityEditFilters = qobject_cast<EntityEditFilters*>(sender());
|
||||||
if (success) {
|
if (success) {
|
||||||
_entityEditFilters->rejectAll(false);
|
qDebug() << "entity edit filter for " << id << "added successfully";
|
||||||
|
entityEditFilters->rejectAll(false);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "entity edit filter unsuccessfully added, stopping...";
|
qDebug() << "entity edit filter unsuccessfully added, stopping...";
|
||||||
stop();
|
stop();
|
||||||
|
|
|
@ -77,8 +77,6 @@ private:
|
||||||
|
|
||||||
QReadWriteLock _viewerSendingStatsLock;
|
QReadWriteLock _viewerSendingStatsLock;
|
||||||
QMap<QUuid, QMap<QUuid, ViewerSendingStats>> _viewerSendingStats;
|
QMap<QUuid, QMap<QUuid, ViewerSendingStats>> _viewerSendingStats;
|
||||||
|
|
||||||
EntityEditFilters* _entityEditFilters{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityServer_h
|
#endif // hifi_EntityServer_h
|
||||||
|
|
|
@ -13,58 +13,99 @@
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <ResourceManager.h>
|
#include <ResourceManager.h>
|
||||||
|
|
||||||
#include "EntityEditFilters.h"
|
#include "EntityEditFilters.h"
|
||||||
|
|
||||||
|
QList<EntityItemID> EntityEditFilters::getZonesByPosition(glm::vec3& position) {
|
||||||
|
QList<EntityItemID> zones;
|
||||||
|
_lock.lockForRead();
|
||||||
|
qCDebug(entities) << "looking at " << _filterFunctionMap.size() << "possible zones";
|
||||||
|
for (auto it = _filterFunctionMap.begin(); it != _filterFunctionMap.end(); it++) {
|
||||||
|
auto id = it.key();
|
||||||
|
if (!id.isInvalidID()) {
|
||||||
|
// for now, look it up in the tree (soon we need to cache or similar?)
|
||||||
|
EntityItemPointer itemPtr = _tree->findEntityByEntityItemID(id);
|
||||||
|
auto zone = std::dynamic_pointer_cast<ZoneEntityItem>(itemPtr);
|
||||||
|
if (zone && zone->containsPoint(position)) {
|
||||||
|
zones.append(id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
zones.append(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_lock.unlock();
|
||||||
|
return zones;
|
||||||
|
}
|
||||||
|
|
||||||
bool EntityEditFilters::filter(glm::vec3& position, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, EntityTree::FilterType filterType) {
|
bool EntityEditFilters::filter(glm::vec3& position, EntityItemProperties& propertiesIn, EntityItemProperties& propertiesOut, bool& wasChanged, EntityTree::FilterType filterType) {
|
||||||
qCDebug(entities) << "in EntityEditFilters";
|
qCDebug(entities) << "in EntityEditFilters";
|
||||||
|
|
||||||
// allows us to start entity server and reject all edits until filter is setup
|
// allows us to start entity server and reject all edits until filter is setup
|
||||||
if (_rejectAll) {
|
if (_rejectAll) {
|
||||||
|
qCDebug(entities) << "rejecting all edits";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool accepted = true;
|
// get the ids of all the zones (plus the global entity edit filter) that the position
|
||||||
|
// lies within
|
||||||
|
auto zoneIDs = getZonesByPosition(position);
|
||||||
|
|
||||||
qCDebug(entities) << "_filterFunctionMap.size:" << _filterFunctionMap.size();
|
// temp debugging -- remove!
|
||||||
//first off lets call the filter (if any) that is domain-wide (EntityItemID())
|
qCDebug(entities) << "zones:";
|
||||||
FilterFunctionPair* pair = _filterFunctionMap.value(EntityItemID());
|
for (auto zoneID : zoneIDs) {
|
||||||
QScriptEngine* engine = _filterScriptEngineMap.value(EntityItemID());
|
qCDebug(entities) << zoneID << ",";
|
||||||
qCDebug(entities) << "pair: " << (qint64) pair << ", engine" << (qint64)engine;
|
}
|
||||||
if (pair != nullptr && engine != nullptr) {
|
|
||||||
|
auto oldProperties = propertiesIn.getDesiredProperties();
|
||||||
|
auto specifiedProperties = propertiesIn.getChangedProperties();
|
||||||
|
propertiesIn.setDesiredProperties(specifiedProperties);
|
||||||
|
for (auto it = zoneIDs.begin(); it != zoneIDs.end(); it++) {
|
||||||
|
qCDebug(entities) << "applying filter for zone" << *it;
|
||||||
|
|
||||||
qCDebug(entities) << "attempting to call filter";
|
// get the filter pair, etc...
|
||||||
auto oldProperties = propertiesIn.getDesiredProperties();
|
_lock.lockForRead();
|
||||||
auto specifiedProperties = propertiesIn.getChangedProperties();
|
FilterFunctionPair* pair = _filterFunctionMap.value(*it);
|
||||||
propertiesIn.setDesiredProperties(specifiedProperties);
|
QScriptEngine* engine = _filterScriptEngineMap.value(*it);
|
||||||
QScriptValue inputValues = propertiesIn.copyToScriptValue(engine, false, true, true);
|
_lock.unlock();
|
||||||
propertiesIn.setDesiredProperties(oldProperties);
|
|
||||||
|
qCDebug(entities) << "pair: " << (qint64) pair << ", engine" << (qint64)engine;
|
||||||
|
if (pair != nullptr && engine != nullptr) {
|
||||||
|
|
||||||
auto in = QJsonValue::fromVariant(inputValues.toVariant()); // grab json copy now, because the inputValues might be side effected by the filter.
|
QScriptValue inputValues = propertiesIn.copyToScriptValue(engine, false, true, true);
|
||||||
QScriptValueList args;
|
propertiesIn.setDesiredProperties(oldProperties);
|
||||||
args << inputValues;
|
|
||||||
args << filterType;
|
|
||||||
|
|
||||||
QScriptValue result = pair->first.call(_nullObjectForFilter, args);
|
auto in = QJsonValue::fromVariant(inputValues.toVariant()); // grab json copy now, because the inputValues might be side effected by the filter.
|
||||||
if (pair->second()) {
|
QScriptValueList args;
|
||||||
result = QScriptValue();
|
args << inputValues;
|
||||||
}
|
args << filterType;
|
||||||
|
|
||||||
accepted = result.isObject();
|
QScriptValue result = pair->first.call(_nullObjectForFilter, args);
|
||||||
|
if (pair->second()) {
|
||||||
if (accepted) {
|
result = QScriptValue();
|
||||||
qCDebug(entities) << "filter result accepted";
|
}
|
||||||
// call rest of them soon
|
|
||||||
propertiesOut.copyFromScriptValue(result, false);
|
|
||||||
// Javascript objects are == only if they are the same object. To compare arbitrary values, we need to use JSON.
|
if (result.isObject()){
|
||||||
auto out = QJsonValue::fromVariant(result.toVariant());
|
qCDebug(entities) << "filter result accepted";
|
||||||
wasChanged = in != out;
|
// make propertiesIn reflect the changes, for next filter...
|
||||||
|
propertiesIn.copyFromScriptValue(result, false);
|
||||||
|
|
||||||
|
// and update propertiesOut too. #TODO: this could be more efficient...
|
||||||
|
propertiesOut.copyFromScriptValue(result, false);
|
||||||
|
// Javascript objects are == only if they are the same object. To compare arbitrary values, we need to use JSON.
|
||||||
|
auto out = QJsonValue::fromVariant(result.toVariant());
|
||||||
|
wasChanged |= (in != out);
|
||||||
|
} else {
|
||||||
|
// an edit was rejected, so we stop here and return false
|
||||||
|
qCDebug(entities) << "Edit rejected by " << *it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return accepted;
|
// if we made it here,
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityEditFilters::removeFilter(EntityItemID& entityID) {
|
void EntityEditFilters::removeFilter(EntityItemID& entityID) {
|
||||||
|
QWriteLocker writeLock(&_lock);
|
||||||
QScriptEngine* engine = _filterScriptEngineMap.value(entityID);
|
QScriptEngine* engine = _filterScriptEngineMap.value(entityID);
|
||||||
if (engine) {
|
if (engine) {
|
||||||
_filterScriptEngineMap.remove(entityID);
|
_filterScriptEngineMap.remove(entityID);
|
||||||
|
@ -78,6 +119,7 @@ void EntityEditFilters::removeFilter(EntityItemID& entityID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityEditFilters::addFilter(EntityItemID& entityID, QString filterURL) {
|
void EntityEditFilters::addFilter(EntityItemID& entityID, QString filterURL) {
|
||||||
|
|
||||||
QUrl scriptURL(filterURL);
|
QUrl scriptURL(filterURL);
|
||||||
|
|
||||||
// The following should be abstracted out for use in Agent.cpp (and maybe later AvatarMixer.cpp)
|
// The following should be abstracted out for use in Agent.cpp (and maybe later AvatarMixer.cpp)
|
||||||
|
@ -151,8 +193,10 @@ void EntityEditFilters::scriptRequestFinished(EntityItemID entityID) {
|
||||||
engine->evaluate(scriptContents);
|
engine->evaluate(scriptContents);
|
||||||
if (!hadUncaughtExceptions(*engine, urlString)) {
|
if (!hadUncaughtExceptions(*engine, urlString)) {
|
||||||
// put the engine in the engine map (so we don't leak them, etc...)
|
// put the engine in the engine map (so we don't leak them, etc...)
|
||||||
|
_lock.lockForWrite();
|
||||||
_filterScriptEngineMap.insert(entityID, engine);
|
_filterScriptEngineMap.insert(entityID, engine);
|
||||||
|
_lock.unlock();
|
||||||
|
|
||||||
// define the uncaughtException function
|
// define the uncaughtException function
|
||||||
FilterFunctionPair* pair = new FilterFunctionPair();
|
FilterFunctionPair* pair = new FilterFunctionPair();
|
||||||
QScriptEngine& engineRef = *engine;
|
QScriptEngine& engineRef = *engine;
|
||||||
|
@ -160,12 +204,20 @@ void EntityEditFilters::scriptRequestFinished(EntityItemID entityID) {
|
||||||
|
|
||||||
// now get the filter function
|
// now get the filter function
|
||||||
auto global = engine->globalObject();
|
auto global = engine->globalObject();
|
||||||
|
auto entitiesObject = engine->newObject();
|
||||||
|
entitiesObject.setProperty("ADD_FILTER_TYPE", EntityTree::FilterType::Add);
|
||||||
|
entitiesObject.setProperty("EDIT_FILTER_TYPE", EntityTree::FilterType::Edit);
|
||||||
|
entitiesObject.setProperty("PHYSICS_FILTER_TYPE", EntityTree::FilterType::Physics);
|
||||||
|
global.setProperty("Entities", entitiesObject);
|
||||||
pair->first = global.property("filter");
|
pair->first = global.property("filter");
|
||||||
if (!pair->first.isFunction()) {
|
if (!pair->first.isFunction()) {
|
||||||
qDebug() << "Filter function specified but not found. Ignoring filter";
|
qDebug() << "Filter function specified but not found. Ignoring filter";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_filterFunctionMap.insert(entityID, pair);
|
_lock.lockForWrite();
|
||||||
|
_filterFunctionMap.insert(entityID, pair);
|
||||||
|
_lock.unlock();
|
||||||
|
|
||||||
qDebug() << "script request filter processed for entity id " << entityID;
|
qDebug() << "script request filter processed for entity id " << entityID;
|
||||||
|
|
||||||
emit filterAdded(entityID, true);
|
emit filterAdded(entityID, true);
|
||||||
|
|
|
@ -29,6 +29,7 @@ class EntityEditFilters : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
EntityEditFilters() {};
|
EntityEditFilters() {};
|
||||||
|
EntityEditFilters(EntityTreePointer tree ): _tree(tree) {};
|
||||||
|
|
||||||
void addFilter(EntityItemID& entityID, QString filterURL);
|
void addFilter(EntityItemID& entityID, QString filterURL);
|
||||||
void removeFilter(EntityItemID& entityID);
|
void removeFilter(EntityItemID& entityID);
|
||||||
|
@ -43,8 +44,13 @@ private slots:
|
||||||
void scriptRequestFinished(EntityItemID entityID);
|
void scriptRequestFinished(EntityItemID entityID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList<EntityItemID> getZonesByPosition(glm::vec3& position);
|
||||||
|
|
||||||
|
EntityTreePointer _tree {};
|
||||||
bool _rejectAll {false};
|
bool _rejectAll {false};
|
||||||
QScriptValue _nullObjectForFilter{};
|
QScriptValue _nullObjectForFilter{};
|
||||||
|
|
||||||
|
QReadWriteLock _lock;
|
||||||
QMap<EntityItemID, FilterFunctionPair*> _filterFunctionMap;
|
QMap<EntityItemID, FilterFunctionPair*> _filterFunctionMap;
|
||||||
QMap<EntityItemID, QScriptEngine*> _filterScriptEngineMap;
|
QMap<EntityItemID, QScriptEngine*> _filterScriptEngineMap;
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,9 +62,6 @@ EntityTree::EntityTree(bool shouldReaverage) :
|
||||||
|
|
||||||
EntityTree::~EntityTree() {
|
EntityTree::~EntityTree() {
|
||||||
eraseAllOctreeElements(false);
|
eraseAllOctreeElements(false);
|
||||||
if (_entityEditFilters) {
|
|
||||||
delete _entityEditFilters;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) {
|
void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) {
|
||||||
|
@ -1751,3 +1748,8 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
|
||||||
}
|
}
|
||||||
return entity->getJointNames();
|
return entity->getJointNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityEditFilters* EntityTree::createEntityEditFilters() {
|
||||||
|
_entityEditFilters = new EntityEditFilters(getThisPointer());
|
||||||
|
return _entityEditFilters;
|
||||||
|
}
|
||||||
|
|
|
@ -275,7 +275,9 @@ public:
|
||||||
void initEntityEditFilterEngine(QScriptEngine* engine, std::function<bool()> entityEditFilterHadUncaughtExceptions);
|
void initEntityEditFilterEngine(QScriptEngine* engine, std::function<bool()> entityEditFilterHadUncaughtExceptions);
|
||||||
void setHasEntityFilter(bool hasFilter) { _hasEntityEditFilter = hasFilter; }
|
void setHasEntityFilter(bool hasFilter) { _hasEntityEditFilter = hasFilter; }
|
||||||
|
|
||||||
void setEntityEditFilters(EntityEditFilters* entityEditFilters) { _entityEditFilters = entityEditFilters; }
|
EntityEditFilters* createEntityEditFilters();
|
||||||
|
EntityEditFilters* getEntityEditFilters() { return _entityEditFilters; }
|
||||||
|
|
||||||
static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME;
|
static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
#include "EntityTreeElement.h"
|
#include "EntityTreeElement.h"
|
||||||
#include "ZoneEntityItem.h"
|
#include "ZoneEntityItem.h"
|
||||||
|
#include "EntityEditFilters.h"
|
||||||
|
|
||||||
|
#include <intrin.h>
|
||||||
|
|
||||||
bool ZoneEntityItem::_zonesArePickable = false;
|
bool ZoneEntityItem::_zonesArePickable = false;
|
||||||
bool ZoneEntityItem::_drawZoneBoundaries = false;
|
bool ZoneEntityItem::_drawZoneBoundaries = false;
|
||||||
|
@ -221,12 +224,24 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
|
||||||
return _zonesArePickable;
|
return _zonesArePickable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZoneEntityItem::setFilterURL(QString url) {
|
||||||
|
_filterURL = url;
|
||||||
|
if (getTree()) {
|
||||||
|
auto entityEditFilters = getTree()->getEntityEditFilters();
|
||||||
|
if (entityEditFilters) {
|
||||||
|
qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID();
|
||||||
|
entityEditFilters->addFilter(getEntityItemID(), url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool ZoneEntityItem::containsPoint(glm::vec3& position) {
|
bool ZoneEntityItem::containsPoint(glm::vec3& position) {
|
||||||
// use _shapeType shortly
|
// use _shapeType shortly
|
||||||
// for now bounding box just so I can get end-to-end working
|
// for now bounding box just so I can get end-to-end working
|
||||||
bool success;
|
bool success;
|
||||||
AABox box = getAABox(success);
|
AABox box = getAABox(success);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
qCDebug(entities) << "box: " << box;
|
||||||
return box.contains(position);
|
return box.contains(position);
|
||||||
}
|
}
|
||||||
// just return false if no AABox
|
// just return false if no AABox
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
||||||
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
||||||
QString getFilterURL() const { return _filterURL; }
|
QString getFilterURL() const { return _filterURL; }
|
||||||
void setFilterURL(const QString url) { _filterURL = url; }
|
void setFilterURL(const QString url);
|
||||||
bool containsPoint(glm::vec3& position);
|
bool containsPoint(glm::vec3& position);
|
||||||
|
|
||||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||||
|
|
Loading…
Reference in a new issue