📄 vrml_proto.c
字号:
last = NULL; list = *( (GF_ChildNodeItem **) field_orig.far_ptr); while (list) { child = gf_node_clone(inScene, list->node, node); gf_node_list_add_child_last((GF_ChildNodeItem **) field.far_ptr, child, &last); list = list->next; } break; case GF_SG_VRML_SFTIME: gf_sg_vrml_field_copy(field.far_ptr, field_orig.far_ptr, field.fieldType); if (!inScene->GetSceneTime) break; /*update SFTime that must be updated when cloning the node*/ if (orig->sgprivate->tag == TAG_ProtoNode) { if (gf_sg_proto_field_is_sftime_offset(orig, &field_orig)) *((SFTime *)field.far_ptr) += inScene->GetSceneTime(inScene->userpriv); } else if (!stricmp(field_orig.name, "startTime") || !stricmp(field_orig.name, "startTime") ) { *((SFTime *)field.far_ptr) += inScene->GetSceneTime(inScene->userpriv); } break; default: gf_sg_vrml_field_copy(field.far_ptr, field_orig.far_ptr, field.fieldType); break; } } if (node->sgprivate->tag==TAG_MPEG4_InputSensor) { GF_Command *com_o, *com_f; u32 k = 0; M_InputSensor *clone_is = (M_InputSensor *)node; M_InputSensor *orig_is = (M_InputSensor *)orig; while ( (com_o = (GF_Command *)gf_list_enum(orig_is->buffer.commandList, &k) ) ) { com_f = gf_sg_command_clone(com_o, node->sgprivate->scenegraph); gf_list_add(clone_is->buffer.commandList, com_f); } } /*register node*/ if (id ) { gf_node_set_id(node, id, orig_name); } gf_node_register(node, cloned_parent);#ifndef GPAC_READ_ONLY /*init node before creating ISed routes so the eventIn handler are in place*/ if (node->sgprivate->tag == TAG_MPEG4_Conditional) BIFS_SetupConditionalClone(node, orig); else #endif if (node->sgprivate->tag != TAG_ProtoNode) gf_node_init(node); if (!inScene->pOwningProto) return node; proto = inScene->pOwningProto; /*create Routes for ISed fields*/ i=0; while ((r1 = (GF_Route*)gf_list_enum(proto->proto_interface->sub_graph->Routes, &i))) { r2 = NULL; /*locate only ISed routes*/ if (!r1->IS_route) continue; /*eventOut*/ if (r1->FromNode == orig) { r2 = gf_sg_route_new(inScene, node, r1->FromField.fieldIndex, (GF_Node *) proto, r1->ToField.fieldIndex); r2->IS_route = 1; } /*eventIn or exposedField*/ else if (r1->ToNode == orig) { r2 = gf_sg_route_new(inScene, (GF_Node *) proto, r1->FromField.fieldIndex, node, r1->ToField.fieldIndex); r2->IS_route = 1; /*activate the route now so that proto instanciation works properly, otherwise we may load scripts with wrong field values Note: we don't activate eventOut routes upon instanciation since no event has been triggered yet*/ gf_sg_route_activate(r2); } } /*remember scripts*/ if (is_script) gf_list_add(proto->scripts_to_load, node); /*this is a proto node, init our internal stuff*/ if (node->sgprivate->tag == TAG_ProtoNode) { node->sgprivate->UserCallback = NULL; node->sgprivate->UserPrivate = NULL; /*NO RENDER, this is filtered at the generic gf_node_render to cope with instanciations and externProto*/ /*load code*/ gf_sg_proto_instanciate((GF_ProtoInstance *)node); } return node;}#ifdef GF_NODE_USE_POINTERSstatic GF_Err protoinst_get_field(GF_Node *node, GF_FieldInfo *info){ info->NDTtype = NDT_SFWorldNode; return gf_sg_proto_get_field(NULL, node, info);}static void protoinst_del(GF_Node *n){ gf_sg_proto_del_instance((GF_ProtoInstance *)n);}#endifGF_Err gf_sg_proto_get_field_ind_static(GF_Node *Node, u32 inField, u8 IndexMode, u32 *allField){ return gf_sg_proto_get_field_index((GF_ProtoInstance *)Node, inField, IndexMode, allField);}static Bool is_same_proto(GF_Proto *p1, GF_Proto *p2){ u32 i, count; if (gf_list_count(p1->proto_fields) != gf_list_count(p2->proto_fields)) return 0; count = gf_list_count(p1->proto_fields); for (i=0; i<count; i++) { GF_ProtoFieldInterface *pf1 = (GF_ProtoFieldInterface*)gf_list_get(p1->proto_fields, i); GF_ProtoFieldInterface *pf2 = (GF_ProtoFieldInterface*)gf_list_get(p2->proto_fields, i); if (pf1->EventType != pf2->EventType) return 0; if (pf1->FieldType != pf2->FieldType) return 0; /*note we don't check names since we're not sure both protos use name coding (MPEG4 only)*/ } return 1;}static GF_Proto *SG_FindProtoByInterface(GF_SceneGraph *sg, GF_Proto *the_proto){ GF_Proto *proto; u32 i, count; assert(sg); /*browse all top-level */ i=0; while ((proto = (GF_Proto*)gf_list_enum(sg->protos, &i))) { if (is_same_proto(proto, the_proto)) return proto; } /*browse all top-level unregistered in reverse order*/ count = gf_list_count(sg->unregistered_protos); for (i=count; i>0; i--) { proto = (GF_Proto*)gf_list_get(sg->unregistered_protos, i-1); if (is_same_proto(proto, the_proto)) return proto; } return NULL;}/*performs common initialization of routes ISed fields and protos once everything is loaded*/void gf_sg_proto_instanciate(GF_ProtoInstance *proto_node){ GF_Node *node, *orig; GF_Route *route, *r2; u32 i; GF_Proto *proto = proto_node->proto_interface; GF_Proto *owner = proto; if (!proto) return; if (owner->ExternProto.count) { GF_ProtoFieldInterface *pfi; GF_SceneGraph *extern_lib; if (!owner->parent_graph->GetExternProtoLib) return; extern_lib = owner->parent_graph->GetExternProtoLib(proto->parent_graph->userpriv, &owner->ExternProto); if (!extern_lib) return; /*this is an hardcoded proto - all routes, node modifications and co are handled internally*/ if (extern_lib == GF_SG_INTERNAL_PROTO) { owner->parent_graph->NodeCallback(owner->parent_graph->userpriv, GF_SG_CALLBACK_INIT, (GF_Node *) proto_node, NULL); return; } /*not loaded yet*/ if (!gf_list_count(extern_lib->protos)) return; /*overwrite this proto by external one*/ proto = NULL; /*start with proto v2 addressing*/ if (owner->ExternProto.vals[0].url) { u32 ID = (u32) -1; char *szName = strrchr(owner->ExternProto.vals[0].url, '#'); if (szName) { szName++; if (sscanf(szName, "%d", &ID)) ID = (u32) -1; } proto = gf_sg_find_proto(extern_lib, ID, szName); } if (!proto) proto = gf_sg_find_proto(extern_lib, owner->ID, NULL); if (!proto) proto = SG_FindProtoByInterface(extern_lib, owner); /*couldn't find proto in the given lib, consider the proto as loaded (give up)*/ if (!proto) { proto_node->is_loaded = 1; return; } i=0; while ((pfi = (GF_ProtoFieldInterface*)gf_list_enum(owner->proto_fields, &i))) { GF_ProtoField *pf = (GF_ProtoField *)gf_list_get(proto_node->fields, i); if (pfi->val_not_loaded && !pf->has_been_accessed) { pfi = (GF_ProtoFieldInterface*)gf_list_get(proto->proto_fields, i); gf_sg_vrml_field_copy(pf->field_pointer, pfi->def_value, pfi->FieldType); } } /*unregister from prev and reg with real proto*/ gf_list_del_item(owner->instances, proto_node); gf_list_add(proto->instances, proto_node); } /*OVERRIDE the proto instance (eg don't instanciate an empty externproto...)*/ proto_node->proto_interface = proto; /*clone all nodes*/ i=0; while ((orig = (GF_Node*)gf_list_enum(proto->node_code, &i))) { /*node is cloned in the new scenegraph and its parent is NULL */ node = gf_node_clone(proto_node->sgprivate->scenegraph, orig, NULL); assert(node); /*assign first rendering node*/ if (i==1) proto_node->RenderingNode = node; gf_list_add(proto_node->node_code, node); } /*instantiate routes (not ISed ones)*/ i=0; while ((route = (GF_Route*)gf_list_enum(proto->sub_graph->Routes, &i))) { if (route->IS_route) continue; r2 = gf_sg_route_new(proto_node->sgprivate->scenegraph, gf_sg_find_node(proto_node->sgprivate->scenegraph, gf_node_get_id(route->FromNode) ), route->FromField.fieldIndex, gf_sg_find_node(proto_node->sgprivate->scenegraph, gf_node_get_id(route->ToNode) ), route->ToField.fieldIndex); if (route->ID) gf_sg_route_set_id(r2, route->ID); if (route->name) gf_sg_route_set_name(r2, route->name); } /*activate all ISed fields so that inits on events is properly done*/ i=0; while ((route = (GF_Route*)gf_list_enum(proto_node->sgprivate->scenegraph->Routes, &i))) { if (!route->IS_route) continue; /*do not activate eventIn to eventIn routes*/ if (route->is_setup) { if ((route->ToField.eventType == GF_SG_EVENT_IN) && (route->FromField.eventType == GF_SG_EVENT_IN) ) continue; } gf_sg_route_activate(route); } /*and load all scripts (this must be done once all fields are routed for the "initialize" method)*/ while (gf_list_count(proto_node->scripts_to_load)) { node = (GF_Node*)gf_list_get(proto_node->scripts_to_load, 0); gf_list_rem(proto_node->scripts_to_load, 0); gf_sg_script_load(node); } /*re-activate all ISed fields pointing to scripts once scripts are loaded (eventIns)*/ i=0; while ((route = (GF_Route*)gf_list_enum(proto_node->sgprivate->scenegraph->Routes, &i))) { if (!route->IS_route || !route->ToNode) continue;/* assert(route->is_setup); if ((route->FromField.eventType == GF_SG_EVENT_OUT) || (route->FromField.eventType == GF_SG_EVENT_IN) ) continue;*/ if ((route->ToNode->sgprivate->tag==TAG_MPEG4_Script) || (route->ToNode->sgprivate->tag==TAG_X3D_Script) ) gf_sg_route_activate(route); } proto_node->is_loaded = 1;}GF_Node *gf_sg_proto_create_node(GF_SceneGraph *scene, GF_Proto *proto, GF_ProtoInstance *from_inst){ u32 i; GF_ProtoField *inst, *from_field; GF_ProtoFieldInterface *field; GF_ProtoInstance *proto_node; GF_SAFEALLOC(proto_node, GF_ProtoInstance) if (!proto_node) return NULL; gf_node_setup((GF_Node *)proto_node, TAG_ProtoNode); proto_node->node_code = gf_list_new(); proto_node->fields = gf_list_new(); proto_node->scripts_to_load = gf_list_new(); proto_node->proto_interface = proto; gf_list_add(proto->instances, proto_node);#ifdef GF_NODE_USE_POINTERS proto_node->sgprivate->node_del = protoinst_del; proto_node->sgprivate->get_field = protoinst_get_field; proto_node->sgprivate->get_field_count = gf_sg_proto_get_num_fields; proto_node->sgprivate->name = strdup(proto->Name);#else proto_node->proto_name = strdup(proto->Name);#endif /*create the namespace*/ proto_node->sgprivate->scenegraph = gf_sg_new_subscene(scene); /*set this proto as owner of the new graph*/ proto_node->sgprivate->scenegraph->pOwningProto = proto_node; /*instanciate fields*/ i=0; while ((field = (GF_ProtoFieldInterface*)gf_list_enum(proto->proto_fields, &i))) { inst = (GF_ProtoField *)malloc(sizeof(GF_ProtoField)); inst->EventType = field->EventType; inst->FieldType = field->FieldType; inst->has_been_accessed = 0; /*this is OK to call on GF_Node (returns NULL) and MFNode (returns gf_list_new() )*/ inst->field_pointer = gf_sg_vrml_field_pointer_new(inst->FieldType); /*regular field, duplicate from default value or instanciated one if specified (since a proto may be partially instanciated when used in another proto)*/ if (gf_sg_vrml_get_sf_type(inst->FieldType) != GF_SG_VRML_SFNODE) { if (from_inst) { from_field = (GF_ProtoField *)gf_list_get(from_inst->fields, i-1); gf_sg_vrml_field_copy(inst->field_pointer, from_field->field_pointer, inst->FieldType); } else { gf_sg_vrml_field_copy(inst->field_pointer, field->def_value, inst->FieldType); } } /*No default values for SFNodes as interfaces ...*/ gf_list_add(proto_node->fields, inst); } return (GF_Node *) proto_node;}GF_Node *gf_sg_proto_create_instance(GF_SceneGraph *sg, GF_Proto *proto){ return gf_sg_proto_create_node(sg, proto, NULL);}GF_Err gf_sg_proto_load_code(GF_Node *node){ GF_ProtoInstance *inst; if (node->sgprivate->tag != TAG_ProtoNode) return GF_BAD_PARAM; inst = (GF_ProtoInstance *) node; if (!inst->proto_interface) return GF_BAD_PARAM; if (inst->is_loaded) return GF_OK; gf_sg_proto_instanciate(inst); return GF_OK;}u32 gf_sg_proto_get_num_fields(GF_Node *node, u8 code_mode){ GF_ProtoInstance *proto; if (!node) return 0; proto = (GF_ProtoInstance *)node; /*watchout for deletion case*/ switch (code_mode) { case GF_SG_FIELD_CODING_IN: return proto->proto_interface ? proto->proto_interface->NumIn : 0; case GF_SG_FIELD_CODING_OUT: return proto->proto_interface ? proto->proto_interface->NumOut : 0; case GF_SG_FIELD_CODING_DEF: return proto->proto_interface ? proto->proto_interface->NumDef : 0; case GF_SG_FIELD_CODING_ALL: return gf_list_count(proto->proto_interface ? proto->proto_interface->proto_fields : proto->fields); /*BIFS-ANIM not supported*/ case GF_SG_FIELD_CODING_DYN: default: return 0; }}void gf_sg_proto_del_instance(GF_ProtoInstance *inst){ GF_ProtoField *field; GF_Node *node; u32 index; index = 0; while (gf_list_count(inst->fields)) { field = (GF_ProtoField *)gf_list_get(inst->fields, 0); gf_list_rem(inst->fields, 0); /*regular type*/ if ( (field->FieldType!=GF_SG_VRML_SFNODE) && (field->FieldType!=GF_SG_VRML_MFNODE)) { gf_sg_vrml_field_pointer_del(field->field_pointer, field->FieldType); } /*node types: delete instances*/ else if (field->field_pointer) { if (field->FieldType == GF_SG_VRML_SFNODE) { gf_node_unregister((GF_Node *) field->field_pointer, (GF_Node *) inst); } else { GF_ChildNodeItem *list = (GF_ChildNodeItem *)field->field_pointer; while (list) { GF_ChildNodeItem *cur = list; gf_node_unregister(list->node, (GF_Node *) inst); list = list->next; free(cur); } } } free(field); index++; } gf_list_del(inst->fields); /*destroy the code*/ while (gf_list_count(inst->node_code)) { node = (GF_Node*)gf_list_get(inst->node_code, 0); gf_node_unregister(node, (GF_Node*) inst); gf_list_rem(inst->node_code, 0); } gf_list_del(inst->node_code); assert(!gf_list_count(inst->scripts_to_load));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -