mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 03:53:52 +02:00
Remove spanner bits.
This commit is contained in:
parent
802cc3eeed
commit
9e5aae4a39
13 changed files with 175 additions and 31 deletions
|
@ -25,7 +25,7 @@ MetavoxelServer::MetavoxelServer(const QByteArray& packet) :
|
|||
}
|
||||
|
||||
void MetavoxelServer::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
edit.apply(_data);
|
||||
edit.apply(_data, SharedObject::getWeakHash());
|
||||
}
|
||||
|
||||
const QString METAVOXEL_SERVER_LOGGING_NAME = "metavoxel-server";
|
||||
|
|
|
@ -44,6 +44,31 @@ void MetavoxelSystem::init() {
|
|||
connect(NodeList::getInstance(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(maybeAttachClient(const SharedNodePointer&)));
|
||||
}
|
||||
|
||||
SharedObjectPointer MetavoxelSystem::findFirstRaySpannerIntersection(
|
||||
const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, float& distance) {
|
||||
SharedObjectPointer closestSpanner;
|
||||
float closestDistance = FLT_MAX;
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
if (node->getType() == NodeType::MetavoxelServer) {
|
||||
QMutexLocker locker(&node->getMutex());
|
||||
MetavoxelClient* client = static_cast<MetavoxelClient*>(node->getLinkedData());
|
||||
if (client) {
|
||||
float clientDistance;
|
||||
SharedObjectPointer clientSpanner = client->getData().findFirstRaySpannerIntersection(
|
||||
origin, direction, attribute, clientDistance);
|
||||
if (clientSpanner && clientDistance < closestDistance) {
|
||||
closestSpanner = clientSpanner;
|
||||
closestDistance = clientDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closestSpanner) {
|
||||
distance = closestDistance;
|
||||
}
|
||||
return closestSpanner;
|
||||
}
|
||||
|
||||
void MetavoxelSystem::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) {
|
||||
if (node->getType() == NodeType::MetavoxelServer) {
|
||||
|
@ -215,7 +240,7 @@ void MetavoxelClient::guide(MetavoxelVisitor& visitor) {
|
|||
|
||||
void MetavoxelClient::applyEdit(const MetavoxelEditMessage& edit) {
|
||||
// apply immediately to local tree
|
||||
edit.apply(_data);
|
||||
edit.apply(_data, _sequencer.getWeakSharedObjectHash());
|
||||
|
||||
// start sending it out
|
||||
_sequencer.sendHighPriorityMessage(QVariant::fromValue(edit));
|
||||
|
@ -255,7 +280,7 @@ void MetavoxelClient::readPacket(Bitstream& in) {
|
|||
// reapply local edits
|
||||
foreach (const DatagramSequencer::HighPriorityMessage& message, _sequencer.getHighPriorityMessages()) {
|
||||
if (message.data.userType() == MetavoxelEditMessage::Type) {
|
||||
message.data.value<MetavoxelEditMessage>().apply(_data);
|
||||
message.data.value<MetavoxelEditMessage>().apply(_data, _sequencer.getWeakSharedObjectHash());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ public:
|
|||
|
||||
void init();
|
||||
|
||||
SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const AttributePointer& attribute, float& distance);
|
||||
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
||||
void simulate(float deltaTime);
|
||||
|
@ -91,6 +94,8 @@ public:
|
|||
MetavoxelClient(const SharedNodePointer& node);
|
||||
virtual ~MetavoxelClient();
|
||||
|
||||
MetavoxelData& getData() { return _data; }
|
||||
|
||||
void guide(MetavoxelVisitor& visitor);
|
||||
|
||||
void applyEdit(const MetavoxelEditMessage& edit);
|
||||
|
|
|
@ -607,8 +607,19 @@ bool RemoveSpannerTool::appliesTo(const AttributePointer& attribute) const {
|
|||
}
|
||||
|
||||
bool RemoveSpannerTool::eventFilter(QObject* watched, QEvent* event) {
|
||||
AttributePointer attribute = AttributeRegistry::getInstance()->getAttribute(_editor->getSelectedAttribute());
|
||||
if (!attribute) {
|
||||
return false;
|
||||
}
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
|
||||
float distance;
|
||||
SharedObjectPointer spanner = Application::getInstance()->getMetavoxels()->findFirstRaySpannerIntersection(
|
||||
Application::getInstance()->getMouseRayOrigin(), Application::getInstance()->getMouseRayDirection(),
|
||||
attribute, distance);
|
||||
if (spanner) {
|
||||
MetavoxelEditMessage message = { QVariant::fromValue(RemoveSpannerEdit(attribute, spanner->getRemoteID())) };
|
||||
Application::getInstance()->getMetavoxels()->applyEdit(message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -201,6 +201,13 @@ void Bitstream::persistAndResetReadMappings() {
|
|||
persistReadMappings(getAndResetReadMappings());
|
||||
}
|
||||
|
||||
void Bitstream::clearSharedObject(int id) {
|
||||
SharedObjectPointer object = _sharedObjectStreamer.takePersistentValue(id);
|
||||
if (object) {
|
||||
_weakSharedObjectHash.remove(object->getRemoteID());
|
||||
}
|
||||
}
|
||||
|
||||
Bitstream& Bitstream::operator<<(bool value) {
|
||||
if (value) {
|
||||
_byte |= (1 << _position);
|
||||
|
@ -487,7 +494,7 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
|||
object = SharedObjectPointer();
|
||||
return *this;
|
||||
}
|
||||
QPointer<SharedObject>& pointer = _transientSharedObjects[id];
|
||||
QPointer<SharedObject>& pointer = _weakSharedObjectHash[id];
|
||||
if (pointer) {
|
||||
const QMetaObject* metaObject;
|
||||
_metaObjectStreamer >> metaObject;
|
||||
|
@ -500,6 +507,7 @@ Bitstream& Bitstream::operator>(SharedObjectPointer& object) {
|
|||
QObject* rawObject;
|
||||
*this >> rawObject;
|
||||
pointer = static_cast<SharedObject*>(rawObject);
|
||||
pointer->setRemoteID(id);
|
||||
}
|
||||
object = static_cast<SharedObject*>(pointer.data());
|
||||
return *this;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
int takePersistentID(P value) { return _persistentIDs.take(value); }
|
||||
|
||||
void removePersistentValue(int id) { _persistentIDs.remove(_persistentValues.take(id)); }
|
||||
T takePersistentValue(int id) { T value = _persistentValues.take(id); _persistentIDs.remove(value); return value; }
|
||||
|
||||
RepeatedValueStreamer& operator<<(T value);
|
||||
RepeatedValueStreamer& operator>>(T& value);
|
||||
|
@ -242,8 +242,11 @@ public:
|
|||
/// Immediately persists and resets the read mappings.
|
||||
void persistAndResetReadMappings();
|
||||
|
||||
/// Returns a reference to the weak hash storing shared objects for this stream.
|
||||
const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _weakSharedObjectHash; }
|
||||
|
||||
/// Removes a shared object from the read mappings.
|
||||
void clearSharedObject(int id) { _sharedObjectStreamer.removePersistentValue(id); }
|
||||
void clearSharedObject(int id);
|
||||
|
||||
Bitstream& operator<<(bool value);
|
||||
Bitstream& operator>>(bool& value);
|
||||
|
@ -339,7 +342,7 @@ private:
|
|||
RepeatedValueStreamer<QScriptString> _scriptStringStreamer;
|
||||
RepeatedValueStreamer<SharedObjectPointer, SharedObject*> _sharedObjectStreamer;
|
||||
|
||||
QHash<int, QPointer<SharedObject> > _transientSharedObjects;
|
||||
WeakSharedObjectHash _weakSharedObjectHash;
|
||||
|
||||
static QHash<QByteArray, const QMetaObject*>& getMetaObjects();
|
||||
static QMultiHash<const QMetaObject*, const QMetaObject*>& getMetaObjectSubClasses();
|
||||
|
|
|
@ -34,6 +34,9 @@ public:
|
|||
|
||||
DatagramSequencer(const QByteArray& datagramHeader = QByteArray(), QObject* parent = NULL);
|
||||
|
||||
/// Returns a reference to the weak hash mapping remote ids to shared objects.
|
||||
const WeakSharedObjectHash& getWeakSharedObjectHash() const { return _inputStream.getWeakSharedObjectHash(); }
|
||||
|
||||
/// Returns the packet number of the last packet sent.
|
||||
int getOutgoingPacketNumber() const { return _outgoingPacketNumber; }
|
||||
|
||||
|
|
|
@ -218,6 +218,48 @@ void MetavoxelData::clear(const AttributePointer& attribute) {
|
|||
}
|
||||
}
|
||||
|
||||
class FirstRaySpannerIntersectionVisitor : public RaySpannerIntersectionVisitor {
|
||||
public:
|
||||
|
||||
FirstRaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const AttributePointer& attribute, const MetavoxelLOD& lod);
|
||||
|
||||
Spanner* getSpanner() const { return _spanner; }
|
||||
float getDistance() const { return _distance; }
|
||||
|
||||
virtual bool visit(Spanner* spanner, float distance);
|
||||
|
||||
private:
|
||||
|
||||
Spanner* _spanner;
|
||||
float _distance;
|
||||
};
|
||||
|
||||
FirstRaySpannerIntersectionVisitor::FirstRaySpannerIntersectionVisitor(
|
||||
const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute, const MetavoxelLOD& lod) :
|
||||
RaySpannerIntersectionVisitor(origin, direction, QVector<AttributePointer>() << attribute,
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), lod),
|
||||
_spanner(NULL) {
|
||||
}
|
||||
|
||||
bool FirstRaySpannerIntersectionVisitor::visit(Spanner* spanner, float distance) {
|
||||
_spanner = spanner;
|
||||
_distance = distance;
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedObjectPointer MetavoxelData::findFirstRaySpannerIntersection(
|
||||
const glm::vec3& origin, const glm::vec3& direction, const AttributePointer& attribute,
|
||||
float& distance, const MetavoxelLOD& lod) {
|
||||
FirstRaySpannerIntersectionVisitor visitor(origin, direction, attribute, lod);
|
||||
guide(visitor);
|
||||
if (!visitor.getSpanner()) {
|
||||
return SharedObjectPointer();
|
||||
}
|
||||
distance = visitor.getDistance();
|
||||
return SharedObjectPointer(visitor.getSpanner());
|
||||
}
|
||||
|
||||
const int X_MAXIMUM_FLAG = 1;
|
||||
const int Y_MAXIMUM_FLAG = 2;
|
||||
const int Z_MAXIMUM_FLAG = 4;
|
||||
|
@ -839,14 +881,14 @@ int RayIntersectionVisitor::visit(MetavoxelInfo& info) {
|
|||
return visit(info, distance);
|
||||
}
|
||||
|
||||
RayIntersectionSpannerVisitor::RayIntersectionSpannerVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
RaySpannerIntersectionVisitor::RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs, const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
RayIntersectionVisitor(origin, direction, inputs + spannerInputs, outputs, lod),
|
||||
_spannerInputCount(spannerInputs.size()) {
|
||||
}
|
||||
|
||||
void RayIntersectionSpannerVisitor::prepare() {
|
||||
void RaySpannerIntersectionVisitor::prepare() {
|
||||
Spanner::incrementVisit();
|
||||
}
|
||||
|
||||
|
@ -860,7 +902,7 @@ bool operator<(const SpannerDistance& first, const SpannerDistance& second) {
|
|||
return first.distance < second.distance;
|
||||
}
|
||||
|
||||
int RayIntersectionSpannerVisitor::visit(MetavoxelInfo& info, float distance) {
|
||||
int RaySpannerIntersectionVisitor::visit(MetavoxelInfo& info, float distance) {
|
||||
QVarLengthArray<SpannerDistance, 4> spannerDistances;
|
||||
for (int i = _inputs.size() - _spannerInputCount; i < _inputs.size(); i++) {
|
||||
foreach (const SharedObjectPointer& object, info.inputValues.at(i).getInlineValue<SharedObjectSet>()) {
|
||||
|
|
|
@ -81,6 +81,10 @@ public:
|
|||
|
||||
void clear(const AttributePointer& attribute);
|
||||
|
||||
/// Convenience function that finds the first spanner intersecting the provided ray.
|
||||
SharedObjectPointer findFirstRaySpannerIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const AttributePointer& attribute, float& distance, const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
||||
/// Expands the tree, increasing its capacity in all dimensions.
|
||||
void expand();
|
||||
|
||||
|
@ -284,10 +288,10 @@ protected:
|
|||
};
|
||||
|
||||
/// Base class for ray intersection spanner visitors.
|
||||
class RayIntersectionSpannerVisitor : public RayIntersectionVisitor {
|
||||
class RaySpannerIntersectionVisitor : public RayIntersectionVisitor {
|
||||
public:
|
||||
|
||||
RayIntersectionSpannerVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
RaySpannerIntersectionVisitor(const glm::vec3& origin, const glm::vec3& direction,
|
||||
const QVector<AttributePointer>& spannerInputs,
|
||||
const QVector<AttributePointer>& inputs = QVector<AttributePointer>(),
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
|
||||
#include "MetavoxelMessages.h"
|
||||
|
||||
void MetavoxelEditMessage::apply(MetavoxelData& data) const {
|
||||
static_cast<const MetavoxelEdit*>(edit.data())->apply(data);
|
||||
void MetavoxelEditMessage::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
static_cast<const MetavoxelEdit*>(edit.data())->apply(data, objects);
|
||||
}
|
||||
|
||||
MetavoxelEdit::~MetavoxelEdit() {
|
||||
|
@ -58,7 +58,7 @@ int BoxSetEditVisitor::visit(MetavoxelInfo& info) {
|
|||
return DEFAULT_ORDER; // subdivide
|
||||
}
|
||||
|
||||
void BoxSetEdit::apply(MetavoxelData& data) const {
|
||||
void BoxSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
// expand to fit the entire edit
|
||||
while (!data.getBounds().contains(region)) {
|
||||
data.expand();
|
||||
|
@ -94,7 +94,7 @@ int GlobalSetEditVisitor::visit(MetavoxelInfo& info) {
|
|||
return STOP_RECURSION; // entirely contained
|
||||
}
|
||||
|
||||
void GlobalSetEdit::apply(MetavoxelData& data) const {
|
||||
void GlobalSetEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
GlobalSetEditVisitor visitor(*this);
|
||||
data.guide(visitor);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ InsertSpannerEdit::InsertSpannerEdit(const AttributePointer& attribute, const Sh
|
|||
spanner(spanner) {
|
||||
}
|
||||
|
||||
void InsertSpannerEdit::apply(MetavoxelData& data) const {
|
||||
void InsertSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
data.insert(attribute, spanner);
|
||||
}
|
||||
|
||||
|
@ -113,14 +113,20 @@ RemoveSpannerEdit::RemoveSpannerEdit(const AttributePointer& attribute, int id)
|
|||
id(id) {
|
||||
}
|
||||
|
||||
void RemoveSpannerEdit::apply(MetavoxelData& data) const {
|
||||
void RemoveSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
SharedObject* object = objects.value(id);
|
||||
if (!object) {
|
||||
qDebug() << "Missing object to remove" << id;
|
||||
return;
|
||||
}
|
||||
data.remove(attribute, object);
|
||||
}
|
||||
|
||||
ClearSpannersEdit::ClearSpannersEdit(const AttributePointer& attribute) :
|
||||
attribute(attribute) {
|
||||
}
|
||||
|
||||
void ClearSpannersEdit::apply(MetavoxelData& data) const {
|
||||
void ClearSpannersEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
data.clear(attribute);
|
||||
}
|
||||
|
||||
|
@ -149,7 +155,7 @@ SetSpannerEdit::SetSpannerEdit(const SharedObjectPointer& spanner) :
|
|||
spanner(spanner) {
|
||||
}
|
||||
|
||||
void SetSpannerEdit::apply(MetavoxelData& data) const {
|
||||
void SetSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||
Spanner* spanner = static_cast<Spanner*>(this->spanner.data());
|
||||
|
||||
// expand to fit the entire spanner
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
|
||||
STREAM QVariant edit;
|
||||
|
||||
void apply(MetavoxelData& data) const;
|
||||
void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(MetavoxelEditMessage)
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
|
||||
virtual ~MetavoxelEdit();
|
||||
|
||||
virtual void apply(MetavoxelData& data) const = 0;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const = 0;
|
||||
};
|
||||
|
||||
/// An edit that sets the region within a box to a value.
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
BoxSetEdit(const Box& region = Box(), float granularity = 0.0f,
|
||||
const OwnedAttributeValue& value = OwnedAttributeValue());
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(BoxSetEdit)
|
||||
|
@ -108,7 +108,7 @@ public:
|
|||
|
||||
GlobalSetEdit(const OwnedAttributeValue& value = OwnedAttributeValue());
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(GlobalSetEdit)
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
InsertSpannerEdit(const AttributePointer& attribute = AttributePointer(),
|
||||
const SharedObjectPointer& spanner = SharedObjectPointer());
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(InsertSpannerEdit)
|
||||
|
@ -141,7 +141,7 @@ public:
|
|||
|
||||
RemoveSpannerEdit(const AttributePointer& attribute = AttributePointer(), int id = 0);
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(RemoveSpannerEdit)
|
||||
|
@ -156,7 +156,7 @@ public:
|
|||
|
||||
ClearSpannersEdit(const AttributePointer& attribute = AttributePointer());
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(ClearSpannersEdit)
|
||||
|
@ -171,7 +171,7 @@ public:
|
|||
|
||||
SetSpannerEdit(const SharedObjectPointer& spanner = SharedObjectPointer());
|
||||
|
||||
virtual void apply(MetavoxelData& data) const;
|
||||
virtual void apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const;
|
||||
};
|
||||
|
||||
DECLARE_STREAMABLE_METATYPE(SetSpannerEdit)
|
||||
|
|
|
@ -18,7 +18,12 @@
|
|||
|
||||
REGISTER_META_OBJECT(SharedObject)
|
||||
|
||||
SharedObject::SharedObject() : _id(++_lastID), _referenceCount(0) {
|
||||
SharedObject::SharedObject() :
|
||||
_id(++_lastID),
|
||||
_remoteID(0),
|
||||
_referenceCount(0) {
|
||||
|
||||
_weakHash.insert(_id, this);
|
||||
}
|
||||
|
||||
void SharedObject::incrementReferenceCount() {
|
||||
|
@ -27,6 +32,7 @@ void SharedObject::incrementReferenceCount() {
|
|||
|
||||
void SharedObject::decrementReferenceCount() {
|
||||
if (--_referenceCount == 0) {
|
||||
_weakHash.remove(_id);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +92,17 @@ void SharedObject::dump(QDebug debug) const {
|
|||
}
|
||||
|
||||
int SharedObject::_lastID = 0;
|
||||
WeakSharedObjectHash SharedObject::_weakHash;
|
||||
|
||||
void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash) {
|
||||
for (WeakSharedObjectHash::iterator it = hash.begin(); it != hash.end(); ) {
|
||||
if (!it.value()) {
|
||||
it = hash.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SharedObjectEditor::SharedObjectEditor(const QMetaObject* metaObject, bool nullable, QWidget* parent) : QWidget(parent) {
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
|
|
|
@ -9,23 +9,38 @@
|
|||
#ifndef __interface__SharedObject__
|
||||
#define __interface__SharedObject__
|
||||
|
||||
#include <QHash>
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
#include <QWidget>
|
||||
#include <QtDebug>
|
||||
|
||||
class QComboBox;
|
||||
|
||||
class SharedObject;
|
||||
|
||||
typedef QHash<int, QPointer<SharedObject> > WeakSharedObjectHash;
|
||||
|
||||
/// A QObject that may be shared over the network.
|
||||
class SharedObject : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/// Returns the weak hash under which all local shared objects are registered.
|
||||
static const WeakSharedObjectHash& getWeakHash() { return _weakHash; }
|
||||
|
||||
Q_INVOKABLE SharedObject();
|
||||
|
||||
int getID() { return _id; }
|
||||
/// Returns the unique local ID for this object.
|
||||
int getID() const { return _id; }
|
||||
|
||||
/// Returns the unique remote ID for this object, or zero if this is a local object.
|
||||
int getRemoteID() const { return _remoteID; }
|
||||
|
||||
void setRemoteID(int remoteID) { _remoteID = remoteID; }
|
||||
|
||||
int getReferenceCount() const { return _referenceCount; }
|
||||
void incrementReferenceCount();
|
||||
|
@ -43,11 +58,16 @@ public:
|
|||
private:
|
||||
|
||||
int _id;
|
||||
int _remoteID;
|
||||
int _referenceCount;
|
||||
|
||||
static int _lastID;
|
||||
static WeakSharedObjectHash _weakHash;
|
||||
};
|
||||
|
||||
/// Removes the null references from the supplied hash.
|
||||
void pruneWeakSharedObjectHash(WeakSharedObjectHash& hash);
|
||||
|
||||
/// A pointer to a shared object.
|
||||
template<class T> class SharedObjectPointerTemplate {
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue