1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 
9 #include <dxconfig.h>
10 
11 
12 
13 
14 #include <dx/dx.h>
15 #include <math.h>
16 #include <string.h>
17 
18 #define WHERE_IN 	in[0]
19 #define DEFAULT_CAMERA 	in[1]
20 #define RESET_CAMERA  	in[2]
21 #define DEFAULT_OBJECT 	in[3]
22 #define RESET_OBJECT 	in[4]
23 #define WINDOW_SIZE     in[5]
24 #define MOUSE           in[6]
25 #define MODE            in[7]
26 #define ARGS            in[8]
27 
28 #define OBJECT		out[0]
29 #define CAMERA		out[1]
30 #define WHERE_OUT	out[2]
31 #define EVENTS		out[3]
32 
33 #define CACHE_CAMERA	"CACHED_CAMERA_"
34 #define CACHE_OBJECT	"CACHED_OBJECT_"
35 
36 static Error Spin(Camera, Camera *, Object, Object *,
37 		int, DXEvents, int *, int, Object, DXEvents *, int *);
38 
39 extern Error DXRegisterForNotification(char *, Pointer); /* from libdx/notify.c */
40 
41 extern int _dxd_nUserInteractors;
42 extern void *_dxd_UserInteractors;
43 
44 int
m_SuperviseState(Object * in,Object * out)45 m_SuperviseState(Object *in, Object *out)
46 {
47     char *where, *cameraCacheTag = NULL, *objectCacheTag = NULL;
48     Pointer modid = NULL;
49     int resetCamera, resetObject;
50     int mode;
51     int windowSz[2];
52     char old[256], new[256];
53     char *left, *right;
54 
55     CAMERA = NULL;
56     WHERE_OUT = NULL;
57     EVENTS = NULL;
58 
59     if (!WHERE_IN || !DXExtractString(WHERE_IN, &where))
60     {
61 	DXSetError(ERROR_MISSING_DATA, "where parameter");
62 	return ERROR;
63     }
64 
65     if (! strstr(where, "#X"))
66     {
67 	DXSetError(ERROR_BAD_PARAMETER, "where must be a SuperviseWindow where output");
68 	goto error;
69     }
70 
71     left = strchr(where, '[');
72     if (left && ((right = strchr(where, ']')) != NULL) && right > left)
73     {
74 	Object o;
75 	char oTag[512], nTag[512];
76 
77 	strncpy(new, where, (left - where));
78 	new[left-where] = '\0';
79 	strncpy(old, left+1, (right - (left+1)));
80 	old[right - (left+1)] = '\0';
81 
82 	DXMessage("old: %s new %s", old, new);
83 
84 	where = new;
85 
86 	sprintf(oTag, "%s%s", CACHE_CAMERA, old);
87 	sprintf(nTag, "%s%s", CACHE_CAMERA, new);
88 	if (NULL != (o = DXGetCacheEntry(oTag, 0, 0)))
89 	{
90 	    DXSetCacheEntry(o, CACHE_PERMANENT, nTag, 0, 0);
91 	    DXSetCacheEntry(NULL, CACHE_PERMANENT, oTag, 0, 0);
92 	}
93 
94 	sprintf(oTag, "%s%s", CACHE_OBJECT, old);
95 	sprintf(nTag, "%s%s", CACHE_OBJECT, new);
96 	if (NULL != (o = DXGetCacheEntry(oTag, 0, 0)))
97 	{
98 	    DXSetCacheEntry(o, CACHE_PERMANENT, nTag, 0, 0);
99 	    DXSetCacheEntry(NULL, CACHE_PERMANENT, oTag, 0, 0);
100 	}
101 
102 	WHERE_OUT = (Object)DXNewString(new);
103     }
104     else
105 	WHERE_OUT = WHERE_IN;
106 
107     if (RESET_CAMERA)
108     {
109 	if (! DXExtractInteger(RESET_CAMERA, &resetCamera))
110 	    DXSetError(ERROR_BAD_PARAMETER, "resetCamera");
111     }
112     else
113 	resetCamera = 0;
114 
115     cameraCacheTag = (char *)DXAllocate(strlen(where)+strlen(CACHE_CAMERA)+2);
116     if (! cameraCacheTag)
117 	goto error;
118 
119     sprintf(cameraCacheTag, "%s%s", CACHE_CAMERA, where);
120 
121     if (! resetCamera)
122     {
123 	Object lastCam;
124 	modid = DXGetModuleId();
125 	DXRegisterForNotification(cameraCacheTag, modid);
126 	DXFreeModuleId(modid);
127 	lastCam = DXGetCacheEntry(cameraCacheTag, 0, 0);
128 	CAMERA = DXCopy(lastCam, COPY_STRUCTURE);
129 	DXReference(CAMERA);
130 	DXDelete(lastCam);
131     }
132 
133     if (! CAMERA)
134     {
135 	if (! DEFAULT_CAMERA)
136 	{
137 	    DXSetError(ERROR_MISSING_DATA,
138 		"either cached camera or default camera must be available");
139 	    goto error;
140 	}
141 	CAMERA = DXCopy((Object)DEFAULT_CAMERA, COPY_STRUCTURE);
142 	DXReference(CAMERA);
143     }
144 
145     if (RESET_OBJECT)
146     {
147 	if (! DXExtractInteger(RESET_OBJECT, &resetObject))
148 	    DXSetError(ERROR_BAD_PARAMETER, "resetObject");
149     }
150     else
151 	resetObject = 0;
152 
153     objectCacheTag = (char *)DXAllocate(strlen(where)+strlen(CACHE_OBJECT)+2);
154     if (! objectCacheTag)
155 	goto error;
156 
157     sprintf(objectCacheTag, "%s%s", CACHE_OBJECT, where);
158 
159     if (! resetObject)
160     {
161 	modid = DXGetModuleId();
162 	DXRegisterForNotification(objectCacheTag, modid);
163 	DXFreeModuleId(modid);
164 	OBJECT = DXGetCacheEntry(objectCacheTag, 0, 0);
165     }
166 
167     if (! OBJECT)
168     {
169 	if (! DEFAULT_OBJECT)
170 	{
171 	    DXSetError(ERROR_MISSING_DATA,
172 		"either cached object or default object must be available");
173 	    goto error;
174 	}
175 	OBJECT = DXCopy((Object)DEFAULT_OBJECT, COPY_STRUCTURE);
176 	DXReference(OBJECT);
177     }
178 
179     mode = -1;
180     if (MODE && !DXExtractInteger(MODE, &mode))
181     {
182 	DXSetError(ERROR_BAD_PARAMETER, "mode must be an int");
183 	goto error;
184     }
185 
186     if (WINDOW_SIZE)
187     {
188 	float w;
189 
190 	if (! DXExtractParameter(WINDOW_SIZE, TYPE_INT, 2, 1, &windowSz))
191 	{
192 	    DXSetError(ERROR_DATA_INVALID, "windowsize");
193 	    goto error;
194 	}
195 
196 	DXSetResolution((Camera)CAMERA, windowSz[0], 1.0);
197 
198 	if (DXGetOrthographic((Camera)CAMERA, &w, NULL))
199 	    DXSetOrthographic((Camera)CAMERA, w,
200 			(double)(windowSz[1]+0.99)/windowSz[0]);
201 	else
202 	{
203 	    DXGetPerspective((Camera)CAMERA, &w, NULL);
204 	    DXSetPerspective((Camera)CAMERA, w,
205 			(double)(windowSz[1]+0.99)/windowSz[0]);
206 	}
207     }
208     else
209 	DXGetCameraResolution((Camera)CAMERA, &windowSz[0], &windowSz[1]);
210 
211 
212     if (mode >= _dxd_nUserInteractors)
213     {
214 	DXSetError(ERROR_BAD_PARAMETER,
215 	    "only %d user interactors are available", _dxd_nUserInteractors);
216 	goto error;
217     }
218 
219     if ((mode >= 0) && MOUSE)
220     {
221 	DXEvents dxEvents;
222 	int nDXEvents;
223 	Category c;
224 	Type t;
225 	int r, s;
226 	DXEvents uEvents;
227 	int nuEvents;
228 
229 	if (DXGetObjectClass(MOUSE) != CLASS_ARRAY)
230 	{
231 	    DXSetError(ERROR_DATA_INVALID, "mouse must be an array");
232 	    return ERROR;
233 	}
234 
235 	DXGetArrayInfo((Array)MOUSE, &nDXEvents, &t, &c, &r, &s);
236 
237 	if (t != TYPE_INT || r != 1 || s != sizeof(DXEvent)/DXTypeSize(TYPE_INT))
238 	{
239 	    DXSetError(ERROR_DATA_INVALID,
240 		    "mouse must be an array of mouse events");
241 	    return ERROR;
242 	}
243 
244 	dxEvents = DXGetArrayData((Array)MOUSE);
245 
246 	if (!Spin((Camera)CAMERA, (Camera *)&CAMERA, OBJECT, &OBJECT,
247 			nDXEvents, dxEvents, windowSz, mode, ARGS,
248 			&uEvents, &nuEvents) ||
249 			! CAMERA || ! OBJECT)
250 	     goto error;
251 
252 	if (nuEvents)
253 	{
254 	    EVENTS = (Object)DXNewArray(TYPE_INT, CATEGORY_REAL, 1, sizeof(DXEvent)/DXTypeSize(TYPE_INT));
255 	    DXAddArrayData((Array)EVENTS, 0, nuEvents, (Pointer)uEvents);
256 	    DXFree((Pointer)uEvents);
257 	}
258     }
259 
260     DXSetCacheEntry(CAMERA, CACHE_PERMANENT, cameraCacheTag, 0, 0);
261     DXSetCacheEntry(OBJECT, CACHE_PERMANENT, objectCacheTag, 0, 0);
262 
263     if (mode == -1)
264     {
265 	DXSetAttribute(CAMERA, "interaction mode", NULL);
266     }
267     else
268     {
269 	Group g = DXNewGroup();
270 	Array a;
271 	int *i;
272 	a = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
273 	DXAddArrayData(a, 0, 1, NULL);
274 	i = (int *)DXGetArrayData(a);
275 	*i = 9; /* INTERACTION_USER in hwClientMessage.c */
276 	DXSetMember(g, "mode", (Object)a);
277 	a = DXNewArray(TYPE_INT, CATEGORY_REAL, 0);
278 	DXAddArrayData(a, 0, 1, NULL);
279 	i = (int *)DXGetArrayData(a);
280 	*i = mode;
281 	DXSetMember(g, "submode", (Object)a);
282 	DXSetMember(g, "args", ARGS);
283 
284 	DXSetAttribute(OBJECT, "interaction mode", (Object)g);
285     }
286 
287     DXUnreference((Object)CAMERA);
288     DXUnreference((Object)OBJECT);
289 
290     DXFree((Pointer)cameraCacheTag);
291     DXFree((Pointer)objectCacheTag);
292 
293     return OK;
294 
295 error:
296     DXFree((Pointer)cameraCacheTag);
297     DXFree((Pointer)objectCacheTag);
298 
299     return ERROR;
300 
301 }
302 
303 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)304 Spin(Camera in_camera, Camera *out_camera,
305 	   Object in_object, Object *out_object,
306 	   int nEvents, DXEvents events, int *wsz,
307 	   int mode, Object args,
308 	   DXEvents *uevents, int *nuevents)
309 {
310     float aspect;
311     float F[3], T[3], U[3];
312     Point fp, tp;
313     Vector uv;
314     float width;
315     int   pixwidth;
316     float fov;
317     int projection;
318 
319     *uevents = NULL;
320     *nuevents = 0;
321 
322     DXGetView(in_camera, (Point *)F, (Point *)T, (Vector *)U);
323 
324     if (DXGetOrthographic(in_camera, &width, &aspect))
325     {
326 	projection = 0;
327     }
328     else
329     {
330 	DXGetPerspective(in_camera, &fov, &aspect);
331 	projection = 1;
332     }
333     DXGetCameraResolution(in_camera, &pixwidth, NULL);
334 
335     if (nEvents)
336     {
337 	int i;
338 	void *udata = NULL;
339 	int mask;
340 	UserInteractor *imode = ((UserInteractor *)_dxd_UserInteractors) + mode;
341 
342 	udata = imode->InitMode(args, wsz[0], wsz[1], &mask);
343 
344 	if (imode->SetCamera)
345 	    imode->SetCamera(udata, T, F, U, projection, fov, width);
346 
347 	if (imode->SetRenderable)
348 	    imode->SetRenderable(udata, in_object);
349 
350 	*nuevents = 0;
351 
352 	for (i = 0; i < nEvents; i++)
353 	{
354 	    if (! (events[i].any.event & mask))
355 	    {
356 		(*nuevents)++;
357 		continue;
358 	    }
359 
360 	    imode->EventHandler(udata, (DXEvent *)(events+i));
361 	}
362 
363 	if (imode->GetCamera)
364 	    imode->GetCamera(udata, T, F, U, &projection, &fov, &width);
365 
366 	if (imode->GetRenderable)
367 	{
368 	    Object tmp;
369 
370 	    imode->GetRenderable(udata, &tmp);
371 	    if (tmp)
372 	    {
373 		DXDelete(in_object);
374 		in_object = DXReference(tmp);
375 		tmp = NULL;
376 	    }
377 	}
378 
379 	imode->EndMode(udata);
380 
381 	if (*nuevents)
382 	{
383 	    int i, j;
384 
385 	    *uevents = DXAllocate(*nuevents * sizeof(DXEvent));
386 	    if (! *uevents)
387 		 return ERROR;
388 
389 	    for (i = j = 0; i < nEvents; i++)
390 		if (! (events[i].any.event & mask))
391 		    (*uevents)[j++] = events[i];
392 	}
393     }
394 
395     if (out_object)
396 	*out_object = in_object;
397 
398     if (out_camera)
399     {
400 	*out_camera = (Camera)DXCopy((Object)in_camera, COPY_STRUCTURE);
401 	if (! *out_camera)
402 	    return ERROR;
403 
404 	DXReference((Object)*out_camera);
405 
406 	aspect = (double)(wsz[1]+0.99)/wsz[0];
407 
408 	fp.x = F[0]; fp.y = F[1]; fp.z = F[2];
409 	tp.x = T[0]; tp.y = T[1]; tp.z = T[2];
410 	uv.x = U[0]; uv.y = U[1]; uv.z = U[2];
411 
412 	DXSetView(*out_camera, fp, tp, uv);
413 	if (projection)
414 	    DXSetPerspective(*out_camera, fov, aspect);
415 	else
416 	    DXSetOrthographic(*out_camera, width, aspect);
417 
418     }
419 
420     return OK;
421 }
422