mirror of
https://github.com/lubosz/overte.git
synced 2025-04-16 09:29:16 +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("");
|
||||
}
|
||||
|
||||
_entityEditFilters = new EntityEditFilters();
|
||||
|
||||
std::static_pointer_cast<EntityTree>(tree)->setEntityEditFilters(_entityEditFilters);
|
||||
auto entityEditFilters = tree->createEntityEditFilters();
|
||||
|
||||
QString filterURL;
|
||||
if (readOptionString("entityEditFilter", settingsSectionObject, filterURL) && !filterURL.isEmpty()) {
|
||||
// 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->addFilter(EntityItemID(), filterURL);
|
||||
entityEditFilters->rejectAll(true);
|
||||
entityEditFilters->addFilter(EntityItemID(), filterURL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,8 +310,10 @@ void EntityServer::entityFilterAdded(EntityItemID id, bool success) {
|
|||
if(id.isInvalidID()) {
|
||||
// this is the domain-wide entity filter, which we want to stop
|
||||
// the world for
|
||||
auto entityEditFilters = qobject_cast<EntityEditFilters*>(sender());
|
||||
if (success) {
|
||||
_entityEditFilters->rejectAll(false);
|
||||
qDebug() << "entity edit filter for " << id << "added successfully";
|
||||
entityEditFilters->rejectAll(false);
|
||||
} else {
|
||||
qDebug() << "entity edit filter unsuccessfully added, stopping...";
|
||||
stop();
|
||||
|
|
|
@ -77,8 +77,6 @@ private:
|
|||
|
||||
QReadWriteLock _viewerSendingStatsLock;
|
||||
QMap<QUuid, QMap<QUuid, ViewerSendingStats>> _viewerSendingStats;
|
||||
|
||||
EntityEditFilters* _entityEditFilters{};
|
||||
};
|
||||
|
||||
#endif // hifi_EntityServer_h
|
||||
|
|
|
@ -13,58 +13,99 @@
|
|||
#include <QUrl>
|
||||
|
||||
#include <ResourceManager.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) {
|
||||
qCDebug(entities) << "in EntityEditFilters";
|
||||
|
||||
// allows us to start entity server and reject all edits until filter is setup
|
||||
if (_rejectAll) {
|
||||
qCDebug(entities) << "rejecting all edits";
|
||||
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();
|
||||
//first off lets call the filter (if any) that is domain-wide (EntityItemID())
|
||||
FilterFunctionPair* pair = _filterFunctionMap.value(EntityItemID());
|
||||
QScriptEngine* engine = _filterScriptEngineMap.value(EntityItemID());
|
||||
qCDebug(entities) << "pair: " << (qint64) pair << ", engine" << (qint64)engine;
|
||||
if (pair != nullptr && engine != nullptr) {
|
||||
// temp debugging -- remove!
|
||||
qCDebug(entities) << "zones:";
|
||||
for (auto zoneID : zoneIDs) {
|
||||
qCDebug(entities) << zoneID << ",";
|
||||
}
|
||||
|
||||
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";
|
||||
auto oldProperties = propertiesIn.getDesiredProperties();
|
||||
auto specifiedProperties = propertiesIn.getChangedProperties();
|
||||
propertiesIn.setDesiredProperties(specifiedProperties);
|
||||
QScriptValue inputValues = propertiesIn.copyToScriptValue(engine, false, true, true);
|
||||
propertiesIn.setDesiredProperties(oldProperties);
|
||||
// get the filter pair, etc...
|
||||
_lock.lockForRead();
|
||||
FilterFunctionPair* pair = _filterFunctionMap.value(*it);
|
||||
QScriptEngine* engine = _filterScriptEngineMap.value(*it);
|
||||
_lock.unlock();
|
||||
|
||||
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.
|
||||
QScriptValueList args;
|
||||
args << inputValues;
|
||||
args << filterType;
|
||||
QScriptValue inputValues = propertiesIn.copyToScriptValue(engine, false, true, true);
|
||||
propertiesIn.setDesiredProperties(oldProperties);
|
||||
|
||||
QScriptValue result = pair->first.call(_nullObjectForFilter, args);
|
||||
if (pair->second()) {
|
||||
result = QScriptValue();
|
||||
}
|
||||
|
||||
accepted = result.isObject();
|
||||
|
||||
if (accepted) {
|
||||
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.
|
||||
auto out = QJsonValue::fromVariant(result.toVariant());
|
||||
wasChanged = in != out;
|
||||
auto in = QJsonValue::fromVariant(inputValues.toVariant()); // grab json copy now, because the inputValues might be side effected by the filter.
|
||||
QScriptValueList args;
|
||||
args << inputValues;
|
||||
args << filterType;
|
||||
|
||||
QScriptValue result = pair->first.call(_nullObjectForFilter, args);
|
||||
if (pair->second()) {
|
||||
result = QScriptValue();
|
||||
}
|
||||
|
||||
|
||||
if (result.isObject()){
|
||||
qCDebug(entities) << "filter result accepted";
|
||||
// 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) {
|
||||
QWriteLocker writeLock(&_lock);
|
||||
QScriptEngine* engine = _filterScriptEngineMap.value(entityID);
|
||||
if (engine) {
|
||||
_filterScriptEngineMap.remove(entityID);
|
||||
|
@ -78,6 +119,7 @@ void EntityEditFilters::removeFilter(EntityItemID& entityID) {
|
|||
}
|
||||
|
||||
void EntityEditFilters::addFilter(EntityItemID& entityID, QString filterURL) {
|
||||
|
||||
QUrl scriptURL(filterURL);
|
||||
|
||||
// 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);
|
||||
if (!hadUncaughtExceptions(*engine, urlString)) {
|
||||
// put the engine in the engine map (so we don't leak them, etc...)
|
||||
_lock.lockForWrite();
|
||||
_filterScriptEngineMap.insert(entityID, engine);
|
||||
|
||||
_lock.unlock();
|
||||
|
||||
// define the uncaughtException function
|
||||
FilterFunctionPair* pair = new FilterFunctionPair();
|
||||
QScriptEngine& engineRef = *engine;
|
||||
|
@ -160,12 +204,20 @@ void EntityEditFilters::scriptRequestFinished(EntityItemID entityID) {
|
|||
|
||||
// now get the filter function
|
||||
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");
|
||||
if (!pair->first.isFunction()) {
|
||||
qDebug() << "Filter function specified but not found. Ignoring filter";
|
||||
return;
|
||||
}
|
||||
_filterFunctionMap.insert(entityID, pair);
|
||||
_lock.lockForWrite();
|
||||
_filterFunctionMap.insert(entityID, pair);
|
||||
_lock.unlock();
|
||||
|
||||
qDebug() << "script request filter processed for entity id " << entityID;
|
||||
|
||||
emit filterAdded(entityID, true);
|
||||
|
|
|
@ -29,6 +29,7 @@ class EntityEditFilters : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
EntityEditFilters() {};
|
||||
EntityEditFilters(EntityTreePointer tree ): _tree(tree) {};
|
||||
|
||||
void addFilter(EntityItemID& entityID, QString filterURL);
|
||||
void removeFilter(EntityItemID& entityID);
|
||||
|
@ -43,8 +44,13 @@ private slots:
|
|||
void scriptRequestFinished(EntityItemID entityID);
|
||||
|
||||
private:
|
||||
QList<EntityItemID> getZonesByPosition(glm::vec3& position);
|
||||
|
||||
EntityTreePointer _tree {};
|
||||
bool _rejectAll {false};
|
||||
QScriptValue _nullObjectForFilter{};
|
||||
|
||||
QReadWriteLock _lock;
|
||||
QMap<EntityItemID, FilterFunctionPair*> _filterFunctionMap;
|
||||
QMap<EntityItemID, QScriptEngine*> _filterScriptEngineMap;
|
||||
};
|
||||
|
|
|
@ -62,9 +62,6 @@ EntityTree::EntityTree(bool shouldReaverage) :
|
|||
|
||||
EntityTree::~EntityTree() {
|
||||
eraseAllOctreeElements(false);
|
||||
if (_entityEditFilters) {
|
||||
delete _entityEditFilters;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTree::setEntityScriptSourceWhitelist(const QString& entityScriptSourceWhitelist) {
|
||||
|
@ -1751,3 +1748,8 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
|
|||
}
|
||||
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 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;
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "EntityEditFilters.h"
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
bool ZoneEntityItem::_zonesArePickable = false;
|
||||
bool ZoneEntityItem::_drawZoneBoundaries = false;
|
||||
|
@ -221,12 +224,24 @@ bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const
|
|||
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) {
|
||||
// use _shapeType shortly
|
||||
// for now bounding box just so I can get end-to-end working
|
||||
bool success;
|
||||
AABox box = getAABox(success);
|
||||
if (success) {
|
||||
qCDebug(entities) << "box: " << box;
|
||||
return box.contains(position);
|
||||
}
|
||||
// just return false if no AABox
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
||||
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
||||
QString getFilterURL() const { return _filterURL; }
|
||||
void setFilterURL(const QString url) { _filterURL = url; }
|
||||
void setFilterURL(const QString url);
|
||||
bool containsPoint(glm::vec3& position);
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const override { return true; }
|
||||
|
|
Loading…
Reference in a new issue