/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #include #include #define WHERE_IN in[0] #define DEFAULT_CAMERA in[1] #define RESET_CAMERA in[2] #define DEFAULT_OBJECT in[3] #define RESET_OBJECT in[4] #define WINDOW_SIZE in[5] #define MOUSE in[6] #define MODE in[7] #define ARGS in[8] #define OBJECT out[0] #define CAMERA out[1] #define WHERE_OUT out[2] #define EVENTS out[3] #define CACHE_CAMERA "CACHED_CAMERA_" #define CACHE_OBJECT "CACHED_OBJECT_" static Error Spin(Camera, Camera *, Object, Object *, int, DXEvents, int *, int, Object, DXEvents *, int *); extern DXRegisterForNotification(char *, Pointer); extern int _dxd_nUserInteractors; extern void *_dxd_UserInteractors; int m_SuperviseState(Object *in, Object *out) { Object cachedObject; Camera cachedCamera; char *where, *cameraCacheTag = NULL, *objectCacheTag = NULL; Pointer modid = NULL; int resetCamera, resetObject; int mode; int windowSz[2]; char old[256], new[256]; char *left, *right; CAMERA = NULL; WHERE_OUT = NULL; EVENTS = NULL; if (!WHERE_IN || !DXExtractString(WHERE_IN, &where)) { DXSetError(ERROR_MISSING_DATA, "where parameter"); return NULL; } if (! strstr(where, "#X")) { DXSetError(ERROR_BAD_PARAMETER, "where must be a SuperviseWindow where output"); goto error; } left = strchr(where, '['); if (left && ((right = strchr(where, ']')) != NULL) && right > left) { Object o; char oTag[512], nTag[512]; strncpy(new, where, (left - where)); new[left-where] = '\0'; strncpy(old, left+1, (right - (left+1))); old[right - (left+1)] = '\0'; DXMessage("old: %s new %s", old, new); where = new; sprintf(oTag, "%s%s", CACHE_CAMERA, old); sprintf(nTag, "%s%s", CACHE_CAMERA, new); if (NULL != (o = DXGetCacheEntry(oTag, 0, 0))) { DXSetCacheEntry(o, CACHE_PERMANENT, nTag, 0, 0); DXSetCacheEntry(NULL, CACHE_PERMANENT, oTag, 0, 0); } sprintf(oTag, "%s%s", CACHE_OBJECT, old); sprintf(nTag, "%s%s", CACHE_OBJECT, new); if (NULL != (o = DXGetCacheEntry(oTag, 0, 0))) { DXSetCacheEntry(o, CACHE_PERMANENT, nTag, 0, 0); DXSetCacheEntry(NULL, CACHE_PERMANENT, oTag, 0, 0); } WHERE_OUT = (Object)DXNewString(new); } else WHERE_OUT = WHERE_IN; if (RESET_CAMERA) { if (! DXExtractInteger(RESET_CAMERA, &resetCamera)) DXSetError(ERROR_BAD_PARAMETER, "resetCamera"); } else resetCamera = 0; cameraCacheTag = (char *)DXAllocate(strlen(where)+strlen(CACHE_CAMERA)+2); if (! cameraCacheTag) goto error; sprintf(cameraCacheTag, "%s%s", CACHE_CAMERA, where); if (! resetCamera) { Object lastCam; modid = DXGetModuleId(); DXRegisterForNotification(cameraCacheTag, modid); DXFreeModuleId(modid); lastCam = DXGetCacheEntry(cameraCacheTag, 0, 0); CAMERA = DXCopy(lastCam, COPY_STRUCTURE); DXReference(CAMERA); DXDelete(lastCam); } if (! CAMERA) { if (! DEFAULT_CAMERA) { DXSetError(ERROR_MISSING_DATA, "either cached camera or default camera must be available"); goto error; } CAMERA = DXCopy((Object)DEFAULT_CAMERA, COPY_STRUCTURE); DXReference(CAMERA); } if (RESET_OBJECT) { if (! DXExtractInteger(RESET_OBJECT, &resetObject)) DXSetError(ERROR_BAD_PARAMETER, "resetObject"); } else resetObject = 0; objectCacheTag = (char *)DXAllocate(strlen(where)+strlen(CACHE_OBJECT)+2); if (! objectCacheTag) goto error; sprintf(objectCacheTag, "%s%s", CACHE_OBJECT, where); if (! resetObject) { modid = DXGetModuleId(); DXRegisterForNotification(objectCacheTag, modid); DXFreeModuleId(modid); OBJECT = DXGetCacheEntry(objectCacheTag, 0, 0); } if (! OBJECT) { if (! DEFAULT_OBJECT) { DXSetError(ERROR_MISSING_DATA, "either cached object or default object must be available"); goto error; } OBJECT = DXCopy((Object)DEFAULT_OBJECT, COPY_STRUCTURE); DXReference(OBJECT); } mode = -1; if (MODE && !DXExtractInteger(MODE, &mode)) { DXSetError(ERROR_BAD_PARAMETER, "mode must be an int"); goto error; } if (WINDOW_SIZE) { float w; if (! DXExtractParameter(WINDOW_SIZE, TYPE_INT, 2, 1, &windowSz)) { DXSetError(ERROR_INVALID_DATA, "windowsize"); goto error; } DXSetResolution((Camera)CAMERA, windowSz[0], 1.0); if (DXGetOrthographic((Camera)CAMERA, &w, NULL)) DXSetOrthographic((Camera)CAMERA, w, (double)(windowSz[1]+0.99)/windowSz[0]); else { DXGetPerspective((Camera)CAMERA, &w, NULL); DXSetPerspective((Camera)CAMERA, w, (double)(windowSz[1]+0.99)/windowSz[0]); } } else DXGetCameraResolution((Camera)CAMERA, &windowSz[0], &windowSz[1]); if (mode >= _dxd_nUserInteractors) { DXSetError(ERROR_BAD_PARAMETER, "only %d user interactors are available", _dxd_nUserInteractors); goto error; } if ((mode >= 0) && MOUSE) { DXEvents dxEvents; int nDXEvents; Category c; Type t; int r, s; DXEvents uEvents; int nuEvents; if (DXGetObjectClass(MOUSE) != CLASS_ARRAY) { DXSetError(ERROR_INVALID_DATA, "mouse must be an array"); return ERROR; } DXGetArrayInfo((Array)MOUSE, &nDXEvents, &t, &c, &r, &s); if (t != TYPE_INT || r != 1 || s != sizeof(DXEvent)/DXTypeSize(TYPE_INT)) { DXSetError(ERROR_INVALID_DATA, "mouse must be an array of mouse events"); return ERROR; } dxEvents = DXGetArrayData((Array)MOUSE); if (!Spin((Camera)CAMERA, (Camera *)&CAMERA, OBJECT, &OBJECT, nDXEvents, dxEvents, windowSz, mode, ARGS, &uEvents, &nuEvents) || ! CAMERA || ! OBJECT) goto error; if (nuEvents) { EVENTS = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 1, sizeof(DXEvent)/DXTypeSize(TYPE_INT)); DXAddArrayData((Array)EVENTS, 0, nuEvents, (Pointer)uEvents); DXFree((Pointer)uEvents); } } DXSetCacheEntry(CAMERA, CACHE_PERMANENT, cameraCacheTag, 0, 0); DXSetCacheEntry(OBJECT, CACHE_PERMANENT, objectCacheTag, 0, 0); if (mode == -1) { DXSetAttribute(CAMERA, "interaction mode", NULL); } else { Group g = DXNewGroup(); Array a; int *i; a = DXNewArray(TYPE_INT, CATEGORY_REAL, 0); DXAddArrayData(a, 0, 1, NULL); i = (int *)DXGetArrayData(a); *i = 9; /* INTERACTION_USER in hwClientMessage.c */ DXSetMember(g, "mode", (Object)a); a = DXNewArray(TYPE_INT, CATEGORY_REAL, 0); DXAddArrayData(a, 0, 1, NULL); i = (int *)DXGetArrayData(a); *i = mode; DXSetMember(g, "submode", (Object)a); DXSetMember(g, "args", ARGS); DXSetAttribute(OBJECT, "interaction mode", (Object)g); } DXUnreference((Object)CAMERA); DXUnreference((Object)OBJECT); DXFree((Pointer)cameraCacheTag); DXFree((Pointer)objectCacheTag); return OK; error: DXFree((Pointer)cameraCacheTag); DXFree((Pointer)objectCacheTag); return ERROR; } static Error Spin(Camera in_camera, Camera *out_camera, Object in_object, Object *out_object, int nEvents, DXEvents events, int *wsz, int mode, Object args, DXEvents *uevents, int *nuevents) { float aspect; float F[3], T[3], U[3]; Point fp, tp; Vector uv; float width; int pixwidth; float fov; int projection; int buttonState; *uevents = NULL; *nuevents = 0; DXGetView(in_camera, (Point *)F, (Point *)T, (Vector *)U); if (DXGetOrthographic(in_camera, &width, &aspect)) { projection = 0; } else { DXGetPerspective(in_camera, &fov, &aspect); projection = 1; } DXGetCameraResolution(in_camera, &pixwidth, NULL); if (nEvents) { int i, activeButton, last_x, last_y; float dx, dy, dz; int last; int buttonState = BUTTON_UP; void *udata = NULL; int mask; UserInteractor *imode = ((UserInteractor *)_dxd_UserInteractors) + mode; udata = imode->InitMode(args, wsz[0], wsz[1], &mask); if (imode->SetCamera) imode->SetCamera(udata, T, F, U, projection, fov, width); if (imode->SetRenderable) imode->SetRenderable(udata, in_object); activeButton = -1; *nuevents = 0; for (i = 0; i < nEvents; i++) { if (! (events[i].any.event & mask)) { (*nuevents)++; continue; } imode->EventHandler(udata, (DXEvent *)(events+i)); } if (imode->GetCamera) imode->GetCamera(udata, T, F, U, &projection, &fov, &width); if (imode->GetRenderable) { Object tmp; imode->GetRenderable(udata, &tmp); if (tmp) { DXDelete(in_object); in_object = DXReference(tmp); tmp = NULL; } } imode->EndMode(udata); if (*nuevents) { int i, j; *uevents = DXAllocate(*nuevents * sizeof(DXEvent)); if (! *uevents) return ERROR; for (i = j = 0; i < nEvents; i++) if (! (events[i].any.event & mask)) (*uevents)[j++] = events[i]; } } if (out_object) *out_object = in_object; if (out_camera) { *out_camera = (Camera)DXCopy((Object)in_camera, COPY_STRUCTURE); if (! *out_camera) return ERROR; DXReference((Object)*out_camera); aspect = (double)(wsz[1]+0.99)/wsz[0]; fp.x = F[0]; fp.y = F[1]; fp.z = F[2]; tp.x = T[0]; tp.y = T[1]; tp.z = T[2]; uv.x = U[0]; uv.y = U[1]; uv.z = U[2]; DXSetView(*out_camera, fp, tp, uv); if (projection) DXSetPerspective(*out_camera, fov, aspect); else DXSetOrthographic(*out_camera, width, aspect); } return OK; }