Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
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 : #include <gpac/internal/laser_dev.h>
32 :
33 :
34 : GF_EXPORT
35 8369 : GF_Command *gf_sg_command_new(GF_SceneGraph *graph, u32 tag)
36 : {
37 : GF_Command *ptr;
38 8369 : GF_SAFEALLOC(ptr, GF_Command);
39 8369 : if (!ptr) return NULL;
40 8369 : ptr->tag = tag;
41 8369 : ptr->in_scene = graph;
42 8369 : ptr->command_fields = gf_list_new();
43 8369 : if (tag < GF_SG_LAST_BIFS_COMMAND) ptr->new_proto_list = gf_list_new();
44 : return ptr;
45 : }
46 :
47 : GF_EXPORT
48 8369 : void gf_sg_command_del(GF_Command *com)
49 : {
50 : #ifndef GPAC_DISABLE_VRML
51 : u32 i;
52 : GF_Proto *proto;
53 : #endif
54 8369 : if (!com) return;
55 :
56 8369 : if (com->tag < GF_SG_LAST_BIFS_COMMAND) {
57 : #ifndef GPAC_DISABLE_VRML
58 13864 : while (gf_list_count(com->command_fields)) {
59 5859 : GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
60 5859 : gf_list_rem(com->command_fields, 0);
61 :
62 5859 : switch (inf->fieldType) {
63 4323 : case GF_SG_VRML_SFNODE:
64 4323 : if (inf->new_node) gf_node_try_destroy(com->in_scene, inf->new_node, NULL);
65 : break;
66 18 : case GF_SG_VRML_MFNODE:
67 18 : if (inf->field_ptr) {
68 : GF_ChildNodeItem *child;
69 18 : child = inf->node_list;
70 54 : while (child) {
71 : GF_ChildNodeItem *cur = child;
72 18 : gf_node_try_destroy(com->in_scene, child->node, NULL);
73 18 : child = child->next;
74 18 : gf_free(cur);
75 : }
76 : }
77 : break;
78 1518 : default:
79 1518 : if (inf->field_ptr) gf_sg_vrml_field_pointer_del(inf->field_ptr, inf->fieldType);
80 : break;
81 : }
82 5859 : gf_free(inf);
83 : }
84 : #endif
85 : } else {
86 : #ifndef GPAC_DISABLE_SVG
87 492 : while (gf_list_count(com->command_fields)) {
88 128 : GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
89 128 : gf_list_rem(com->command_fields, 0);
90 :
91 128 : if (inf->new_node) gf_node_unregister(inf->new_node, NULL);
92 114 : else if (inf->node_list) {
93 : GF_ChildNodeItem *child;
94 : child = inf->node_list;
95 166 : while (child) {
96 : GF_ChildNodeItem *cur = child;
97 160 : gf_node_try_destroy(com->in_scene, child->node, NULL);
98 160 : child = child->next;
99 160 : gf_free(cur);
100 : }
101 108 : } else if (inf->field_ptr) {
102 100 : gf_svg_delete_attribute_value(inf->fieldType, inf->field_ptr, com->in_scene);
103 : }
104 128 : gf_free(inf);
105 : }
106 : #endif
107 : }
108 8369 : gf_list_del(com->command_fields);
109 :
110 : #ifndef GPAC_DISABLE_VRML
111 8369 : i=0;
112 16797 : while ((proto = (GF_Proto*)gf_list_enum(com->new_proto_list, &i))) {
113 59 : gf_sg_proto_del(proto);
114 : }
115 8369 : gf_list_del(com->new_proto_list);
116 : #endif
117 :
118 8369 : if (com->node) {
119 6230 : gf_node_try_destroy(com->in_scene, com->node, NULL);
120 : }
121 :
122 8369 : if (com->del_proto_list) gf_free(com->del_proto_list);
123 8369 : if (com->def_name) gf_free(com->def_name);
124 8369 : if (com->scripts_to_load) gf_list_del(com->scripts_to_load);
125 8369 : if (com->unres_name) gf_free(com->unres_name);
126 8369 : gf_free(com);
127 : }
128 :
129 649 : static void SG_CheckFieldChange(GF_Node *node, GF_FieldInfo *field)
130 : {
131 : /*and propagate eventIn if any*/
132 649 : if (field->on_event_in) {
133 116 : field->on_event_in(node, NULL);
134 : }
135 : #ifndef GPAC_DISABLE_VRML
136 533 : else if ((field->eventType==GF_SG_EVENT_IN) && (gf_node_get_tag(node) == TAG_MPEG4_Script)) {
137 4 : gf_sg_script_event_in(node, field);
138 : }
139 : else {
140 : /*Notify eventOut in all cases to handle protos*/
141 529 : gf_node_event_out(node, field->fieldIndex);
142 : }
143 : #endif
144 : /*signal node modif*/
145 649 : gf_node_changed(node, field);
146 649 : }
147 :
148 : #ifndef GPAC_DISABLE_SVG
149 0 : static void gf_node_unregister_children_deactivate(GF_Node *container, GF_ChildNodeItem *child)
150 : {
151 0 : while (child) {
152 : GF_ChildNodeItem *cur;
153 0 : gf_node_unregister(child->node, container);
154 0 : gf_node_deactivate(child->node);
155 : cur = child;
156 0 : child = child->next;
157 0 : gf_free(cur);
158 : }
159 0 : }
160 : #endif
161 :
162 :
163 : GF_EXPORT
164 2609 : GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset)
165 : {
166 : GF_Err e;
167 : #if !defined(GPAC_DISABLE_VRML) || !defined(GPAC_DISABLE_SVG)
168 : GF_CommandField *inf;
169 : GF_Node *node;
170 : #endif
171 :
172 : #ifndef GPAC_DISABLE_VRML
173 : GF_FieldInfo field;
174 : void *slot_ptr;
175 : GF_Node *def;
176 : #endif
177 :
178 2609 : if (!com || !graph) return GF_BAD_PARAM;
179 :
180 2609 : if (com->never_apply) return GF_OK;
181 :
182 : e = GF_OK;
183 2609 : switch (com->tag) {
184 : #ifndef GPAC_DISABLE_VRML
185 414 : case GF_SG_SCENE_REPLACE:
186 : /*unregister root*/
187 414 : gf_node_unregister(graph->RootNode, NULL);
188 : /*remove all protos and routes*/
189 840 : while (gf_list_count(graph->routes_to_activate))
190 12 : gf_list_rem(graph->routes_to_activate, 0);
191 :
192 414 : if (!com->aggregated) {
193 : /*destroy all routes*/
194 449 : while (gf_list_count(graph->Routes)) {
195 36 : GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0);
196 : /*this will unregister the route from the graph, so don't delete the chain entry*/
197 36 : gf_sg_route_del(r);
198 : }
199 : /*destroy all proto*/
200 413 : while (gf_list_count(graph->protos)) {
201 0 : GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
202 : /*this will unregister the proto from the graph, so don't delete the chain entry*/
203 0 : gf_sg_proto_del(p);
204 : }
205 : }
206 : /*DO NOT TOUCH node registry*/
207 : /*DO NOT TOUCH UNREGISTERED PROTOS*/
208 :
209 : /*if no protos (previously aggregated command) create proto list*/
210 414 : if (!graph->protos) graph->protos = gf_list_new();
211 :
212 : /*move all protos in graph*/
213 488 : while (gf_list_count(com->new_proto_list)) {
214 74 : GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
215 74 : gf_list_rem(com->new_proto_list, 0);
216 74 : gf_list_del_item(graph->unregistered_protos, p);
217 74 : gf_list_add(graph->protos, p);
218 : }
219 : /*assign new root (no need to register/unregister)*/
220 414 : graph->RootNode = com->node;
221 414 : com->node = NULL;
222 : break;
223 :
224 46 : case GF_SG_NODE_REPLACE:
225 46 : if (!gf_list_count(com->command_fields)) return GF_OK;
226 40 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
227 40 : e = gf_node_replace(com->node, inf->new_node, 0);
228 : //TOCHECK - this is commented as registering shouldn't happen (already done at command creation) and creates mem leak
229 : // if (inf->new_node) gf_node_register(inf->new_node, NULL);
230 40 : break;
231 :
232 493 : case GF_SG_MULTIPLE_REPLACE:
233 : case GF_SG_FIELD_REPLACE:
234 : {
235 : u32 j;
236 : GF_ChildNodeItem *list, *cur, *prev;
237 493 : j=0;
238 1497 : while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) {
239 511 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
240 511 : if (e) return e;
241 :
242 511 : switch (field.fieldType) {
243 16 : case GF_SG_VRML_SFNODE:
244 : {
245 16 : node = *((GF_Node **) field.far_ptr);
246 16 : e = gf_node_unregister(node, com->node);
247 16 : *((GF_Node **) field.far_ptr) = inf->new_node;
248 16 : if (!e) gf_node_register(inf->new_node, com->node);
249 : break;
250 : }
251 6 : case GF_SG_VRML_MFNODE:
252 6 : gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr));
253 6 : * ((GF_ChildNodeItem **) field.far_ptr) = NULL;
254 :
255 6 : list = * ((GF_ChildNodeItem **) inf->field_ptr);
256 : prev=NULL;
257 18 : while (list) {
258 6 : cur = gf_malloc(sizeof(GF_ChildNodeItem));
259 6 : cur->next = NULL;
260 6 : cur->node = list->node;
261 6 : if (prev) {
262 0 : prev->next = cur;
263 : } else {
264 6 : * ((GF_ChildNodeItem **) field.far_ptr) = cur;
265 : }
266 6 : gf_node_register(list->node, com->node);
267 : prev = cur;
268 6 : list = list->next;
269 : }
270 : break;
271 0 : case GF_SG_VRML_SFCOMMANDBUFFER:
272 : {
273 : u32 i, count;
274 : GF_SceneGraph *sg;
275 0 : SFCommandBuffer *cb_dst = (SFCommandBuffer *)field.far_ptr;
276 0 : SFCommandBuffer *cb_src = (SFCommandBuffer *)inf->field_ptr;
277 :
278 : /*reset dest*/
279 0 : if (!cb_dst->commandList) cb_dst->commandList = gf_list_new();
280 :
281 0 : while (gf_list_count(cb_dst->commandList)) {
282 0 : GF_Command *sub_com = (GF_Command *)gf_list_get(cb_dst->commandList, 0);
283 0 : gf_sg_command_del(sub_com);
284 0 : gf_list_rem(cb_dst->commandList, 0);
285 : }
286 0 : if (cb_dst->buffer) {
287 0 : gf_free(cb_dst->buffer);
288 0 : cb_dst->buffer = NULL;
289 : }
290 :
291 : /*clone command list*/
292 0 : sg = gf_node_get_graph(com->node);
293 0 : count = gf_list_count(cb_src->commandList);
294 0 : for (i=0; i<count; i++) {
295 0 : GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, i);
296 0 : GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, sg, 0);
297 0 : gf_list_add(cb_dst->commandList, new_com);
298 : }
299 : }
300 : break;
301 :
302 489 : default:
303 : /*this is a regular field, reset it and clone - we cannot switch pointers since the
304 : original fields are NOT pointers*/
305 489 : if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
306 51 : e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
307 : }
308 489 : if (e) return e;
309 489 : gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType);
310 :
311 489 : if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
312 56 : *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
313 : break;
314 : }
315 511 : SG_CheckFieldChange(com->node, &field);
316 : }
317 493 : break;
318 : }
319 :
320 84 : case GF_SG_MULTIPLE_INDEXED_REPLACE:
321 : case GF_SG_INDEXED_REPLACE:
322 : {
323 84 : u32 sftype, i=0;
324 270 : while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) {
325 102 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
326 102 : if (e) return e;
327 :
328 : /*if MFNode remove the child and set new node*/
329 102 : if (field.fieldType == GF_SG_VRML_MFNODE) {
330 : /*we must remove the node before in case the new node uses the same ID (not forbidden) and this
331 : command removes the last instance of the node with the same ID*/
332 23 : gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node);
333 23 : if (inf->new_node) gf_node_register(inf->new_node, NULL);
334 : }
335 : /*erase the field item*/
336 : else {
337 79 : if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
338 9 : inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
339 : /*may happen with text and default value*/
340 9 : if (inf->pos < 0) {
341 0 : inf->pos = 0;
342 0 : gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
343 : }
344 : }
345 79 : e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
346 79 : if (e) return e;
347 79 : sftype = gf_sg_vrml_get_sf_type(field.fieldType);
348 79 : gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
349 : /*note we don't add time offset, since there's no MFTime*/
350 : }
351 102 : SG_CheckFieldChange(com->node, &field);
352 : }
353 84 : break;
354 : }
355 17 : case GF_SG_ROUTE_REPLACE:
356 : {
357 : GF_Route *r;
358 : char *name;
359 17 : r = gf_sg_route_find(graph, com->RouteID);
360 17 : def = gf_sg_find_node(graph, com->fromNodeID);
361 17 : node = gf_sg_find_node(graph, com->toNodeID);
362 17 : if (!node || !def) return GF_SG_UNKNOWN_NODE;
363 : name = NULL;
364 17 : if (r) {
365 17 : name = r->name;
366 17 : r->name = NULL;
367 17 : gf_sg_route_del(r);
368 : }
369 17 : r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
370 17 : gf_sg_route_set_id(r, com->RouteID);
371 17 : if (name) {
372 17 : gf_sg_route_set_name(r, name);
373 17 : gf_free(name);
374 : }
375 : break;
376 : }
377 33 : case GF_SG_NODE_DELETE_EX:
378 : case GF_SG_NODE_DELETE:
379 : {
380 33 : if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0);
381 : break;
382 : }
383 35 : case GF_SG_ROUTE_DELETE:
384 : {
385 35 : return gf_sg_route_del_by_id(graph, com->RouteID);
386 : }
387 9 : case GF_SG_INDEXED_DELETE:
388 : {
389 9 : if (!gf_list_count(com->command_fields)) return GF_OK;
390 9 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
391 :
392 9 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
393 9 : if (e) return e;
394 9 : if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
395 :
396 : /*then we need special handling in case of a node*/
397 9 : if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) {
398 0 : e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL);
399 : } else {
400 9 : if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
401 0 : inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
402 : }
403 : /*this is a regular MFField, just remove the item (gf_realloc)*/
404 9 : e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos);
405 : }
406 : /*deletion -> node has changed*/
407 9 : if (!e) SG_CheckFieldChange(com->node, &field);
408 : break;
409 : }
410 70 : case GF_SG_NODE_INSERT:
411 : {
412 70 : if (!gf_list_count(com->command_fields)) return GF_OK;
413 70 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
414 :
415 70 : e = gf_node_insert_child(com->node, inf->new_node, inf->pos);
416 70 : if (!e) e = gf_node_register(inf->new_node, com->node);
417 70 : if (!e) {
418 70 : gf_node_event_out(com->node, inf->fieldIndex);
419 70 : gf_node_changed(com->node, NULL);
420 : }
421 : break;
422 : }
423 1345 : case GF_SG_ROUTE_INSERT:
424 : {
425 : GF_Route *r;
426 1345 : def = gf_sg_find_node(graph, com->fromNodeID);
427 1345 : node = gf_sg_find_node(graph, com->toNodeID);
428 1345 : if (!node || !def) return GF_SG_UNKNOWN_NODE;
429 1345 : r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
430 1345 : if (com->RouteID) gf_sg_route_set_id(r, com->RouteID);
431 1345 : if (com->def_name) {
432 44 : gf_sg_route_set_name(r, com->def_name);
433 44 : gf_free(com->def_name);
434 44 : com->def_name = NULL;
435 : }
436 : break;
437 : }
438 9 : case GF_SG_INDEXED_INSERT:
439 : {
440 : u32 sftype;
441 9 : if (!gf_list_count(com->command_fields)) return GF_OK;
442 9 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
443 9 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
444 9 : if (e) return e;
445 :
446 : /*rescale the MFField and parse the SFField*/
447 9 : if (field.fieldType != GF_SG_VRML_MFNODE) {
448 9 : if (inf->pos == -1) {
449 0 : e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr);
450 : } else {
451 9 : e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
452 : }
453 9 : if (e) return e;
454 9 : sftype = gf_sg_vrml_get_sf_type(field.fieldType);
455 9 : gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
456 : } else {
457 0 : if (inf->new_node) {
458 0 : if (inf->pos == -1) {
459 0 : gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node);
460 : } else {
461 0 : gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos);
462 : }
463 0 : gf_node_register(inf->new_node, com->node);
464 : }
465 : }
466 9 : if (!e) SG_CheckFieldChange(com->node, &field);
467 : break;
468 : }
469 : case GF_SG_PROTO_INSERT:
470 : /*destroy all proto*/
471 18 : while (gf_list_count(com->new_proto_list)) {
472 9 : GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
473 9 : gf_list_rem(com->new_proto_list, 0);
474 9 : gf_list_del_item(graph->unregistered_protos, p);
475 9 : gf_list_add(graph->protos, p);
476 : }
477 : return GF_OK;
478 : case GF_SG_PROTO_DELETE:
479 : {
480 : u32 i;
481 9 : for (i=0; i<com->del_proto_list_size; i++) {
482 : /*note this will check for unregistered protos, but since IDs are unique we are sure we will
483 : not destroy an unregistered one*/
484 9 : GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL);
485 9 : if (proto) gf_sg_proto_del(proto);
486 : }
487 : }
488 : return GF_OK;
489 : case GF_SG_PROTO_DELETE_ALL:
490 : /*destroy all proto*/
491 27 : while (gf_list_count(graph->protos)) {
492 18 : GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
493 18 : gf_list_rem(graph->protos, 0);
494 : /*this will unregister the proto from the graph, so don't delete the chain entry*/
495 18 : gf_sg_proto_del(p);
496 : }
497 : /*DO NOT TOUCH UNREGISTERED PROTOS*/
498 : return GF_OK;
499 18 : case GF_SG_XREPLACE:
500 : {
501 : s32 pos = -2;
502 : GF_Node *target = NULL;
503 : GF_ChildNodeItem *list, *cur;
504 : GF_FieldInfo value;
505 18 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
506 18 : if (!inf) return GF_SG_UNKNOWN_NODE;
507 :
508 18 : e = gf_node_get_field(com->node, inf->fieldIndex, &field);
509 18 : if (e) return e;
510 18 : target = com->node;
511 :
512 18 : if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
513 : GF_FieldInfo idxField;
514 9 : if ((inf->pos != -2) || com->toNodeID) {
515 9 : if (com->toNodeID) {
516 9 : GF_Node *idxNode = gf_sg_find_node(graph, com->toNodeID);
517 9 : if (!idxNode) return GF_SG_UNKNOWN_NODE;
518 :
519 9 : if (gf_node_get_field(idxNode, com->toFieldIndex, &idxField) != GF_OK) return GF_OK;
520 : pos = 0;
521 9 : switch (idxField.fieldType) {
522 0 : case GF_SG_VRML_SFBOOL:
523 0 : if (*(SFBool*)idxField.far_ptr) pos = 1;
524 : break;
525 9 : case GF_SG_VRML_SFINT32:
526 9 : if (*(SFInt32*)idxField.far_ptr >=0) pos = *(SFInt32*)idxField.far_ptr;
527 : break;
528 0 : case GF_SG_VRML_SFFLOAT:
529 0 : if ( (*(SFFloat *)idxField.far_ptr) >=0) pos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) );
530 : break;
531 0 : case GF_SG_VRML_SFTIME:
532 0 : if ( (*(SFTime *)idxField.far_ptr) >=0) pos = (s32) floor( (*(SFTime *)idxField.far_ptr) );
533 : break;
534 : }
535 : } else {
536 : pos = inf->pos;
537 : }
538 : }
539 : }
540 : /*override target node*/
541 18 : if ((field.fieldType==GF_SG_VRML_MFNODE) && (pos>=-1) && com->ChildNodeTag) {
542 9 : target = gf_node_list_get_child(*(GF_ChildNodeItem **)field.far_ptr, pos);
543 9 : if (!target) return GF_SG_UNKNOWN_NODE;
544 9 : if (gf_node_get_field(target, com->child_field, &field) != GF_OK) return GF_SG_UNKNOWN_NODE;
545 : pos=-2;
546 : }
547 :
548 18 : if (com->fromNodeID) {
549 9 : GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
550 9 : if (!fromNode) return GF_SG_UNKNOWN_NODE;
551 9 : e = gf_node_get_field(fromNode, com->fromFieldIndex, &value);
552 9 : if (e) return e;
553 : } else {
554 9 : value.far_ptr = inf->field_ptr;
555 9 : value.fieldType = inf->fieldType;
556 : }
557 : /*indexed replacement*/
558 18 : if (pos>=-1) {
559 : /*if MFNode remove the child and set new node*/
560 0 : if (field.fieldType == GF_SG_VRML_MFNODE) {
561 0 : GF_Node *nn = *(GF_Node**)value.far_ptr;
562 0 : gf_node_replace_child(target, (GF_ChildNodeItem**) field.far_ptr, pos, nn);
563 0 : if (nn) gf_node_register(nn, NULL);
564 : }
565 : /*erase the field item*/
566 : else {
567 : u32 sftype;
568 0 : if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) {
569 0 : pos = ((GenMFField *)field.far_ptr)->count - 1;
570 : /*may happen with text and default value*/
571 0 : if (pos < 0) {
572 : pos = 0;
573 0 : gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
574 : }
575 : }
576 0 : e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, pos);
577 0 : if (e) return e;
578 0 : sftype = gf_sg_vrml_get_sf_type(field.fieldType);
579 0 : gf_sg_vrml_field_copy(slot_ptr, value.far_ptr, sftype);
580 : /*note we don't add time offset, since there's no MFTime*/
581 : }
582 : } else {
583 : GF_ChildNodeItem *prev;
584 18 : switch (field.fieldType) {
585 0 : case GF_SG_VRML_SFNODE:
586 : {
587 0 : node = *((GF_Node **) field.far_ptr);
588 0 : e = gf_node_unregister(node, target);
589 0 : *((GF_Node **) field.far_ptr) = *((GF_Node **) value.far_ptr) ;
590 0 : if (!e) gf_node_register(*(GF_Node **) value.far_ptr, target);
591 : break;
592 : }
593 0 : case GF_SG_VRML_MFNODE:
594 0 : gf_node_unregister_children(target, * ((GF_ChildNodeItem **) field.far_ptr));
595 0 : * ((GF_ChildNodeItem **) field.far_ptr) = NULL;
596 :
597 0 : list = * ((GF_ChildNodeItem **) value.far_ptr);
598 : prev=NULL;
599 0 : while (list) {
600 0 : cur = gf_malloc(sizeof(GF_ChildNodeItem));
601 0 : cur->next = NULL;
602 0 : cur->node = list->node;
603 0 : if (prev) {
604 0 : prev->next = cur;
605 : } else {
606 0 : * ((GF_ChildNodeItem **) field.far_ptr) = cur;
607 : }
608 0 : gf_node_register(list->node, target);
609 : prev = cur;
610 0 : list = list->next;
611 : }
612 : break;
613 :
614 18 : default:
615 18 : if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
616 0 : e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
617 : }
618 18 : if (e) return e;
619 18 : gf_sg_vrml_field_clone(field.far_ptr, value.far_ptr, field.fieldType, graph);
620 :
621 18 : if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
622 0 : *(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
623 : break;
624 : }
625 : }
626 18 : SG_CheckFieldChange(target, &field);
627 : }
628 18 : return GF_OK;
629 : /*only used by BIFS*/
630 : case GF_SG_GLOBAL_QUANTIZER:
631 : return GF_OK;
632 :
633 : #endif /*GPAC_DISABLE_VRML*/
634 :
635 :
636 : #ifndef GPAC_DISABLE_SVG
637 : /*laser commands*/
638 0 : case GF_SG_LSR_NEW_SCENE:
639 : /*DO NOT TOUCH node registry*/
640 :
641 : /*assign new root (no need to register/unregister)*/
642 0 : graph->RootNode = com->node;
643 0 : com->node = NULL;
644 : break;
645 0 : case GF_SG_LSR_DELETE:
646 0 : if (!com->node) return GF_NON_COMPLIANT_BITSTREAM;
647 0 : if (!gf_list_count(com->command_fields)) {
648 0 : gf_node_replace(com->node, NULL, 0);
649 0 : gf_node_deactivate(com->node);
650 0 : return GF_OK;
651 : }
652 0 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
653 0 : node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos);
654 0 : if (node) {
655 0 : e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL);
656 0 : gf_node_deactivate(node);
657 : }
658 : break;
659 0 : case GF_SG_LSR_INSERT:
660 0 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
661 0 : if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
662 0 : if (inf->new_node) {
663 0 : if (inf->pos<0)
664 0 : gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
665 : else
666 0 : gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos);
667 :
668 0 : gf_node_register(inf->new_node, com->node);
669 0 : gf_node_activate(inf->new_node);
670 0 : gf_node_changed(com->node, NULL);
671 : } else {
672 : /*NOT SUPPORTED*/
673 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n"));
674 : }
675 : break;
676 0 : case GF_SG_LSR_ADD:
677 : case GF_SG_LSR_REPLACE:
678 0 : inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
679 0 : if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
680 0 : if (inf->new_node) {
681 0 : if (inf->pos<0) {
682 : /*if fieldIndex (eg attributeName) is set, this is children replacement*/
683 0 : if (inf->fieldIndex>0) {
684 0 : gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
685 0 : ((SVG_Element *)com->node)->children = NULL;
686 0 : gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
687 0 : gf_node_register(inf->new_node, com->node);
688 0 : gf_node_activate(inf->new_node);
689 : } else {
690 0 : e = gf_node_replace(com->node, inf->new_node, 0);
691 0 : gf_node_activate(inf->new_node);
692 : }
693 : } else {
694 0 : node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos);
695 0 : gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node);
696 0 : gf_node_register(inf->new_node, com->node);
697 0 : if (node) gf_node_deactivate(node);
698 0 : gf_node_activate(inf->new_node);
699 : }
700 : /*signal node modif*/
701 0 : gf_node_changed(com->node, NULL);
702 0 : return e;
703 0 : } else if (inf->node_list) {
704 : GF_ChildNodeItem *child, *cur, *prev;
705 0 : gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
706 0 : ((SVG_Element *)com->node)->children = NULL;
707 :
708 : prev = NULL;
709 0 : child = inf->node_list;
710 0 : while (child) {
711 0 : cur = (GF_ChildNodeItem*)gf_malloc(sizeof(GF_ChildNodeItem));
712 0 : cur->next = NULL;
713 0 : cur->node = child->node;
714 0 : gf_node_register(child->node, com->node);
715 0 : gf_node_activate(child->node);
716 0 : if (prev) prev->next = cur;
717 0 : else ((SVG_Element *)com->node)->children = cur;
718 : prev = cur;
719 0 : child = child->next;
720 : }
721 : /*signal node modif*/
722 0 : gf_node_changed(com->node, NULL);
723 0 : return GF_OK;
724 : }
725 : /*attribute modif*/
726 0 : else if (inf->field_ptr) {
727 : GF_FieldInfo a, b;
728 0 : if (inf->fieldIndex==(u32) -2) {
729 : GF_Point2D scale, translate;
730 : Fixed rotate;
731 : GF_Matrix2D *dest;
732 0 : gf_node_get_field_by_name(com->node, "transform", &a);
733 0 : dest = (GF_Matrix2D*)a.far_ptr;
734 :
735 0 : if (com->tag==GF_SG_LSR_REPLACE) {
736 0 : if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) {
737 0 : gf_mx2d_init(*dest);
738 0 : if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr;
739 0 : else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr;
740 0 : else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle;
741 :
742 0 : gf_mx2d_add_scale(dest, scale.x, scale.y);
743 0 : gf_mx2d_add_rotation(dest, 0, 0, rotate);
744 0 : gf_mx2d_add_translation(dest, translate.x, translate.y);
745 : }
746 : } else {
747 0 : GF_Point2D *pt = (GF_Point2D *)inf->field_ptr;
748 0 : if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y);
749 0 : else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y);
750 0 : else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
751 : }
752 : /*signal node modif*/
753 0 : gf_node_changed(com->node, &a);
754 : } else {
755 0 : if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
756 0 : char *str = *(SVG_String*)inf->field_ptr;
757 :
758 0 : if (com->tag == GF_SG_LSR_REPLACE) {
759 0 : GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
760 0 : if (t && (t->sgprivate->tag==TAG_DOMText)) {
761 0 : if (t->textContent) gf_free(t->textContent);
762 0 : t->textContent = NULL;
763 0 : if (str) t->textContent = gf_strdup(str);
764 : }
765 : } else {
766 0 : if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
767 : }
768 : /*signal node modif*/
769 0 : gf_node_changed(com->node, NULL);
770 : }
771 0 : else if ((inf->fieldIndex==TAG_LSR_ATT_scale)
772 : || (inf->fieldIndex==TAG_LSR_ATT_translation)
773 0 : || (inf->fieldIndex==TAG_LSR_ATT_rotation)
774 : ) {
775 : SVG_Transform *mx;
776 0 : gf_node_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a);
777 0 : mx = a.far_ptr;
778 0 : if (com->tag == GF_SG_LSR_REPLACE) {
779 : GF_Point2D scale, translate;
780 : SVG_Point_Angle rotate;
781 0 : if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) {
782 0 : gf_mx2d_init(mx->mat);
783 0 : if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr;
784 0 : else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr;
785 0 : else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr;
786 :
787 0 : gf_mx2d_add_scale(&mx->mat, scale.x, scale.y);
788 0 : gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle);
789 0 : gf_mx2d_add_translation(&mx->mat, translate.x, translate.y);
790 : }
791 : } else {
792 0 : if (inf->fieldIndex==TAG_LSR_ATT_scale) gf_mx2d_add_scale(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
793 0 : if (inf->fieldIndex==TAG_LSR_ATT_translation) gf_mx2d_add_translation(&mx->mat, ((GF_Point2D*)inf->field_ptr)->x, ((GF_Point2D*)inf->field_ptr)->y);
794 0 : if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
795 : }
796 : /*signal node modif*/
797 0 : gf_node_changed(com->node, &a);
798 : }
799 0 : else if (gf_node_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) {
800 0 : b = a;
801 0 : b.far_ptr = inf->field_ptr;
802 0 : if (com->tag == GF_SG_LSR_REPLACE) {
803 0 : gf_svg_attributes_copy(&a, &b, 0);
804 : } else {
805 0 : gf_svg_attributes_add(&a, &b, &a, 0);
806 : }
807 0 : if (a.fieldType==XMLRI_datatype) {
808 0 : gf_node_dirty_set(com->node, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
809 : }
810 : /*signal node modif*/
811 0 : gf_node_changed(com->node, &a);
812 : }
813 : }
814 0 : } else if (com->fromNodeID) {
815 : GF_FieldInfo a, b;
816 0 : GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
817 0 : if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM;
818 0 : if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM;
819 :
820 0 : if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
821 0 : char *str = inf->field_ptr ? *(SVG_String*)inf->field_ptr : NULL;
822 :
823 0 : if (com->tag == GF_SG_LSR_REPLACE) {
824 0 : GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
825 0 : if (t && (t->sgprivate->tag==TAG_DOMText)) {
826 0 : if (t->textContent) gf_free(t->textContent);
827 0 : t->textContent = NULL;
828 0 : if (str) t->textContent = gf_strdup(str);
829 : }
830 : } else {
831 0 : if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
832 : }
833 : } else {
834 0 : gf_node_get_field(com->node, inf->fieldIndex, &a);
835 0 : if (com->tag == GF_SG_LSR_REPLACE) {
836 0 : e = gf_svg_attributes_copy(&a, &b, 0);
837 : } else {
838 0 : e = gf_svg_attributes_add(&a, &b, &a, 0);
839 : }
840 : }
841 0 : gf_node_changed(com->node, &a);
842 0 : return e;
843 : } else {
844 : return GF_NON_COMPLIANT_BITSTREAM;
845 : }
846 : break;
847 0 : case GF_SG_LSR_ACTIVATE:
848 0 : gf_node_activate(com->node);
849 : break;
850 0 : case GF_SG_LSR_DEACTIVATE:
851 0 : gf_node_deactivate(com->node);
852 0 : gf_node_changed(com->node, NULL);
853 : break;
854 : case GF_SG_LSR_SEND_EVENT:
855 : {
856 : GF_DOM_Event evt;
857 : memset(&evt, 0, sizeof(GF_DOM_Event));
858 0 : evt.type = com->send_event_name;
859 0 : evt.detail = com->send_event_integer;
860 0 : evt.clientX = com->send_event_x;
861 0 : evt.clientY = com->send_event_y;
862 0 : gf_dom_event_fire(com->node, &evt);
863 : }
864 : break;
865 : #endif
866 :
867 0 : default:
868 0 : return GF_NOT_SUPPORTED;
869 : }
870 705 : if (e) return e;
871 :
872 : #ifndef GPAC_DISABLE_VRML
873 2514 : if (com->scripts_to_load) {
874 70 : while (gf_list_count(com->scripts_to_load)) {
875 35 : GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0);
876 35 : gf_list_rem(com->scripts_to_load, 0);
877 35 : gf_sg_script_load(script);
878 : }
879 35 : gf_list_del(com->scripts_to_load);
880 35 : com->scripts_to_load = NULL;
881 : }
882 : #endif
883 :
884 : return GF_OK;
885 : }
886 :
887 : GF_EXPORT
888 5987 : GF_CommandField *gf_sg_command_field_new(GF_Command *com)
889 : {
890 : GF_CommandField *ptr;
891 5987 : GF_SAFEALLOC(ptr, GF_CommandField);
892 5987 : if (ptr)
893 5987 : gf_list_add(com->command_fields, ptr);
894 5987 : return ptr;
895 : }
896 :
897 :
898 : GF_EXPORT
899 365 : GF_Err gf_sg_command_apply_list(GF_SceneGraph *graph, GF_List *comList, Double time_offset)
900 : {
901 : GF_Err e;
902 : GF_Command *com;
903 365 : u32 i=0;
904 1365 : while ((com = (GF_Command *)gf_list_enum(comList, &i))) {
905 636 : e = gf_sg_command_apply(graph, com, time_offset);
906 636 : if (e) return e;
907 : }
908 : return GF_OK;
909 : }
910 :
911 : #ifndef GPAC_DISABLE_VRML
912 58 : GF_Command *gf_sg_vrml_command_clone(GF_Command *com, GF_SceneGraph *inGraph, Bool force_clone)
913 : {
914 : u32 i, count;
915 : GF_Command *dest;
916 :
917 : /*FIXME - to do*/
918 58 : if (gf_list_count(com->new_proto_list)) return NULL;
919 58 : dest = gf_sg_command_new(inGraph, com->tag);
920 :
921 58 : if (com->in_scene!=inGraph) force_clone = 1;
922 :
923 : /*node the command applies to - may be NULL*/
924 0 : if (force_clone) {
925 58 : dest->node = gf_node_clone(inGraph, com->node, NULL, "", 0);
926 : } else {
927 0 : dest->node = com->node;
928 0 : gf_node_register(dest->node, NULL);
929 : }
930 : /*route insert, replace and delete*/
931 58 : dest->RouteID = com->RouteID;
932 58 : if (com->def_name) dest->def_name = gf_strdup(com->def_name);
933 : //this is an union
934 : //if (com->send_event_string) dest->send_event_string = gf_strdup(com->send_event_string);
935 :
936 58 : dest->fromNodeID = com->fromNodeID;
937 58 : dest->fromFieldIndex = com->fromFieldIndex;
938 58 : dest->toNodeID = com->toNodeID;
939 58 : dest->toFieldIndex = com->toFieldIndex;
940 58 : dest->send_event_integer = com->send_event_integer;
941 58 : dest->send_event_x = com->send_event_x;
942 58 : dest->send_event_y = com->send_event_y;
943 :
944 58 : dest->del_proto_list_size = com->del_proto_list_size;
945 58 : if (com->del_proto_list_size) {
946 0 : dest->del_proto_list = (u32*)gf_malloc(sizeof(u32) * com->del_proto_list_size);
947 0 : memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size);
948 : }
949 58 : count = gf_list_count(com->command_fields);
950 108 : for (i=0; i<count; i++) {
951 50 : GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i);
952 50 : GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest);
953 :
954 50 : fd->fieldIndex = fo->fieldIndex;
955 50 : fd->fieldType = fo->fieldType;
956 50 : fd->pos = fo->pos;
957 :
958 : /*FIXME - this can also be LASeR commands, not supported for now*/
959 50 : if (fo->field_ptr) {
960 50 : fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType);
961 50 : gf_sg_vrml_field_clone(fd->field_ptr, fo->field_ptr, fo->fieldType, dest->in_scene);
962 : }
963 :
964 50 : if (fo->new_node) {
965 0 : if (force_clone) {
966 0 : fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node, "", 0);
967 : } else {
968 0 : fd->new_node = fo->new_node;
969 0 : gf_node_register(fd->new_node, NULL);
970 : }
971 0 : fd->field_ptr = &fd->new_node;
972 : }
973 50 : if (fo->node_list) {
974 : GF_ChildNodeItem *child, *cur, *prev;
975 : prev = NULL;
976 : child = fo->node_list;
977 0 : while (child) {
978 0 : cur = (GF_ChildNodeItem*) gf_malloc(sizeof(GF_ChildNodeItem));
979 0 : if (force_clone) {
980 0 : cur->node = gf_node_clone(inGraph, child->node, dest->node, "", 0);
981 : } else {
982 0 : cur->node = child->node;
983 0 : gf_node_register(cur->node, NULL);
984 : }
985 0 : cur->next = NULL;
986 0 : if (prev) prev->next = cur;
987 0 : else fd->node_list = cur;
988 : prev = cur;
989 0 : child = child->next;
990 : }
991 0 : fd->field_ptr = &fd->node_list;
992 : }
993 : }
994 : return dest;
995 : }
996 :
997 : #endif
998 :
|