FreeWRL / FreeX3D 4.3.0
fieldSet.c
1/*
2
3 FreeWRL support library.
4 VRML/X3D fields manipulation.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28
29#include <config.h>
30#include <system.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35#include <io_files.h>
36
37#include "../vrml_parser/Structs.h"
38#include "../vrml_parser/CRoutes.h"
39#include "../main/headers.h"
40#include "../vrml_parser/CParseGeneral.h"
41#include "../main/Snapshot.h"
42#include "../scenegraph/Collision.h"
43#include "../scenegraph/quaternion.h"
44#include "../scenegraph/Viewer.h"
45#include "../input/SensInterps.h"
46#include "../input/EAIHeaders.h"
47#include "../input/EAIHelpers.h" /* resolving implicit declarations */
48#include "../x3d_parser/Bindable.h"
49
50#include "JScript.h"
51#include "CScripts.h"
52#include "fieldSet.h"
53#include "fieldGet.h"
54
55
56
57/* Useful dump routines defined in world_script/field[GS]et.c */
58void dumpOneNode(int myptr);
59void dumpOne_X3D_Node(struct X3D_Node * boxptr);
60void fudgeIfNeeded(int myptr,int myoffset);
61
62
63/*******************************************************************
64
65A group of routines to SET a field in memory - in the FreeWRL
66scene graph.
67
68Different methods are used, depending on the format of the call.
69
70*********************************************************************/
71
72/* copy new scanned in data over to the memory area in the scene graph. */
73static char *Multi_Struct_memptr (int type, char *memptr) {
74 struct Multi_Vec3f *mp;
75 char * retval;
76
77 /* is this a straight copy, or do we have a struct to send to? */
78 /* now, some internal reps use a structure defined as:
79 struct Multi_Vec3f { int n; struct SFColor *p; };
80 so, we have to put the data in the p pointer, so as to
81 not overwrite the data. */
82
83 retval = memptr;
84
85 switch (type) {
86 case FIELDTYPE_MFInt32:
87 case FIELDTYPE_MFFloat:
88 case FIELDTYPE_MFRotation:
89 case FIELDTYPE_MFVec3f:
90 case FIELDTYPE_MFColorRGBA:
91 case FIELDTYPE_MFColor:
92 case FIELDTYPE_MFString:
93 case FIELDTYPE_MFVec2f:
94 mp = (struct Multi_Vec3f*) memptr;
95 /* printf ("Multi_Struct_memptr, have multi thing, have %d elements, pointer %p\n",mp->n, (char *) mp->p); */
96 retval = (char *) (mp->p);
97
98 default: {}
99 }
100if (retval == memptr) printf ("Multi_Struct_memptr, just returning original pointer...\n");
101
102 return retval;
103}
104
105
106/*
107SF_TYPE(SFBool, sfbool, Bool)
108MF_TYPE(MFBool, mfbool, Bool)
109SF_TYPE(SFColor, sfcolor, Color)
110MF_TYPE(MFColor, mfcolor, Color)
111SF_TYPE(SFColorRGBA, sfcolorrgba, ColorRGBA)
112MF_TYPE(MFColorRGBA, mfcolorrgba, ColorRGBA)
113*/
114
115/* how many rows are in this data type? SF nodes have 1, other nodes... */
116static int returnNumberOfRows(int datatype,union anyVrml *memptr) {
117 switch (datatype) {
118
119 #define SF_TYPE(fttype, type, ttype) \
120 case FIELDTYPE_##fttype: return 1; break;
121
122 #define MF_TYPE(fttype, type, ttype) \
123 case FIELDTYPE_##fttype: return memptr->type.n; break;
124
125#include "../vrml_parser/VrmlTypeList.h"
126
127#undef SF_TYPE
128#undef MF_TYPE
129
130 default:
131 parseError("Unsupported type in defaultValue!");
132
133
134
135 }
136 return 1;
137}
138
139
140
141/* set a field; used in JavaScript, and in the Parser VRML parser
142
143 fields are:
144 ptr: pointer to a node (eg, X3D_Box)
145 field: string field name (eg, "size")
146 value: string of value (eg "2 2 2");
147
148This is used mainly in parsing */
149
150void setField_fromJavascript (struct X3D_Node *node, char *field, char *value, int isXML) {
151 int foffset;
152 int coffset;
153 int ctype;
154 int ctmp;
155
156 #ifdef SETFIELDVERBOSE
157 printf ("\nsetField_fromJavascript, node %p field %s value %s\n", (char*) node, field, value);
158 #endif
159
160 /* is this a valid field? */
161 foffset = findRoutedFieldInFIELDNAMES(node,field,1);
162 if (foffset < 0) {
163 ConsoleMessage ("field %s is not a valid field of a node %s",field,stringNodeType(node->_nodeType));
164 printf ("field %s is not a valid field of a node %s\n",field,stringNodeType(node->_nodeType));
165 return;
166 }
167
168 /* get offsets for this field in this nodeType */
169 #ifdef SETFIELDVERBOSE
170 printf ("getting nodeOffsets for type %s field %s value %s\n",stringNodeType(node->_nodeType),field,value);
171 #endif
172
173 findFieldInOFFSETS(node->_nodeType, foffset, &coffset, &ctype, &ctmp);
174
175 #ifdef SETFIELDVERBOSE
176 printf ("so, offset is %d, type %d value %s\n",coffset, ctype, value);
177 #endif
178
179 if (coffset <= 0) {
180 printf ("setField_fromJavascript, trouble finding field %s in node %s\n",field,stringNodeType(node->_nodeType));
181 if(isProto(node))
182 printf("this is a Proto...have to go through PROTO defs to get to it\n");
183 /*
184 printf ("is this maybe a PROTO?? if so, it will be a Group node with FreeWRL__protoDef set to an index\n");
185 if (node->_nodeType == NODE_Group) {
186 struct X3D_Group *group = (struct X3D_Group *)node;
187 printf ("it IS a group...\n");
188 if (group->FreeWRL__protoDef!= INT_ID_UNDEFINED) {
189 printf ("and, this is a PROTO...have to go through PROTO defs to get to it\n");
190 }
191 }
192 */
193 }
194
195 Parser_scanStringValueToMem(node, (size_t) coffset, ctype, value, isXML);
196}
197
198
199/* and incoming EAI event has come in, and the destination is an inputOnly field of a script.
200 Make It So. This mimics the routing function "getField_ToJavascript" except that we do not
201 have a routing entry for the from address and size and type, so we have to do this by hand.
202*/
203
204static int setField_FromEAI_ToScript(int tonode, int toname,
205 int datatype, void *data, unsigned rowcount) {
206
207
208 int datalen;
209
210 #ifdef SETFIELDVERBOSE
211 printf ("doing setField_FromEAI_ToScript, for script %u, nameIndex %u, type %s\n",tonode, toname, stringFieldtypeType(datatype));
212 #endif
213
214 switch (datatype) {
215 case FIELDTYPE_SFBool:
216 case FIELDTYPE_SFFloat:
217 case FIELDTYPE_SFTime:
218 case FIELDTYPE_SFDouble:
219 case FIELDTYPE_SFInt32:
220 case FIELDTYPE_SFString:
221
222 /* this one expects datalen to be in bytes */
223 datalen = returnElementLength(datatype) * returnElementRowSize(datatype);
224 #ifdef SETFIELDVERBOSE
225 printf ("SFSingle in setField_FromEAI_ToScript, setting script, dataLength is made up of %d x %d x %d for %s\n",
226 returnElementLength(datatype), returnElementRowSize(datatype), rowcount, stringFieldtypeType(datatype));
227 #endif
228
229 set_one_ECMAtype (tonode, toname, datatype, data, datalen);
230 break;
231 case FIELDTYPE_SFColor:
232 case FIELDTYPE_SFVec2f:
233 case FIELDTYPE_SFVec3f:
234 case FIELDTYPE_SFVec3d:
235 case FIELDTYPE_SFRotation:
236 /* this one expects datalen to be in bytes */
237 datalen = returnElementLength(datatype) * returnElementRowSize(datatype);
238 #ifdef SETFIELDVERBOSE
239 printf ("SFColor-style in setField_FromEAI_ToScript, setting script, dataLength is made up of %d x %d x %d for %s\n",
240 returnElementLength(datatype), returnElementRowSize(datatype), rowcount, stringFieldtypeType(datatype));
241 #endif
242 set_one_MultiElementType (tonode, toname, data, datalen);
243 break;
244 case FIELDTYPE_SFNode:
245 #ifdef SETFIELDVERBOSE
246 printf ("SFNode copy, tonode %u...\n",tonode);
247 #endif
248
249 datalen = returnElementLength(FIELDTYPE_SFNode);
250 set_one_MultiElementType (tonode, toname, data, datalen);
251 break;
252
253
254
255 case FIELDTYPE_MFColor:
256 case FIELDTYPE_MFVec3f:
257 case FIELDTYPE_MFVec3d:
258 case FIELDTYPE_MFVec2f:
259 case FIELDTYPE_MFFloat:
260 case FIELDTYPE_MFTime:
261 case FIELDTYPE_MFInt32:
262 case FIELDTYPE_MFString:
263 case FIELDTYPE_MFNode:
264 case FIELDTYPE_MFRotation:
265 case FIELDTYPE_SFImage:
266 #ifdef SETFIELDVERBOSE
267 printf ("going to call MF types in set_one_MFElementType rowcount %d\n",rowcount);
268 #endif
269 set_one_MFElementType(tonode, toname, datatype, data, rowcount);
270 break;
271 default : {
272 printf("WARNING: setField_FromEAI_ToScript, type %s not handled yet\n",
273 stringFieldtypeType(datatype));
274 }
275 }
276
277
278 return TRUE;
279
280}
281
282void fudgeIfNeeded(int myptr,int myoffset){
283 /*
284 * Problem to solve:
285 * Before operating on a set_ABC field that is of type multi,
286 * we should copy across the data from the ABC field,
287 * because if we do not, ONEVAL will not work.
288 *
289 * Method: We have been given myptr and myoffset (by the EAI request).
290 * We can map the offset to an name like set_ABC, and map set_ABC to ABC
291 * We can then copy the data from ABC to set_ABC
292 */
293 struct X3D_Node *boxptr;
294 int *np;
295 int f_indx;
296 int myc = 0;
297 int scanning = TRUE;
298 int foundSet = 0; /* Did we find set_ABC ? */
299 int foundAlt = 0; /* Did we find ABC ? */
300
301 char *setnameIs = NULL ;
302 char *altnameIs = NULL ;
303 int relSet = 0 ; /* RoutingElementLength of set_ABC */
304 int relAlt = 0 ; /* RoutingElementLength of ABC */
305
306 void *sourceNode = NULL;
307 void *destNode = NULL;
308
309 boxptr = getEAINodeFromTable(myptr,-1);
310 #ifdef SETFIELDVERBOSE
311 printf ("%s,%d fudgeIfNeeded node %u -> %p\n",__FILE__,__LINE__, (unsigned int)myptr, boxptr);
312 #endif
313
314 /* Iterate over all the fields in the node because there is no easy way of getting to the name from the offset */
315 np = (int *) NODE_OFFSETS[boxptr->_nodeType];
316 while (scanning && (*np != INT_ID_UNDEFINED)) {
317 /* We need not skip hidden fields (EAI cannot see them anyway) */
318
319 /* The primary basis of comparison is 'myoffset' because this is
320 * what the EAI request passed to FreeWRL.
321 */
322 if (myoffset == np[1]) {
323 #ifdef SETFIELDVERBOSE
324 printf("Field %d %s ", myc, stringFieldType(np[0]));
325 #endif
326 if (0 == strncmp("set_",stringFieldType(np[0]),4)) {
327 int offset=np[1];
328 #ifdef SETFIELDVERBOSE
329 printf(" , Found a set_ ; offset=%d\n",offset);
330 #endif
331
332 /* We do not really need setnameIs (except to calculate altnamesIs
333 * but we do use it later on just for debugging.
334 */
335 setnameIs = (char *)stringFieldType(np[0]);
336 altnameIs = setnameIs+4;
337
338 /* Use this as a flag to see if we need to return quickly or not. */
339 foundSet = myc;
340
341 /* This has to be negative and the same as what
342 * we are going to be copying from. Also, we need
343 * to pass this to Multimemcpy
344 */
345 relSet = returnRoutingElementLength(np[2]);
346
347 /* Also needed by Multimemcpy */
348 destNode = offsetPointer_deref(void *, boxptr, offset);
349 } else {
350 #ifdef SETFIELDVERBOSE
351 printf("\n");
352 #endif
353 }
354 scanning = FALSE;
355 }
356 myc ++;
357 np += FIELDOFFSET_LENGTH;
358 }
359
360 /* If foundSet is zero, then the field name is not set_ABC */
361 if (!foundSet) return;
362
363 #ifdef SETFIELDVERBOSE
364 printf("%s,%d setnameIs=%s , altnameIs=%s foundSet=%d relSet=%d\n",__FILE__,__LINE__,setnameIs,altnameIs,foundSet,relSet);
365 #endif
366
367 /* We now know everything we need to know about the destination;
368 * find out what we need to know about the source
369 */
370
371 f_indx = findFieldInFIELDNAMES(altnameIs);
372 /* Mind, is findFieldInFIELDNAMES any quicker ?
373 * If hashing is not used, then using strcmp below might be faster
374 * because we are only comparing a subset, not all the names...
375 */
376
377 #ifdef SETFIELDVERBOSE
378 printf ("field index %s is %d, it had better not be -1 !! \n",altnameIs,f_indx);
379 #endif
380 myc = 0;
381 scanning = TRUE;
382 np = (int *) NODE_OFFSETS[boxptr->_nodeType];
383 while (scanning && (*np != INT_ID_UNDEFINED)) {
384 /* It is now less messy if we skip the hidden fields */
385 if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
386 #ifdef SETFIELDVERBOSE
387 printf("Field %d %s", myc, stringFieldType(np[0]));
388 #endif
389
390 /* We need not compare strings, but see comment about findFieldInFIELDNAMES above
391 if (0 == strcmp(altnameIs,stringFieldType(np[0]))) {
392 */
393 if (f_indx == np[0]) {
394 #ifdef SETFIELDVERBOSE
395 printf(" , Found alternate name, ie %s f_indx=%d offset=%d\n",altnameIs,f_indx,np[1]);
396 #endif
397 foundAlt = myc;
398
399 /* See relSet comment above */
400 relAlt = returnRoutingElementLength(np[2]);
401
402 /* Also needed by Multimemcpy */
403 sourceNode = offsetPointer_deref(void *, boxptr, np[1]);
404 scanning = FALSE;
405 } else {
406 #ifdef SETFIELDVERBOSE
407 printf("\n");
408 #endif
409 }
410 }
411 myc ++;
412 np += FIELDOFFSET_LENGTH;
413 }
414 if (!foundAlt) return;
415
416 #ifdef SETFIELDVERBOSE
417 printf("%s,%d setnameIs=%s , altnameIs=%s foundAlt=%d relAlt=%d\n",__FILE__,__LINE__,setnameIs,altnameIs,foundAlt,relAlt);
418 #endif
419
420 /* final check for compatibility */
421 if (relAlt == relSet && relSet < 0) {
422 #ifdef SETFIELDVERBOSE
423 printf("%s,%d About to call Multimemcpy (boxptr=%p, boxptr=%p, destNode=%p, sourceNode=%p, relAlt=%d);\n",__FILE__, __LINE__, boxptr, boxptr, destNode, sourceNode, relAlt);
424 #endif
425 Multimemcpy (boxptr, boxptr, destNode, sourceNode, relAlt);
426 } else {
427 return;
428 }
429
430 #ifdef SETFIELDVERBOSE
431 printf("=================================== Fudged %s,%d ==================================\n",__FILE__,__LINE__);
432 dumpOneNode(myptr);
433 printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
434 #endif
435
436 return;
437}
438
439void dumpOneNode(int myptr) {
440 struct X3D_Node *boxptr;
441 bool eaiverbose = gglobal()->EAI_C_CommonFunctions.eaiverbose;
442 boxptr = getEAINodeFromTable(myptr,-1);
443
444 if (eaiverbose) {
445 printf ("GETFIELDDEFS, node %u -> %p\n",(unsigned int)myptr, boxptr);
446 }
447 dumpOne_X3D_Node(boxptr) ;
448}
449
450void dumpOne_X3D_Node(struct X3D_Node * boxptr) {
451 int myc;
452 int *np;
453
454 char *tmpptr;
455 int dtmp;
456 char ctmp;
457 char utilBuf[EAIREADSIZE];
458 int errcount;
459
460 if (boxptr == 0) {
461 printf ("makeFIELDDEFret have null node here \n");
462 return;
463 }
464
465 printf ("node type is %s\n",stringNodeType(boxptr->_nodeType));
466
467 /* Iterate over all the fields in the node */
468 np = (int *) NODE_OFFSETS[boxptr->_nodeType];
469 myc = 0;
470 while (*np != -1) {
471 /* is this a hidden field? */
472 if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
473 ctmp = (char) mapFieldTypeToEAItype(np[2]);
474 dtmp = mapEAItypeToFieldType(ctmp);
475
476 tmpptr = offsetPointer_deref (char *, boxptr,np[1]);
477 printf("%s,%d ",__FILE__,__LINE__);
478 printf("Field %d %s , ", myc, stringFieldType(np[0]));
479 printf("offset=%d bytes , ", np[1]);
480/*
481 printf("field_type= %c (%d) , ", ctmp , dtmp);
482 printf("Routing=%s , ", stringKeywordType(np[3]));
483 printf("Spec=%d , ", np[4]) ;
484*/
485 errcount = UtilEAI_Convert_mem_to_ASCII (dtmp,tmpptr, utilBuf);
486 if (0 == errcount) {
487 printf ("\t\tValue = %s\n",utilBuf);
488 } else {
489 printf ("\t\tValue = indeterminate....\n");
490 }
491 myc ++;
492 }
493 np += FIELDOFFSET_LENGTH;
494 }
495}
496
497/* an incoming EAI/CLASS event has come in, convert the ASCII characters
498 * to an internal representation, and act upon it */
499
500unsigned int setField_FromEAI (char *ptr) {
501 unsigned char nt;
502 int datatype;
503 int nodeIndex, fieldIndex;
504 struct X3D_Node* nodeptr;
505 int offset;
506 int myoffset;
507 unsigned int scripttype;
508 char *eol;
509
510 char * memptr = 0;
511 struct X3D_Node* myptr = 0;
512
513 int valIndex;
514 struct Multi_Color *tcol;
515 int retint; /* used to get return value of sscanf */
516
517 union anyVrml myAnyValue;
518
519 #ifdef SETFIELDVERBOSE
520 printf ("%s,%d setField_FromEAI, string :%s:\n",__FILE__,__LINE__,ptr);
521 #endif
522
523 /* we have an event, get the data properly scanned in from the ASCII string. */
524
525 /* node type */
526 while (*ptr==' ')ptr++; /* remove blank space at front of string */
527 nt = *ptr; ptr++; /* get the ASCII indication of node type */
528 datatype = mapEAItypeToFieldType(nt);
529
530 /* blank space */
531 ptr++;
532
533 /* nodeptr, offset */
534 retint=sscanf (ptr, "%d %d %d",&nodeIndex, &fieldIndex, &scripttype);
535 if (retint != 3) ConsoleMessage ("setField_FromEAI: error reading 3 numbers from the string :%s:\n",ptr);
536 #ifdef SETFIELDVERBOSE
537 printf("setField_FromEAI: nodeIndex=%d, fieldIndex=%d, scripttype=%d\n",nodeIndex, fieldIndex, scripttype);
538 #endif
539
540 while ((*ptr) > ' ') ptr++; /* node ptr */
541 while ((*ptr) == ' ') ptr++; /* inter number space(s) */
542 while ((*ptr) > ' ') ptr++; /* node offset */
543 while ((*ptr) == ' ') ptr++; /* inter number space(s) */
544 while ((*ptr) > ' ') ptr++; /* script type */
545
546 #ifdef SETFIELDVERBOSE
547 {
548 struct X3D_Node *np;
549 int nt;
550 /* get the actual node pointer from this index */
551 np = getEAINodeFromTable(nodeIndex,fieldIndex);
552
553 printf("=================================== Pre op %s,%d ==================================\n",__FILE__,__LINE__);
554 dumpOneNode(nodeIndex);
555 printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
556
557 nt = getEAINodeTypeFromTable(nodeIndex);
558
559 printf ("EAI_SendEvent, type %s, nodeptr (index %d) %u offset %d script type %d ",
560 stringFieldtypeType(datatype),nodeIndex, np->_nodeType, fieldIndex, scripttype);
561 printf ("np->_nodeType %s\n",stringNodeType(np->_nodeType));
562
563 if (nt == EAI_NODETYPE_SCRIPT) printf ("setField_FromEAI - sending to a script node!\n");
564 else if (nt == EAI_NODETYPE_PROTO) printf ("setField_FromEAI - sending to a script node!\n");
565 else if(nt == EAI_NODETYPE_STANDARD) printf ("setField_FromEAI - sending to a standard node!\n");
566 else printf ("setField_FromEAI - unknown type!\n");
567 }
568 #endif
569
570
571 /* We have either a event to a memory location, or to a script. */
572 /* the field scripttype tells us whether this is true or not. */
573
574 if (scripttype == EAI_NODETYPE_SCRIPT) {
575 /* a local temporary area for us */
576 memptr = (char *) &myAnyValue;
577 } else {
578 memptr = (char *) getEAIMemoryPointer (nodeIndex,fieldIndex);
579 }
580
581 offset = getEAIActualOffset(nodeIndex, fieldIndex);
582 myoffset = offset;
583 nodeptr = getEAINodeFromTable(nodeIndex,fieldIndex);
584 myptr = nodeptr;
585
586 /* now, we are at start of the incoming data. */
587 /* lets go to the first non-blank character in the string */
588 while (*ptr == ' ') ptr++;
589
590 #ifdef SETFIELDVERBOSE
591 printf ("setField_FromEAI EAI_SendEvent, event string now is :%s:\n",ptr);
592 #endif
593
594 /* is this a MF node, that has floats or ints, and the set1Value method is called? */
595 /* check out the java external/field/MF*java files for the string "ONEVAL " */
596 if (strncmp("ONEVAL ",ptr, strlen("ONEVAL ")) == 0) {
597 #ifdef SETFIELDVERBOSE
598 printf ("%s,%d This is a ONEVAL operation\n",__FILE__,__LINE__);
599 #endif
600
601 fudgeIfNeeded(nodeIndex,myoffset);
602
603 ptr += strlen ("ONEVAL ");
604
605 /* find out which element the user wants to set - that should be the next number */
606 while (*ptr==' ')ptr++;
607 retint=sscanf (ptr,"%d",&valIndex);
608 #ifdef SETFIELDVERBOSE
609 printf ("%s,%d Request to set element %d\n",__FILE__,__LINE__,valIndex);
610 #endif
611
612 if (retint != 1) ConsoleMessage ("setField_FromEAI: error reading 1 numbers from the string :%s:\n",ptr);
613 while (*ptr>' ')ptr++; /* past the number */
614 while (*ptr==' ')ptr++;
615
616 /* lets do some bounds checking here. */
617 tcol = (struct Multi_Color *) memptr;
618 #ifdef SETFIELDVERBOSE
619 printf ("%s,%d now, we have valIndex %d, tcol->n %d\n",__FILE__,__LINE__,valIndex,tcol->n);
620 #endif
621
622 if (valIndex >= tcol->n) {
623 void *nmemptr;
624 int malSize;
625
626 /* expand this array so that we can put the value in */
627 /*
628 printf ("have to expand MF value, had %d, wanted %d\n",tcol->n, valIndex);
629 printf ("and we have elementLength %d and rowSize %d\n",returnElementLength(datatype) ,returnElementRowSize(datatype));
630 */
631
632 /* if we want index "5", say, we make it "5+1" long because we are zero based */
633 malSize = (valIndex+1) * returnElementLength(datatype) * returnElementRowSize(datatype);
634 nmemptr = MALLOC(void *, malSize);
635
636 /* zero the new array - this will give us null holes, maybe */
637 bzero (nmemptr,(size_t)malSize);
638 /* printf ("locked and loaded %d bytes\n",malSize); */
639
640 /* copy the old data over */
641 memcpy (nmemptr,tcol->p, tcol->n * returnElementLength(datatype) * returnElementRowSize(datatype));
642
643 /* printf ("copied over %d bytes from the old school \n",tcol->n * returnElementLength(datatype) * returnElementRowSize(datatype)); */
644
645 /* if this is Strings, then verify that ALL pointers are ok, and point to some string */
646 if (datatype == FIELDTYPE_MFString) {
647 int count;
648 struct Uni_String * *strarr = (struct Uni_String **) nmemptr;
649 for (count = 0; count <=valIndex ; count++) {
650
651 /* is this one NULL? If so, make it into something */
652 if ((*strarr) == NULL) *strarr = newASCIIString (""); /* "created from set1Value" */
653 /* printf ("index %d, the stringis :%s:\n",count,(*strarr)->strptr); */
654 strarr++;
655 }
656 }
657
658 tcol->n = 0;
659 FREE_IF_NZ(tcol->p);
660 tcol->p = nmemptr;
661 tcol->n = valIndex+1;
662
663 /* printf ("now, we have valIndex %d, tcol->n %d\n",valIndex,tcol->n); */
664 } else {
665 #ifdef SETFIELDVERBOSE
666 printf ("%s,%d Size OK, replacing element %d in %d elements\n",__FILE__,__LINE__,valIndex,tcol->n);
667 #endif
668 }
669
670
671 /* if this is a struct Multi* node type, move the actual memory pointer to the data */
672 memptr = Multi_Struct_memptr(datatype, (void *) memptr);
673
674 /* and index into that array; we have the index, and sizes to worry about */
675 memptr += valIndex * returnElementLength(datatype) * returnElementRowSize(datatype);
676
677 /* and change the nodetype to reflect this change */
678 datatype = convertToSFType(datatype);
679
680 /* For ONEVAL need to pass memptr, not nodeptr */
681 myptr = X3D_NODE(memptr);
682 myoffset = 0;
683 } else {
684 #ifdef SETFIELDVERBOSE
685 printf ("%s,%d Not a ONEVAL operation\n",__FILE__,__LINE__);
686 #endif
687 }
688
689 /* lets replace the end of the string with a NULL, for parsing purposes */
690 eol = strchr (ptr,'\n'); if (eol != NULL) *eol = '\0';
691
692 /* at this point, we have:
693 memptr = pointer to memory location to start scanning;
694 offset = actual offset in node, or 0 if ONEVAL invoked;
695 nodeptr = actual memory pointer of X3D_Node* */
696
697 /* first, parse the value into the local variable */
698 Parser_scanStringValueToMem(myptr,myoffset,datatype,ptr,FALSE);
699
700 if (scripttype == EAI_NODETYPE_SCRIPT) {
701 struct Shader_Script * sp;
702 int rowCount;
703
704 /* we send along the script number, not the node pointer */
705 sp = (struct Shader_Script *) (X3D_SCRIPT(nodeptr)->__scriptObj);
706
707 mark_script (sp->num);
708
709 /* now, send the number of rows along; SFs return 1, MFS return rows */
710 rowCount = returnNumberOfRows(datatype,(union anyVrml *) memptr);
711 #ifdef SETFIELDVERBOSE
712 printf("%s,%d rowCount=%d\n",__FILE__,__LINE__,rowCount);
713 #endif
714
715 /* inch the type along, to the data pointer */
716 memptr = Multi_Struct_memptr(datatype, memptr);
717
718 setField_FromEAI_ToScript(sp->num,offset,datatype,memptr,rowCount);
719 } else {
720
721
722 /* if this is a geometry, make it re-render.
723 Some nodes (PROTO interface params w/o IS's)
724 will have an offset of zero, and are thus not
725 "real" nodes, only memory locations
726 */
727
728 update_node ((void *)nodeptr);
729
730 /* if anything uses this for routing, tell it that it has changed */
731 MARK_EVENT (X3D_NODE(nodeptr),offset);
732 }
733
734
735 #ifdef SETFIELDVERBOSE
736 printf("================================== Post op %s,%d ==================================\n",__FILE__,__LINE__);
737 dumpOneNode(nodeIndex);
738 printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
739 #endif
740
741 /* replace the end of the line with a newline */
742 if (eol != NULL) *eol = '\n';
743 return TRUE;
744
745}
746
747
748/* find the ASCII string name of this field of this node */
749char *findFIELDNAMESfromNodeOffset(struct X3D_Node *node, int offset) {
750 int* np;
751 if (node == 0) return "unknown";
752
753 np = (int *) NODE_OFFSETS[node->_nodeType];
754 np++; /* go to the offset field */
755
756 while ((*np != -1) && (*np != offset)) np += FIELDOFFSET_LENGTH;
757
758 if (*np == -1) return "fieldNotFound";
759
760 /* go back to the field name */
761 np --;
762 return ((char *) FIELDNAMES[*np]);
763}
764
765/* go through the generated table FIELDTYPES, and find the int of this string, returning it, or -1 on error
766 or if it is an "internal" field */
767int findFieldInARR(const char* field, const char** arr, size_t cnt)
768{
769 int x;
770 size_t mystrlen;
771
772 if (field == NULL) return -1;
773
774 #ifdef SETFIELDVERBOSE
775 if (field[0] == '_') {
776 printf ("findFieldInFIELDNAMES - internal field %s\n",field);
777 }
778 #endif
779
780 mystrlen = strlen(field);
781 for (x=0; x!=cnt; ++x) {
782 if (strlen(arr[x]) == mystrlen) {
783 if (strcmp(field, arr[x])==0) return x;
784 }
785 }
786 return -1;
787
788}
789#define DEF_FINDFIELD(arr) \
790 int findFieldIn##arr(const char* field) \
791 { \
792 return findFieldInARR(field, arr, arr##_COUNT); \
793 }
794DEF_FINDFIELD(FIELDNAMES)
795DEF_FINDFIELD(FIELD)
796DEF_FINDFIELD(EXPOSED_FIELD)
797DEF_FINDFIELD(EVENT_IN)
798DEF_FINDFIELD(EVENT_OUT)
799DEF_FINDFIELD(KEYWORDS)
800DEF_FINDFIELD(PROTOKEYWORDS)
801DEF_FINDFIELD(NODES)
802DEF_FINDFIELD(PROFILES)
803DEF_FINDFIELD(COMPONENTS)
804DEF_FINDFIELD(FIELDTYPES)
805DEF_FINDFIELD(X3DSPECIAL)
806DEF_FINDFIELD(GEOSPATIAL)
807DEF_FINDFIELD(MULTITEXTUREMODE);
808DEF_FINDFIELD(MULTITEXTURESOURCE);
809DEF_FINDFIELD(MULTITEXTUREFUNCTION);
810
811/* lets see if this node has a routed field fromTo = 0 = from node, anything else = to node */
812/* returns the FIELDNAMES index. */
813/* for user-fields, the additional check is skipped */
814int findRoutedFieldInARR (struct X3D_Node * node, const char *field, int fromTo,
815 const char** arr, size_t cnt, BOOL user) {
816 int retval;
817 char mychar[200];
818 int a,b,c;
819
820 retval = -1;
821
822#define FIELDCHECK(fld) \
823 if (retval >= 0) { \
824 if (user) return retval; \
825 {int fieldNamesIndex = findIndexInFIELDNAMES(retval, arr, cnt); \
826 if (fieldNamesIndex >= 0) { \
827 findFieldInOFFSETS (node->_nodeType, fieldNamesIndex,\
828 &a, &b, &c); \
829 /* did this return any of the ints as != -1? */ \
830 /* printf (" findRoutedField for field %s, nodetype %s is %d\n", fld,stringNodeType(node->_nodeType),a); */ \
831 if (a >= 0) return retval; /* found it! */ \
832 }} \
833 }
834
835
836 /* step try the field as is. */
837 retval = findFieldInARR(field, arr, cnt);
838 /* printf ("findRoutedField, field %s retval %d\n",field,retval); */
839 FIELDCHECK (field)
840
841 /* try REMOVING/STRIPPING the "set_" or "_changed" */
842 strncpy (mychar, field, 100);
843 if (fromTo != 0) {
844 if (strlen(field) > strlen("set_"))
845 retval=findFieldInARR(mychar+strlen("set_"), arr, cnt);
846 } else {
847 if (strlen(field) > strlen("_changed")) {
848 mychar[strlen(field) - strlen("_changed")] = '\0';
849 retval = findFieldInARR(mychar, arr, cnt);
850 }
851 }
852 /* printf ("findRoutedField, mychar %s retval %d\n",mychar,retval); */
853 FIELDCHECK (mychar)
854
855 /* try ADDING the "set_" or "_changed" some nodes have fields ending in "_changed" - maybe the
856 user forgot about that? (eg, ProximitySensor) */
857 if (fromTo != 0) {
858 strcpy (mychar,"set_");
859 strncat (mychar, field,100);
860 retval=findFieldInARR(mychar, arr, cnt);
861 } else {
862 strncpy (mychar, field, 100);
863 strcat (mychar,"_changed");
864 retval = findFieldInARR(mychar, arr, cnt);
865 }
866 /* printf ("findRoutedField, mychar %s retval %d\n",mychar,retval); */
867 FIELDCHECK (mychar)
868
869
870 return retval;
871}
872#define DEF_FINDROUTEDFIELD(arr) \
873 int findRoutedFieldIn##arr(struct X3D_Node* node, const char* field, int fromTo) \
874 { \
875 return findRoutedFieldInARR(node, field, fromTo, arr, arr##_COUNT, FALSE); \
876 }
877DEF_FINDROUTEDFIELD(FIELDNAMES)
878DEF_FINDROUTEDFIELD(EXPOSED_FIELD)
879DEF_FINDROUTEDFIELD(EVENT_IN)
880DEF_FINDROUTEDFIELD(EVENT_OUT)
881
882
883/* go through the OFFSETS for this node, looking for field, and return offset, type, and kind */
884void findFieldInOFFSETS(int nodeType, const int field, int *coffset, int *ctype, int *ckind) {
885 int *x;
886 int X3DLevel;
887 int mask = 0;
888
889 x = (int *) NODE_OFFSETS[nodeType];
890
891 #ifdef SETFIELDVERBOSE
892 printf ("findFieldInOFFSETS, nodeType %s\n",stringNodeType(nodeType));
893 printf ("findFieldInOffsets, comparing %d to %d\n",*x, field);
894 #endif
895
896 while ((*x != field) && (*x != -1)) {
897 x += FIELDOFFSET_LENGTH;
898 }
899 if (*x == field) {
900 x++; *coffset = (int)*x; x++; *ctype = (int)*x; x++; *ckind = (int)*x; x++; X3DLevel = (int)*x;
901
902 #ifdef SETFIELDVERBOSE
903 printf ("found field, coffset %d ctype %d ckind %d X3DLevel %x\n",*coffset, *ctype, *ckind, X3DLevel);
904 #endif
905
906 /* do we care if, maybe, this field is not correct for requested version of FreeWRL? */
907 if (gglobal()->internalc.global_strictParsing) {
908 if (inputFileVersion[0] == 2) { /* VRML 2.0 */
909 if ((X3DLevel & SPEC_VRML) == SPEC_VRML) {
910 return; /* field ok */
911 }
912 } else if (inputFileVersion[0] == 3) { /* X3D V3.x */
913 switch (inputFileVersion[1]) {
914 case 0: mask = SPEC_X3D30; break;
915 case 1: mask = SPEC_X3D31; break;
916 case 2: mask = SPEC_X3D32; break;
917 case 3: mask = SPEC_X3D33; break;
918 case 4: mask = SPEC_X3D34; break;
919 default: {printf ("unknown X3D level %d\n",inputFileVersion[1]);
920 mask = SPEC_X3D33;
921 }
922 }
923 if ((X3DLevel & mask) == mask) {
924 return; /* field ok */
925 }
926 } else {
927 printf ("unknown input file version %d for strictParsing! help!\n",inputFileVersion[0]);
928 }
929 ConsoleMessage ("strictParsing, Node %s field %s is not valid for X3D version %d.%d",
930 stringNodeType(nodeType),stringFieldType(field),inputFileVersion[0],inputFileVersion[1]);
931 }
932
933 return;
934 }
935 if (*x == -1) {
936 #ifdef SETFIELDVERBOSE
937 printf ("did not find field %d in OFFSETS\n",field);
938 #endif
939
940 *coffset = -1; *ctype = -1, *ckind = -1;
941 return;
942 }
943}
944
945
946/************************************************************************/
947/* a script is returning a MFNode type; add or remove this to the C */
948/* children field */
949/* note params - tn is the address of the actual field, parent is parent*/
950/* structure */
951/************************************************************************/
952
953void getMFNodetype (struct X3D_Node *strp, struct Multi_Node *tn, struct X3D_Node *parent, int ar) {
954 /* now, perform the add/remove */
955 AddRemoveChildren (parent, tn, &strp, 1, ar,__FILE__,__LINE__);
956}
957
958
959/* Map the given index into arr to an index into FIELDNAMES or -1, if the
960 * string in question isn't there. */
961int findIndexInFIELDNAMES(int index, const char** arr, size_t arrCnt) {
962 int i;
963
964 /* If this is already FIELDNAMES, return index. */
965 if(arr==FIELDNAMES)
966 return index;
967
968 /* Look for the string */
969 for(i=0; i!=FIELDNAMES_COUNT; ++i) {
970 if(!strcmp(FIELDNAMES[i], arr[index]))
971 return i;
972 }
973
974 /* Not found */
975 return -1;
976}