iup-stack/iup/srctuio/iup_tuio.cpp

463 lines
11 KiB
C++
Raw Normal View History

2023-02-20 16:44:45 +00:00
/** \file
* \brief IupTuioClient control
*
* See Copyright Notice in "iup.h"
*/
#include "TuioListener.h"
#include "TuioClient.h"
#include "iup.h"
#include "iuptuio.h"
#include "iupcbs.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "iup_object.h"
#include "iup_assert.h"
#include "iup_str.h"
#include "iup_register.h"
#include "iup_drv.h"
#include "iup_drvinfo.h"
using namespace TUIO;
struct iTuioCursorEnvent{
int id;
float x, y;
char state;
iTuioCursorEnvent(int _id, float _x, float _y, char _state);
};
iTuioCursorEnvent::iTuioCursorEnvent(int _id, float _x, float _y, char _state)
:id(_id), x(_x), y(_y), state(_state)
{
}
class IupTuioListener : public TuioListener
{
int changed, locked;
TuioClient* client;
Ihandle* ih;
std::list<iTuioCursorEnvent> cursor_events;
void processCursor(TuioCursor *tcur, const char* state, const char* action);
void initCursorInfo(std::list<TuioCursor*> &cursorList, int cursor_count, int* pid, int* pstate);
void finishCursorInfo(std::list<TuioCursor*> &cursorList, int cursor_count, int* px, int* py, int* pstate, int w, int h, int use_client_coord, Ihandle* ih_canvas);
void updateCursorInfo(int *cursor_count, int* pid, int* px, int* py, int* pstate, int id, int x, int y, int state);
int GetMainCursor(std::list<TuioCursor*> &cursorList);
static int timer_action_cb(Ihandle *timer);
public:
int debug;
Ihandle* timer;
IupTuioListener(Ihandle* _ih, TuioClient* _client);
void addTuioObject(TuioObject *tobj);
void updateTuioObject(TuioObject *tobj);
void removeTuioObject(TuioObject *tobj);
void addTuioCursor(TuioCursor *tcur);
void updateTuioCursor(TuioCursor *tcur);
void removeTuioCursor(TuioCursor *tcur);
void addTuioBlob(TuioBlob *tblb);
void updateTuioBlob(TuioBlob *tblb);
void removeTuioBlob(TuioBlob *tblb);
void refresh(TuioTime frameTime);
};
IupTuioListener::IupTuioListener(Ihandle* _ih, TuioClient* _client)
:changed(0), locked(0), client(_client), ih(_ih), debug(0)
{
timer = IupTimer();
IupSetAttribute(timer, "TIME", "50");
IupSetAttribute(timer, "_IUP_TUIOLISTENER", (char*)this);
IupSetCallback(timer, "ACTION_CB", timer_action_cb);
}
void IupTuioListener::addTuioObject(TuioObject*)
{
/* unused */
}
void IupTuioListener::updateTuioObject(TuioObject*)
{
/* unused */
}
void IupTuioListener::removeTuioObject(TuioObject*)
{
/* unused */
}
void IupTuioListener::addTuioBlob(TuioBlob*)
{
/* unused */
}
void IupTuioListener::updateTuioBlob(TuioBlob*)
{
/* unused */
}
void IupTuioListener::removeTuioBlob(TuioBlob*)
{
/* unused */
}
void IupTuioListener::addTuioCursor(TuioCursor *tcur)
{
IupTuioListener::processCursor(tcur, "DOWN", "AddCursor");
}
void IupTuioListener::updateTuioCursor(TuioCursor *tcur)
{
IupTuioListener::processCursor(tcur, "MOVE", "UpdateCursor");
}
void IupTuioListener::removeTuioCursor(TuioCursor *tcur)
{
IupTuioListener::processCursor(tcur, "UP", "RemoveCursor");
}
void IupTuioListener::processCursor(TuioCursor *tcur, const char* state, const char* action)
{
float x = tcur->getX();
float y = tcur->getY();
int id = (int)tcur->getSessionID();
cursor_events.push_back(iTuioCursorEnvent(id, x, y, state[0]));
this->changed = 1;
if (this->debug)
printf("IupTuioClient-%s(id=%d sid=%d x=%d y=%d)\n", action, tcur->getCursorID(), (int)tcur->getSessionID(), (int)tcur->getX(), (int)tcur->getY());
}
void IupTuioListener::refresh(TuioTime frameTime)
{
if (this->changed)
{
Ihandle* ih_canvas = IupGetAttributeHandle(this->ih, "TARGETCANVAS");
if (!ih_canvas)
ih_canvas = this->ih;
this->changed = 0;
IFniiis cb = (IFniiis)IupGetCallback(ih_canvas, "TOUCH_CB");
IFniIIII mcb = (IFniIIII)IupGetCallback(ih_canvas, "MULTITOUCH_CB");
if (cb || mcb)
{
this->client->lockCursorList();
this->locked = 1;
}
if (this->debug)
printf("IupTuioClient-RefreshChanged(time=%d)\n", (int)frameTime.getTotalMilliseconds());
}
}
void IupTuioListener::initCursorInfo(std::list<TuioCursor*> &cursorList, int cursor_count, int* pid, int* pstate)
{
std::list <TuioCursor*>::iterator iter;
int i;
for (i = 0, iter = cursorList.begin() ; i<cursor_count; iter++, i++)
{
TuioCursor* tcur = (*iter);
pid[i] = (int)tcur->getSessionID();
pstate[i] = 0; /* mark to be updated later */
}
}
int IupTuioListener::GetMainCursor(std::list<TuioCursor*> &cursorList)
{
std::list <TuioCursor*>::iterator iter;
std::list <TuioCursor*>::iterator end = cursorList.end();
int min_id = -1;
for (iter = cursorList.begin(); iter!=end; iter++)
{
TuioCursor* tcur = (*iter);
int id = (int)tcur->getSessionID();
if (min_id == -1 || id < min_id)
min_id = id;
}
return min_id;
}
void IupTuioListener::finishCursorInfo(std::list<TuioCursor*> &cursorList, int cursor_count, int* px, int* py, int* pstate, int w, int h, int use_client_coord, Ihandle* ih_canvas)
{
std::list <TuioCursor*>::iterator iter;
std::list <TuioCursor*>::iterator end = cursorList.end();
int i;
for (i = 0, iter = cursorList.begin(); i<cursor_count && iter!=end; iter++, i++)
{
if (pstate[i] == 0) /* if still 0, then it was not updated, must fill it here */
{
TuioCursor* tcur = (*iter);
int x = tcur->getScreenX(w);
int y = tcur->getScreenY(h);
if (use_client_coord)
iupdrvScreenToClient(ih_canvas, &x, &y);
px[i] = x;
py[i] = y;
pstate[i] = 'M'; /* mark as MOVE */
}
}
}
void IupTuioListener::updateCursorInfo(int *cursor_count, int* pid, int* px, int* py, int* pstate, int id, int x, int y, int state)
{
int i;
for(i = 0; i < *cursor_count; i++)
{
if (pid[i] == id)
{
px[i] = x;
py[i] = y;
pstate[i] = state;
return;
}
}
if (state == 'U') /* UP - not in the cursorList, add it */
{
pid[i] = id;
px[i] = x;
py[i] = y;
pstate[i] = state;
(*cursor_count)++;
}
}
int IupTuioListener::timer_action_cb(Ihandle *timer)
{
IupTuioListener* listener = reinterpret_cast<IupTuioListener*>(IupGetAttribute(timer, "_IUP_TUIOLISTENER"));
if (!listener->locked)
return IUP_DEFAULT;
std::list<TuioCursor*> cursorList = listener->client->getTuioCursors();
int events_count = (int)listener->cursor_events.size();
int cursor_count = (int)cursorList.size();
int total_count = events_count+cursor_count;
if (!total_count)
{
listener->locked = 0;
listener->client->unlockCursorList();
return IUP_DEFAULT;
}
int use_client_coord = 0;
Ihandle* ih_canvas = IupGetAttributeHandle(listener->ih, "TARGETCANVAS");
if (ih_canvas)
use_client_coord = 1;
else
ih_canvas = listener->ih;
IFniiis cb = (IFniiis)IupGetCallback(ih_canvas, "TOUCH_CB");
IFniIIII mcb = (IFniIIII)IupGetCallback(ih_canvas, "MULTITOUCH_CB");
int w, h, x, y;
iupdrvGetFullSize(&w, &h);
int *px=NULL, *py=NULL, *pid=NULL, *pstate=NULL;
if (mcb)
{
px = new int[total_count];
py = new int[total_count];
pid = new int[total_count];
pstate = new int[total_count];
listener->initCursorInfo(cursorList, cursor_count, pid, pstate);
}
int min_id = -1;
if (cb)
min_id = listener->GetMainCursor(cursorList);
for (int i = 0; i<events_count; i++)
{
const iTuioCursorEnvent& evt = listener->cursor_events.front();
const char* state = (evt.state=='D')? "DOWN": ((evt.state=='U')? "UP": "MOVE");
x = (int)floor(evt.x*w+0.5f);
y = (int)floor(evt.y*h+0.5f);
if (use_client_coord)
iupdrvScreenToClient(ih_canvas, &x, &y);
if (cb)
{
if (min_id == evt.id)
state = (evt.state=='D')? "DOWN-PRIMARY": ((evt.state=='U')? "UP-PRIMARY": "MOVE-PRIMARY");
if (cb(ih_canvas, evt.id, x, y, (char*)state)==IUP_CLOSE)
IupExitLoop();
}
if (mcb)
listener->updateCursorInfo(&cursor_count, pid, px, py, pstate, evt.id, x, y, state[0]);
listener->cursor_events.pop_front();
}
if (mcb)
{
listener->finishCursorInfo(cursorList, cursor_count, px, py, pstate, w, h, use_client_coord, ih_canvas);
if (mcb(ih_canvas, cursor_count, pid, px, py, pstate)==IUP_CLOSE)
IupExitLoop();
delete[] px;
delete[] py;
delete[] pid;
delete[] pstate;
}
listener->locked = 0;
listener->client->unlockCursorList();
return IUP_DEFAULT;
}
/**************************************************************************************/
struct _IcontrolData
{
IupTuioListener* listener;
TuioClient* client;
};
static int iTuioSetConnectAttrib(Ihandle* ih, const char* value)
{
if (ih->data->client->isConnected())
{
IupSetAttribute(ih->data->listener->timer, "RUN", "NO");
ih->data->client->disconnect();
}
if (iupStrEqualNoCase(value, "YES"))
{
ih->data->client->connect(false);
IupSetAttribute(ih->data->listener->timer, "RUN", "YES");
}
else if (iupStrEqualNoCase(value, "LOCKED"))
{
ih->data->client->connect(true);
IupSetAttribute(ih->data->listener->timer, "RUN", "YES");
}
return 0;
}
static char* iTuioGetConnectAttrib(Ihandle *ih)
{
if (ih->data->client->isConnected())
return (char*)"Yes";
else
return (char*)"No";
}
static int iTuioSetDebugAttrib(Ihandle* ih, const char* value)
{
ih->data->listener->debug = iupStrBoolean(value);
return 0;
}
static char* iTuioGetDebugAttrib(Ihandle *ih)
{
if (ih->data->listener->debug)
return (char*)"Yes";
else
return (char*)"No";
}
static int iTuioCreateMethod(Ihandle* ih, void** params)
{
int port = 3333;
if (params && params[0])
#if defined (WIN32) && defined (_M_X64)
port = (int)(long long)(params[0]);
#else
port = (int)(long)(params[0]); /* must cast to long first to avoid 64bit C++ compiler error */
#endif
ih->data = iupALLOCCTRLDATA();
ih->data->client = new TuioClient(port);
ih->data->listener = new IupTuioListener(ih, ih->data->client);
ih->data->client->addTuioListener(ih->data->listener);
return IUP_NOERROR;
}
static void iTuioDestroyMethod(Ihandle* ih)
{
IupDestroy(ih->data->listener->timer);
delete ih->data->client;
delete ih->data->listener;
}
Ihandle* IupTuioClient(int port)
{
void *params[2];
params[0] = (void*)port;
params[1] = NULL;
return IupCreatev("tuioclient", params);
}
static Iclass* iTuioNewClass(void)
{
Iclass* ic = iupClassNew(NULL);
ic->name = (char*)"tuioclient";
ic->cons = (char*)"TuioClient";
ic->format = (char*)"i"; /* (int) */
ic->nativetype = IUP_TYPEVOID;
ic->childtype = IUP_CHILDNONE;
ic->is_interactive = 0;
ic->New = iTuioNewClass;
ic->Create = iTuioCreateMethod;
ic->Destroy = iTuioDestroyMethod;
/* Base Callbacks */
iupBaseRegisterBaseCallbacks(ic);
iupClassRegisterCallback(ic, "TOUCH_CB", "iiis");
iupClassRegisterCallback(ic, "MULTITOUCH_CB", "iIIII");
iupClassRegisterAttribute(ic, "CONNECT", iTuioGetConnectAttrib, iTuioSetConnectAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
iupClassRegisterAttribute(ic, "DEBUG", iTuioGetDebugAttrib, iTuioSetDebugAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
return ic;
}
int IupTuioOpen(void)
{
if (!IupIsOpened())
return IUP_ERROR;
if (IupGetGlobal("_IUP_TUIO_OPEN"))
return IUP_OPENED;
iupRegisterClass(iTuioNewClass());
IupSetGlobal("_IUP_TUIO_OPEN", "1");
return IUP_NOERROR;
}