📄 base_scenegraph.c
字号:
node->sgprivate->parents->next = NULL; node->sgprivate->parents->node = parentNode; } else { GF_ParentList *item, *nlist = node->sgprivate->parents; while (nlist->next) nlist = nlist->next; item = (GF_ParentList*)malloc(sizeof(GF_ParentList)); item->next = NULL; item->node = parentNode; nlist->next = item; } } return GF_OK;}/*replace or remove node instance in the given node (eg in all GF_Node or MFNode fields)this doesn't propagate in the scene graph. If updateOrderedGroup and new_node is NULL, the order field of OGis updated*/static void ReplaceDEFNode(GF_Node *FromNode, GF_Node *node, GF_Node *newNode, Bool updateOrderedGroup){ u32 i, j; GF_Node *p; GF_ChildNodeItem *list; GF_FieldInfo field; /*browse all fields*/ for (i=0; i<gf_node_get_field_count(FromNode); i++) { gf_node_get_field(FromNode, i, &field); switch (field.fieldType) { case GF_SG_VRML_SFNODE: /*set to NULL for SFFields*/ p = *((GF_Node **) field.far_ptr); /*this is a USE / DEF*/ if (p == node) { *((GF_Node **) field.far_ptr) = NULL; if (newNode) { *((GF_Node **) field.far_ptr) = newNode; } goto exit; } break; case GF_SG_VRML_MFNODE: list = *(GF_ChildNodeItem **) field.far_ptr; j=0; while (list) { /*replace nodes different from newNode but with same ID*/ if ((newNode == list->node) || (list->node != node)) { list = list->next; j++; continue; } if (newNode) { list->node = newNode; } else { gf_node_list_del_child( (GF_ChildNodeItem **) field.far_ptr, list->node); if (updateOrderedGroup && (FromNode->sgprivate->tag==TAG_MPEG4_OrderedGroup)) { M_OrderedGroup *og = (M_OrderedGroup *)FromNode; gf_sg_vrml_mf_remove(&og->order, GF_SG_VRML_SFINT32, j); } } goto exit; } break; /*not a node, continue*/ default: continue; } } /*since we don't filter parent nodes this is called once per USE, not per container, so return if found*/exit: gf_node_changed(FromNode, &field);}#ifndef GPAC_DISABLE_SVGstatic void Replace_IRI(GF_SceneGraph *sg, GF_Node *old_node, GF_Node *newNode){ u32 i, count; count = gf_list_count(sg->xlink_hrefs); for (i=0; i<count; i++) { XMLRI *iri = (XMLRI *)gf_list_get(sg->xlink_hrefs, i); if (iri->target == old_node) { iri->target = newNode; if (!newNode) { gf_list_rem(sg->xlink_hrefs, i); i--; count--; } } }}/*replace or remove node instance in the given node (eg in all IRI)*/static void ReplaceIRINode(GF_Node *FromNode, GF_Node *old_node, GF_Node *newNode){ GF_ChildNodeItem *prev = NULL; GF_ChildNodeItem *child = ((SVG_Element *)FromNode)->children; while (child) { if (child->node != old_node) { prev = child; child = child->next; continue; } if (newNode) { child->node = newNode; } else { if (prev) prev->next = child->next; else ((SVG_Element *)FromNode)->children = child->next; free(child); } break; }}#endif/*get all parents of the node and replace, the instance of the node and finally destroy the node*/GF_Err gf_node_replace(GF_Node *node, GF_Node *new_node, Bool updateOrderedGroup){ u32 type; Bool replace_root; GF_Node *par; GF_SceneGraph *pSG = node->sgprivate->scenegraph; /*if this is a proto its is registered in its parent graph, not the current*/ if (node == (GF_Node*)pSG->pOwningProto) pSG = pSG->parent_scene;// if (!SG_SearchForNodeIndex(pSG, node, &i)) return GF_BAD_PARAM;// assert(node == pSG->node_registry[i]); type = node->sgprivate->tag;#ifndef GPAC_DISABLE_SVG if (((type>= GF_NODE_RANGE_FIRST_SVG) && (type<= GF_NODE_RANGE_LAST_SVG)) #ifdef GPAC_ENABLE_SVG_SA || ((type>= GF_NODE_RANGE_FIRST_SVG_SA) && (type<= GF_NODE_RANGE_LAST_SVG_SA)) #endif#ifdef GPAC_ENABLE_SVG_SANI || ((type>= GF_NODE_RANGE_FIRST_SVG_SANI) && (type<= GF_NODE_RANGE_LAST_SVG_SANI))#endif ) { type = 1; Replace_IRI(pSG, node, new_node); } else #endif type = 0; /*first check if this is the root node*/ replace_root = (node->sgprivate->scenegraph->RootNode == node) ? 1 : 0; while (node->sgprivate->parents) { Bool do_break = node->sgprivate->parents->next ? 0 : 1; par = node->sgprivate->parents->node;#ifndef GPAC_DISABLE_SVG if (type) ReplaceIRINode(par, node, new_node); else#endif ReplaceDEFNode(par, node, new_node, updateOrderedGroup); if (new_node) gf_node_register(new_node, par); gf_node_unregister(node, par); gf_node_changed(par, NULL); if (do_break) break; } if (replace_root) { pSG = node->sgprivate->scenegraph; gf_node_unregister(node, NULL); pSG->RootNode = new_node; } return GF_OK;}static GFINLINE void insert_node_def(GF_SceneGraph *sg, GF_Node *def, u32 ID, const char *name){ NodeIDedItem *reg_node, *cur; reg_node = (NodeIDedItem *) malloc(sizeof(NodeIDedItem)); reg_node->node = def; reg_node->NodeID = ID; reg_node->NodeName = name ? strdup(name) : NULL; reg_node->next = NULL; if (!sg->id_node) { sg->id_node = reg_node; sg->id_node_last = sg->id_node; } else if (sg->id_node->NodeID>ID) { reg_node->next = sg->id_node; sg->id_node = reg_node; } else if (sg->id_node_last->NodeID < ID) { sg->id_node_last->next = reg_node; sg->id_node_last = reg_node; } else { cur = sg->id_node; while (cur->next) { if (cur->next->NodeID>ID) { reg_node->next = cur->next; cur->next = reg_node; return; } cur = cur->next; } cur->next = reg_node; }}GF_EXPORTGF_Err gf_node_set_id(GF_Node *p, u32 ID, const char *name){ GF_SceneGraph *pSG; if (!ID || !p || !p->sgprivate->scenegraph) return GF_BAD_PARAM; pSG = p->sgprivate->scenegraph; /*if this is a proto register to the parent graph, not the current*/ if (p == (GF_Node*)pSG->pOwningProto) pSG = pSG->parent_scene; /*new DEF ID*/ if (!(p->sgprivate->flags & GF_NODE_IS_DEF) ) { p->sgprivate->flags |= GF_NODE_IS_DEF; } /*reassigning ID, remove node def*/ else { remove_node_id(pSG, p); } insert_node_def(pSG, p, ID, name); return GF_OK;}GF_EXPORTGF_Err gf_node_remove_id(GF_Node *p){ GF_SceneGraph *pSG; if (!p) return GF_BAD_PARAM; pSG = p->sgprivate->scenegraph; /*if this is a proto register to the parent graph, not the current*/ if (p == (GF_Node*)pSG->pOwningProto) pSG = pSG->parent_scene; /*new DEF ID*/ if (p->sgprivate->flags & GF_NODE_IS_DEF) { remove_node_id(pSG, p); p->sgprivate->flags &= ~GF_NODE_IS_DEF; return GF_OK; } return GF_BAD_PARAM;}/*calls RenderNode on this node*/GF_EXPORTvoid gf_node_render(GF_Node *node, void *renderStack){ if (!node || !node->sgprivate) return; if (node->sgprivate->flags & GF_NODE_IS_DEACTIVATED) return; if (node->sgprivate->tag != TAG_ProtoNode) { if (node->sgprivate->UserCallback) { #ifdef GF_CYCLIC_RENDER_ON if (node->sgprivate->flags & GF_NODE_IN_RENDER) return; node->sgprivate->flags |= GF_NODE_IN_RENDER; assert(node->sgprivate->flags);#endif GF_LOG(GF_LOG_DEBUG, GF_LOG_SCENE, ("[SceneGraph] Traversing node %s\n", gf_node_get_class_name(node) )); node->sgprivate->UserCallback(node, renderStack, 0);#ifdef GF_CYCLIC_RENDER_ON node->sgprivate->flags &= ~GF_NODE_IN_RENDER;#endif } return; } /*proto only traverses its first child*/ if (((GF_ProtoInstance *) node)->RenderingNode) { node = ((GF_ProtoInstance *) node)->RenderingNode; } /*if no rendering function is assigned this is a real proto (otherwise this is an hardcoded one)*/ else if (!node->sgprivate->UserCallback) { /*if no rendering node, check if the proto is fully instanciated (externProto)*/ GF_ProtoInstance *proto_inst = (GF_ProtoInstance *) node; gf_node_dirty_clear(node, 0); /*proto has been deleted or dummy proto (without node code)*/ if (!proto_inst->proto_interface || proto_inst->is_loaded) return; /*try to load the code*/ gf_sg_proto_instanciate(proto_inst); if (!proto_inst->RenderingNode) { gf_node_dirty_set(node, 0, 1); return; } node = proto_inst->RenderingNode; node->sgprivate->scenegraph->NodeCallback(node->sgprivate->scenegraph->userpriv, GF_SG_CALLBACK_MODIFIED, node, NULL); } if (node->sgprivate->UserCallback) {#ifdef GF_CYCLIC_RENDER_ON if (node->sgprivate->flags & GF_NODE_IN_RENDER) return; node->sgprivate->flags |= GF_NODE_IN_RENDER;#endif GF_LOG(GF_LOG_DEBUG, GF_LOG_SCENE, ("[SceneGraph] Traversing node %s\n", gf_node_get_class_name(node) )); node->sgprivate->UserCallback(node, renderStack, 0);#ifdef GF_CYCLIC_RENDER_ON node->sgprivate->flags &= ~GF_NODE_IN_RENDER;#endif }}GF_EXPORTvoid gf_node_allow_cyclic_render(GF_Node *node){#ifdef GF_CYCLIC_RENDER_ON if (node) node->sgprivate->flags &= ~GF_NODE_IN_RENDER;#endif}/*blindly calls RenderNode on all nodes in the "children" list*/GF_EXPORTvoid gf_node_render_children(GF_Node *node, void *renderStack){ GF_ChildNodeItem *child; assert(node); child = ((GF_ParentNode *)node)->children; while (child) { gf_node_render(child->node, renderStack); child = child->next; }}GF_EXPORTGF_SceneGraph *gf_node_get_graph(GF_Node *node){ return (node ? node->sgprivate->scenegraph : NULL);}GF_EXPORTGF_Node *gf_sg_find_node(GF_SceneGraph *sg, u32 nodeID){ NodeIDedItem *reg_node = sg->id_node; while (reg_node) { if (reg_node->NodeID == nodeID) return reg_node->node; reg_node = reg_node->next; } return NULL;}GF_EXPORTGF_Node *gf_sg_find_node_by_name(GF_SceneGraph *sg, char *name){ if (name) { NodeIDedItem *reg_node = sg->id_node; while (reg_node) { if (reg_node->NodeName && !strcmp(reg_node->NodeName, name)) return reg_node->node; reg_node = reg_node->next; } } return NULL;}GF_EXPORTu32 gf_sg_get_next_available_node_id(GF_SceneGraph *sg) { u32 ID; NodeIDedItem *reg_node; if (!sg->id_node) return 1; reg_node = sg->id_node; ID = reg_node->NodeID; /*nodes are sorted*/ while (reg_node->next) { if (ID+1<reg_node->next->NodeID) return ID+1; ID = reg_node->next->NodeID; reg_node = reg_node->next; } return ID+1;}u32 gf_sg_get_max_node_id(GF_SceneGraph *sg){ NodeIDedItem *reg_node; if (!sg->id_node) return 0; if (sg->id_node_last) return sg->id_node_last->NodeID; reg_node = sg->id_node; while (reg_node->next) reg_node = reg_node->next; return reg_node->NodeID;}void gf_node_setup(GF_Node *p, u32 tag){ GF_SAFEALLOC(p->sgprivate, NodePriv); p->sgprivate->tag = tag; p->sgprivate->flags = GF_SG_NODE_DIRTY;}GF_Node *gf_sg_new_base_node(){ GF_Node *newnode = (GF_Node *)malloc(sizeof(GF_Node)); gf_node_setup(newnode, TAG_UndefinedNode); return newnode;}GF_EXPORTu32 gf_node_get_tag(GF_Node*p){ assert(p); return p->sgprivate->tag;}GF_EXPORTu32 gf_node_get_id(GF_Node*p){ NodeIDedItem *reg_node; GF_SceneGraph *sg; assert(p); if (!(p->sgprivate->flags & GF_NODE_IS_DEF)) return 0; sg = p->sgprivate->scenegraph; /*if this is a proto, look in parent graph*/ if (p == (GF_Node*)sg->pOwningProto) sg = sg->parent_scene; reg_node = sg->id_node; while (reg_node) { if (reg_node->node==p) return reg_node->NodeID; reg_node = reg_node->next; } return 0;}GF_EXPORTconst char *gf_node_get_name(GF_Node*p){ GF_SceneGraph *sg; NodeIDedItem *reg_node; assert(p); if (!(p->sgprivate->flags & GF_NODE_IS_DEF)) return NULL; sg = p->sgprivate->scenegraph; /*if this is a proto, look in parent graph*/ if (p == (GF_Node*)sg->pOwningProto) sg = sg->parent_scene; reg_node = sg->id_node; while (reg_node) { if (reg_node->node==p) return reg_node->NodeName; reg_node = reg_node->next; } return NULL;}GF_EXPORTconst char *gf_node_get_name_and_id(GF_Node*p, u32 *id){ GF_SceneGraph *sg; NodeIDedItem *reg_node; assert(p); if (!(p->sgprivate->flags & GF_NODE_IS_DEF)) { *id = 0; return NULL; } sg = p->sgprivate->scenegraph; /*if this is a proto, look in parent graph*/ if (p == (GF_Node*)sg->pOwningProto) sg = sg->parent_scene; reg_node = sg->id_node; while (reg_node) { if (reg_node->node==p) { *id = reg_node->NodeID; return reg_node->NodeName; } reg_node = reg_node->next; } *id = 0; return NULL;}GF_EXPORTvoid *gf_node_get_private(GF_Node*p){ assert(p); return p->sgprivate->UserPrivate;}GF_EXPORTvoid gf_node_set_private(GF_Node*p, void *pr){ assert(p); p->sgprivate->UserPrivate = pr;}GF_EXPORTGF_Err gf_node_set_callback_function(GF_Node *p, void (*RenderNode)(GF_Node *node, void *render_stack, Bool is_destroy) ){ assert(p); p->sgprivate->UserCallback = RenderNode; return GF_OK;}void gf_sg_parent_setup(GF_Node *node){ ((GF_ParentNode *)node)->children = NULL; node->sgprivate->flags |= GF_SG_CHILD_DIRTY;}GF_EXPORTvoid gf_node_unregister_children(GF_Node *container, GF_ChildNodeItem *child){ GF_ChildNodeItem *cur; while (child) { gf_node_unregister(child->node, container); cur = child; child = child->next; free(cur); }}GF_EXPORTGF_Err gf_node_list_insert_child(GF_ChildNodeItem **list, GF_Node *n, u32 pos){ GF_ChildNodeItem *child, *cur, *prev; u32 cur_pos = 0; assert(pos != (u32) -1); child = *list; cur = (GF_ChildNodeItem*) malloc(sizeof(GF_ChildNodeItem)); if (!cur) return GF_OUT_OF_MEM; cur->node = n; cur->next = NULL; prev = NULL; while (child) { if (pos==cur_pos) break; /*append*/ if (!child->next) { child->next = cur; return GF_OK; } prev = child; child = child->next; cur_pos++; } cur->next = child; if (prev) prev->next = cur; else *list = cur; return GF_OK;}GF_EXPORTGF_Node *gf_node_list_get_child(GF_ChildNodeItem *list, s32 pos){ s32 cur_pos = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -