mirror of https://github.com/axmolengine/axmol.git
Implements a socket.io client extension, adds a test case and updates the android makefiles.
Contains the following tasks: -initial socket.io extension commit -sioclientimpl subclasses websocket:delegate to respond to websocket events -implement static connect methods and basic client creation -move SocketIO class files into correct extension folder (network) -create SocketIO test in TestCpp -update project references -add missing static modifier to connect method -implement basic test methods -update extensions tests with SocketIO test entry -implement basic handshake and opensocket methods for SocketIO -add Delegate class to handle callbacks, implement virtual Delegate methods in test -implement socket and client registries for lookup when connecting to hosts and endpoints -connect delegate onOpen method by separating impl creation from connection -update test to demonstrate onOpen callback -create send and emit methods, move SIOClient into header file, add send and emit methods to test -implement basic socket.io message parsing -improve logging for events and messages -add logic to pull event name from payload -schedule heartbeat to keep connection alive, scheduled for 90% of the heartbeat interval from the server for safety -add onConnect handler to to catch socket.io onconnect vs websocket onopen -add disconnect and disconnectFromEndpoint methods to properly disconnect and destroy objects -modify SIOClientImpl to track _uri for easier lookup in registries -connect handler for onMessage to message event from socket.io, modify onError handler to take a string instead of WebSocket error code -create SIOEvent callback type, implement event registry in clients, add test for event registration and callback -update SIOEvent to use std::function and c++11, utilize cocos2d CC_CALLBACK method to bind selectors, this ensures that the *this reference is properly passed -check for connect before sending or emitting in the client, cleanup some codes -change connect logic to reuse existing socket connections instead of opening a new one -implements get and set Tag methods for clients for easy reference -improve endpoint handling, add endpoint tests to test layer -additional error handling within socket disconnect error and failure to open connection -fixes extracting endpoint from socket.io messages (in cases of the connect message, where there is 1 less colon for the connect message to the default namespace). Also fixes connecting to the default namespace "/" in the connectToEndpoint method -add disconnect and onClose handlers to client so that onClose is called in the delegate -add disconnect test methods to test layers -change c-style casts to static_casts when using a CCDICT_FOREACH -remove some unneeded namespace completion -add usage documentation -add handling for disconnect from server, cleanup some codes -update comments and documentation in the socketiotest -update includes so the NDK doesn't complain when compiling with c++11 -add socketio.cpp and test.cpp to the android makefiles -update test URL to my public server, test script can also be found in my repo at https://github.com/hannon235/socket.io-testserver.git Signed-off-by: Chris Hannon <himynameschris@gmail.com>
This commit is contained in:
parent
cfc12d780c
commit
126ebb888c
|
@ -78,6 +78,7 @@ GUI/CCEditBox/CCEditBox.cpp \
|
||||||
GUI/CCEditBox/CCEditBoxImplAndroid.cpp \
|
GUI/CCEditBox/CCEditBoxImplAndroid.cpp \
|
||||||
network/HttpClient.cpp \
|
network/HttpClient.cpp \
|
||||||
network/WebSocket.cpp \
|
network/WebSocket.cpp \
|
||||||
|
network/SocketIO.cpp \
|
||||||
physics_nodes/CCPhysicsDebugNode.cpp \
|
physics_nodes/CCPhysicsDebugNode.cpp \
|
||||||
physics_nodes/CCPhysicsSprite.cpp \
|
physics_nodes/CCPhysicsSprite.cpp \
|
||||||
LocalStorage/LocalStorageAndroid.cpp \
|
LocalStorage/LocalStorageAndroid.cpp \
|
||||||
|
|
|
@ -0,0 +1,714 @@
|
||||||
|
/****************************************************************************
|
||||||
|
Copyright (c) 2010-2013 cocos2d-x.org
|
||||||
|
Copyright (c) 2013 Chris Hannon
|
||||||
|
|
||||||
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
*based on the SocketIO library created by LearnBoost at http://socket.io
|
||||||
|
*using spec version 1 found at https://github.com/LearnBoost/socket.io-spec
|
||||||
|
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "SocketIO.h"
|
||||||
|
#include "cocos-ext.h"
|
||||||
|
#include "network/WebSocket.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
NS_CC_EXT_BEGIN
|
||||||
|
|
||||||
|
//class declarations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The implementation of the socket.io connection
|
||||||
|
* Clients/endpoints may share the same impl to accomplish multiplexing on the same websocket
|
||||||
|
*/
|
||||||
|
class SIOClientImpl :
|
||||||
|
public Object,
|
||||||
|
public WebSocket::Delegate
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int _port, _heartbeat, _timeout;
|
||||||
|
std::string _host, _sid, _uri;
|
||||||
|
bool _connected;
|
||||||
|
|
||||||
|
WebSocket *_ws;
|
||||||
|
|
||||||
|
Dictionary* _clients;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SIOClientImpl(const std::string& host, int port);
|
||||||
|
virtual ~SIOClientImpl(void);
|
||||||
|
|
||||||
|
static SIOClientImpl* create(const std::string& host, int port);
|
||||||
|
|
||||||
|
virtual void onOpen(cocos2d::extension::WebSocket* ws);
|
||||||
|
virtual void onMessage(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::Data& data);
|
||||||
|
virtual void onClose(cocos2d::extension::WebSocket* ws);
|
||||||
|
virtual void onError(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::ErrorCode& error);
|
||||||
|
|
||||||
|
void connect();
|
||||||
|
void disconnect();
|
||||||
|
bool init();
|
||||||
|
void handshake();
|
||||||
|
void handshakeResponse(HttpClient *sender, HttpResponse *response);
|
||||||
|
void openSocket();
|
||||||
|
void heartbeat(float dt);
|
||||||
|
|
||||||
|
SIOClient* getClient(const std::string& endpoint);
|
||||||
|
void addClient(const std::string& endpoint, SIOClient* client);
|
||||||
|
|
||||||
|
void connectToEndpoint(const std::string& endpoint);
|
||||||
|
void disconnectFromEndpoint(const std::string& endpoint);
|
||||||
|
|
||||||
|
void send(std::string endpoint, std::string s);
|
||||||
|
void emit(std::string endpoint, std::string eventname, std::string args);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//method implementations
|
||||||
|
|
||||||
|
//begin SIOClientImpl methods
|
||||||
|
SIOClientImpl::SIOClientImpl(const std::string& host, int port) :
|
||||||
|
_port(port),
|
||||||
|
_host(host),
|
||||||
|
_connected(false)
|
||||||
|
{
|
||||||
|
_clients = Dictionary::create();
|
||||||
|
_clients->retain();
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << host << ":" << port;
|
||||||
|
_uri = s.str();
|
||||||
|
|
||||||
|
_ws = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClientImpl::~SIOClientImpl() {
|
||||||
|
|
||||||
|
if(_connected) disconnect();
|
||||||
|
|
||||||
|
CC_SAFE_DELETE(_clients);
|
||||||
|
CC_SAFE_DELETE(_ws);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::handshake() {
|
||||||
|
CCLog("SIOClientImpl::handshake() called");
|
||||||
|
|
||||||
|
std::stringstream pre;
|
||||||
|
pre << "http://" << _uri << "/socket.io/1";
|
||||||
|
|
||||||
|
HttpRequest* request = new HttpRequest();
|
||||||
|
request->setUrl(pre.str().c_str());
|
||||||
|
request->setRequestType(HttpRequest::kHttpGet);
|
||||||
|
|
||||||
|
request->setResponseCallback(this, httpresponse_selector(SIOClientImpl::handshakeResponse));
|
||||||
|
request->setTag("handshake");
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::handshake() waiting");
|
||||||
|
|
||||||
|
HttpClient::getInstance()->send(request);
|
||||||
|
|
||||||
|
request->release();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::handshakeResponse(HttpClient *sender, HttpResponse *response) {
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::handshakeResponse() called");
|
||||||
|
|
||||||
|
if (0 != strlen(response->getHttpRequest()->getTag()))
|
||||||
|
{
|
||||||
|
CCLog("%s completed", response->getHttpRequest()->getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
int statusCode = response->getResponseCode();
|
||||||
|
char statusString[64] = {};
|
||||||
|
sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());
|
||||||
|
CCLog("response code: %d", statusCode);
|
||||||
|
|
||||||
|
if (!response->isSucceed())
|
||||||
|
{
|
||||||
|
CCLog("SIOClientImpl::handshake() failed");
|
||||||
|
CCLog("error buffer: %s", response->getErrorBuffer());
|
||||||
|
|
||||||
|
DictElement* el = NULL;
|
||||||
|
|
||||||
|
CCDICT_FOREACH(_clients, el) {
|
||||||
|
|
||||||
|
SIOClient* c = static_cast<SIOClient*>(el->getObject());
|
||||||
|
|
||||||
|
c->getDelegate()->onError(c, response->getErrorBuffer());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::handshake() succeeded");
|
||||||
|
|
||||||
|
std::vector<char> *buffer = response->getResponseData();
|
||||||
|
std::stringstream s;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < buffer->size(); i++)
|
||||||
|
{
|
||||||
|
s << (*buffer)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::handshake() dump data: %s", s.str().c_str());
|
||||||
|
|
||||||
|
std::string res = s.str();
|
||||||
|
std::string sid;
|
||||||
|
int pos;
|
||||||
|
int heartbeat, timeout;
|
||||||
|
|
||||||
|
pos = res.find(":");
|
||||||
|
if(pos >= 0) {
|
||||||
|
sid = res.substr(0, pos);
|
||||||
|
res.erase(0, pos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = res.find(":");
|
||||||
|
if(pos >= 0){
|
||||||
|
heartbeat = atoi(res.substr(pos+1, res.size()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = res.find(":");
|
||||||
|
if(pos >= 0){
|
||||||
|
timeout = atoi(res.substr(pos+1, res.size()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
_sid = sid;
|
||||||
|
_heartbeat = heartbeat;
|
||||||
|
_timeout = timeout;
|
||||||
|
|
||||||
|
openSocket();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::openSocket() {
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::openSocket() called");
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << _uri << "/socket.io/1/websocket/" << _sid;
|
||||||
|
|
||||||
|
_ws = new WebSocket();
|
||||||
|
if(!_ws->init(*this, s.str()))
|
||||||
|
{
|
||||||
|
CC_SAFE_DELETE(_ws);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SIOClientImpl::init() {
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::init() successful");
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::connect() {
|
||||||
|
|
||||||
|
this->handshake();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::disconnect() {
|
||||||
|
|
||||||
|
if(_ws->getReadyState() == WebSocket::kStateOpen) {
|
||||||
|
|
||||||
|
std::string s = "0::";
|
||||||
|
|
||||||
|
_ws->send(s);
|
||||||
|
|
||||||
|
CCLog("Disconnect sent");
|
||||||
|
|
||||||
|
_ws->close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Director::sharedDirector()->getScheduler()->unscheduleAllForTarget(this);
|
||||||
|
|
||||||
|
_connected = false;
|
||||||
|
|
||||||
|
SocketIO::instance()->removeSocket(_uri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClientImpl* SIOClientImpl::create(const std::string& host, int port) {
|
||||||
|
|
||||||
|
SIOClientImpl *s = new SIOClientImpl(host, port);
|
||||||
|
|
||||||
|
if(s && s->init()) {
|
||||||
|
|
||||||
|
return s;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClient* SIOClientImpl::getClient(const std::string& endpoint) {
|
||||||
|
|
||||||
|
return static_cast<SIOClient*>(_clients->objectForKey(endpoint));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::addClient(const std::string& endpoint, SIOClient* client) {
|
||||||
|
|
||||||
|
_clients->setObject(client, endpoint);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::connectToEndpoint(const std::string& endpoint) {
|
||||||
|
|
||||||
|
std::string path = endpoint == "/" ? "" : endpoint;
|
||||||
|
|
||||||
|
std::string s = "1::" + path;
|
||||||
|
|
||||||
|
_ws->send(s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::disconnectFromEndpoint(const std::string& endpoint) {
|
||||||
|
|
||||||
|
_clients->removeObjectForKey(endpoint);
|
||||||
|
|
||||||
|
if(_clients->count() == 0 || endpoint == "/") {
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::disconnectFromEndpoint out of endpoints, checking for disconnect");
|
||||||
|
|
||||||
|
if(_connected) this->disconnect();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::string path = endpoint == "/" ? "" : endpoint;
|
||||||
|
|
||||||
|
std::string s = "0::" + path;
|
||||||
|
|
||||||
|
_ws->send(s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::heartbeat(float dt) {
|
||||||
|
|
||||||
|
std::string s = "2::";
|
||||||
|
|
||||||
|
_ws->send(s);
|
||||||
|
|
||||||
|
CCLog("Heartbeat sent");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SIOClientImpl::send(std::string endpoint, std::string s) {
|
||||||
|
std::stringstream pre;
|
||||||
|
|
||||||
|
std::string path = endpoint == "/" ? "" : endpoint;
|
||||||
|
|
||||||
|
pre << "3::" << path << ":" << s;
|
||||||
|
|
||||||
|
std::string msg = pre.str();
|
||||||
|
|
||||||
|
CCLog("sending message: %s", msg.c_str());
|
||||||
|
|
||||||
|
_ws->send(msg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::emit(std::string endpoint, std::string eventname, std::string args) {
|
||||||
|
|
||||||
|
std::stringstream pre;
|
||||||
|
|
||||||
|
std::string path = endpoint == "/" ? "" : endpoint;
|
||||||
|
|
||||||
|
pre << "5::" << path << ":{\"name\":\"" << eventname << "\",\"args\":" << args << "}";
|
||||||
|
|
||||||
|
std::string msg = pre.str();
|
||||||
|
|
||||||
|
CCLog("emitting event with data: %s", msg.c_str());
|
||||||
|
|
||||||
|
_ws->send(msg);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::onOpen(cocos2d::extension::WebSocket* ws) {
|
||||||
|
|
||||||
|
_connected = true;
|
||||||
|
|
||||||
|
SocketIO::instance()->addSocket(_uri, this);
|
||||||
|
|
||||||
|
DictElement* e = NULL;
|
||||||
|
|
||||||
|
CCDICT_FOREACH(_clients, e) {
|
||||||
|
|
||||||
|
SIOClient *c = static_cast<SIOClient*>(e->getObject());
|
||||||
|
|
||||||
|
c->onOpen();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Director::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(SIOClientImpl::heartbeat), this, (_heartbeat * .9), false);
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::onOpen socket connected!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::onMessage(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::Data& data) {
|
||||||
|
|
||||||
|
CCLog("SIOClientImpl::onMessage received: %s", data.bytes);
|
||||||
|
|
||||||
|
int control = atoi(&data.bytes[0]);
|
||||||
|
|
||||||
|
std::string payload, msgid, endpoint, s_data, eventname;
|
||||||
|
payload = data.bytes;
|
||||||
|
|
||||||
|
int pos, pos2;
|
||||||
|
|
||||||
|
pos = payload.find(":");
|
||||||
|
if(pos >=0 ) {
|
||||||
|
payload.erase(0, pos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = payload.find(":");
|
||||||
|
if(pos > 0 ) {
|
||||||
|
msgid = atoi(payload.substr(0, pos+1).c_str());
|
||||||
|
}
|
||||||
|
payload.erase(0, pos+1);
|
||||||
|
|
||||||
|
pos = payload.find(":");
|
||||||
|
if(pos >= 0) {
|
||||||
|
|
||||||
|
endpoint = payload.substr(0, pos);
|
||||||
|
payload.erase(0, pos+1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
endpoint = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(endpoint == "") endpoint = "/";
|
||||||
|
|
||||||
|
|
||||||
|
s_data = payload;
|
||||||
|
SIOClient *c = NULL;
|
||||||
|
c = getClient(endpoint);
|
||||||
|
if(c == NULL) CCLog("SIOClientImpl::onMessage client lookup returned NULL");
|
||||||
|
|
||||||
|
switch(control) {
|
||||||
|
case 0:
|
||||||
|
CCLog("Received Disconnect Signal for Endpoint: %s\n", endpoint.c_str());
|
||||||
|
if(c) c->receivedDisconnect();
|
||||||
|
disconnectFromEndpoint(endpoint);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
CCLog("Connected to endpoint: %s \n",endpoint.c_str());
|
||||||
|
if(c) c->onConnect();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
CCLog("Heartbeat received\n");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
CCLog("Message received: %s \n", s_data.c_str());
|
||||||
|
if(c) c->getDelegate()->onMessage(c, s_data);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
CCLog("JSON Message Received: %s \n", s_data.c_str());
|
||||||
|
if(c) c->getDelegate()->onMessage(c, s_data);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
CCLog("Event Received with data: %s \n", s_data.c_str());
|
||||||
|
|
||||||
|
if(c) {
|
||||||
|
eventname = "";
|
||||||
|
pos = s_data.find(":");
|
||||||
|
pos2 = s_data.find(",");
|
||||||
|
if(pos2 > pos) {
|
||||||
|
s_data = s_data.substr(pos+1, pos2-pos-1);
|
||||||
|
std::remove_copy(s_data.begin(), s_data.end(),
|
||||||
|
std::back_inserter(eventname), '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
c->fireEvent(eventname, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
CCLog("Message Ack\n");
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
CCLog("Error\n");
|
||||||
|
if(c) c->getDelegate()->onError(c, s_data);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
CCLog("Noop\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::onClose(cocos2d::extension::WebSocket* ws) {
|
||||||
|
|
||||||
|
if(_clients->count() > 0) {
|
||||||
|
|
||||||
|
DictElement *e;
|
||||||
|
|
||||||
|
CCDICT_FOREACH(_clients, e) {
|
||||||
|
|
||||||
|
SIOClient *c = static_cast<SIOClient *>(e->getObject());
|
||||||
|
|
||||||
|
c->receivedDisconnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this->release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClientImpl::onError(cocos2d::extension::WebSocket* ws, const cocos2d::extension::WebSocket::ErrorCode& error) {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//begin SIOClient methods
|
||||||
|
SIOClient::SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate)
|
||||||
|
: _host(host)
|
||||||
|
, _port(port)
|
||||||
|
, _path(path)
|
||||||
|
, _socket(impl)
|
||||||
|
, _connected(false)
|
||||||
|
, _delegate(&delegate)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClient::~SIOClient(void) {
|
||||||
|
|
||||||
|
if(_connected) {
|
||||||
|
_socket->disconnectFromEndpoint(_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::onOpen() {
|
||||||
|
|
||||||
|
if(_path != "/") {
|
||||||
|
|
||||||
|
_socket->connectToEndpoint(_path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::onConnect() {
|
||||||
|
|
||||||
|
_connected = true;
|
||||||
|
_delegate->onConnect(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::send(std::string s) {
|
||||||
|
|
||||||
|
if(_connected) {
|
||||||
|
_socket->send(_path, s);
|
||||||
|
} else {
|
||||||
|
_delegate->onError(this, "Client not yet connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::emit(std::string eventname, std::string args) {
|
||||||
|
|
||||||
|
if(_connected) {
|
||||||
|
_socket->emit(_path, eventname, args);
|
||||||
|
} else {
|
||||||
|
_delegate->onError(this, "Client not yet connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::disconnect() {
|
||||||
|
|
||||||
|
_connected = false;
|
||||||
|
|
||||||
|
_socket->disconnectFromEndpoint(_path);
|
||||||
|
|
||||||
|
_delegate->onClose(this);
|
||||||
|
|
||||||
|
this->release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::receivedDisconnect() {
|
||||||
|
|
||||||
|
_connected = false;
|
||||||
|
|
||||||
|
_delegate->onClose(this);
|
||||||
|
|
||||||
|
this->release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::on(const std::string& eventName, SIOEvent e) {
|
||||||
|
|
||||||
|
_eventRegistry[eventName] = e;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SIOClient::fireEvent(const std::string& eventName, const std::string& data) {
|
||||||
|
|
||||||
|
CCLog("SIOClient::fireEvent called with event name: %s and data: %s", eventName.c_str(), data.c_str());
|
||||||
|
|
||||||
|
if(_eventRegistry[eventName]) {
|
||||||
|
|
||||||
|
SIOEvent e = _eventRegistry[eventName];
|
||||||
|
|
||||||
|
e(this, data);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCLog("SIOClient::fireEvent no event with name %s found", eventName.c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//begin SocketIO methods
|
||||||
|
SocketIO *SocketIO::_inst = NULL;
|
||||||
|
|
||||||
|
SocketIO::SocketIO() {
|
||||||
|
|
||||||
|
_sockets = Dictionary::create();
|
||||||
|
_sockets->retain();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketIO::~SocketIO(void) {
|
||||||
|
CC_SAFE_DELETE(_sockets);
|
||||||
|
delete _inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketIO* SocketIO::instance() {
|
||||||
|
|
||||||
|
if(!_inst)
|
||||||
|
_inst = new SocketIO();
|
||||||
|
|
||||||
|
return _inst;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClient* SocketIO::connect(SocketIO::SIODelegate& delegate, const std::string& uri) {
|
||||||
|
|
||||||
|
std::string host = uri;
|
||||||
|
int port, pos;
|
||||||
|
|
||||||
|
pos = host.find("//");
|
||||||
|
if(pos >= 0) {
|
||||||
|
host.erase(0, pos+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = host.find(":");
|
||||||
|
if(pos >= 0){
|
||||||
|
port = atoi(host.substr(pos+1, host.size()).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = host.find("/", 0);
|
||||||
|
std::string path = "/";
|
||||||
|
if(pos >= 0){
|
||||||
|
path += host.substr(pos + 1, host.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = host.find(":");
|
||||||
|
if(pos >= 0){
|
||||||
|
host.erase(pos, host.size());
|
||||||
|
}else if((pos = host.find("/"))>=0) {
|
||||||
|
host.erase(pos, host.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << host << ":" << port;
|
||||||
|
|
||||||
|
SIOClientImpl* socket = NULL;
|
||||||
|
SIOClient *c = NULL;
|
||||||
|
|
||||||
|
socket = SocketIO::instance()->getSocket(s.str());
|
||||||
|
|
||||||
|
if(socket == NULL) {
|
||||||
|
//create a new socket, new client, connect
|
||||||
|
socket = SIOClientImpl::create(host, port);
|
||||||
|
|
||||||
|
c = new SIOClient(host, port, path, socket, delegate);
|
||||||
|
|
||||||
|
socket->addClient(path, c);
|
||||||
|
|
||||||
|
socket->connect();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//check if already connected to endpoint, handle
|
||||||
|
c = socket->getClient(path);
|
||||||
|
|
||||||
|
if(c == NULL) {
|
||||||
|
|
||||||
|
c = new SIOClient(host, port, path, socket, delegate);
|
||||||
|
|
||||||
|
socket->addClient(path, c);
|
||||||
|
|
||||||
|
socket->connectToEndpoint(path);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SIOClientImpl* SocketIO::getSocket(const std::string& uri) {
|
||||||
|
|
||||||
|
return static_cast<SIOClientImpl*>(_sockets->objectForKey(uri));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIO::addSocket(const std::string& uri, SIOClientImpl* socket) {
|
||||||
|
_sockets->setObject(socket, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIO::removeSocket(const std::string& uri) {
|
||||||
|
_sockets->removeObjectForKey(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_CC_EXT_END
|
|
@ -0,0 +1,179 @@
|
||||||
|
/****************************************************************************
|
||||||
|
Copyright (c) 2010-2013 cocos2d-x.org
|
||||||
|
Copyright (c) 2013 Chris Hannon http://www.channon.us
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
*based on the SocketIO library created by LearnBoost at http://socket.io
|
||||||
|
*using spec version 1 found at https://github.com/LearnBoost/socket.io-spec
|
||||||
|
|
||||||
|
Usage is described below, a full working example can be found in TestCpp under ExtionsTest/NetworkTest/SocketIOTest
|
||||||
|
|
||||||
|
creating a new connection to a socket.io server running at localhost:3000
|
||||||
|
|
||||||
|
SIOClient *client = SocketIO::connect(*delegate, "ws://localhost:3000");
|
||||||
|
|
||||||
|
the connection process will begin and if successful delegate::onOpen will be called
|
||||||
|
if the connection process results in an error, delegate::onError will be called with the err msg
|
||||||
|
|
||||||
|
sending a message to the server
|
||||||
|
|
||||||
|
client->send("Hello!");
|
||||||
|
|
||||||
|
emitting an event to be handled by the server, argument json formatting is up to you
|
||||||
|
|
||||||
|
client->emit("eventname", "[{\"arg\":\"value\"}]");
|
||||||
|
|
||||||
|
registering an event callback, target should be a member function in a subclass of SIODelegate
|
||||||
|
CC_CALLBACK_2 is used to wrap the callback with std::bind and store as an SIOEvent
|
||||||
|
|
||||||
|
client->on("eventname", CC_CALLBACK_2(TargetClass::targetfunc, *targetclass_instance));
|
||||||
|
|
||||||
|
event target function should match this pattern, *this pointer will be made available
|
||||||
|
|
||||||
|
void TargetClass::targetfunc(SIOClient *, const std::string&)
|
||||||
|
|
||||||
|
disconnect from the endpoint by calling disconnect(), onClose will be called on the delegate once complete
|
||||||
|
in the onClose method the pointer should be set to NULL or used to connect to a new endpoint
|
||||||
|
|
||||||
|
client->disconnect();
|
||||||
|
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __CC_SOCKETIO_H__
|
||||||
|
#define __CC_SOCKETIO_H__
|
||||||
|
|
||||||
|
#include "ExtensionMacros.h"
|
||||||
|
#include "cocos2d.h"
|
||||||
|
|
||||||
|
NS_CC_EXT_BEGIN
|
||||||
|
|
||||||
|
//forward declarations
|
||||||
|
class SIOClientImpl;
|
||||||
|
class SIOClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Singleton and wrapper class to provide static creation method as well as registry of all sockets
|
||||||
|
*/
|
||||||
|
class SocketIO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SocketIO();
|
||||||
|
virtual ~SocketIO(void);
|
||||||
|
|
||||||
|
static SocketIO *instance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The delegate class to process socket.io events
|
||||||
|
*/
|
||||||
|
class SIODelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~SIODelegate() {}
|
||||||
|
virtual void onConnect(SIOClient* client) = 0;
|
||||||
|
virtual void onMessage(SIOClient* client, const std::string& data) = 0;
|
||||||
|
virtual void onClose(SIOClient* client) = 0;
|
||||||
|
virtual void onError(SIOClient* client, const std::string& data) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Static client creation method, similar to socketio.connect(uri) in JS
|
||||||
|
* @param delegate The delegate which want to receive events from the socket.io client
|
||||||
|
* @param uri The URI of the socket.io server
|
||||||
|
* @return An initialized SIOClient if connected successfully, otherwise NULL
|
||||||
|
*/
|
||||||
|
static SIOClient* connect(SocketIO::SIODelegate& delegate, const std::string& uri);
|
||||||
|
|
||||||
|
SIOClientImpl* getSocket(const std::string& uri);
|
||||||
|
void addSocket(const std::string& uri, SIOClientImpl* socket);
|
||||||
|
void removeSocket(const std::string& uri);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static SocketIO *_inst;
|
||||||
|
|
||||||
|
Dictionary* _sockets;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//c++11 style callbacks entities will be created using CC_CALLBACK (which uses std::bind)
|
||||||
|
typedef std::function<void(SIOClient*, const std::string&)> SIOEvent;
|
||||||
|
//c++11 map to callbacks
|
||||||
|
typedef std::map<std::string, SIOEvent> EventRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A single connection to a socket.io endpoint
|
||||||
|
*/
|
||||||
|
class SIOClient
|
||||||
|
: public Object
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int _port;
|
||||||
|
std::string _host, _path, _tag;
|
||||||
|
bool _connected;
|
||||||
|
SIOClientImpl* _socket;
|
||||||
|
|
||||||
|
SocketIO::SIODelegate* _delegate;
|
||||||
|
|
||||||
|
EventRegistry _eventRegistry;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SIOClient(const std::string& host, int port, const std::string& path, SIOClientImpl* impl, SocketIO::SIODelegate& delegate);
|
||||||
|
virtual ~SIOClient(void);
|
||||||
|
|
||||||
|
SocketIO::SIODelegate* getDelegate() { return _delegate; };
|
||||||
|
|
||||||
|
void onOpen();
|
||||||
|
void onConnect();
|
||||||
|
void receivedDisconnect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnect from the endpoint, onClose will be called on the delegate when comlpete
|
||||||
|
*/
|
||||||
|
void disconnect();
|
||||||
|
/**
|
||||||
|
* @brief Send a message to the socket.io server
|
||||||
|
*/
|
||||||
|
void send(std::string s);
|
||||||
|
/**
|
||||||
|
* @brief The delegate class to process socket.io events
|
||||||
|
*/
|
||||||
|
void emit(std::string eventname, std::string args);
|
||||||
|
/**
|
||||||
|
* @brief Used to resgister a socket.io event callback
|
||||||
|
* Event argument should be passed using CC_CALLBACK2(&Base::function, this)
|
||||||
|
*/
|
||||||
|
void on(const std::string& eventName, SIOEvent e);
|
||||||
|
void fireEvent(const std::string& eventName, const std::string& data);
|
||||||
|
|
||||||
|
inline void setTag(const char* tag)
|
||||||
|
{
|
||||||
|
_tag = tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const char* getTag()
|
||||||
|
{
|
||||||
|
return _tag.c_str();
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_CC_EXT_END
|
||||||
|
|
||||||
|
#endif /* defined(__CC_JSB_SOCKETIO_H__) */
|
|
@ -166,6 +166,7 @@
|
||||||
<ClCompile Include="..\GUI\CCScrollView\CCTableViewCell.cpp" />
|
<ClCompile Include="..\GUI\CCScrollView\CCTableViewCell.cpp" />
|
||||||
<ClCompile Include="..\LocalStorage\LocalStorage.cpp" />
|
<ClCompile Include="..\LocalStorage\LocalStorage.cpp" />
|
||||||
<ClCompile Include="..\network\HttpClient.cpp" />
|
<ClCompile Include="..\network\HttpClient.cpp" />
|
||||||
|
<ClCompile Include="..\network\SocketIO.cpp" />
|
||||||
<ClCompile Include="..\network\Websocket.cpp" />
|
<ClCompile Include="..\network\Websocket.cpp" />
|
||||||
<ClCompile Include="..\physics_nodes\CCPhysicsDebugNode.cpp" />
|
<ClCompile Include="..\physics_nodes\CCPhysicsDebugNode.cpp" />
|
||||||
<ClCompile Include="..\physics_nodes\CCPhysicsSprite.cpp" />
|
<ClCompile Include="..\physics_nodes\CCPhysicsSprite.cpp" />
|
||||||
|
@ -287,6 +288,7 @@
|
||||||
<ClInclude Include="..\network\HttpClient.h" />
|
<ClInclude Include="..\network\HttpClient.h" />
|
||||||
<ClInclude Include="..\network\HttpRequest.h" />
|
<ClInclude Include="..\network\HttpRequest.h" />
|
||||||
<ClInclude Include="..\network\HttpResponse.h" />
|
<ClInclude Include="..\network\HttpResponse.h" />
|
||||||
|
<ClInclude Include="..\network\SocketIO.h" />
|
||||||
<ClInclude Include="..\network\Websocket.h" />
|
<ClInclude Include="..\network\Websocket.h" />
|
||||||
<ClInclude Include="..\physics_nodes\CCPhysicsDebugNode.h" />
|
<ClInclude Include="..\physics_nodes\CCPhysicsDebugNode.h" />
|
||||||
<ClInclude Include="..\physics_nodes\CCPhysicsSprite.h" />
|
<ClInclude Include="..\physics_nodes\CCPhysicsSprite.h" />
|
||||||
|
|
|
@ -354,6 +354,9 @@
|
||||||
<ClCompile Include="..\CCArmature\external_tool\Json\lib_json\json_writer.cpp">
|
<ClCompile Include="..\CCArmature\external_tool\Json\lib_json\json_writer.cpp">
|
||||||
<Filter>CCArmature\external_tool</Filter>
|
<Filter>CCArmature\external_tool</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\network\SocketIO.cpp">
|
||||||
|
<Filter>network</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\GUI\CCScrollView\CCScrollView.h">
|
<ClInclude Include="..\GUI\CCScrollView\CCScrollView.h">
|
||||||
|
@ -712,6 +715,9 @@
|
||||||
<ClInclude Include="..\CCArmature\external_tool\Json\lib_json\writer.h">
|
<ClInclude Include="..\CCArmature\external_tool\Json\lib_json\writer.h">
|
||||||
<Filter>CCArmature\external_tool</Filter>
|
<Filter>CCArmature\external_tool</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\network\SocketIO.h">
|
||||||
|
<Filter>network</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\CCArmature\external_tool\Json\lib_json\json_internalarray.inl">
|
<None Include="..\CCArmature\external_tool\Json\lib_json\json_internalarray.inl">
|
||||||
|
|
|
@ -63,6 +63,7 @@ Classes/ExtensionsTest/ComponentsTest/ProjectileController.cpp \
|
||||||
Classes/ExtensionsTest/ComponentsTest/SceneController.cpp \
|
Classes/ExtensionsTest/ComponentsTest/SceneController.cpp \
|
||||||
Classes/ExtensionsTest/NetworkTest/HttpClientTest.cpp \
|
Classes/ExtensionsTest/NetworkTest/HttpClientTest.cpp \
|
||||||
Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp \
|
Classes/ExtensionsTest/NetworkTest/WebSocketTest.cpp \
|
||||||
|
Classes/ExtensionsTest/NetworkTest/SocketIOTest.cpp \
|
||||||
Classes/ExtensionsTest/EditBoxTest/EditBoxTest.cpp \
|
Classes/ExtensionsTest/EditBoxTest/EditBoxTest.cpp \
|
||||||
Classes/ExtensionsTest/TableViewTest/TableViewTestScene.cpp \
|
Classes/ExtensionsTest/TableViewTest/TableViewTestScene.cpp \
|
||||||
Classes/ExtensionsTest/TableViewTest/CustomTableViewCell.cpp \
|
Classes/ExtensionsTest/TableViewTest/CustomTableViewCell.cpp \
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||||
#include "NetworkTest/WebSocketTest.h"
|
#include "NetworkTest/WebSocketTest.h"
|
||||||
|
#include "NetworkTest/SocketIOTest.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
|
||||||
|
@ -61,6 +62,8 @@ static struct {
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|
||||||
{ "WebSocketTest", [](Object *sender){ runWebSocketTest();}
|
{ "WebSocketTest", [](Object *sender){ runWebSocketTest();}
|
||||||
},
|
},
|
||||||
|
{ "SocketIOTest", [](Object *sender){ runSocketIOTest();}
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
|
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) || (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN)
|
||||||
{ "EditBoxTest", [](Object *sender){ runEditBoxTest();}
|
{ "EditBoxTest", [](Object *sender){ runEditBoxTest();}
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
//
|
||||||
|
// SocketIOTest.cpp
|
||||||
|
// TestCpp
|
||||||
|
//
|
||||||
|
// Created by Chris Hannon on 6/26/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include "SocketIOTest.h"
|
||||||
|
#include "../ExtensionsTest.h"
|
||||||
|
|
||||||
|
USING_NS_CC;
|
||||||
|
USING_NS_CC_EXT;
|
||||||
|
|
||||||
|
SocketIOTestLayer::SocketIOTestLayer(void)
|
||||||
|
: _sioClient(NULL)
|
||||||
|
, _sioEndpoint(NULL)
|
||||||
|
{
|
||||||
|
//set the clients to NULL until we are ready to connect
|
||||||
|
|
||||||
|
Size winSize = Director::sharedDirector()->getWinSize();
|
||||||
|
|
||||||
|
const int MARGIN = 40;
|
||||||
|
const int SPACE = 35;
|
||||||
|
|
||||||
|
LabelTTF *label = LabelTTF::create("SocketIO Extension Test", "Arial", 28);
|
||||||
|
label->setPosition(ccp(winSize.width / 2, winSize.height - MARGIN));
|
||||||
|
addChild(label, 0);
|
||||||
|
|
||||||
|
Menu *menuRequest = Menu::create();
|
||||||
|
menuRequest->setPosition(PointZero);
|
||||||
|
addChild(menuRequest);
|
||||||
|
|
||||||
|
// Test to create basic client in the default namespace
|
||||||
|
LabelTTF *labelSIOClient = LabelTTF::create("Open SocketIO Client", "Arial", 22);
|
||||||
|
MenuItemLabel *itemSIOClient = MenuItemLabel::create(labelSIOClient, CC_CALLBACK_1(SocketIOTestLayer::onMenuSIOClientClicked, this));
|
||||||
|
itemSIOClient->setPosition(ccp(VisibleRect::left().x + labelSIOClient->getContentSize().width / 2 + 5, winSize.height - MARGIN - SPACE));
|
||||||
|
menuRequest->addChild(itemSIOClient);
|
||||||
|
|
||||||
|
// Test to create a client at the endpoint '/testpoint'
|
||||||
|
LabelTTF *labelSIOEndpoint = LabelTTF::create("Open SocketIO Endpoint", "Arial", 22);
|
||||||
|
MenuItemLabel *itemSIOEndpoint = MenuItemLabel::create(labelSIOEndpoint, CC_CALLBACK_1(SocketIOTestLayer::onMenuSIOEndpointClicked, this));
|
||||||
|
itemSIOEndpoint->setPosition(ccp(VisibleRect::right().x - labelSIOEndpoint->getContentSize().width / 2 - 5, winSize.height - MARGIN - SPACE));
|
||||||
|
menuRequest->addChild(itemSIOEndpoint);
|
||||||
|
|
||||||
|
// Test sending message to default namespace
|
||||||
|
LabelTTF *labelTestMessage = LabelTTF::create("Send Test Message", "Arial", 22);
|
||||||
|
MenuItemLabel *itemTestMessage = MenuItemLabel::create(labelTestMessage, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestMessageClicked, this));
|
||||||
|
itemTestMessage->setPosition(ccp(VisibleRect::left().x + labelTestMessage->getContentSize().width / 2 + 5, winSize.height - MARGIN - 2 * SPACE));
|
||||||
|
menuRequest->addChild(itemTestMessage);
|
||||||
|
|
||||||
|
// Test sending message to the endpoint '/testpoint'
|
||||||
|
LabelTTF *labelTestMessageEndpoint = LabelTTF::create("Test Endpoint Message", "Arial", 22);
|
||||||
|
MenuItemLabel *itemTestMessageEndpoint = MenuItemLabel::create(labelTestMessageEndpoint, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestMessageEndpointClicked, this));
|
||||||
|
itemTestMessageEndpoint->setPosition(ccp(VisibleRect::right().x - labelTestMessageEndpoint->getContentSize().width / 2 - 5, winSize.height - MARGIN - 2 * SPACE));
|
||||||
|
menuRequest->addChild(itemTestMessageEndpoint);
|
||||||
|
|
||||||
|
// Test sending event 'echotest' to default namespace
|
||||||
|
LabelTTF *labelTestEvent = LabelTTF::create("Send Test Event", "Arial", 22);
|
||||||
|
MenuItemLabel *itemTestEvent = MenuItemLabel::create(labelTestEvent, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestEventClicked, this));
|
||||||
|
itemTestEvent->setPosition(ccp(VisibleRect::left().x + labelTestEvent->getContentSize().width / 2 + 5, winSize.height - MARGIN - 3 * SPACE));
|
||||||
|
menuRequest->addChild(itemTestEvent);
|
||||||
|
|
||||||
|
// Test sending event 'echotest' to the endpoint '/testpoint'
|
||||||
|
LabelTTF *labelTestEventEndpoint = LabelTTF::create("Test Endpoint Event", "Arial", 22);
|
||||||
|
MenuItemLabel *itemTestEventEndpoint = MenuItemLabel::create(labelTestEventEndpoint, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestEventEndpointClicked, this));
|
||||||
|
itemTestEventEndpoint->setPosition(ccp(VisibleRect::right().x - labelTestEventEndpoint->getContentSize().width / 2 - 5, winSize.height - MARGIN - 3 * SPACE));
|
||||||
|
menuRequest->addChild(itemTestEventEndpoint);
|
||||||
|
|
||||||
|
// Test disconnecting basic client
|
||||||
|
LabelTTF *labelTestClientDisconnect = LabelTTF::create("Disconnect Socket", "Arial", 22);
|
||||||
|
MenuItemLabel *itemClientDisconnect = MenuItemLabel::create(labelTestClientDisconnect, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestClientDisconnectClicked, this));
|
||||||
|
itemClientDisconnect->setPosition(ccp(VisibleRect::left().x + labelTestClientDisconnect->getContentSize().width / 2 + 5, winSize.height - MARGIN - 4 * SPACE));
|
||||||
|
menuRequest->addChild(itemClientDisconnect);
|
||||||
|
|
||||||
|
// Test disconnecting the endpoint '/testpoint'
|
||||||
|
LabelTTF *labelTestEndpointDisconnect = LabelTTF::create("Disconnect Endpoint", "Arial", 22);
|
||||||
|
MenuItemLabel *itemTestEndpointDisconnect = MenuItemLabel::create(labelTestEndpointDisconnect, CC_CALLBACK_1(SocketIOTestLayer::onMenuTestEndpointDisconnectClicked, this));
|
||||||
|
itemTestEndpointDisconnect->setPosition(ccp(VisibleRect::right().x - labelTestEndpointDisconnect->getContentSize().width / 2 - 5, winSize.height - MARGIN - 4 * SPACE));
|
||||||
|
menuRequest->addChild(itemTestEndpointDisconnect);
|
||||||
|
|
||||||
|
// Sahred Status Label
|
||||||
|
_sioClientStatus = LabelTTF::create("Not connected...", "Arial", 14, CCSizeMake(320, 100), kTextAlignmentLeft);
|
||||||
|
_sioClientStatus->setAnchorPoint(ccp(0, 0));
|
||||||
|
_sioClientStatus->setPosition(ccp(VisibleRect::left().x, VisibleRect::rightBottom().y));
|
||||||
|
this->addChild(_sioClientStatus);
|
||||||
|
|
||||||
|
// Back Menu
|
||||||
|
MenuItemFont *itemBack = MenuItemFont::create("Back", CC_CALLBACK_1(SocketIOTestLayer::toExtensionsMainLayer, this));
|
||||||
|
itemBack->setPosition(ccp(VisibleRect::rightBottom().x - 50, VisibleRect::rightBottom().y + 25));
|
||||||
|
Menu *menuBack = Menu::create(itemBack, NULL);
|
||||||
|
menuBack->setPosition(PointZero);
|
||||||
|
addChild(menuBack);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SocketIOTestLayer::~SocketIOTestLayer(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//test event callback handlers, these will be registered with socket.io
|
||||||
|
void SocketIOTestLayer::testevent(SIOClient *client, const std::string& data) {
|
||||||
|
|
||||||
|
CCLog("SocketIOTestLayer::testevent called with data: %s", data.c_str());
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " received event testevent with data: " << data.c_str();
|
||||||
|
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::echotest(SIOClient *client, const std::string& data) {
|
||||||
|
|
||||||
|
CCLog("SocketIOTestLayer::echotest called with data: %s", data.c_str());
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " received event echotest with data: " << data.c_str();
|
||||||
|
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::toExtensionsMainLayer(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
ExtensionsTestScene *pScene = new ExtensionsTestScene();
|
||||||
|
pScene->runThisTest();
|
||||||
|
pScene->release();
|
||||||
|
|
||||||
|
if(_sioEndpoint) _sioEndpoint->disconnect();
|
||||||
|
if(_sioClient) _sioClient->disconnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuSIOClientClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
//create a client by using this static method, url does not need to contain the protocol
|
||||||
|
_sioClient = SocketIO::connect(*this, "ws://channon.us:3000");
|
||||||
|
//you may set a tag for the client for reference in callbacks
|
||||||
|
_sioClient->setTag("Test Client");
|
||||||
|
|
||||||
|
//register event callbacks using the CC_CALLBACK_2() macro and passing the instance of the target class
|
||||||
|
_sioClient->on("testevent", CC_CALLBACK_2(SocketIOTestLayer::testevent, this));
|
||||||
|
_sioClient->on("echotest", CC_CALLBACK_2(SocketIOTestLayer::echotest, this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuSIOEndpointClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
//repeat the same connection steps for the namespace "testpoint"
|
||||||
|
_sioEndpoint = SocketIO::connect(*this, "ws://channon.us:3000/testpoint");
|
||||||
|
//a tag to differentiate in shared callbacks
|
||||||
|
_sioEndpoint->setTag("Test Endpoint");
|
||||||
|
|
||||||
|
//demonstrating how callbacks can be shared within a delegate
|
||||||
|
_sioEndpoint->on("testevent", CC_CALLBACK_2(SocketIOTestLayer::testevent, this));
|
||||||
|
_sioEndpoint->on("echotest", CC_CALLBACK_2(SocketIOTestLayer::echotest, this));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestMessageClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
//check that the socket is != NULL before sending or emitting events
|
||||||
|
//the client should be NULL either before initialization and connection or after disconnect
|
||||||
|
if(_sioClient != NULL) _sioClient->send("Hello Socket.IO!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestMessageEndpointClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_sioEndpoint != NULL) _sioEndpoint->send("Hello Socket.IO!");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestEventClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
//check that the socket is != NULL before sending or emitting events
|
||||||
|
//the client should be NULL either before initialization and connection or after disconnect
|
||||||
|
if(_sioClient != NULL) _sioClient->emit("echotest","[{\"name\":\"myname\",\"type\":\"mytype\"}]");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestEventEndpointClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_sioEndpoint != NULL) _sioEndpoint->emit("echotest","[{\"name\":\"myname\",\"type\":\"mytype\"}]");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestClientDisconnectClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_sioClient != NULL) _sioClient->disconnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMenuTestEndpointDisconnectClicked(cocos2d::Object *sender)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(_sioEndpoint != NULL) _sioEndpoint->disconnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delegate methods
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onConnect(cocos2d::extension::SIOClient* client)
|
||||||
|
{
|
||||||
|
CCLog("SocketIOTestLayer::onConnect called");
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " connected!";
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onMessage(cocos2d::extension::SIOClient* client, const std::string& data)
|
||||||
|
{
|
||||||
|
CCLog("SocketIOTestLayer::onMessage received: %s", data.c_str());
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " received message with content: " << data.c_str();
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onClose(cocos2d::extension::SIOClient* client)
|
||||||
|
{
|
||||||
|
CCLog("SocketIOTestLayer::onClose called");
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " closed!";
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
|
||||||
|
//set the local pointer to NULL or connect to another client
|
||||||
|
//the client object will be released on its own after this method completes
|
||||||
|
if(client == _sioClient) {
|
||||||
|
|
||||||
|
_sioClient = NULL;
|
||||||
|
} else if(client == _sioEndpoint) {
|
||||||
|
|
||||||
|
_sioEndpoint = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketIOTestLayer::onError(cocos2d::extension::SIOClient* client, const std::string& data)
|
||||||
|
{
|
||||||
|
CCLog("SocketIOTestLayer::onError received: %s", data.c_str());
|
||||||
|
|
||||||
|
std::stringstream s;
|
||||||
|
s << client->getTag() << " received error with content: " << data.c_str();
|
||||||
|
_sioClientStatus->setString(s.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void runSocketIOTest()
|
||||||
|
{
|
||||||
|
Scene *pScene = Scene::create();
|
||||||
|
SocketIOTestLayer *pLayer = new SocketIOTestLayer();
|
||||||
|
pScene->addChild(pLayer);
|
||||||
|
|
||||||
|
Director::sharedDirector()->replaceScene(pScene);
|
||||||
|
pLayer->release();
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// SocketIOTest.h
|
||||||
|
// TestCpp
|
||||||
|
//
|
||||||
|
// Created by Chris Hannon on 6/26/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
#ifndef __TestCpp__SocketIOTest__
|
||||||
|
#define __TestCpp__SocketIOTest__
|
||||||
|
|
||||||
|
#include "cocos2d.h"
|
||||||
|
#include "cocos-ext.h"
|
||||||
|
#include "network/SocketIO.h"
|
||||||
|
|
||||||
|
class SocketIOTestLayer
|
||||||
|
: public cocos2d::Layer
|
||||||
|
, public cocos2d::extension::SocketIO::SIODelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SocketIOTestLayer(void);
|
||||||
|
virtual ~SocketIOTestLayer(void);
|
||||||
|
|
||||||
|
virtual void onConnect(cocos2d::extension::SIOClient* client);
|
||||||
|
virtual void onMessage(cocos2d::extension::SIOClient* client, const std::string& data);
|
||||||
|
virtual void onClose(cocos2d::extension::SIOClient* client);
|
||||||
|
virtual void onError(cocos2d::extension::SIOClient* client, const std::string& data);
|
||||||
|
|
||||||
|
void toExtensionsMainLayer(cocos2d::Object *sender);
|
||||||
|
|
||||||
|
void onMenuSIOClientClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestMessageClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestEventClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestClientDisconnectClicked(cocos2d::Object *sender);
|
||||||
|
|
||||||
|
void onMenuSIOEndpointClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestMessageEndpointClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestEventEndpointClicked(cocos2d::Object *sender);
|
||||||
|
void onMenuTestEndpointDisconnectClicked(cocos2d::Object *sender);
|
||||||
|
|
||||||
|
|
||||||
|
void testevent(cocos2d::extension::SIOClient *client, const std::string& data);
|
||||||
|
void echotest(cocos2d::extension::SIOClient *client, const std::string& data);
|
||||||
|
|
||||||
|
cocos2d::extension::SIOClient *_sioClient, *_sioEndpoint;
|
||||||
|
|
||||||
|
cocos2d::LabelTTF *_sioClientStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
void runSocketIOTest();
|
||||||
|
|
||||||
|
#endif /* defined(__TestCpp__SocketIOTest__) */
|
|
@ -150,6 +150,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(O
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.cpp" />
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.cpp" />
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.cpp" />
|
||||||
|
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\SocketIOTest.cpp" />
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.cpp" />
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.cpp" />
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.cpp" />
|
<ClCompile Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.cpp" />
|
||||||
|
@ -258,6 +259,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\..\external\libwebsockets\win32\lib\*.*" "$(O
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\ControlExtensionTest\CCControlStepperTest\CCControlStepperTest.h" />
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\EditBoxTest\EditBoxTest.h" />
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\HttpClientTest.h" />
|
||||||
|
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\SocketIOTest.h" />
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\WebSocketTest.h" />
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.h" />
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.h" />
|
<ClInclude Include="..\Classes\ExtensionsTest\TableViewTest\CustomTableViewCell.h" />
|
||||||
|
|
|
@ -549,6 +549,9 @@
|
||||||
<ClCompile Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.cpp">
|
<ClCompile Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.cpp">
|
||||||
<Filter>Classes\ExtensionsTest\Scale9SpriteTest</Filter>
|
<Filter>Classes\ExtensionsTest\Scale9SpriteTest</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\Classes\ExtensionsTest\NetworkTest\SocketIOTest.cpp">
|
||||||
|
<Filter>Classes\ExtensionsTest\NetworkTest</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="main.h">
|
<ClInclude Include="main.h">
|
||||||
|
@ -1043,5 +1046,8 @@
|
||||||
<ClInclude Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.h">
|
<ClInclude Include="..\Classes\ExtensionsTest\Scale9SpriteTest\Scale9SpriteTest.h">
|
||||||
<Filter>Classes\ExtensionsTest\Scale9SpriteTest</Filter>
|
<Filter>Classes\ExtensionsTest\Scale9SpriteTest</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\Classes\ExtensionsTest\NetworkTest\SocketIOTest.h">
|
||||||
|
<Filter>Classes\ExtensionsTest\NetworkTest</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue