This source file includes following definitions.
- gf_sg_command_new
- gf_sg_command_del
- SG_CheckFieldChange
- gf_node_unregister_children_deactivate
- gf_sg_command_apply
- gf_sg_command_field_new
- gf_sg_command_apply_list
- gf_sg_vrml_command_clone
#include <gpac/internal/scenegraph_dev.h>
#include <gpac/nodes_mpeg4.h>
#include <gpac/internal/laser_dev.h>
GF_EXPORT
GF_Command *gf_sg_command_new(GF_SceneGraph *graph, u32 tag)
{
GF_Command *ptr;
GF_SAFEALLOC(ptr, GF_Command);
if (!ptr) return NULL;
ptr->tag = tag;
ptr->in_scene = graph;
ptr->command_fields = gf_list_new();
if (tag < GF_SG_LAST_BIFS_COMMAND) ptr->new_proto_list = gf_list_new();
return ptr;
}
GF_EXPORT
void gf_sg_command_del(GF_Command *com)
{
#ifndef GPAC_DISABLE_VRML
u32 i;
GF_Proto *proto;
#endif
if (!com) return;
if (com->tag < GF_SG_LAST_BIFS_COMMAND) {
#ifndef GPAC_DISABLE_VRML
while (gf_list_count(com->command_fields)) {
GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
gf_list_rem(com->command_fields, 0);
switch (inf->fieldType) {
case GF_SG_VRML_SFNODE:
if (inf->new_node) gf_node_try_destroy(com->in_scene, inf->new_node, NULL);
break;
case GF_SG_VRML_MFNODE:
if (inf->field_ptr) {
GF_ChildNodeItem *cur, *child;
child = inf->node_list;
while (child) {
cur = child;
gf_node_try_destroy(com->in_scene, child->node, NULL);
child = child->next;
gf_free(cur);
}
}
break;
default:
if (inf->field_ptr) gf_sg_vrml_field_pointer_del(inf->field_ptr, inf->fieldType);
break;
}
gf_free(inf);
}
#endif
} else {
#ifndef GPAC_DISABLE_SVG
while (gf_list_count(com->command_fields)) {
GF_CommandField *inf = (GF_CommandField *)gf_list_get(com->command_fields, 0);
gf_list_rem(com->command_fields, 0);
if (inf->new_node) gf_node_unregister(inf->new_node, NULL);
else if (inf->node_list) {
GF_ChildNodeItem *cur, *child;
child = inf->node_list;
while (child) {
cur = child;
gf_node_try_destroy(com->in_scene, child->node, NULL);
child = child->next;
gf_free(cur);
}
} else if (inf->field_ptr) {
gf_svg_delete_attribute_value(inf->fieldType, inf->field_ptr, com->in_scene);
}
gf_free(inf);
}
#endif
}
gf_list_del(com->command_fields);
#ifndef GPAC_DISABLE_VRML
i=0;
while ((proto = (GF_Proto*)gf_list_enum(com->new_proto_list, &i))) {
gf_sg_proto_del(proto);
}
gf_list_del(com->new_proto_list);
#endif
if (com->node) {
gf_node_try_destroy(com->in_scene, com->node, NULL);
}
if (com->del_proto_list) gf_free(com->del_proto_list);
if (com->def_name) gf_free(com->def_name);
if (com->scripts_to_load) gf_list_del(com->scripts_to_load);
if (com->unres_name) gf_free(com->unres_name);
gf_free(com);
}
static void SG_CheckFieldChange(GF_Node *node, GF_FieldInfo *field)
{
if (field->on_event_in) {
field->on_event_in(node, NULL);
}
#ifndef GPAC_DISABLE_VRML
else if ((field->eventType==GF_SG_EVENT_IN) && (gf_node_get_tag(node) == TAG_MPEG4_Script)) {
gf_sg_script_event_in(node, field);
}
else {
gf_node_event_out(node, field->fieldIndex);
}
#endif
gf_node_changed(node, field);
}
#ifndef GPAC_DISABLE_SVG
static void gf_node_unregister_children_deactivate(GF_Node *container, GF_ChildNodeItem *child)
{
GF_ChildNodeItem *cur;
while (child) {
gf_node_unregister(child->node, container);
gf_node_deactivate(child->node);
cur = child;
child = child->next;
gf_free(cur);
}
}
#endif
GF_EXPORT
GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset)
{
GF_Err e;
#if !defined(GPAC_DISABLE_VRML) || !defined(GPAC_DISABLE_SVG)
GF_CommandField *inf;
GF_Node *node;
#endif
#ifndef GPAC_DISABLE_VRML
GF_FieldInfo field;
void *slot_ptr;
GF_Node *def;
#endif
if (!com || !graph) return GF_BAD_PARAM;
if (com->never_apply) return GF_OK;
e = GF_OK;
switch (com->tag) {
#ifndef GPAC_DISABLE_VRML
case GF_SG_SCENE_REPLACE:
gf_node_unregister(graph->RootNode, NULL);
while (gf_list_count(graph->routes_to_activate))
gf_list_rem(graph->routes_to_activate, 0);
if (!com->aggregated) {
while (gf_list_count(graph->Routes)) {
GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0);
gf_sg_route_del(r);
}
while (gf_list_count(graph->protos)) {
GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
gf_sg_proto_del(p);
}
}
if (!graph->protos) graph->protos = gf_list_new();
while (gf_list_count(com->new_proto_list)) {
GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
gf_list_rem(com->new_proto_list, 0);
gf_list_del_item(graph->unregistered_protos, p);
gf_list_add(graph->protos, p);
}
graph->RootNode = com->node;
com->node = NULL;
break;
case GF_SG_NODE_REPLACE:
if (!gf_list_count(com->command_fields)) return GF_OK;
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
e = gf_node_replace(com->node, inf->new_node, 0);
break;
case GF_SG_MULTIPLE_REPLACE:
case GF_SG_FIELD_REPLACE:
{
u32 j;
GF_ChildNodeItem *list, *cur, *prev;
j=0;
while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &j))) {
e = gf_node_get_field(com->node, inf->fieldIndex, &field);
if (e) return e;
switch (field.fieldType) {
case GF_SG_VRML_SFNODE:
{
node = *((GF_Node **) field.far_ptr);
e = gf_node_unregister(node, com->node);
*((GF_Node **) field.far_ptr) = inf->new_node;
if (!e) gf_node_register(inf->new_node, com->node);
break;
}
case GF_SG_VRML_MFNODE:
gf_node_unregister_children(com->node, * ((GF_ChildNodeItem **) field.far_ptr));
* ((GF_ChildNodeItem **) field.far_ptr) = NULL;
list = * ((GF_ChildNodeItem **) inf->field_ptr);
prev=NULL;
while (list) {
cur = gf_malloc(sizeof(GF_ChildNodeItem));
cur->next = NULL;
cur->node = list->node;
if (prev) {
prev->next = cur;
} else {
* ((GF_ChildNodeItem **) field.far_ptr) = cur;
}
gf_node_register(list->node, com->node);
prev = cur;
list = list->next;
}
break;
case GF_SG_VRML_SFCOMMANDBUFFER:
{
u32 i, count;
GF_SceneGraph *sg;
SFCommandBuffer *cb_dst = (SFCommandBuffer *)field.far_ptr;
SFCommandBuffer *cb_src = (SFCommandBuffer *)inf->field_ptr;
if (!cb_dst->commandList) cb_dst->commandList = gf_list_new();
while (gf_list_count(cb_dst->commandList)) {
GF_Command *sub_com = (GF_Command *)gf_list_get(cb_dst->commandList, 0);
gf_sg_command_del(sub_com);
gf_list_rem(cb_dst->commandList, 0);
}
if (cb_dst->buffer) {
gf_free(cb_dst->buffer);
cb_dst->buffer = NULL;
}
sg = gf_node_get_graph(com->node);
count = gf_list_count(cb_src->commandList);
for (i=0; i<count; i++) {
GF_Command *sub_com = (GF_Command *)gf_list_get(cb_src->commandList, i);
GF_Command *new_com = gf_sg_vrml_command_clone(sub_com, sg, 0);
gf_list_add(cb_dst->commandList, new_com);
}
}
break;
default:
if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
}
if (e) return e;
gf_sg_vrml_field_copy(field.far_ptr, inf->field_ptr, field.fieldType);
if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
*(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
break;
}
SG_CheckFieldChange(com->node, &field);
}
break;
}
case GF_SG_MULTIPLE_INDEXED_REPLACE:
case GF_SG_INDEXED_REPLACE:
{
u32 sftype, i=0;
while ((inf = (GF_CommandField*)gf_list_enum(com->command_fields, &i))) {
e = gf_node_get_field(com->node, inf->fieldIndex, &field);
if (e) return e;
if (field.fieldType == GF_SG_VRML_MFNODE) {
gf_node_replace_child(com->node, (GF_ChildNodeItem**) field.far_ptr, inf->pos, inf->new_node);
if (inf->new_node) gf_node_register(inf->new_node, NULL);
}
else {
if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
if (inf->pos < 0) {
inf->pos = 0;
gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
}
}
e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
if (e) return e;
sftype = gf_sg_vrml_get_sf_type(field.fieldType);
gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
}
SG_CheckFieldChange(com->node, &field);
}
break;
}
case GF_SG_ROUTE_REPLACE:
{
GF_Route *r;
char *name;
r = gf_sg_route_find(graph, com->RouteID);
def = gf_sg_find_node(graph, com->fromNodeID);
node = gf_sg_find_node(graph, com->toNodeID);
if (!node || !def) return GF_SG_UNKNOWN_NODE;
name = NULL;
if (r) {
name = r->name;
r->name = NULL;
gf_sg_route_del(r);
}
r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
gf_sg_route_set_id(r, com->RouteID);
if (name) {
gf_sg_route_set_name(r, name);
gf_free(name);
}
break;
}
case GF_SG_NODE_DELETE_EX:
case GF_SG_NODE_DELETE:
{
if (com->node) gf_node_replace(com->node, NULL, (com->tag==GF_SG_NODE_DELETE_EX) ? 1 : 0);
break;
}
case GF_SG_ROUTE_DELETE:
{
return gf_sg_route_del_by_id(graph, com->RouteID);
}
case GF_SG_INDEXED_DELETE:
{
if (!gf_list_count(com->command_fields)) return GF_OK;
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
e = gf_node_get_field(com->node, inf->fieldIndex, &field);
if (e) return e;
if (gf_sg_vrml_is_sf_field(field.fieldType)) return GF_NON_COMPLIANT_BITSTREAM;
if (gf_sg_vrml_get_sf_type(field.fieldType) == GF_SG_VRML_SFNODE) {
e = gf_node_replace_child(com->node, (GF_ChildNodeItem **) field.far_ptr, inf->pos, NULL);
} else {
if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) {
inf->pos = ((GenMFField *)field.far_ptr)->count - 1;
}
e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos);
}
if (!e) SG_CheckFieldChange(com->node, &field);
break;
}
case GF_SG_NODE_INSERT:
{
if (!gf_list_count(com->command_fields)) return GF_OK;
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
e = gf_node_insert_child(com->node, inf->new_node, inf->pos);
if (!e) gf_node_register(inf->new_node, com->node);
if (!e) gf_node_event_out(com->node, inf->fieldIndex);
if (!e) gf_node_changed(com->node, NULL);
break;
}
case GF_SG_ROUTE_INSERT:
{
GF_Route *r;
def = gf_sg_find_node(graph, com->fromNodeID);
node = gf_sg_find_node(graph, com->toNodeID);
if (!node || !def) return GF_SG_UNKNOWN_NODE;
r = gf_sg_route_new(graph, def, com->fromFieldIndex, node, com->toFieldIndex);
if (com->RouteID) gf_sg_route_set_id(r, com->RouteID);
if (com->def_name) {
gf_sg_route_set_name(r, com->def_name);
gf_free(com->def_name);
com->def_name = NULL;
}
break;
}
case GF_SG_INDEXED_INSERT:
{
u32 sftype;
if (!gf_list_count(com->command_fields)) return GF_OK;
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
e = gf_node_get_field(com->node, inf->fieldIndex, &field);
if (e) return e;
if (field.fieldType != GF_SG_VRML_MFNODE) {
if (inf->pos == -1) {
e = gf_sg_vrml_mf_append(field.far_ptr, field.fieldType, & slot_ptr);
} else {
e = gf_sg_vrml_mf_insert(field.far_ptr, field.fieldType, & slot_ptr, inf->pos);
}
if (e) return e;
sftype = gf_sg_vrml_get_sf_type(field.fieldType);
gf_sg_vrml_field_copy(slot_ptr, inf->field_ptr, sftype);
} else {
if (inf->new_node) {
if (inf->pos == -1) {
gf_node_list_add_child( (GF_ChildNodeItem **) field.far_ptr, inf->new_node);
} else {
gf_node_list_insert_child((GF_ChildNodeItem **) field.far_ptr, inf->new_node, inf->pos);
}
gf_node_register(inf->new_node, com->node);
}
}
if (!e) SG_CheckFieldChange(com->node, &field);
break;
}
case GF_SG_PROTO_INSERT:
while (gf_list_count(com->new_proto_list)) {
GF_Proto *p = (GF_Proto*)gf_list_get(com->new_proto_list, 0);
gf_list_rem(com->new_proto_list, 0);
gf_list_del_item(graph->unregistered_protos, p);
gf_list_add(graph->protos, p);
}
return GF_OK;
case GF_SG_PROTO_DELETE:
{
u32 i;
for (i=0; i<com->del_proto_list_size; i++) {
GF_Proto *proto = gf_sg_find_proto(graph, com->del_proto_list[i], NULL);
if (proto) gf_sg_proto_del(proto);
}
}
return GF_OK;
case GF_SG_PROTO_DELETE_ALL:
while (gf_list_count(graph->protos)) {
GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0);
gf_list_rem(graph->protos, 0);
gf_sg_proto_del(p);
}
return GF_OK;
case GF_SG_XREPLACE:
{
s32 pos = -2;
GF_Node *target = NULL;
GF_ChildNodeItem *list, *cur, *prev;
GF_FieldInfo value;
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
if (!inf) return GF_SG_UNKNOWN_NODE;
e = gf_node_get_field(com->node, inf->fieldIndex, &field);
if (e) return e;
target = com->node;
if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
GF_FieldInfo idxField;
if ((inf->pos != -2) || com->toNodeID) {
if (com->toNodeID) {
GF_Node *idxNode = gf_sg_find_node(graph, com->toNodeID);
if (!idxNode) return GF_SG_UNKNOWN_NODE;
if (gf_node_get_field(idxNode, com->toFieldIndex, &idxField) != GF_OK) return GF_OK;
pos = 0;
switch (idxField.fieldType) {
case GF_SG_VRML_SFBOOL:
if (*(SFBool*)idxField.far_ptr) pos = 1;
break;
case GF_SG_VRML_SFINT32:
if (*(SFInt32*)idxField.far_ptr >=0) pos = *(SFInt32*)idxField.far_ptr;
break;
case GF_SG_VRML_SFFLOAT:
if ( (*(SFFloat *)idxField.far_ptr) >=0) pos = (s32) floor( FIX2FLT(*(SFFloat*)idxField.far_ptr) );
break;
case GF_SG_VRML_SFTIME:
if ( (*(SFTime *)idxField.far_ptr) >=0) pos = (s32) floor( (*(SFTime *)idxField.far_ptr) );
break;
}
} else {
pos = inf->pos;
}
}
}
if ((field.fieldType==GF_SG_VRML_MFNODE) && (pos>=-1) && com->ChildNodeTag) {
target = gf_node_list_get_child(*(GF_ChildNodeItem **)field.far_ptr, pos);
if (!target) return GF_SG_UNKNOWN_NODE;
if (gf_node_get_field(target, com->child_field, &field) != GF_OK) return GF_SG_UNKNOWN_NODE;
pos=-2;
}
if (com->fromNodeID) {
GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
if (!fromNode) return GF_SG_UNKNOWN_NODE;
e = gf_node_get_field(fromNode, com->fromFieldIndex, &value);
if (e) return e;
} else {
value.far_ptr = inf->field_ptr;
value.fieldType = inf->fieldType;
}
if (pos>=-1) {
if (field.fieldType == GF_SG_VRML_MFNODE) {
GF_Node *nn = *(GF_Node**)value.far_ptr;
gf_node_replace_child(target, (GF_ChildNodeItem**) field.far_ptr, pos, nn);
if (nn) gf_node_register(nn, NULL);
}
else {
u32 sftype;
if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) {
pos = ((GenMFField *)field.far_ptr)->count - 1;
if (pos < 0) {
pos = 0;
gf_sg_vrml_mf_alloc(field.far_ptr, field.fieldType, 1);
}
}
e = gf_sg_vrml_mf_get_item(field.far_ptr, field.fieldType, & slot_ptr, pos);
if (e) return e;
sftype = gf_sg_vrml_get_sf_type(field.fieldType);
gf_sg_vrml_field_copy(slot_ptr, value.far_ptr, sftype);
}
} else {
switch (field.fieldType) {
case GF_SG_VRML_SFNODE:
{
node = *((GF_Node **) field.far_ptr);
e = gf_node_unregister(node, target);
*((GF_Node **) field.far_ptr) = *((GF_Node **) value.far_ptr) ;
if (!e) gf_node_register(*(GF_Node **) value.far_ptr, target);
break;
}
case GF_SG_VRML_MFNODE:
gf_node_unregister_children(target, * ((GF_ChildNodeItem **) field.far_ptr));
* ((GF_ChildNodeItem **) field.far_ptr) = NULL;
list = * ((GF_ChildNodeItem **) value.far_ptr);
prev=NULL;
while (list) {
cur = gf_malloc(sizeof(GF_ChildNodeItem));
cur->next = NULL;
cur->node = list->node;
if (prev) {
prev->next = cur;
} else {
* ((GF_ChildNodeItem **) field.far_ptr) = cur;
}
gf_node_register(list->node, target);
prev = cur;
list = list->next;
}
break;
default:
if (!gf_sg_vrml_is_sf_field(field.fieldType)) {
e = gf_sg_vrml_mf_reset(field.far_ptr, field.fieldType);
}
if (e) return e;
gf_sg_vrml_field_clone(field.far_ptr, value.far_ptr, field.fieldType, graph);
if ((field.fieldType==GF_SG_VRML_SFTIME) && !strstr(field.name, "media"))
*(SFTime *)field.far_ptr = *(SFTime *)field.far_ptr + time_offset;
break;
}
}
SG_CheckFieldChange(target, &field);
}
return GF_OK;
case GF_SG_GLOBAL_QUANTIZER:
return GF_OK;
#endif
#ifndef GPAC_DISABLE_SVG
case GF_SG_LSR_NEW_SCENE:
graph->RootNode = com->node;
com->node = NULL;
break;
case GF_SG_LSR_DELETE:
if (!com->node) return GF_NON_COMPLIANT_BITSTREAM;
if (!gf_list_count(com->command_fields)) {
gf_node_replace(com->node, NULL, 0);
gf_node_deactivate(com->node);
return GF_OK;
}
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
node = gf_node_list_get_child(((SVG_Element *)com->node)->children, inf->pos);
if (node) {
e = gf_node_replace_child(com->node, &((SVG_Element *)com->node)->children, inf->pos, NULL);
gf_node_deactivate(node);
}
break;
case GF_SG_LSR_INSERT:
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
if (inf->new_node) {
if (inf->pos<0)
gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
else
gf_node_list_insert_child(& ((SVG_Element *)com->node)->children, inf->new_node, inf->pos);
gf_node_register(inf->new_node, com->node);
gf_node_activate(inf->new_node);
gf_node_changed(com->node, NULL);
} else {
GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[LASeR] VALUE INSERTION NOT SUPPORTED\n"));
}
break;
case GF_SG_LSR_ADD:
case GF_SG_LSR_REPLACE:
inf = (GF_CommandField*)gf_list_get(com->command_fields, 0);
if (!com->node || !inf) return GF_NON_COMPLIANT_BITSTREAM;
if (inf->new_node) {
if (inf->pos<0) {
if (inf->fieldIndex>0) {
gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
((SVG_Element *)com->node)->children = NULL;
gf_node_list_add_child(& ((SVG_Element *)com->node)->children, inf->new_node);
gf_node_register(inf->new_node, com->node);
gf_node_activate(inf->new_node);
} else {
e = gf_node_replace(com->node, inf->new_node, 0);
gf_node_activate(inf->new_node);
}
} else {
node = gf_node_list_get_child( ((SVG_Element *)com->node)->children, inf->pos);
gf_node_replace_child(com->node, & ((SVG_Element *)com->node)->children, inf->pos, inf->new_node);
gf_node_register(inf->new_node, com->node);
if (node) gf_node_deactivate(node);
gf_node_activate(inf->new_node);
}
gf_node_changed(com->node, NULL);
return e;
} else if (inf->node_list) {
GF_ChildNodeItem *child, *cur, *prev;
gf_node_unregister_children_deactivate(com->node, ((SVG_Element *)com->node)->children);
((SVG_Element *)com->node)->children = NULL;
prev = NULL;
child = inf->node_list;
while (child) {
cur = (GF_ChildNodeItem*)gf_malloc(sizeof(GF_ChildNodeItem));
cur->next = NULL;
cur->node = child->node;
gf_node_register(child->node, com->node);
gf_node_activate(child->node);
if (prev) prev->next = cur;
else ((SVG_Element *)com->node)->children = cur;
prev = cur;
child = child->next;
}
gf_node_changed(com->node, NULL);
return GF_OK;
}
else if (inf->field_ptr) {
GF_FieldInfo a, b;
if (inf->fieldIndex==(u32) -2) {
GF_Point2D scale, translate;
Fixed rotate;
GF_Matrix2D *dest;
gf_node_get_field_by_name(com->node, "transform", &a);
dest = (GF_Matrix2D*)a.far_ptr;
if (com->tag==GF_SG_LSR_REPLACE) {
if (gf_mx2d_decompose(dest, &scale, &rotate, &translate)) {
gf_mx2d_init(*dest);
if (inf->fieldType==SVG_TRANSFORM_SCALE) scale = *(GF_Point2D *)inf->field_ptr;
else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) translate = *(GF_Point2D *)inf->field_ptr;
else if (inf->fieldType==SVG_TRANSFORM_ROTATE) rotate = ((SVG_Point_Angle*)inf->field_ptr)->angle;
gf_mx2d_add_scale(dest, scale.x, scale.y);
gf_mx2d_add_rotation(dest, 0, 0, rotate);
gf_mx2d_add_translation(dest, translate.x, translate.y);
}
} else {
GF_Point2D *pt = (GF_Point2D *)inf->field_ptr;
if (inf->fieldType==SVG_TRANSFORM_SCALE) gf_mx2d_add_scale(dest, pt->x, pt->y);
else if (inf->fieldType==SVG_TRANSFORM_TRANSLATE) gf_mx2d_add_translation(dest, pt->x, pt->y);
else if (inf->fieldType == SVG_TRANSFORM_ROTATE) gf_mx2d_add_rotation(dest, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
}
gf_node_changed(com->node, &a);
} else {
if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
char *str = *(SVG_String*)inf->field_ptr;
if (com->tag == GF_SG_LSR_REPLACE) {
GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
if (t && (t->sgprivate->tag==TAG_DOMText)) {
if (t->textContent) gf_free(t->textContent);
t->textContent = NULL;
if (str) t->textContent = gf_strdup(str);
}
} else {
if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
}
gf_node_changed(com->node, NULL);
}
else if ((inf->fieldIndex==TAG_LSR_ATT_scale)
|| (inf->fieldIndex==TAG_LSR_ATT_translation)
|| (inf->fieldIndex==TAG_LSR_ATT_rotation)
) {
SVG_Transform *mx;
gf_node_get_attribute_by_tag(com->node, TAG_SVG_ATT_transform, 1, 0, &a);
mx = a.far_ptr;
if (com->tag == GF_SG_LSR_REPLACE) {
GF_Point2D scale, translate;
SVG_Point_Angle rotate;
if (gf_mx2d_decompose(&mx->mat, &scale, &rotate.angle, &translate)) {
gf_mx2d_init(mx->mat);
if (inf->fieldIndex==TAG_LSR_ATT_scale) scale = *(GF_Point2D *)inf->field_ptr;
else if (inf->fieldIndex==TAG_LSR_ATT_translation) translate = *(GF_Point2D *)inf->field_ptr;
else if (inf->fieldIndex==TAG_LSR_ATT_rotation) rotate = *(SVG_Point_Angle*)inf->field_ptr;
gf_mx2d_add_scale(&mx->mat, scale.x, scale.y);
gf_mx2d_add_rotation(&mx->mat, 0, 0, rotate.angle);
gf_mx2d_add_translation(&mx->mat, translate.x, translate.y);
}
} else {
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);
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);
if (inf->fieldIndex==TAG_LSR_ATT_rotation) gf_mx2d_add_rotation(&mx->mat, 0, 0, ((SVG_Point_Angle*)inf->field_ptr)->angle);
}
gf_node_changed(com->node, &a);
}
else if (gf_node_get_attribute_by_tag(com->node, inf->fieldIndex, 1, 0, &a) == GF_OK) {
b = a;
b.far_ptr = inf->field_ptr;
if (com->tag == GF_SG_LSR_REPLACE) {
gf_svg_attributes_copy(&a, &b, 0);
} else {
gf_svg_attributes_add(&a, &b, &a, 0);
}
if (a.fieldType==XMLRI_datatype) {
gf_node_dirty_set(com->node, GF_SG_SVG_XLINK_HREF_DIRTY, 0);
}
gf_node_changed(com->node, &a);
}
}
} else if (com->fromNodeID) {
GF_FieldInfo a, b;
GF_Node *fromNode = gf_sg_find_node(graph, com->fromNodeID);
if (!fromNode) return GF_NON_COMPLIANT_BITSTREAM;
if (gf_node_get_field(fromNode, com->fromFieldIndex, &b) != GF_OK) return GF_NON_COMPLIANT_BITSTREAM;
if ((inf->fieldIndex==(u32) -1) && (inf->fieldType==DOM_String_datatype)) {
char *str = inf->field_ptr ? *(SVG_String*)inf->field_ptr : NULL;
if (com->tag == GF_SG_LSR_REPLACE) {
GF_DOMText *t = ((SVG_Element*)com->node)->children ? (GF_DOMText*) ((SVG_Element*)com->node)->children->node :NULL;
if (t && (t->sgprivate->tag==TAG_DOMText)) {
if (t->textContent) gf_free(t->textContent);
t->textContent = NULL;
if (str) t->textContent = gf_strdup(str);
}
} else {
if (str) gf_dom_add_text_node(com->node, gf_strdup(str));
}
} else {
gf_node_get_field(com->node, inf->fieldIndex, &a);
if (com->tag == GF_SG_LSR_REPLACE) {
e = gf_svg_attributes_copy(&a, &b, 0);
} else {
e = gf_svg_attributes_add(&a, &b, &a, 0);
}
}
gf_node_changed(com->node, &a);
return e;
} else {
return GF_NON_COMPLIANT_BITSTREAM;
}
break;
case GF_SG_LSR_ACTIVATE:
gf_node_activate(com->node);
break;
case GF_SG_LSR_DEACTIVATE:
gf_node_deactivate(com->node);
gf_node_changed(com->node, NULL);
break;
case GF_SG_LSR_SEND_EVENT:
{
GF_DOM_Event evt;
memset(&evt, 0, sizeof(GF_DOM_Event));
evt.type = com->send_event_name;
evt.detail = com->send_event_integer;
evt.clientX = com->send_event_x;
evt.clientY = com->send_event_y;
gf_dom_event_fire(com->node, &evt);
}
break;
#endif
default:
return GF_NOT_SUPPORTED;
}
if (e) return e;
#ifndef GPAC_DISABLE_VRML
if (com->scripts_to_load) {
while (gf_list_count(com->scripts_to_load)) {
GF_Node *script = (GF_Node *)gf_list_get(com->scripts_to_load, 0);
gf_list_rem(com->scripts_to_load, 0);
gf_sg_script_load(script);
}
gf_list_del(com->scripts_to_load);
com->scripts_to_load = NULL;
}
#endif
return GF_OK;
}
GF_EXPORT
GF_CommandField *gf_sg_command_field_new(GF_Command *com)
{
GF_CommandField *ptr;
GF_SAFEALLOC(ptr, GF_CommandField);
gf_list_add(com->command_fields, ptr);
return ptr;
}
GF_EXPORT
GF_Err gf_sg_command_apply_list(GF_SceneGraph *graph, GF_List *comList, Double time_offset)
{
GF_Err e;
GF_Command *com;
u32 i=0;
while ((com = (GF_Command *)gf_list_enum(comList, &i))) {
e = gf_sg_command_apply(graph, com, time_offset);
if (e) return e;
}
return GF_OK;
}
#ifndef GPAC_DISABLE_VRML
GF_Command *gf_sg_vrml_command_clone(GF_Command *com, GF_SceneGraph *inGraph, Bool force_clone)
{
u32 i, count;
GF_Command *dest;
if (gf_list_count(com->new_proto_list)) return NULL;
dest = gf_sg_command_new(inGraph, com->tag);
if (com->in_scene!=inGraph) force_clone = 1;
if (force_clone) {
dest->node = gf_node_clone(inGraph, com->node, NULL, "", 0);
} else {
dest->node = com->node;
gf_node_register(dest->node, NULL);
}
dest->RouteID = com->RouteID;
if (com->def_name) dest->def_name = gf_strdup(com->def_name);
dest->fromNodeID = com->fromNodeID;
dest->fromFieldIndex = com->fromFieldIndex;
dest->toNodeID = com->toNodeID;
dest->toFieldIndex = com->toFieldIndex;
dest->send_event_integer = com->send_event_integer;
dest->send_event_x = com->send_event_x;
dest->send_event_y = com->send_event_y;
if (com->send_event_string)
dest->send_event_string = gf_strdup(com->send_event_string);
dest->del_proto_list_size = com->del_proto_list_size;
if (com->del_proto_list_size) {
dest->del_proto_list = (u32*)gf_malloc(sizeof(u32) * com->del_proto_list_size);
memcpy(dest->del_proto_list, com->del_proto_list, sizeof(u32) * com->del_proto_list_size);
}
count = gf_list_count(com->command_fields);
for (i=0; i<count; i++) {
GF_CommandField *fo = (GF_CommandField *)gf_list_get(com->command_fields, i);
GF_CommandField *fd = (GF_CommandField *)gf_sg_command_field_new(dest);
fd->fieldIndex = fo->fieldIndex;
fd->fieldType = fo->fieldType;
fd->pos = fo->pos;
if (fo->field_ptr) {
fd->field_ptr = gf_sg_vrml_field_pointer_new(fd->fieldType);
gf_sg_vrml_field_clone(fd->field_ptr, fo->field_ptr, fo->fieldType, dest->in_scene);
}
if (fo->new_node) {
if (force_clone) {
fd->new_node = gf_node_clone(inGraph, fo->new_node, dest->node, "", 0);
} else {
fd->new_node = fo->new_node;
gf_node_register(fd->new_node, NULL);
}
fd->field_ptr = &fd->new_node;
}
if (fo->node_list) {
GF_ChildNodeItem *child, *cur, *prev;
prev = NULL;
child = fo->node_list;
while (child) {
cur = (GF_ChildNodeItem*) gf_malloc(sizeof(GF_ChildNodeItem));
if (force_clone) {
cur->node = gf_node_clone(inGraph, child->node, dest->node, "", 0);
} else {
cur->node = child->node;
gf_node_register(cur->node, NULL);
}
cur->next = NULL;
if (prev) prev->next = cur;
else fd->node_list = cur;
prev = cur;
child = child->next;
}
fd->field_ptr = &fd->node_list;
}
}
return dest;
}
#endif