mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-30 18:50:51 +02:00
remove notion of owning node from NodeData
This commit is contained in:
parent
820132cb45
commit
8d2e9823de
27 changed files with 40 additions and 59 deletions
|
@ -47,7 +47,7 @@ unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *no
|
||||||
|
|
||||||
void attachAvatarDataToNode(Node* newNode) {
|
void attachAvatarDataToNode(Node* newNode) {
|
||||||
if (newNode->getLinkedData() == NULL) {
|
if (newNode->getLinkedData() == NULL) {
|
||||||
newNode->setLinkedData(new AvatarData(newNode));
|
newNode->setLinkedData(new AvatarData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 };
|
||||||
GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 };
|
GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 };
|
||||||
|
|
||||||
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels)
|
||||||
: NodeData(NULL),
|
: NodeData(),
|
||||||
_treeScale(treeScale),
|
_treeScale(treeScale),
|
||||||
_maxVoxels(maxVoxels),
|
_maxVoxels(maxVoxels),
|
||||||
_initialized(false) {
|
_initialized(false) {
|
||||||
|
|
|
@ -58,8 +58,8 @@ const int NUM_BODY_CONE_SIDES = 9;
|
||||||
const float CHAT_MESSAGE_SCALE = 0.0015f;
|
const float CHAT_MESSAGE_SCALE = 0.0015f;
|
||||||
const float CHAT_MESSAGE_HEIGHT = 0.1f;
|
const float CHAT_MESSAGE_HEIGHT = 0.1f;
|
||||||
|
|
||||||
Avatar::Avatar(Node* owningNode) :
|
Avatar::Avatar() :
|
||||||
AvatarData(owningNode),
|
AvatarData(),
|
||||||
_head(this),
|
_head(this),
|
||||||
_hand(this),
|
_hand(this),
|
||||||
_skeletonModel(this),
|
_skeletonModel(this),
|
||||||
|
|
|
@ -69,9 +69,7 @@ class Avatar : public AvatarData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Avatar();
|
||||||
Avatar(Node* owningNode = NULL);
|
|
||||||
~Avatar();
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void simulate(float deltaTime, Transmitter* transmitter);
|
void simulate(float deltaTime, Transmitter* transmitter);
|
||||||
|
@ -109,6 +107,8 @@ public:
|
||||||
/// \param collision[out] the details of the collision point
|
/// \param collision[out] the details of the collision point
|
||||||
/// \return whether or not the sphere collided
|
/// \return whether or not the sphere collided
|
||||||
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
|
virtual bool findSphereCollision(const glm::vec3& sphereCenter, float sphereRadius, CollisionInfo& collision);
|
||||||
|
|
||||||
|
virtual bool isMyAvatar() { return false; }
|
||||||
|
|
||||||
int parseData(unsigned char* sourceBuffer, int numBytes);
|
int parseData(unsigned char* sourceBuffer, int numBytes);
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,7 @@ void AvatarManager::processKillAvatar(const QByteArray& datagram) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::clearHash() {
|
void AvatarManager::clearHash() {
|
||||||
|
qDebug() << "clear the hash!";
|
||||||
// clear the AvatarManager hash - typically happens on the removal of the avatar-mixer
|
// clear the AvatarManager hash - typically happens on the removal of the avatar-mixer
|
||||||
_avatarHash.clear();
|
_avatarHash.clear();
|
||||||
}
|
}
|
|
@ -43,7 +43,7 @@ Hand::Hand(Avatar* owningAvatar) :
|
||||||
|
|
||||||
void Hand::init() {
|
void Hand::init() {
|
||||||
// Different colors for my hand and others' hands
|
// Different colors for my hand and others' hands
|
||||||
if (_owningAvatar && _owningAvatar->getOwningNode() == NULL) {
|
if (_owningAvatar && _owningAvatar->isMyAvatar()) {
|
||||||
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
_ballColor = glm::vec3(0.0, 0.4, 0.0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -54,8 +54,6 @@ void Hand::init() {
|
||||||
void Hand::reset() {
|
void Hand::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glm::vec3 Hand::getAndResetGrabDelta() {
|
glm::vec3 Hand::getAndResetGrabDelta() {
|
||||||
const float HAND_GRAB_SCALE_DISTANCE = 2.f;
|
const float HAND_GRAB_SCALE_DISTANCE = 2.f;
|
||||||
glm::vec3 delta = _grabDelta * _owningAvatar->getScale() * HAND_GRAB_SCALE_DISTANCE;
|
glm::vec3 delta = _grabDelta * _owningAvatar->getScale() * HAND_GRAB_SCALE_DISTANCE;
|
||||||
|
|
|
@ -37,8 +37,8 @@ const bool USING_HEAD_LEAN = false;
|
||||||
const float SKIN_COLOR[] = {1.0f, 0.84f, 0.66f};
|
const float SKIN_COLOR[] = {1.0f, 0.84f, 0.66f};
|
||||||
const float DARK_SKIN_COLOR[] = {0.9f, 0.78f, 0.63f};
|
const float DARK_SKIN_COLOR[] = {0.9f, 0.78f, 0.63f};
|
||||||
|
|
||||||
MyAvatar::MyAvatar(Node* owningNode) :
|
MyAvatar::MyAvatar() :
|
||||||
Avatar(owningNode),
|
Avatar(),
|
||||||
_mousePressed(false),
|
_mousePressed(false),
|
||||||
_bodyPitchDelta(0.0f),
|
_bodyPitchDelta(0.0f),
|
||||||
_bodyRollDelta(0.0f),
|
_bodyRollDelta(0.0f),
|
||||||
|
|
|
@ -24,7 +24,7 @@ enum AvatarHandState
|
||||||
|
|
||||||
class MyAvatar : public Avatar {
|
class MyAvatar : public Avatar {
|
||||||
public:
|
public:
|
||||||
MyAvatar(Node* owningNode = NULL);
|
MyAvatar();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void simulate(float deltaTime, Transmitter* transmitter);
|
void simulate(float deltaTime, Transmitter* transmitter);
|
||||||
|
@ -63,6 +63,8 @@ public:
|
||||||
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
bool getDriveKeys(int key) { return _driveKeys[key]; };
|
||||||
void jump() { _shouldJump = true; };
|
void jump() { _shouldJump = true; };
|
||||||
|
|
||||||
|
bool isMyAvatar() { return true; }
|
||||||
|
|
||||||
static void sendKillAvatar();
|
static void sendKillAvatar();
|
||||||
|
|
||||||
// Set/Get update the thrust that will move the avatar around
|
// Set/Get update the thrust that will move the avatar around
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#include "AudioRingBuffer.h"
|
#include "AudioRingBuffer.h"
|
||||||
|
|
||||||
AudioRingBuffer::AudioRingBuffer(int numFrameSamples) :
|
AudioRingBuffer::AudioRingBuffer(int numFrameSamples) :
|
||||||
NodeData(NULL),
|
NodeData(),
|
||||||
_sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES),
|
_sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES),
|
||||||
_isStarved(true),
|
_isStarved(true),
|
||||||
_hasStarted(false)
|
_hasStarted(false)
|
||||||
|
|
|
@ -22,8 +22,8 @@ using namespace std;
|
||||||
|
|
||||||
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
||||||
|
|
||||||
AvatarData::AvatarData(Node* owningNode) :
|
AvatarData::AvatarData() :
|
||||||
NodeData(owningNode),
|
NodeData(),
|
||||||
_handPosition(0,0,0),
|
_handPosition(0,0,0),
|
||||||
_bodyYaw(-90.0),
|
_bodyYaw(-90.0),
|
||||||
_bodyPitch(0.0),
|
_bodyPitch(0.0),
|
||||||
|
|
|
@ -70,7 +70,7 @@ class AvatarData : public NodeData {
|
||||||
Q_PROPERTY(float bodyRoll READ getBodyRoll WRITE setBodyRoll)
|
Q_PROPERTY(float bodyRoll READ getBodyRoll WRITE setBodyRoll)
|
||||||
Q_PROPERTY(QString chatMessage READ getQStringChatMessage WRITE setChatMessage)
|
Q_PROPERTY(QString chatMessage READ getQStringChatMessage WRITE setChatMessage)
|
||||||
public:
|
public:
|
||||||
AvatarData(Node* owningNode = NULL);
|
AvatarData();
|
||||||
~AvatarData();
|
~AvatarData();
|
||||||
|
|
||||||
const glm::vec3& getPosition() const { return _position; }
|
const glm::vec3& getPosition() const { return _position; }
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "OctreeSendThread.h"
|
#include "OctreeSendThread.h"
|
||||||
|
|
||||||
OctreeQueryNode::OctreeQueryNode(Node* owningNode) :
|
OctreeQueryNode::OctreeQueryNode() :
|
||||||
OctreeQuery(owningNode),
|
|
||||||
_viewSent(false),
|
_viewSent(false),
|
||||||
_octreePacketAvailableBytes(MAX_PACKET_SIZE),
|
_octreePacketAvailableBytes(MAX_PACKET_SIZE),
|
||||||
_maxSearchLevel(1),
|
_maxSearchLevel(1),
|
||||||
|
@ -38,9 +37,8 @@ OctreeQueryNode::OctreeQueryNode(Node* owningNode) :
|
||||||
_sequenceNumber = 0;
|
_sequenceNumber = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer) {
|
void OctreeQueryNode::initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID) {
|
||||||
// Create octree sending thread...
|
// Create octree sending thread...
|
||||||
QUuid nodeUUID = getOwningNode()->getUUID();
|
|
||||||
_octreeSendThread = new OctreeSendThread(nodeUUID, octreeServer);
|
_octreeSendThread = new OctreeSendThread(nodeUUID, octreeServer);
|
||||||
_octreeSendThread->initialize(true);
|
_octreeSendThread->initialize(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class OctreeServer;
|
||||||
|
|
||||||
class OctreeQueryNode : public OctreeQuery {
|
class OctreeQueryNode : public OctreeQuery {
|
||||||
public:
|
public:
|
||||||
OctreeQueryNode(Node* owningNode);
|
OctreeQueryNode();
|
||||||
virtual ~OctreeQueryNode();
|
virtual ~OctreeQueryNode();
|
||||||
|
|
||||||
virtual PACKET_TYPE getMyPacketType() const = 0;
|
virtual PACKET_TYPE getMyPacketType() const = 0;
|
||||||
|
@ -80,7 +80,7 @@ public:
|
||||||
|
|
||||||
OctreeSceneStats stats;
|
OctreeSceneStats stats;
|
||||||
|
|
||||||
void initializeOctreeSendThread(OctreeServer* octreeServer);
|
void initializeOctreeSendThread(OctreeServer* octreeServer, const QUuid& nodeUUID);
|
||||||
bool isOctreeSendThreadInitalized() { return _octreeSendThread; }
|
bool isOctreeSendThreadInitalized() { return _octreeSendThread; }
|
||||||
|
|
||||||
void dumpOutOfView();
|
void dumpOutOfView();
|
||||||
|
|
|
@ -22,7 +22,7 @@ OctreeServer* OctreeServer::_instance = NULL;
|
||||||
|
|
||||||
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
void OctreeServer::attachQueryNodeToNode(Node* newNode) {
|
||||||
if (newNode->getLinkedData() == NULL) {
|
if (newNode->getLinkedData() == NULL) {
|
||||||
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode(newNode);
|
OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode();
|
||||||
newQueryNodeData->resetOctreePacket(true); // don't bump sequence
|
newQueryNodeData->resetOctreePacket(true); // don't bump sequence
|
||||||
newNode->setLinkedData(newQueryNodeData);
|
newNode->setLinkedData(newQueryNodeData);
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,7 @@ void OctreeServer::processDatagram(const QByteArray& dataByteArray, const HifiSo
|
||||||
}
|
}
|
||||||
OctreeQueryNode* nodeData = (OctreeQueryNode*) node->getLinkedData();
|
OctreeQueryNode* nodeData = (OctreeQueryNode*) node->getLinkedData();
|
||||||
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
|
if (nodeData && !nodeData->isOctreeSendThreadInitalized()) {
|
||||||
nodeData->initializeOctreeSendThread(this);
|
nodeData->initializeOctreeSendThread(this, nodeUUID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (packetType == PACKET_TYPE_JURISDICTION_REQUEST) {
|
} else if (packetType == PACKET_TYPE_JURISDICTION_REQUEST) {
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
uint64_t getLoadElapsedTime() const { return (_persistThread) ? _persistThread->getLoadElapsedTime() : 0; }
|
uint64_t getLoadElapsedTime() const { return (_persistThread) ? _persistThread->getLoadElapsedTime() : 0; }
|
||||||
|
|
||||||
// Subclasses must implement these methods
|
// Subclasses must implement these methods
|
||||||
virtual OctreeQueryNode* createOctreeQueryNode(Node* newNode) = 0;
|
virtual OctreeQueryNode* createOctreeQueryNode() = 0;
|
||||||
virtual Octree* createTree() = 0;
|
virtual Octree* createTree() = 0;
|
||||||
virtual unsigned char getMyNodeType() const = 0;
|
virtual unsigned char getMyNodeType() const = 0;
|
||||||
virtual PACKET_TYPE getMyQueryMessageType() const = 0;
|
virtual PACKET_TYPE getMyQueryMessageType() const = 0;
|
||||||
|
|
|
@ -22,8 +22,8 @@ using namespace std;
|
||||||
|
|
||||||
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
||||||
|
|
||||||
OctreeQuery::OctreeQuery(Node* owningNode) :
|
OctreeQuery::OctreeQuery() :
|
||||||
NodeData(owningNode),
|
NodeData(),
|
||||||
_uuid(),
|
_uuid(),
|
||||||
_cameraPosition(0,0,0),
|
_cameraPosition(0,0,0),
|
||||||
_cameraOrientation(),
|
_cameraOrientation(),
|
||||||
|
|
|
@ -51,7 +51,7 @@ class OctreeQuery : public NodeData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OctreeQuery(Node* owningNode = NULL);
|
OctreeQuery();
|
||||||
virtual ~OctreeQuery();
|
virtual ~OctreeQuery();
|
||||||
|
|
||||||
int getBroadcastData(unsigned char* destinationBuffer);
|
int getBroadcastData(unsigned char* destinationBuffer);
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
class ParticleNodeData : public OctreeQueryNode {
|
class ParticleNodeData : public OctreeQueryNode {
|
||||||
public:
|
public:
|
||||||
ParticleNodeData(Node* owningNode) :
|
ParticleNodeData() :
|
||||||
OctreeQueryNode(owningNode),
|
OctreeQueryNode(),
|
||||||
_lastDeletedParticlesSentAt(0) { };
|
_lastDeletedParticlesSentAt(0) { };
|
||||||
|
|
||||||
virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_PARTICLE_DATA; }
|
virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_PARTICLE_DATA; }
|
||||||
|
|
|
@ -26,8 +26,8 @@ ParticleServer::~ParticleServer() {
|
||||||
tree->removeNewlyCreatedHook(this);
|
tree->removeNewlyCreatedHook(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
OctreeQueryNode* ParticleServer::createOctreeQueryNode(Node* newNode) {
|
OctreeQueryNode* ParticleServer::createOctreeQueryNode() {
|
||||||
return new ParticleNodeData(newNode);
|
return new ParticleNodeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Octree* ParticleServer::createTree() {
|
Octree* ParticleServer::createTree() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
~ParticleServer();
|
~ParticleServer();
|
||||||
|
|
||||||
// Subclasses must implement these methods
|
// Subclasses must implement these methods
|
||||||
virtual OctreeQueryNode* createOctreeQueryNode(Node* newNode);
|
virtual OctreeQueryNode* createOctreeQueryNode();
|
||||||
virtual Octree* createTree();
|
virtual Octree* createTree();
|
||||||
virtual unsigned char getMyNodeType() const { return NODE_TYPE_PARTICLE_SERVER; }
|
virtual unsigned char getMyNodeType() const { return NODE_TYPE_PARTICLE_SERVER; }
|
||||||
virtual PACKET_TYPE getMyQueryMessageType() const { return PACKET_TYPE_PARTICLE_QUERY; }
|
virtual PACKET_TYPE getMyQueryMessageType() const { return PACKET_TYPE_PARTICLE_QUERY; }
|
||||||
|
|
|
@ -8,12 +8,6 @@
|
||||||
|
|
||||||
#include "NodeData.h"
|
#include "NodeData.h"
|
||||||
|
|
||||||
NodeData::NodeData(Node* owningNode) :
|
|
||||||
_owningNode(owningNode)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeData::~NodeData() {
|
NodeData::~NodeData() {
|
||||||
|
|
||||||
}
|
}
|
|
@ -16,14 +16,9 @@ class Node;
|
||||||
class NodeData : public QObject {
|
class NodeData : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
NodeData(Node* owningNode = NULL);
|
|
||||||
|
|
||||||
virtual ~NodeData() = 0;
|
virtual ~NodeData() = 0;
|
||||||
virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
virtual int parseData(unsigned char* sourceBuffer, int numBytes) = 0;
|
||||||
|
|
||||||
Node* getOwningNode() { return _owningNode; }
|
|
||||||
protected:
|
|
||||||
Node* _owningNode;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
class VoxelNodeData : public OctreeQueryNode {
|
class VoxelNodeData : public OctreeQueryNode {
|
||||||
public:
|
public:
|
||||||
VoxelNodeData(Node* owningNode) : OctreeQueryNode(owningNode) { };
|
VoxelNodeData() : OctreeQueryNode() { };
|
||||||
virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_VOXEL_DATA; }
|
virtual PACKET_TYPE getMyPacketType() const { return PACKET_TYPE_VOXEL_DATA; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ VoxelServer::~VoxelServer() {
|
||||||
// nothing special to do here...
|
// nothing special to do here...
|
||||||
}
|
}
|
||||||
|
|
||||||
OctreeQueryNode* VoxelServer::createOctreeQueryNode(Node* newNode) {
|
OctreeQueryNode* VoxelServer::createOctreeQueryNode() {
|
||||||
return new VoxelNodeData(newNode);
|
return new VoxelNodeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
Octree* VoxelServer::createTree() {
|
Octree* VoxelServer::createTree() {
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); }
|
int getEnvironmentDataCount() const { return sizeof(_environmentData)/sizeof(EnvironmentData); }
|
||||||
|
|
||||||
// Subclasses must implement these methods
|
// Subclasses must implement these methods
|
||||||
virtual OctreeQueryNode* createOctreeQueryNode(Node* newNode);
|
virtual OctreeQueryNode* createOctreeQueryNode();
|
||||||
virtual Octree* createTree();
|
virtual Octree* createTree();
|
||||||
virtual unsigned char getMyNodeType() const { return NODE_TYPE_VOXEL_SERVER; }
|
virtual unsigned char getMyNodeType() const { return NODE_TYPE_VOXEL_SERVER; }
|
||||||
virtual PACKET_TYPE getMyQueryMessageType() const { return PACKET_TYPE_VOXEL_QUERY; }
|
virtual PACKET_TYPE getMyQueryMessageType() const { return PACKET_TYPE_VOXEL_QUERY; }
|
||||||
|
|
|
@ -6,9 +6,4 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VoxelQuery.h"
|
#include "VoxelQuery.h"
|
||||||
|
|
||||||
VoxelQuery::VoxelQuery(Node* owningNode) : OctreeQuery(owningNode) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,8 @@
|
||||||
class VoxelQuery : public OctreeQuery {
|
class VoxelQuery : public OctreeQuery {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VoxelQuery(Node* owningNode = NULL);
|
|
||||||
|
|
||||||
// currently just an alias
|
// currently just an alias
|
||||||
|
VoxelQuery() : OctreeQuery() {};
|
||||||
private:
|
private:
|
||||||
// privatize the copy constructor and assignment operator so they cannot be called
|
// privatize the copy constructor and assignment operator so they cannot be called
|
||||||
VoxelQuery(const VoxelQuery&);
|
VoxelQuery(const VoxelQuery&);
|
||||||
|
|
Loading…
Reference in a new issue