00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #if defined(_MSC_VER)
00030 #include <winsock2.h>
00031 #else
00032 #include <stdio.h>
00033 #include <arpa/inet.h>
00034 #include <fcntl.h>
00035 #include <sys/types.h>
00036 #include <unistd.h>
00037 #include <sys/socket.h>
00038 #include <time.h>
00039 #include <netinet/in.h>
00040 #endif
00041
00042 #include "MobileInterface.h"
00043 #include "DisplayDevice.h"
00044 #include "TextEvent.h"
00045 #include "CommandQueue.h"
00046 #include "Inform.h"
00047 #include "PickList.h"
00048 #include "Animation.h"
00049 #include "VMDApp.h"
00050 #include "math.h"
00051 #include "stdlib.h"
00052
00053
00054
00055 #define CURRENTAPIVERSION 9
00056
00057
00058 #define PACKET_ORIENT 1 // device orientation (gyro, accel, etc)
00059 #define PACKET_TOUCH 2 // touchpad events (up, down, move, etc)
00060 #define PACKET_HEARTBEAT 3 // heartbeat.. likely every second
00061 #define PACKET_CONNECT 4 // information about new connection
00062 #define PACKET_DISCONNECT 5 // notice that a device has disconnected
00063 #define PACKET_BUTTON 6 // button state has changed.
00064
00065
00066 #define EVENT_NON_TOUCH -1
00067 #define EVENT_TOUCH_DOWN 0
00068 #define EVENT_TOUCH_UP 1
00069 #define EVENT_TOUCH_MOVE 2
00070 #define EVENT_TOUCH_SOMEUP 5
00071 #define EVENT_TOUCH_SOMEDOWN 6
00072 #define EVENT_COMMAND 7
00073
00074
00075 #define SEND_HEARTBEAT 0
00076 #define SEND_ADDCLIENT 1
00077 #define SEND_REMOVECLIENT 2
00078 #define SEND_SETACTIVECLIENT 3
00079 #define SEND_SETMODE 4
00080 #define SEND_MESSAGE 5
00081
00082
00083
00084
00085 static void swap4_aligned(void *v, long ndata) {
00086 int *data = (int *) v;
00087 long i;
00088 int *N;
00089 for (i=0; i<ndata; i++) {
00090 N = data + i;
00091 *N=(((*N>>24)&0xff) | ((*N&0xff)<<24) |
00092 ((*N>>8)&0xff00) | ((*N&0xff00)<<8));
00093 }
00094 }
00095
00096
00097 void Mobile::prepareSendBuffer(const int eventType)
00098 {
00099 memset(statusSendBuffer, 0, sizeof(statusSendBuffer));
00100 int caretLoc = 0;
00101 *(statusSendBuffer + caretLoc) = 1;
00102 caretLoc += sizeof(int);
00103 *(statusSendBuffer + caretLoc) = CURRENTAPIVERSION;
00104 caretLoc += sizeof(int);
00105
00106
00107 *(statusSendBuffer + caretLoc) = moveMode;
00108 caretLoc += sizeof(int);
00109
00110
00111 *(statusSendBuffer + caretLoc) = eventType;
00112 caretLoc += sizeof(int);
00113
00114
00115
00116 caretLoc += 4;
00117
00118 *(statusSendBuffer + caretLoc) = clientNick.num();
00119 caretLoc += sizeof(int);
00120
00121
00122
00123 for (int i=0; i<clientNick.num();i++)
00124 {
00125 int strLength = strlen((const char *)(*(clientNick)[i]));
00126 *(statusSendBuffer + caretLoc) = strLength;
00127 caretLoc += sizeof(int);
00128
00129 memcpy((statusSendBuffer + caretLoc), (const char *)(*(clientNick)[i]), strLength);
00130 caretLoc += strLength;
00131
00132
00133 *(statusSendBuffer + caretLoc) = (clientActive[i] ? 1 : 0);
00134 caretLoc += sizeof(int);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144 statusSendBufferLength = caretLoc;
00145 }
00146
00147
00148
00149
00150 typedef struct {
00151
00152 char buffer[1024];
00153 struct sockaddr_in sockaddr;
00154 #if defined(_MSC_VER)
00155 SOCKET sockfd;
00156 #else
00157 int sockfd;
00158 #endif
00159 int fromlen;
00160
00161
00162 int seqnum;
00163 int buttons;
00164 float rx;
00165 float ry;
00166 float rz;
00167 float tx;
00168 float ty;
00169 float tz;
00170 int padaction;
00171 int touchcnt;
00172 int upid;
00173 int touchid[16];
00174 float padx[16];
00175 float pady[16];
00176 float rotmatrix[9];
00177 } mobilehandle;
00178
00179
00180
00181 static void * mobile_listener_create(int port) {
00182 mobilehandle *ph = (mobilehandle *) calloc(1, sizeof(mobilehandle));
00183 if (ph == NULL)
00184 return NULL;
00185
00186 #if defined(_MSC_VER)
00187
00188 WSADATA wsaData;
00189 if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR)
00190 return NULL;
00191 #endif
00192
00193 if ((ph->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00194 perror("socket: ");
00195 free(ph);
00196 return NULL;
00197 }
00198
00199
00200 #if defined(_MSC_VER)
00201 u_long nonblock = 1;
00202 ioctlsocket(ph->sockfd, FIONBIO, &nonblock);
00203 #else
00204 int sockflags;
00205 sockflags = fcntl(ph->sockfd, F_GETFL, 0);
00206 fcntl(ph->sockfd, F_SETFL, sockflags | O_NONBLOCK);
00207 #endif
00208
00209 memset(&ph->sockaddr, 0, sizeof(ph->sockaddr));
00210 ph->sockaddr.sin_family = AF_INET;
00211 ph->sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
00212 ph->sockaddr.sin_port = htons(port);
00213
00214 if (bind(ph->sockfd, (struct sockaddr *)&ph->sockaddr, sizeof(sockaddr)) < 0) {
00215 perror("bind: ");
00216 free(ph);
00217 return NULL;
00218 }
00219
00220 return ph;
00221 }
00222
00223
00224 static int mobile_listener_poll(void *voidhandle,
00225 float &tx, float &ty, float &tz,
00226 float &rx, float &ry, float &rz,
00227 int &padaction, int &upid,
00228 int &touchcnt, int *touchid,
00229 float *padx, float *pady,
00230 int &buttons, int &packtype, JString &incomingIP,
00231 JString ¤tNick, int &listenerPort,
00232 float &tranScal, float &rotScal, float &zoomScal,
00233 JString &commandToSend) {
00234 mobilehandle *ph = (mobilehandle *) voidhandle;
00235
00236 int offset = 0;
00237
00238 memset(ph->buffer, 0, sizeof(ph->buffer));
00239 #if defined(_MSC_VER)
00240 int fromlen=sizeof(ph->sockaddr);
00241 #else
00242 socklen_t fromlen=sizeof(ph->sockaddr);
00243 #endif
00244 int packlen=0;
00245
00246 packlen=recvfrom(ph->sockfd, ph->buffer, sizeof(ph->buffer), 0, (struct sockaddr *)&ph->sockaddr, &fromlen);
00247
00248 if (packlen < 1) {
00249 return 0;
00250 }
00251
00252
00253 if (((int*)ph->buffer)[0] != 1) {
00254 swap4_aligned(ph->buffer, sizeof(ph->buffer) / 4);
00255 }
00256 if (((int*)ph->buffer)[0] != 1) {
00257 printf("Received unrecognized mobile packet...\n");
00258 return 0;
00259 }
00260
00261 int endianism = ((int*)ph->buffer)[offset++];
00262 int apiversion = ((int*)ph->buffer)[offset++];
00263
00264
00265
00266 if (endianism != 1 || (apiversion < 7 || apiversion > CURRENTAPIVERSION)) {
00267 msgWarn << "Dropped incoming mobile input packet from "
00268 << inet_ntoa((ph->sockaddr).sin_addr)
00269 << ", version: " << apiversion << sendmsg;
00270 return 0;
00271 }
00272
00273
00274 char nickName[17];
00275 memcpy(nickName, ph->buffer+(offset*sizeof(int)), 16);
00276 nickName[16] = 0;
00277 currentNick = nickName;
00278
00279 offset += 4;
00280
00281 if (apiversion >= 9) {
00282 listenerPort = ((int*)ph->buffer)[offset++];
00283 rotScal = ((float*)ph->buffer)[offset++];
00284 zoomScal = ((float*)ph->buffer)[offset++];
00285 tranScal = ((float*)ph->buffer)[offset++];
00286 } else {
00287 listenerPort = 4141;
00288 }
00289
00290 packtype = ((int*)ph->buffer)[offset++];
00291
00292 ph->buttons = ((int*)ph->buffer)[offset++];
00293 ph->seqnum = ((int*)ph->buffer)[offset++];
00294
00295
00296 buttons = ph->buttons;
00297 incomingIP = inet_ntoa((ph->sockaddr).sin_addr);
00298
00299
00300
00301 if (packtype == EVENT_COMMAND) {
00302
00303
00304
00305
00306
00307 int msgSize = ((int*)ph->buffer)[offset++];
00308
00309
00310
00311 if (msgSize > 0) {
00312 char *tmpmsg = new char[msgSize+1];
00313 memcpy(tmpmsg, ph->buffer+(offset*sizeof(int)), msgSize);
00314 tmpmsg[msgSize] = 0;
00315
00316 commandToSend = tmpmsg;
00317 delete tmpmsg;
00318 } else {
00319 commandToSend = "";
00320 }
00321
00322 return 1;
00323 }
00324
00325
00326 padaction = EVENT_NON_TOUCH;
00327
00328
00329
00330
00331
00332
00333
00334
00335 ph->rx = 0;
00336 ph->ry = 0;
00337 ph->rz = 0;
00338 ph->tx = 0;
00339 ph->ty = 0;
00340 ph->tz = 0;
00341 ph->padaction = EVENT_NON_TOUCH;
00342 ph->upid = 0;
00343 memset(ph->touchid, 0, sizeof(ph->touchid));
00344 memset(ph->padx, 0, sizeof(ph->padx));
00345 memset(ph->pady, 0, sizeof(ph->pady));
00346 memset(ph->rotmatrix, 0, sizeof(9*sizeof(float)));
00347
00348
00349 int i;
00350
00351 switch (packtype) {
00352 case PACKET_ORIENT:
00353
00354
00355
00356
00357
00358
00359
00360 ph->rz = ((float*)ph->buffer)[offset ];
00361 ph->rx = ((float*)ph->buffer)[offset+1];
00362 ph->ry = ((float*)ph->buffer)[offset+2];
00363 ph->tx = ((float*)ph->buffer)[offset+3];
00364 ph->ty = ((float*)ph->buffer)[offset+4];
00365 ph->tz = ((float*)ph->buffer)[offset+5];
00366
00367
00368 for (i=0; i<9; i++)
00369 ph->rotmatrix[i] = ((float*)ph->buffer)[offset+6+i];
00370 break;
00371
00372 case PACKET_TOUCH: case PACKET_HEARTBEAT:
00373 float xdpi = ((float*)ph->buffer)[offset];
00374 float ydpi = ((float*)ph->buffer)[offset+1];
00375
00376
00377 float xinvdpi = 1.0f / xdpi;
00378 float yinvdpi = 1.0f / ydpi;
00379
00380
00381
00382
00383 ph->padaction = ((int*) ph->buffer)[offset+4];
00384 ph->upid = ((int*) ph->buffer)[offset+5];
00385
00386 if (ph->padaction == 1) {
00387 ph->touchcnt = touchcnt = 0;
00388 } else {
00389 ph->touchcnt = ((int*) ph->buffer)[offset+6];
00390 touchcnt = ph->touchcnt;
00391
00392 for (int i=0; i<ph->touchcnt; i++) {
00393 float px, py;
00394 int ptrid;
00395 ptrid = ((int*) ph->buffer)[offset+7+3*i];
00396 px = ((float*) ph->buffer)[offset+8+3*i];
00397 py = ((float*) ph->buffer)[offset+9+3*i];
00398
00399
00400
00401
00402 ph->padx[i] = px * xinvdpi;
00403 ph->pady[i] = py * yinvdpi;
00404 }
00405 }
00406
00407
00408 break;
00409 }
00410
00411
00412 if (packtype == PACKET_ORIENT) {
00413 rx = -ph->rx;
00414 ry = -(ph->rz-180);
00415 rz = ph->ry;
00416 tx = 0.0;
00417 ty = 0.0;
00418 tz = 0.0;
00419 }
00420
00421 if (packtype == PACKET_TOUCH) {
00422 padaction = ph->padaction;
00423 upid = ph->upid;
00424
00425 for (int i=0; i<ph->touchcnt; i++) {
00426 padx[i] = ph->padx[i];
00427 pady[i] = ph->pady[i];
00428 }
00429 }
00430
00431 #if 1
00432
00433
00434 float t_null_region = 0.01f;
00435 float r_null_region = 10.0f;
00436 float atx = fabsf(tx);
00437 float aty = fabsf(ty);
00438 float atz = fabsf(tz);
00439 float arx = fabsf(rx);
00440 float ary = fabsf(ry);
00441 float arz = fabsf(rz);
00442
00443
00444 if (atx > t_null_region) {
00445 tx = ((tx > 0) ? (tx - t_null_region) : (tx + t_null_region));
00446 } else {
00447 tx = 0;
00448 }
00449 if (aty > t_null_region) {
00450 ty = ((ty > 0) ? (ty - t_null_region) : (ty + t_null_region));
00451 } else {
00452 ty = 0;
00453 }
00454 if (atz > t_null_region) {
00455 tz = ((tz > 0) ? (tz - t_null_region) : (tz + t_null_region));
00456 } else {
00457 tz = 0;
00458 }
00459 if (arx > r_null_region) {
00460 rx = ((rx > 0) ? (rx - r_null_region) : (rx + r_null_region));
00461 } else {
00462 rx = 0;
00463 }
00464 if (ary > r_null_region) {
00465 ry = ((ry > 0) ? (ry - r_null_region) : (ry + r_null_region));
00466 } else {
00467 ry = 0;
00468 }
00469 if (arz > r_null_region) {
00470 rz = ((rz > 0) ? (rz - r_null_region) : (rz + r_null_region));
00471 } else {
00472 rz = 0;
00473 }
00474 #endif
00475
00476 return 1;
00477 }
00478
00479
00480
00481 static int mobile_listener_destroy(void *voidhandle) {
00482 mobilehandle *ph = (mobilehandle *) voidhandle;
00483
00484 #if defined(_MSC_VER)
00485 closesocket(ph->sockfd);
00486 #else
00487 close(ph->sockfd);
00488 #endif
00489 free(ph);
00490
00491
00492
00493
00494
00495 return 0;
00496 }
00497
00498
00499
00500
00501 Mobile::Mobile(VMDApp *vmdapp)
00502 : UIObject(vmdapp) {
00503 mobile = NULL;
00504 port = 3141;
00505
00506 packtimer = wkf_timer_create();
00507 wkf_timer_start(packtimer);
00508
00509 statustimer = wkf_timer_create();
00510 wkf_timer_start(statustimer);
00511
00512
00513 statusSendSeconds = 5.0f;
00514
00515 touchinprogress = 0;
00516 touchcount = 0;
00517 touchmode = ROTATE;
00518 touchscale = 1.0;
00519 touchscalestartdist = 0;
00520 touchrotstartangle = 0;
00521 touchdeltaX = 0;
00522 touchdeltaY = 0;
00523 buttonDown = 0;
00524
00525 tranScaling = 1.0;
00526 rotScaling = 1.0;
00527 zoomScaling = 1.0;
00528
00529 reset();
00530 }
00531
00532
00533
00534
00535 Mobile::~Mobile(void) {
00536 wkf_timer_destroy(packtimer);
00537 wkf_timer_destroy(statustimer);
00538
00539 for (int i=0; i<clientNick.num();i++)
00540 {
00541 delete clientNick[i];
00542 delete clientIP[i];
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552 if (mobile != NULL)
00553 mobile_listener_destroy(mobile);
00554 }
00555
00556
00557 int send_dgram(const char *host_addr, int port, const char *buf, int buflen) {
00558 struct sockaddr_in addr;
00559 int sockfd;
00560
00561 if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
00562 return -1;
00563 }
00564
00565 memset(&addr, 0, sizeof(addr));
00566 addr.sin_family = AF_INET;
00567 addr.sin_port = htons(port);
00568 addr.sin_addr.s_addr = inet_addr(host_addr);
00569
00570 sendto(sockfd, buf, buflen, 0, (struct sockaddr *)&addr, sizeof(addr));
00571
00572 #if defined(_MSC_VER)
00573 closesocket(sockfd);
00574 #else
00575 close(sockfd);
00576 #endif
00577
00578 return 0;
00579 }
00580
00581
00582 void Mobile::sendStatus(const int eventType)
00583 {
00584 prepareSendBuffer(eventType);
00585
00586
00587 for (int i=0; i< clientIP.num(); i++)
00588 {
00589
00590
00591 *(statusSendBuffer + 16) = (clientActive[i] ? 1 : 0);
00592
00593 send_dgram((const char *)*(clientIP[i]), clientListenerPort[i],
00594 statusSendBuffer, statusSendBufferLength);
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604 wkf_timer_start(statustimer);
00605 }
00606
00607
00608
00609 void Mobile::checkAndSendStatus()
00610 {
00611 if (wkf_timer_timenow(statustimer) > statusSendSeconds) {
00612 sendStatus(SEND_HEARTBEAT);
00613 }
00614 }
00615
00616
00617
00618
00619 bool Mobile::isInControl(JString* nick, JString* ip, const int port, const int packtype)
00620 {
00621
00622 int i;
00623 for (i=0; i < clientNick.num(); i++) {
00624 if (*nick == *(clientNick[i]) && *ip == *(clientIP[i])) {
00625
00626 break;
00627 }
00628 }
00629
00630 if (i < clientNick.num())
00631 {
00632
00633 if (packtype == PACKET_DISCONNECT) {
00634 removeClient(i);
00635 return false;
00636 }
00637 return clientActive[i];
00638 } else {
00639 JString *tmpNick, *tmpIp;
00640 tmpNick = new JString(*nick);
00641 tmpIp = new JString(*ip);
00642
00643
00644 if (clientNick.num() == 0)
00645 {
00646 addNewClient(tmpNick, tmpIp, port, true);
00647 return true;
00648 } else {
00649 addNewClient(tmpNick, tmpIp, port, false);
00650 return false;
00651 }
00652 }
00653 return false;
00654 }
00655
00657
00658
00659 void Mobile::reset(void) {
00660
00661 move_mode(OFF);
00662
00663
00664 set_max_stride(20);
00665
00666
00667
00668 transInc = 1.0f / 25000.0f;
00669 rotInc = 1.0f / 200.0f;
00670 scaleInc = 1.0f / 25000.0f;
00671 animInc = 1.0f / 1.0f;
00672 }
00673
00674
00675
00676
00677
00678
00679 int Mobile::act_on_command(int type, Command *cmd) {
00680 return FALSE;
00681 }
00682
00683
00684
00685
00686 int Mobile::check_event(void) {
00687 float tx, ty, tz, rx, ry, rz;
00688 int touchid[16];
00689 float padx[16], pady[16];
00690
00691 int padaction, upid, buttons, touchcnt;
00692 int buttonchanged;
00693 int win_event=FALSE;
00694 int packtype;
00695 JString incIP, nick, commandToSend;
00696 bool inControl = false;
00697
00698 int clientPort;
00699
00700
00701
00702
00703
00704
00705 checkAndSendStatus();
00706
00707
00708 rx=ry=rz=tx=ty=tz=0.0f;
00709 buttons=padaction=upid=0;
00710 memset(touchid, 0, sizeof(touchid));
00711 memset(padx, 0, sizeof(padx));
00712 memset(pady, 0, sizeof(pady));
00713 touchcnt=0;
00714
00715
00716 while (moveMode != OFF &&
00717 mobile_listener_poll(mobile, rx, ry, rz, tx, ty, tz, padaction, upid,
00718 touchcnt, touchid, padx, pady, buttons, packtype,
00719 incIP, nick, clientPort, tranScaling, rotScaling,
00720 zoomScaling, commandToSend))
00721 {
00722
00723 win_event = TRUE;
00724
00725
00726
00727 if (packtype == EVENT_COMMAND) {
00728
00729
00730 char strTmp[11];
00731 sprintf(strTmp, "%d",buttons);
00732 JString jstr = "{" + nick + "} {" + incIP + "} {" + strTmp +
00733 "} {" + commandToSend + "}";
00734
00735
00736 runcommand(new MobileDeviceCommandEvent(jstr));
00737 break;
00738 }
00739
00740
00741
00742 if (isInControl(&nick, &incIP, clientPort, packtype))
00743 {
00744 DisplayDevice::EventCodes keydev=DisplayDevice::WIN_KBD;
00745 inControl = true;
00746
00747
00748 buttonchanged = buttons ^ buttonDown;
00749
00750
00751 if (buttonchanged) {
00752
00753 if (buttonchanged == (1<<0) && (buttonchanged & buttons)) {
00754 runcommand(new UserKeyEvent(keydev, '0', (int) DisplayDevice::AUX));
00755 }
00756 if (buttonchanged == (1<<1) && (buttonchanged & buttons)) {
00757 runcommand(new UserKeyEvent(keydev, '1', (int) DisplayDevice::AUX));
00758 }
00759 if (buttonchanged == (1<<2) && (buttonchanged & buttons)) {
00760 runcommand(new UserKeyEvent(keydev, '2', (int) DisplayDevice::AUX));
00761 }
00762 if (buttonchanged == (1<<3) && (buttonchanged & buttons)) {
00763 runcommand(new UserKeyEvent(keydev, '3', (int) DisplayDevice::AUX));
00764 }
00765
00766
00767 if (buttonchanged == (1<<31)) {
00768 if (buttonchanged & buttons) {
00769 app->scene_resetview();
00770 }
00771 }
00772 }
00773
00774 #if 0
00775 printf("Touchpad action: %d upid %d", padaction, upid);
00776 for (int i=0; i<touchcnt; i++) {
00777 printf("ID[%d] x: %.2f y: %.2f ",
00778 i, padx[i], pady[i]);
00779 }
00780 printf("\n");
00781 #endif
00782
00783 if (padaction != EVENT_NON_TOUCH) {
00784
00785
00786 if (touchcnt < touchcount ||
00787 padaction == EVENT_TOUCH_UP || padaction == EVENT_TOUCH_SOMEUP) {
00788
00789 touchinprogress = 0;
00790 touchmode = ROTATE;
00791 touchcount = 0;
00792 touchstartX = 0;
00793 touchstartY = 0;
00794 touchdeltaX = 0;
00795 touchdeltaY = 0;
00796 touchscale = 1.0;
00797 touchscalestartdist = 0;
00798 touchrotstartangle = 0;
00799 }
00800
00801
00802 if (touchcnt > touchcount ||
00803 padaction == EVENT_TOUCH_DOWN ||
00804 padaction == EVENT_TOUCH_SOMEDOWN) {
00805
00806 touchcount = touchcnt;
00807 touchstartX = 0;
00808 touchstartY = 0;
00809 touchdeltaX = 0;
00810 touchdeltaY = 0;
00811 touchscale = 1.0;
00812 touchscalestartdist = 0;
00813 touchrotstartangle = 0;
00814
00815
00816 if (touchcount == 1) {
00817
00818 touchinprogress=1;
00819 touchmode = ROTATE;
00820 touchstartX = padx[0];
00821 touchstartY = pady[0];
00822 } else if (touchcount == 2) {
00823 touchinprogress=1;
00824 touchstartX = (padx[0] + padx[1]) * 0.5f;
00825 touchstartY = (pady[0] + pady[1]) * 0.5f;
00826
00827 float dx = padx[1] - padx[0];
00828 float dy = pady[1] - pady[0];
00829 touchscalestartdist = sqrtf(dx*dx + dy*dy) + 0.00001f;
00830 if (touchscalestartdist > 0.65f) {
00831 touchrotstartangle = atan2(dx, -dy) + VMD_PI;
00832
00833 touchmode = SCALEROTZ;
00834 } else {
00835
00836 touchmode = TRANSLATE;
00837 }
00838 }
00839 }
00840
00841 if (touchinprogress && padaction == EVENT_TOUCH_MOVE) {
00842 if (touchmode == ROTATE) {
00843 touchdeltaX = padx[0] - touchstartX;
00844 touchdeltaY = pady[0] - touchstartY;
00845 } else if (touchmode == SCALEROTZ) {
00846
00847
00848 if (moveMode == MOVE) {
00849 float dx = padx[1] - padx[0];
00850 float dy = pady[1] - pady[0];
00851 float dist = sqrtf(dx*dx + dy*dy);
00852
00853
00854 float newscale = (dist / touchscalestartdist) / touchscale;
00855 if (fabsf(newscale - 1.0f) > 0.01f) {
00856 touchscale *= newscale;
00857 app->scene_scale_by((newscale - 1.0f) * zoomScaling + 1.0f);
00858 }
00859
00860
00861
00862
00863
00864 float newrotangle = atan2(dx, -dy) + VMD_PI;
00865 float rotby = (newrotangle-touchrotstartangle)*180.0f/VMD_PI;
00866 if (fabsf(rotby) > 0.25f) {
00867 app->scene_rotate_by(-rotScaling*rotby, 'z');
00868 touchrotstartangle=newrotangle;
00869 }
00870 }
00871 } else if (touchmode == TRANSLATE) {
00872 touchdeltaX = ((padx[0]+padx[1])*0.5f) - touchstartX;
00873 touchdeltaY = ((pady[0]+pady[1])*0.5f) - touchstartY;
00874 }
00875 }
00876
00877 }
00878
00879
00880 buttonDown = buttons;
00881 }
00882
00883
00884 wkf_timer_start(packtimer);
00885 }
00886
00887
00888
00889
00890
00891
00892 if (!win_event && wkf_timer_timenow(packtimer) > 3.0) {
00893 touchinprogress = 0;
00894 touchmode = ROTATE;
00895 touchcount = 0;
00896 touchstartX = 0;
00897 touchstartY = 0;
00898 touchdeltaX = 0;
00899 touchdeltaY = 0;
00900 touchscalestartdist = 0;
00901 touchrotstartangle = 0;
00902 }
00903
00904 if (touchinprogress) {
00905 if (moveMode == MOVE) {
00906 if (touchmode == ROTATE) {
00907
00908
00909 app->scene_rotate_by(touchdeltaY*rotScaling*0.5f, 'x');
00910 app->scene_rotate_by(touchdeltaX*rotScaling*0.5f, 'y');
00911 } else if (touchmode == TRANSLATE) {
00912 app->scene_translate_by(touchdeltaX*tranScaling*0.005f, -touchdeltaY*tranScaling*0.005f, 0.0f);
00913 }
00914 } else if (moveMode == ANIMATE) {
00915 if (fabsf(touchdeltaX) > 0.25f) {
00916 #if 0
00917
00918 float speed = fabsf(expf(fabsf((fabsf(touchdeltaX) * animInc) / 1.7f))) - 1.0f;
00919 #else
00920
00921 float speed = fabsf(touchdeltaX) * animInc;
00922 #endif
00923
00924 if (speed > 0) {
00925 if (speed < 1.0)
00926 app->animation_set_speed(speed);
00927 else
00928 app->animation_set_speed(1.0f);
00929
00930 int stride = 1;
00931 if (fabs(speed - 1.0) > (double) maxstride)
00932 stride = maxstride;
00933 else
00934 stride = 1 + (int) fabs(speed-1.0);
00935 if (stride < 1)
00936 stride = 1;
00937 app->animation_set_stride(stride);
00938
00939 if (touchdeltaX > 0) {
00940 app->animation_set_dir(Animation::ANIM_FORWARD1);
00941 } else {
00942 app->animation_set_dir(Animation::ANIM_REVERSE1);
00943 }
00944 } else {
00945 app->animation_set_dir(Animation::ANIM_PAUSE);
00946 app->animation_set_speed(1.0f);
00947 }
00948 } else {
00949 app->animation_set_dir(Animation::ANIM_PAUSE);
00950 app->animation_set_speed(1.0f);
00951 }
00952 }
00953 } else {
00954
00955
00956 }
00957
00958 if (win_event) {
00959 return TRUE;
00960 } else {
00961 return FALSE;
00962 }
00963 }
00964
00965
00967
00968 const char* Mobile::get_mode_str(MoveMode mm) {
00969 const char* modestr;
00970
00971 switch (mm) {
00972 default:
00973 case OFF: modestr = "off"; break;
00974 case MOVE: modestr = "move"; break;
00975 case ANIMATE: modestr = "animate"; break;
00976 case TRACKER: modestr = "tracker"; break;
00977 case USER: modestr = "user"; break;
00978 }
00979
00980 return modestr;
00981 }
00982
00983
00984 int Mobile::get_port () {
00985 return port;
00986 }
00987
00988
00989 int Mobile::get_APIsupported () {
00990 return CURRENTAPIVERSION;
00991 }
00992
00993
00994 int Mobile::get_move_mode () {
00995 return moveMode;
00996 }
00997
00998
00999 void Mobile::get_client_list (ResizeArray <JString*>* &nick,
01000 ResizeArray <JString*>* &ip, ResizeArray <bool>* &active)
01001 {
01002 nick = &clientNick;
01003 ip = &clientIP;
01004 active = &clientActive;
01005 }
01006
01007
01008 int Mobile::sendMsgToClient(const char *nick, const char *ip,
01009 const char *msgType, const char *msg)
01010 {
01011
01012
01013 bool found = false;
01014 int i;
01015 for (i=0; i<clientNick.num();i++)
01016 {
01017 if (*(clientNick[i]) == nick) {
01018
01019 if (*(clientIP[i]) == ip) {
01020 found = true;
01021 break;
01022 }
01023 }
01024 }
01025
01026 if (found) {
01027
01028 prepareSendBuffer(SEND_MESSAGE);
01029
01030 *(statusSendBuffer + 16) = (clientActive[i] ? 1 : 0);
01031
01032
01033 int length = statusSendBufferLength;
01034
01035
01036 int tmpInt;
01037 if (EOF == sscanf(msgType, "%d", &tmpInt))
01038 {
01039 return false;
01040 }
01041 *(statusSendBuffer + length) = tmpInt;
01042 length += sizeof(int);
01043
01044 int msgLength = strlen(msg);
01045 *(statusSendBuffer + length) = msgLength;
01046 length += sizeof(int);
01047
01048 memcpy((statusSendBuffer + length), msg, msgLength);
01049 length += msgLength;
01050
01051 send_dgram((const char *)*(clientIP[i]), clientListenerPort[i],
01052 statusSendBuffer, length);
01053 return true;
01054 } else {
01055 return false;
01056 }
01057 }
01058
01059
01060 int Mobile::set_activeClient(const char *nick, const char *ip)
01061 {
01062
01063
01064 bool found = false;
01065 int i;
01066 for (i=0; i<clientNick.num();i++)
01067 {
01068 if (*(clientNick[i]) == nick) {
01069
01070 if (*(clientIP[i]) == ip) {
01071 found = true;
01072 break;
01073 }
01074 }
01075 }
01076
01077 if (found) {
01078
01079 for (int j=0; j<clientActive.num();j++)
01080 {
01081 clientActive[j] = false;
01082 }
01083
01084
01085 touchinprogress = 0;
01086 touchmode = ROTATE;
01087 touchcount = 0;
01088 touchstartX = 0;
01089 touchstartY = 0;
01090 touchdeltaX = 0;
01091 touchdeltaY = 0;
01092 touchscalestartdist = 0;
01093 touchrotstartangle = 0;
01094
01095
01096 clientActive[i] = true;
01097
01098 sendStatus(SEND_SETACTIVECLIENT);
01099 return true;
01100 } else {
01101 return false;
01102 }
01103 }
01104
01105
01106
01107 void Mobile::get_tracker_status(float &tx, float &ty, float &tz,
01108 float &rx, float &ry, float &rz,
01109 int &buttons) {
01110 tx = trtx * transInc;
01111 ty = trty * transInc;
01112 tz = -trtz * transInc;
01113 rx = trrx * rotInc;
01114 ry = trry * rotInc;
01115 rz = -trrz * rotInc;
01116 buttons = trbuttons;
01117 }
01118
01119
01120
01121
01122 int Mobile::move_mode(MoveMode mm) {
01123
01124 moveMode = mm;
01125
01126 if (moveMode != OFF && !mobile) {
01127 mobile = mobile_listener_create(port);
01128 if (mobile == NULL) {
01129 msgErr << "Failed to open mobile port " << port
01130 << ", move mode disabled" << sendmsg;
01131 moveMode = OFF;
01132 } else {
01133 msgInfo << "Opened mobile port " << port << sendmsg;
01134 }
01135 }
01136
01137
01138 if (moveMode == OFF && mobile) {
01139 mobile_listener_destroy(mobile);
01140 mobile = 0;
01141 removeAllClients();
01142 }
01143
01145 if (moveMode != TRACKER) {
01146 trtx=trty=trtz=trrx=trry=trrz=0.0f;
01147 trbuttons=0;
01148 }
01149
01150 runcommand(new MobileStateChangedEvent());
01151 sendStatus(SEND_SETMODE);
01152
01153 return TRUE;
01154 }
01155
01156
01157
01158 int Mobile::network_port(int newport) {
01159
01160 if (mobile != NULL) {
01161 mobile_listener_destroy(mobile);
01162 removeAllClients();
01163 }
01164
01165 if (moveMode != OFF) {
01166 mobile = mobile_listener_create(newport);
01167 if (mobile == NULL) {
01168 msgErr << "Failed to open mobile port " << newport
01169 << ", move mode disabled" << sendmsg;
01170 moveMode = OFF;
01171 } else {
01172 port = newport;
01173
01174 msgInfo << "Opened mobile port " << port << sendmsg;
01175 }
01176 runcommand(new MobileStateChangedEvent());
01177 } else {
01178 port = newport;
01179 }
01180
01181 return TRUE;
01182 }
01183
01184
01185
01186 int Mobile::addNewClient(JString* nick, JString* ip, const int port, const bool active)
01187 {
01188
01189 clientNick.append(nick);
01190 clientIP.append(ip);
01191 clientListenerPort.append(port);
01192 clientActive.append(active);
01193
01194
01195 runcommand(new MobileStateChangedEvent());
01196 sendStatus(SEND_ADDCLIENT);
01197 return 0;
01198 }
01199
01200
01201 void Mobile::removeAllClients()
01202 {
01203 while (clientNick.num() > 0) {
01204 removeClient(0);
01205 }
01206 }
01207
01208
01209 int Mobile::removeClient(const int num)
01210 {
01211 delete clientNick[num];
01212 clientNick.remove(num);
01213
01214 delete clientIP[num];
01215 clientIP.remove(num);
01216
01217 clientActive.remove(num);
01218
01219 clientListenerPort.remove(num);
01220
01221
01222 int iCount;
01223 for (iCount=0; iCount<clientActive.num();iCount++)
01224 {
01225 if (clientActive[iCount]) {
01226 break;
01227 }
01228 }
01229
01230
01231
01232
01233 if (iCount == clientActive.num() && clientActive.num() > 0)
01234 {
01235 clientActive[0] = true;
01236 }
01237
01238
01239 runcommand(new MobileStateChangedEvent());
01240 sendStatus(SEND_REMOVECLIENT);
01241 return 0;
01242 }
01243
01244
01245