1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2019
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / Scene Graph sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 
27 #include <gpac/internal/scenegraph_dev.h>
28 /*MPEG4 tags (for internal nodes)*/
29 #include <gpac/nodes_mpeg4.h>
30 
31 
32 #ifndef GPAC_DISABLE_VRML
33 
format_sftime_string(Fixed _val,char * str)34 static void format_sftime_string(Fixed _val, char *str)
35 {
36 	u32 h, m, s;
37 	Bool neg = 0;
38 	Float val = FIX2FLT(_val);
39 	if (val<0) {
40 		val = -val;
41 		neg = 1;
42 	}
43 	h = (u32) (val/3600);
44 	m = (u32) (val/60) - h*60;
45 	s = (u32) (val) - h*3600 - m*60;
46 	sprintf(str, "%s%02d:%02d:%02d", neg ? "-" : "", h, m, s);
47 }
48 
valuator_get_output(M_Valuator * p,GenMFField * inMFField,u32 inType,Bool do_sum,u32 i,SFVec4f * output,u32 * num_out)49 static void valuator_get_output(M_Valuator *p, GenMFField *inMFField, u32 inType, Bool do_sum, u32 i, SFVec4f *output, u32 *num_out)
50 {
51 	if (!inMFField) return;
52 
53 	switch (inType) {
54 	case GF_SG_VRML_MFINT32:
55 	{
56 		SFInt32 sfi = ((MFInt32 *)inMFField)->vals[i];
57 		Fixed vi = INT2FIX(sfi);
58 		output->x = gf_mulfix(p->Factor1, vi) + p->Offset1;
59 		output->y = gf_mulfix(p->Factor2, vi) + p->Offset2;
60 		output->z = gf_mulfix(p->Factor3, vi) + p->Offset3;
61 		output->q = gf_mulfix(p->Factor4, vi) + p->Offset4;
62 	}
63 	break;
64 	case GF_SG_VRML_MFFLOAT:
65 	{
66 		Fixed sff = ((MFFloat *)inMFField)->vals[i];
67 		output->x = gf_mulfix(p->Factor1, sff) + p->Offset1;
68 		output->y = gf_mulfix(p->Factor2, sff) + p->Offset2;
69 		output->z = gf_mulfix(p->Factor3, sff) + p->Offset3;
70 		output->q = gf_mulfix(p->Factor4, sff) + p->Offset4;
71 	}
72 	break;
73 	case GF_SG_VRML_MFCOLOR:
74 	{
75 		SFColor sfc = ((MFColor *)inMFField)->vals[i];
76 		output->x = gf_mulfix(p->Factor1, sfc.red) + p->Offset1;
77 		output->y = gf_mulfix(p->Factor2, sfc.green) + p->Offset2;
78 		output->z = gf_mulfix(p->Factor3, sfc.blue) + p->Offset3;
79 		output->q = p->Offset4;
80 		*num_out = 3;
81 	}
82 	break;
83 	case GF_SG_VRML_MFVEC2F:
84 	{
85 		SFVec2f sfv = ((MFVec2f *)inMFField)->vals[i];
86 		output->x = gf_mulfix(p->Factor1, sfv.x) + p->Offset1;
87 		output->y = gf_mulfix(p->Factor2, sfv.y) + p->Offset2;
88 		output->z = p->Offset3;
89 		output->q = p->Offset4;
90 		*num_out = 2;
91 	}
92 	break;
93 	case GF_SG_VRML_MFVEC3F:
94 	{
95 		SFVec3f sfv = ((MFVec3f *)inMFField)->vals[i];
96 		output->x = gf_mulfix(p->Factor1, sfv.x) + p->Offset1;
97 		output->y = gf_mulfix(p->Factor2, sfv.y) + p->Offset2;
98 		output->z = gf_mulfix(p->Factor3, sfv.z) + p->Offset3;
99 		output->q = p->Offset4;
100 		*num_out = 3;
101 	}
102 	break;
103 	case GF_SG_VRML_MFVEC4F:
104 	case GF_SG_VRML_MFROTATION:
105 	{
106 		SFVec4f sfv = ((MFVec4f *)inMFField)->vals[i];
107 		output->x = gf_mulfix(p->Factor1, sfv.x) + p->Offset1;
108 		output->y = gf_mulfix(p->Factor2, sfv.y) + p->Offset2;
109 		output->z = gf_mulfix(p->Factor3, sfv.z) + p->Offset3;
110 		output->q = gf_mulfix(p->Factor4, sfv.q) + p->Offset4;
111 		*num_out = 4;
112 	}
113 	break;
114 	case GF_SG_VRML_MFSTRING:
115 		/*cf below*/
116 		output->x = output->y = output->z = output->q = 0;
117 		if (((MFString *)inMFField)->vals[i]) {
118 			if (!stricmp(((MFString *)inMFField)->vals[i], "true")) {
119 				output->x = output->y = output->z = output->q = FIX_ONE;
120 			} else if (!strstr(((MFString *)inMFField)->vals[i], ".")) {
121 				output->x = INT2FIX( atoi(((MFString *)inMFField)->vals[i]) );
122 				output->y = output->z = output->q = output->x;
123 			} else {
124 				output->x = FLT2FIX( atof(((MFString *)inMFField)->vals[i]) );
125 				output->y = output->z = output->q = output->x;
126 			}
127 		}
128 
129 		output->x = gf_mulfix(p->Factor1, output->x) + p->Offset1;
130 		output->y = gf_mulfix(p->Factor2, output->y) + p->Offset2;
131 		output->z = gf_mulfix(p->Factor3, output->z) + p->Offset3;
132 		output->q = gf_mulfix(p->Factor4, output->q) + p->Offset4;
133 		break;
134 
135 	}
136 	if (do_sum) {
137 		output->x = output->x + output->y + output->z + output->q;
138 		output->y = output->z = output->q = output->x;
139 	}
140 }
141 
SetValuatorOutput(M_Valuator * p,SFVec4f * inSFField,GenMFField * inMFField,u32 inType)142 static void SetValuatorOutput(M_Valuator *p, SFVec4f *inSFField, GenMFField *inMFField, u32 inType)
143 {
144 	char str[500];
145 	u32 i, j;
146 	GF_Route *r;
147 	SFVec4f output, sf_out;
148 	MFVec4f *mf_output = (MFVec4f *)gf_node_get_private((GF_Node*)p);
149 	u32 count, num_out;
150 	Bool do_sum;
151 	output.x = output.y = output.z = output.q = 0;
152 	sf_out.x = sf_out.y = sf_out.z = sf_out.q = 0;
153 	if (!p->sgprivate->interact || !mf_output) return;
154 
155 	do_sum = p->Sum;
156 	num_out = 1;
157 
158 	if (!inMFField) {
159 		count = 1;
160 		output.x = gf_mulfix(p->Factor1, inSFField->x) + p->Offset1;
161 		output.y = gf_mulfix(p->Factor2, inSFField->y) + p->Offset2;
162 		output.z = gf_mulfix(p->Factor3, inSFField->z) + p->Offset3;
163 		output.q = gf_mulfix(p->Factor4, inSFField->q) + p->Offset4;
164 
165 		if (do_sum) {
166 			output.x = output.x + output.y + output.z + output.q;
167 			output.y = output.z = output.q = output.x;
168 			do_sum = 0;
169 		}
170 
171 		switch (inType) {
172 		case GF_SG_VRML_SFVEC2F:
173 			num_out = 2;
174 			break;
175 		case GF_SG_VRML_SFVEC3F:
176 		case GF_SG_VRML_SFCOLOR:
177 			num_out = 3;
178 			break;
179 		case GF_SG_VRML_SFVEC4F:
180 		case GF_SG_VRML_SFROTATION:
181 			num_out = 4;
182 			break;
183 		}
184 	} else {
185 		count = inMFField->count;
186 	}
187 
188 	/*allocate temp buffer and compute values*/
189 	gf_sg_vrml_mf_alloc(mf_output, GF_SG_VRML_MFVEC4F, count);
190 	for (i=0; i<count; i++) {
191 		if (inType) {
192 			valuator_get_output(p, inMFField, inType, do_sum, i, &output, &num_out);
193 			mf_output->vals[i] = output;
194 		} else if (!i) {
195 			mf_output->vals[0] = output;
196 		}
197 		if (!i) sf_out = output;
198 	}
199 
200 	gf_sg_vrml_mf_alloc(&p->outMFColor, GF_SG_VRML_MFCOLOR, count);
201 	gf_sg_vrml_mf_alloc(&p->outMFFloat, GF_SG_VRML_MFFLOAT, count);
202 	gf_sg_vrml_mf_alloc(&p->outMFInt32, GF_SG_VRML_MFINT32, count);
203 	gf_sg_vrml_mf_alloc(&p->outMFRotation, GF_SG_VRML_MFROTATION, count);
204 	gf_sg_vrml_mf_alloc(&p->outMFString, GF_SG_VRML_MFSTRING, count);
205 	gf_sg_vrml_mf_alloc(&p->outMFVec2f, GF_SG_VRML_MFVEC2F, count);
206 	gf_sg_vrml_mf_alloc(&p->outMFVec3f, GF_SG_VRML_MFVEC3F, count);
207 
208 	/*valuator is a special case, all routes are triggered*/
209 	j=0;
210 	while ((r = (GF_Route*)gf_list_enum(p->sgprivate->interact->routes, &j))) {
211 		if (r->FromNode != (GF_Node *)p) continue;
212 		if (!r->is_setup) gf_sg_route_setup(r);
213 		if (r->FromField.eventType != GF_SG_EVENT_OUT) continue;
214 
215 		/*TODO we could optimize more and check if the field has been set or not ...*/
216 		switch (r->FromField.fieldType) {
217 		case GF_SG_VRML_SFBOOL:
218 			p->outSFBool = (Bool) (sf_out.x ? 1 : 0);
219 			break;
220 		case GF_SG_VRML_SFFLOAT:
221 			p->outSFFloat = sf_out.x;
222 			break;
223 		case GF_SG_VRML_SFINT32:
224 			p->outSFInt32 = FIX2INT(sf_out.x);
225 			break;
226 		case GF_SG_VRML_SFTIME:
227 			p->outSFTime = (SFTime) FIX2FLT(sf_out.x);
228 			break;
229 		case GF_SG_VRML_SFROTATION:
230 			p->outSFRotation.x = sf_out.x;
231 			p->outSFRotation.y = sf_out.y;
232 			p->outSFRotation.z = sf_out.z;
233 			p->outSFRotation.q = sf_out.q;
234 			break;
235 		case GF_SG_VRML_SFCOLOR:
236 			p->outSFColor.red = sf_out.x;
237 			p->outSFColor.green = sf_out.y;
238 			p->outSFColor.blue = sf_out.z;
239 			break;
240 		case GF_SG_VRML_SFVEC2F:
241 			p->outSFVec2f.x = sf_out.x;
242 			p->outSFVec2f.y = sf_out.y;
243 			break;
244 		case GF_SG_VRML_SFVEC3F:
245 			p->outSFVec3f.x = sf_out.x;
246 			p->outSFVec3f.y = sf_out.y;
247 			p->outSFVec3f.z = sf_out.z;
248 			break;
249 		case GF_SG_VRML_SFSTRING:
250 			if (num_out==1) {
251 				if (inType==GF_SG_VRML_SFTIME) {
252 					format_sftime_string(output.x, str);
253 				} else {
254 					sprintf(str, "%.6f", FIX2FLT(sf_out.x));
255 				}
256 			} else if (num_out==2) {
257 				sprintf(str, "%.4f %.4f", FIX2FLT(sf_out.x), FIX2FLT(sf_out.y));
258 			} else if (num_out==3) {
259 				sprintf(str, "%.3f %.3f %.3f", FIX2FLT(sf_out.x), FIX2FLT(sf_out.y), FIX2FLT(sf_out.z));
260 			} else if (num_out==4) {
261 				sprintf(str, "%.2f %.2f %.2f %.2f", FIX2FLT(sf_out.x), FIX2FLT(sf_out.y), FIX2FLT(sf_out.z), FIX2FLT(sf_out.q));
262 			}
263 			if (p->outSFString.buffer ) gf_free(p->outSFString.buffer);
264 			p->outSFString.buffer = gf_strdup(str);
265 			break;
266 
267 
268 		case GF_SG_VRML_MFFLOAT:
269 			gf_sg_vrml_mf_alloc(&p->outMFFloat, GF_SG_VRML_MFFLOAT, count);
270 			for (i=0; i<count; i++)
271 				p->outMFFloat.vals[i] = mf_output->vals[i].x;
272 			break;
273 		case GF_SG_VRML_MFINT32:
274 			gf_sg_vrml_mf_alloc(&p->outMFInt32, GF_SG_VRML_MFINT32, count);
275 			for (i=0; i<count; i++)
276 				p->outMFInt32.vals[i] = FIX2INT(mf_output->vals[i].x);
277 			break;
278 		case GF_SG_VRML_MFCOLOR:
279 			gf_sg_vrml_mf_alloc(&p->outMFColor, GF_SG_VRML_MFCOLOR, count);
280 			for (i=0; i<count; i++) {
281 				p->outMFColor.vals[i].red = mf_output->vals[i].x;
282 				p->outMFColor.vals[i].green = mf_output->vals[i].y;
283 				p->outMFColor.vals[i].blue = mf_output->vals[i].z;
284 			}
285 			break;
286 		case GF_SG_VRML_MFVEC2F:
287 			gf_sg_vrml_mf_alloc(&p->outMFVec2f, GF_SG_VRML_MFVEC2F, count);
288 			for (i=0; i<count; i++) {
289 				p->outMFVec2f.vals[i].x = mf_output->vals[i].x;
290 				p->outMFVec2f.vals[i].y = mf_output->vals[i].y;
291 			}
292 			break;
293 		case GF_SG_VRML_MFVEC3F:
294 			gf_sg_vrml_mf_alloc(&p->outMFVec3f, GF_SG_VRML_MFVEC3F, count);
295 			for (i=0; i<count; i++) {
296 				p->outMFVec3f.vals[i].x = mf_output->vals[i].x;
297 				p->outMFVec3f.vals[i].y = mf_output->vals[i].y;
298 				p->outMFVec3f.vals[i].z = mf_output->vals[i].z;
299 			}
300 			break;
301 		case GF_SG_VRML_MFROTATION:
302 			gf_sg_vrml_mf_alloc(&p->outMFRotation, GF_SG_VRML_MFROTATION, count);
303 			for (i=0; i<count; i++) {
304 				p->outMFRotation.vals[i].x = mf_output->vals[i].x;
305 				p->outMFRotation.vals[i].y = mf_output->vals[i].y;
306 				p->outMFRotation.vals[i].z = mf_output->vals[i].z;
307 				p->outMFRotation.vals[i].q = mf_output->vals[i].q;
308 			}
309 			break;
310 		case GF_SG_VRML_MFSTRING:
311 			gf_sg_vrml_mf_alloc(&p->outMFString, GF_SG_VRML_MFSTRING, count);
312 			gf_sg_vrml_mf_alloc(&p->outMFVec2f, GF_SG_VRML_MFVEC2F, count);
313 			for (i=0; i<count; i++) {
314 				if (num_out==1) {
315 					if (inType==GF_SG_VRML_SFTIME) {
316 						format_sftime_string(mf_output->vals[i].x, str);
317 					} else {
318 						sprintf(str, "%g", FIX2FLT(mf_output->vals[i].x));
319 					}
320 				} else if (num_out==2) {
321 					sprintf(str, "%g %g", FIX2FLT(mf_output->vals[i].x), FIX2FLT(mf_output->vals[i].y));
322 				} else if (num_out==3) {
323 					sprintf(str, "%g %g %g", FIX2FLT(mf_output->vals[i].x), FIX2FLT(mf_output->vals[i].y), FIX2FLT(mf_output->vals[i].z));
324 				} else if (num_out==4) {
325 					sprintf(str, "%g %g %g %g", FIX2FLT(mf_output->vals[i].x), FIX2FLT(mf_output->vals[i].y), FIX2FLT(mf_output->vals[i].z), FIX2FLT(mf_output->vals[i].q));
326 				}
327 				if (p->outMFString.vals[i]) gf_free(p->outMFString.vals[i]);
328 				p->outMFString.vals[i] = gf_strdup(str);
329 			}
330 			break;
331 		}
332 		if (r->IS_route) {
333 			gf_sg_route_activate(r);
334 		} else {
335 			gf_sg_route_queue(p->sgprivate->scenegraph, r);
336 		}
337 	}
338 }
339 
340 
341 /*
342 valuator spec (9.4.2.116.2)
343 "In the special case of a scalar input type (e.g. SFBool, SFInt32) that is cast to a vectorial output type (e.g.
344 SFVec2f), for all components i of output.i, input.i shall take the value of the scalar input type, after appropriate type
345 conversion"
346 */
347 
Valuator_SetInSFBool(GF_Node * n,GF_Route * route)348 static void Valuator_SetInSFBool(GF_Node *n, GF_Route *route)
349 {
350 	SFVec4f val;
351 	M_Valuator *_this = (M_Valuator *) n;
352 	val.x = val.y = val.z = val.q = _this->inSFBool ? FIX_ONE : 0;
353 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFBOOL);
354 }
Valuator_SetInSFFloat(GF_Node * n,GF_Route * route)355 static void Valuator_SetInSFFloat(GF_Node *n, GF_Route *route)
356 {
357 	SFVec4f val;
358 	M_Valuator *_this = (M_Valuator *) n;
359 	val.x = val.y = val.z = val.q = _this->inSFFloat;
360 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFFLOAT);
361 }
Valuator_SetInSFInt32(GF_Node * n,GF_Route * route)362 static void Valuator_SetInSFInt32(GF_Node *n, GF_Route *route)
363 {
364 	SFVec4f val;
365 	M_Valuator *_this = (M_Valuator *) n;
366 	val.x = val.y = val.z = val.q = INT2FIX(_this->inSFInt32);
367 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFINT32);
368 }
Valuator_SetInSFTime(GF_Node * n,GF_Route * route)369 static void Valuator_SetInSFTime(GF_Node *n, GF_Route *route)
370 {
371 	SFVec4f val;
372 	M_Valuator *_this = (M_Valuator *) n;
373 	val.x = val.y = val.z = val.q = FLT2FIX(_this->inSFTime);
374 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFTIME);
375 }
Valuator_SetInSFColor(GF_Node * n,GF_Route * route)376 static void Valuator_SetInSFColor(GF_Node *n, GF_Route *route)
377 {
378 	SFVec4f val;
379 	M_Valuator *_this = (M_Valuator *) n;
380 	val.x = _this->inSFColor.red;
381 	val.y = _this->inSFColor.green;
382 	val.z = _this->inSFColor.blue;
383 	val.q = 0;
384 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFCOLOR);
385 }
Valuator_SetInSFVec2f(GF_Node * n,GF_Route * route)386 static void Valuator_SetInSFVec2f(GF_Node *n, GF_Route *route)
387 {
388 	SFVec4f val;
389 	M_Valuator *_this = (M_Valuator *) n;
390 	val.x = _this->inSFVec2f.x;
391 	val.y = _this->inSFVec2f.y;
392 	val.z = val.q = 0;
393 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFVEC2F);
394 }
Valuator_SetInSFVec3f(GF_Node * n,GF_Route * route)395 static void Valuator_SetInSFVec3f(GF_Node *n, GF_Route *route)
396 {
397 	SFVec4f val;
398 	M_Valuator *_this = (M_Valuator *) n;
399 	val.x = _this->inSFVec3f.x;
400 	val.y = _this->inSFVec3f.y;
401 	val.z = _this->inSFVec3f.z;
402 	val.q = 0;
403 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFVEC3F);
404 }
Valuator_SetInSFRotation(GF_Node * n,GF_Route * route)405 static void Valuator_SetInSFRotation(GF_Node *n, GF_Route *route)
406 {
407 	SFVec4f val;
408 	if (n) {
409 		M_Valuator *_this = (M_Valuator *) n;
410 		val = _this->inSFRotation;
411 		SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFROTATION);
412 	}
413 }
414 
415 /*
416 valuator spec (9.4.2.116.2)
417 Convert if the content of the string represents an int, float or
418 double value. Boolean string values 'true' and 'false' are
419 converted to 1.0 and 0.0 respectively. Any other string is converted to 0.0
420 */
Valuator_SetInSFString(GF_Node * n,GF_Route * route)421 static void Valuator_SetInSFString(GF_Node *n, GF_Route *route)
422 {
423 	SFVec4f val;
424 	M_Valuator *_this = (M_Valuator *) n;
425 
426 	if (! _this->inSFString.buffer) return;
427 
428 	if (!stricmp(_this->inSFString.buffer, "true")) {
429 		val.x = val.y = val.z = val.q = FIX_ONE;
430 	} else if (!strstr(_this->inSFString.buffer, ".")) {
431 		val.x = INT2FIX( atoi(_this->inSFString.buffer) );
432 		val.y = val.z = val.q = val.x;
433 	} else {
434 		val.x = FLT2FIX( atof(_this->inSFString.buffer) );
435 		val.y = val.z = val.q = val.x;
436 	}
437 	SetValuatorOutput(_this, &val, NULL, GF_SG_VRML_SFSTRING);
438 }
439 
Valuator_SetInMFColor(GF_Node * n,GF_Route * route)440 static void Valuator_SetInMFColor(GF_Node *n, GF_Route *route)
441 {
442 	if (n) {
443 		M_Valuator *_this = (M_Valuator *) n;
444 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFColor, GF_SG_VRML_MFCOLOR);
445 	}
446 }
447 
Valuator_SetInMFFloat(GF_Node * n,GF_Route * route)448 static void Valuator_SetInMFFloat(GF_Node *n, GF_Route *route)
449 {
450 	if (n) {
451 		M_Valuator *_this = (M_Valuator *) n;
452 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFFloat, GF_SG_VRML_MFFLOAT);
453 	}
454 }
Valuator_SetInMFInt32(GF_Node * n,GF_Route * route)455 static void Valuator_SetInMFInt32(GF_Node *n, GF_Route *route)
456 {
457 	if (n) {
458 		M_Valuator *_this = (M_Valuator *) n;
459 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFInt32, GF_SG_VRML_MFINT32);
460 	}
461 }
Valuator_SetInMFVec2f(GF_Node * n,GF_Route * route)462 static void Valuator_SetInMFVec2f(GF_Node *n, GF_Route *route)
463 {
464 	M_Valuator *_this = (M_Valuator *) n;
465 	SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFVec2f, GF_SG_VRML_MFVEC2F);
466 }
Valuator_SetInMFVec3f(GF_Node * n,GF_Route * route)467 static void Valuator_SetInMFVec3f(GF_Node *n, GF_Route *route)
468 {
469 	if (n) {
470 		M_Valuator *_this = (M_Valuator *) n;
471 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFVec3f, GF_SG_VRML_MFVEC3F);
472 	}
473 }
Valuator_SetInMFRotation(GF_Node * n,GF_Route * route)474 static void Valuator_SetInMFRotation(GF_Node *n, GF_Route *route)
475 {
476 	if (n) {
477 		M_Valuator *_this = (M_Valuator *) n;
478 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFRotation, GF_SG_VRML_MFROTATION);
479 	}
480 }
Valuator_SetInMFString(GF_Node * n,GF_Route * route)481 static void Valuator_SetInMFString(GF_Node *n, GF_Route *route)
482 {
483 	if (n) {
484 		M_Valuator *_this = (M_Valuator *) n;
485 		SetValuatorOutput(_this, NULL, (GenMFField *) &_this->inMFString, GF_SG_VRML_MFSTRING);
486 	}
487 }
488 
489 
valuator_destroy(GF_Node * node,void * rs,Bool is_destroy)490 static void valuator_destroy(GF_Node *node, void *rs, Bool is_destroy)
491 {
492 	if (is_destroy) {
493 		MFVec4f *stack = (MFVec4f *)gf_node_get_private(node);
494 		gf_sg_vrml_field_pointer_del(stack, GF_SG_VRML_MFROTATION);
495 	}
496 }
497 
InitValuator(M_Valuator * node)498 Bool InitValuator(M_Valuator *node)
499 {
500 	MFVec4f *temp = gf_sg_vrml_field_pointer_new(GF_SG_VRML_MFROTATION);
501 	if (!temp) return 1;
502 
503 	node->on_inSFTime = Valuator_SetInSFTime;
504 	node->on_inSFBool = Valuator_SetInSFBool;
505 	node->on_inSFColor = Valuator_SetInSFColor;
506 	node->on_inSFInt32 = Valuator_SetInSFInt32;
507 	node->on_inSFFloat = Valuator_SetInSFFloat;
508 	node->on_inSFVec2f = Valuator_SetInSFVec2f;
509 	node->on_inSFVec3f = Valuator_SetInSFVec3f;
510 	node->on_inSFRotation = Valuator_SetInSFRotation;
511 	node->on_inSFString = Valuator_SetInSFString;
512 	node->on_inMFColor = Valuator_SetInMFColor;
513 	node->on_inMFInt32 = Valuator_SetInMFInt32;
514 	node->on_inMFFloat = Valuator_SetInMFFloat;
515 	node->on_inMFVec2f = Valuator_SetInMFVec2f;
516 	node->on_inMFVec3f = Valuator_SetInMFVec3f;
517 	node->on_inMFRotation = Valuator_SetInMFRotation;
518 	node->on_inMFString = Valuator_SetInMFString;
519 
520 	gf_node_set_private((GF_Node*)node, temp);
521 	gf_node_set_callback_function((GF_Node*)node, valuator_destroy);
522 
523 #ifdef GPAC_ENABLE_COVERAGE
524 	//we are a bit lazy here
525 	if (gf_sys_is_cov_mode()) {
526 		Valuator_SetInSFRotation(NULL, NULL);
527 		Valuator_SetInMFColor(NULL, NULL);
528 		Valuator_SetInMFFloat(NULL, NULL);
529 		Valuator_SetInMFInt32(NULL, NULL);
530 		Valuator_SetInMFVec3f(NULL, NULL);
531 		Valuator_SetInMFRotation(NULL, NULL);
532 		Valuator_SetInMFString(NULL, NULL);
533 	}
534 #endif
535 	return 1;
536 }
537 
538 
539 #endif /*GPAC_DISABLE_VRML*/
540