📄 vrml_proto.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Scene Graph sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/scenegraph_dev.h>/*MPEG4 & X3D tags (for node tables & script handling)*/#include <gpac/nodes_mpeg4.h>#include <gpac/nodes_x3d.h>GF_Proto *gf_sg_proto_new(GF_SceneGraph *inScene, u32 ProtoID, char *name, Bool unregistered){ GF_Proto *tmp; if (!inScene) return NULL; /*make sure we don't define a proto already defined in this scope*/ if (!unregistered) { tmp = gf_sg_find_proto(inScene, ProtoID, name); if (tmp) return NULL; } GF_SAFEALLOC(tmp, GF_Proto) if (!tmp) return NULL; tmp->proto_fields = gf_list_new(); tmp->node_code = gf_list_new(); tmp->parent_graph = inScene; tmp->sub_graph = gf_sg_new_subscene(inScene); tmp->instances = gf_list_new(); if (name) tmp->Name = strdup(name); else tmp->Name = strdup("Unnamed Proto"); tmp->ID = ProtoID; if (!unregistered) { gf_list_add(inScene->protos, tmp); } else { gf_list_add(inScene->unregistered_protos, tmp); } return tmp;}GF_Err gf_sg_proto_set_in_graph(GF_Proto *proto, GF_SceneGraph *inScene, Bool set_in){ u32 i; GF_Proto *tmp; GF_List *removeFrom; GF_List *insertIn; if (set_in) { removeFrom = proto->parent_graph->unregistered_protos; insertIn = proto->parent_graph->protos; } else { insertIn = proto->parent_graph->unregistered_protos; removeFrom = proto->parent_graph->protos; } gf_list_del_item(removeFrom, proto); i=0; while ((tmp = (GF_Proto*)gf_list_enum(insertIn, &i))) { if (tmp==proto) return GF_OK; if (!set_in) continue; /*if registering, make sure no other proto has the same ID/name*/ if (tmp->ID==proto->ID) return GF_BAD_PARAM; if (!stricmp(tmp->Name, proto->Name)) return GF_BAD_PARAM; } return gf_list_add(insertIn, proto);}GF_Err gf_sg_proto_del(GF_Proto *proto){ GF_Node *node; GF_ProtoFieldInterface *field; s32 i; if (!proto) return GF_OK; i = gf_list_del_item(proto->parent_graph->protos, proto); if (i<0) i = gf_list_del_item(proto->parent_graph->unregistered_protos, proto); if (proto->userpriv && proto->OnDelete) proto->OnDelete(proto->userpriv); /*first destroy the code*/ while (gf_list_count(proto->node_code)) { node = (GF_Node*)gf_list_get(proto->node_code, 0); gf_node_unregister(node, NULL); gf_list_rem(proto->node_code, 0); } gf_list_del(proto->node_code); /*delete interface*/ while (gf_list_count(proto->proto_fields)) { field = (GF_ProtoFieldInterface*)gf_list_get(proto->proto_fields, 0); if (field->userpriv && field->OnDelete) field->OnDelete(field->userpriv); if (field->FieldType==GF_SG_VRML_SFNODE) { if (field->def_sfnode_value) gf_node_unregister(field->def_sfnode_value, NULL); } else if (field->FieldType==GF_SG_VRML_MFNODE) { if (field->def_mfnode_value) gf_node_unregister_children(NULL, field->def_mfnode_value); } else if (field->def_value) gf_sg_vrml_field_pointer_del(field->def_value, field->FieldType); if (field->FieldName) free(field->FieldName); /*QP fields are SF fields, we can safely free() them*/ if (field->qp_max_value) free(field->qp_max_value); if (field->qp_min_value) free(field->qp_min_value); free(field); gf_list_rem(proto->proto_fields, 0); } gf_list_del(proto->proto_fields); while (gf_list_count(proto->instances)) { GF_ProtoInstance *p = (GF_ProtoInstance *)gf_list_get(proto->instances, 0); gf_list_rem(proto->instances, 0); p->proto_interface = NULL; } /*delete sub graph*/ gf_sg_del(proto->sub_graph); if (proto->Name) free(proto->Name); gf_sg_mfurl_del(proto->ExternProto); gf_list_del(proto->instances); free(proto); return GF_OK;}GF_SceneGraph *gf_sg_proto_get_graph(GF_Proto *proto){ return proto ? proto->sub_graph : NULL;}void gf_sg_proto_set_private(GF_Proto *p, void *ptr, void (*OnDelete)(void *ptr) ){ if (p) { p->userpriv = ptr; p->OnDelete = OnDelete; }}void *gf_sg_proto_get_private(GF_Proto *p){ return p ? p->userpriv : NULL;}GF_EXPORTMFURL *gf_sg_proto_get_extern_url(GF_Proto *proto){ return proto ? &proto->ExternProto : NULL;}GF_Err gf_sg_proto_add_node_code(GF_Proto *proto, GF_Node *pNode){ if (!proto) return GF_BAD_PARAM; return gf_list_add(proto->node_code, pNode);}GF_ProtoFieldInterface *gf_sg_proto_field_find_by_name(GF_Proto *proto, char *fieldName){ GF_ProtoFieldInterface *ptr; u32 i=0; while ((ptr = (GF_ProtoFieldInterface*)gf_list_enum(proto->proto_fields, &i))) { if (ptr->FieldName && !strcmp(ptr->FieldName, fieldName)) return ptr; } return NULL;}GF_ProtoFieldInterface *gf_sg_proto_field_new(GF_Proto *proto, u32 fieldType, u32 eventType, char *fieldName){ GF_ProtoFieldInterface *tmp; if (fieldName) { tmp = gf_sg_proto_field_find_by_name(proto, fieldName); if (tmp) return NULL; } GF_SAFEALLOC(tmp, GF_ProtoFieldInterface) if (!tmp) return NULL; tmp->FieldType = fieldType; tmp->EventType = eventType; /*create container - can be NULL if SF node*/ if ( fieldType == GF_SG_VRML_SFNODE) { tmp->def_sfnode_value = NULL; tmp->def_value = &tmp->def_sfnode_value; } else if ( fieldType == GF_SG_VRML_MFNODE) { tmp->def_mfnode_value = NULL; tmp->def_value = &tmp->def_mfnode_value; } else { tmp->def_value = gf_sg_vrml_field_pointer_new(fieldType); } if (fieldName) tmp->FieldName = strdup(fieldName); tmp->ALL_index = gf_list_count(proto->proto_fields); tmp->OUT_index = tmp->DEF_index = tmp->IN_index = (u32) -1; switch (eventType) { case GF_SG_EVENT_EXPOSED_FIELD: tmp->IN_index = proto->NumIn; proto->NumIn ++; tmp->OUT_index = proto->NumOut; proto->NumOut ++; case GF_SG_EVENT_FIELD: tmp->DEF_index = proto->NumDef; proto->NumDef ++; break; case GF_SG_EVENT_IN: tmp->IN_index = proto->NumIn; proto->NumIn ++; break; case GF_SG_EVENT_OUT: tmp->OUT_index = proto->NumOut; proto->NumOut ++; break; } gf_list_add(proto->proto_fields, tmp); return tmp;}void gf_sg_proto_field_set_private(GF_ProtoFieldInterface *field, void *ptr, void (*OnDelete)(void *ptr)){ if (field) { field->userpriv = ptr; field->OnDelete = OnDelete; }}void *gf_sg_proto_field_get_private(GF_ProtoFieldInterface *field){ return field ? field->userpriv : NULL;}GF_Err gf_sg_proto_field_get_field(GF_ProtoFieldInterface *field, GF_FieldInfo *info){ if (!field || !info) return GF_BAD_PARAM; memset(info, 0, sizeof(GF_FieldInfo)); info->fieldIndex = field->ALL_index; info->fieldType = field->FieldType; info->eventType = field->EventType; info->far_ptr = field->def_value; info->name = field->FieldName; info->NDTtype = NDT_SFWorldNode; return GF_OK;}GF_Err gf_sg_proto_get_field(GF_Proto *proto, GF_Node *node, GF_FieldInfo *info){ GF_ProtoFieldInterface *proto_field; GF_ProtoInstance *inst; GF_ProtoField *field; if (!proto && !node) return GF_BAD_PARAM; if (proto) { proto_field = (GF_ProtoFieldInterface*)gf_list_get(proto->proto_fields, info->fieldIndex); if (!proto_field) return GF_BAD_PARAM; info->fieldType = proto_field->FieldType; info->eventType = proto_field->EventType; info->fieldIndex = proto_field->ALL_index; info->NDTtype = NDT_SFWorldNode; info->far_ptr = proto_field->def_value; info->name = proto_field->FieldName; return GF_OK; } /*otherwise this is an instanciated proto*/ if (node->sgprivate->tag!=TAG_ProtoNode) return GF_BAD_PARAM; inst = (GF_ProtoInstance *) node; field = (GF_ProtoField*)gf_list_get(inst->fields, info->fieldIndex); if (!field) return GF_BAD_PARAM; info->fieldType = field->FieldType; info->eventType = field->EventType; /*SF/MF nodes need pointers to field object - cf gf_sg_proto_create_node*/ if (gf_sg_vrml_get_sf_type(field->FieldType) == GF_SG_VRML_SFNODE) { info->far_ptr = &field->field_pointer; } else { info->far_ptr = field->field_pointer; } /*set the name - watchout for deletion case*/ if (inst->proto_interface) { proto_field = (GF_ProtoFieldInterface*)gf_list_get(inst->proto_interface->proto_fields, info->fieldIndex); info->name = proto_field->FieldName; } else { info->name = "ProtoFieldDeleted"; } info->NDTtype = NDT_SFWorldNode; return GF_OK;}s32 gf_sg_proto_get_field_index_by_name(GF_Proto *proto, GF_Node *node, char *name){ u32 i; GF_ProtoFieldInterface *proto_field; GF_Proto *__proto; if (node && (node->sgprivate->tag!=TAG_ProtoNode)) return -1; __proto = proto ? proto : ((GF_ProtoInstance *) node)->proto_interface; if (!__proto ) return -1; for (i=0; i<gf_list_count(__proto->proto_fields); i++) { proto_field = (GF_ProtoFieldInterface*)gf_list_get(__proto->proto_fields, i); if (proto_field->FieldName && !strcmp(proto_field->FieldName, name)) return i; } return -1;}GF_EXPORTGF_Node *gf_node_clone(GF_SceneGraph *inScene, GF_Node *orig, GF_Node *cloned_parent){ u32 i, count, id; const char *orig_name; Bool is_script; GF_Node *node, *child; GF_ChildNodeItem *list, *last; GF_Route *r1, *r2; void BIFS_SetupConditionalClone(GF_Node *node, GF_Node *orig); GF_ProtoInstance *proto; GF_Proto *proto_node; GF_FieldInfo field_orig, field; /*this is not a mistake*/ if (!orig) return NULL; /*check for DEF/USE*/ orig_name = gf_node_get_name_and_id(orig, &id); if (id) { node = gf_sg_find_node(inScene, id); /*node already created, USE*/ if (node) { gf_node_register(node, cloned_parent); return node; } } /*create a node*/ if (orig->sgprivate->tag == TAG_ProtoNode) { proto_node = ((GF_ProtoInstance *)orig)->proto_interface; /*create the instance but don't load the code -c we MUST wait for ISed routes to be cloned before*/ node = gf_sg_proto_create_node(inScene, proto_node, (GF_ProtoInstance *) orig); } else { node = gf_node_new(inScene, orig->sgprivate->tag); } count = gf_node_get_field_count(orig); is_script = 0; if ((orig->sgprivate->tag==TAG_MPEG4_Script) || (orig->sgprivate->tag==TAG_X3D_Script)) is_script = 1; if (is_script) gf_sg_script_prepare_clone(node, orig); /*copy each field*/ for (i=0; i<count; i++) { gf_node_get_field(orig, i, &field_orig); /*get target ptr*/ gf_node_get_field(node, i, &field); assert(field.eventType==field_orig.eventType); assert(field.fieldType==field_orig.fieldType); /*duplicate it*/ switch (field.fieldType) { case GF_SG_VRML_SFNODE: child = gf_node_clone(inScene, (* ((GF_Node **) field_orig.far_ptr)), node); *((GF_Node **) field.far_ptr) = child; break; case GF_SG_VRML_MFNODE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -