static void ttd_add_item(M_Form *form) { s32 *new_gr; gf_sg_vrml_mf_append(&form->groups, GF_SG_VRML_MFINT32, (void **) &new_gr); (*new_gr) = gf_node_list_get_count(form->children); gf_sg_vrml_mf_append(&form->groups, GF_SG_VRML_MFINT32, (void **) &new_gr); (*new_gr) = -1; /*store line info*/ gf_sg_vrml_mf_append(&form->groupsIndex, GF_SG_VRML_MFINT32, (void **) &new_gr); (*new_gr) = gf_node_list_get_count(form->children); }
static void RenderSwitch(GF_Node *node, void *rs, Bool is_destroy) { GF_ChildNodeItem *l; u32 i, count; Bool prev_switch; GF_ChildNodeItem *children; s32 whichChoice; GF_Node *child; SwitchStack *st = (SwitchStack *)gf_node_get_private(node); RenderEffect2D *eff; eff = (RenderEffect2D *)rs; if (is_destroy) { free(st); return; } if (gf_node_get_name(node)) { node = node; } /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ if (gf_node_get_tag(node)==TAG_MPEG4_Switch) { children = ((M_Switch *)node)->choice; whichChoice = ((M_Switch *)node)->whichChoice; } else { children = ((X_Switch *)node)->children; whichChoice = ((X_Switch *)node)->whichChoice; } count = gf_node_list_get_count(children); prev_switch = eff->trav_flags; /*check changes in choice field*/ if ((gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) || (st->last_switch != whichChoice) ) { eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF; i=0; l = children; while (l) { // if ((s32) i!=whichChoice) gf_node_render(l->node, eff); if ((s32) i == st->last_switch) gf_node_render(l->node, eff); l = l->next; i++; } eff->trav_flags &= ~GF_SR_TRAV_SWITCHED_OFF; st->last_switch = whichChoice; } gf_node_dirty_clear(node, 0); /*no need to check for sensors since a sensor is active for the whole parent group, that is for switch itself CSQ: switch cannot be used to switch sensors, too bad...*/ eff->trav_flags = prev_switch; if (whichChoice>=0) { child = (GF_Node*)gf_node_list_get_child(children, whichChoice); gf_node_render(child, eff); } }
static void TraverseOrderedGroup(GF_Node *node, void *rs, Bool is_destroy) { u32 i, count; struct og_pos *priorities; Bool invalidate_backup; OrderedGroupStack *stack = (OrderedGroupStack *) gf_node_get_private(node); M_OrderedGroup *og = (M_OrderedGroup *) node; GF_TraverseState *tr_state = (GF_TraverseState *)rs; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); group_2d_destroy(node, (GroupingNode2D*)stack); if (stack->positions) gf_free(stack->positions); gf_free(stack); return; } if (!og->order.count || (tr_state->traversing_mode==TRAVERSE_GET_BOUNDS) ) { gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); group_2d_traverse(node, (GroupingNode2D*)stack, tr_state); return; } invalidate_backup = tr_state->invalidate_all; /*check whether the OrderedGroup node has changed*/ if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { if (stack->positions) gf_free(stack->positions); count = gf_node_list_get_count(og->children); priorities = (struct og_pos*)gf_malloc(sizeof(struct og_pos)*count); for (i=0; i<count; i++) { priorities[i].position = i; priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0; } qsort(priorities, count, sizeof(struct og_pos), compare_priority); stack->positions = (u32*)gf_malloc(sizeof(u32) * count); for (i=0; i<count; i++) stack->positions[i] = priorities[i].position; gf_free(priorities); tr_state->invalidate_all = 1; gf_node_dirty_clear(node, GF_SG_NODE_DIRTY); } group_2d_traverse_with_order(node, (GroupingNode2D*)stack, tr_state, stack->positions); tr_state->invalidate_all = invalidate_backup; }
// AddRecursive -- recursively adds items with an ID to the dictionnary void V4SceneManager::AddRecursive(GF_Node * node, bool parentAdded) { // skips empty nodes if (!node) return; // skips the dictionnary const char * c = gf_node_get_name(node); if ( (c != NULL) && (!strcmp(c, DICTNAME)) ) return; // if node as an id adds it to the dictionnary and the node pool u32 id = gf_node_get_id(node); if (id) { pools.Add(node); // children of added node are not added to the dictionnary if (!parentAdded) AddEffective(node); parentAdded = true; } GF_FieldInfo field; GF_ChildNodeItem * list; int count = gf_node_get_field_count(node); // tests all fields, if a field is a node then adds it and process its children recursively for (int i=0; i<count; i++) { gf_node_get_field(node, i, &field); // single value node field if (field.fieldType == GF_SG_VRML_SFNODE) AddRecursive( * ((GF_Node **) field.far_ptr), parentAdded ); // multiple value node field if (field.fieldType == GF_SG_VRML_MFNODE) { list = *( (GF_ChildNodeItem **) field.far_ptr); for (u32 j=0; j<gf_node_list_get_count(list); j++) AddRecursive( (GF_Node *) gf_node_list_get_child(list, j), parentAdded ); } } }
static void svg_sani_UpdateGradient(SVG_SANI_GradientStack *st, GF_ChildNodeItem *children) { u32 count; Fixed alpha, max_offset; if (!gf_node_dirty_get(st->txh.owner)) return; gf_node_dirty_clear(st->txh.owner, 0); st->txh.needs_refresh = 1; st->txh.transparent = 0; count = gf_node_list_get_count(children); st->nb_col = 0; st->cols = (u32*)realloc(st->cols, sizeof(u32)*count); st->keys = (Fixed*)realloc(st->keys, sizeof(Fixed)*count); max_offset = 0; while (children) { Fixed key; SVG_SANI_stopElement *gstop = (SVG_SANI_stopElement *) children->node; children = children->next; if (gf_node_get_tag((GF_Node *)gstop) != TAG_SVG_SANI_stop) continue; if (gstop->stop_opacity.type==SVG_NUMBER_VALUE) alpha = gstop->stop_opacity.value; else alpha = FIX_ONE; st->cols[st->nb_col] = GF_COL_ARGB_FIXED(alpha, gstop->stop_color.color.red, gstop->stop_color.color.green, gstop->stop_color.color.blue); key = gstop->offset.value; if (gstop->offset.value>FIX_ONE) key/=100; if (key>max_offset) max_offset=key; else key = max_offset; st->keys[st->nb_col] = key; st->nb_col++; if (alpha!=FIX_ONE) st->txh.transparent = 1; } st->txh.compositor->r2d->stencil_set_gradient_interpolation(st->txh.hwtx, st->keys, st->cols, st->nb_col); st->txh.compositor->r2d->stencil_set_gradient_mode(st->txh.hwtx, /*lg->spreadMethod*/ GF_GRADIENT_MODE_PAD); }
static void TraverseLOD(GF_Node *node, void *rs, Bool is_destroy) { GF_ChildNodeItem *children; MFFloat *ranges; SFVec3f pos, usr; u32 which_child, nb_children; Fixed dist; Bool do_all; GF_Matrix mx; SFVec3f center; GF_TraverseState *tr_state = (GF_TraverseState *)rs; s32 *prev_child = (s32 *)gf_node_get_private(node); if (is_destroy) { gf_free(prev_child); gf_sc_check_focus_upon_destroy(node); return; } /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ if (gf_node_get_tag(node) == TAG_MPEG4_LOD) { children = ((M_LOD *) node)->level; ranges = &((M_LOD *) node)->range; center = ((M_LOD *) node)->center; #ifndef GPAC_DISABLE_X3D } else { children = ((X_LOD *) node)->children; ranges = &((X_LOD *) node)->range; center = ((X_LOD *) node)->center; #endif } if (!children) return; nb_children = gf_node_list_get_count(children); if (!tr_state->camera) { do_all = 1; which_child = 0; } else { /*can't cache the matrix here*/ usr = tr_state->camera->position; pos = center; gf_mx_copy(mx, tr_state->model_matrix); gf_mx_inverse(&mx); gf_mx_apply_vec(&mx, &usr); gf_vec_diff(pos, pos, usr); dist = gf_vec_len(pos); for (which_child=0; which_child<ranges->count; which_child++) { if (dist<ranges->vals[which_child]) break; } if (which_child>=nb_children) which_child = nb_children-1; /*check if we're traversing the same child or not for audio rendering*/ do_all = 0; if (gf_node_dirty_get(node)) { gf_node_dirty_clear(node, 0); do_all = 1; } else if ((s32) which_child != *prev_child) { *prev_child = which_child; do_all = 1; } } if (do_all) { u32 i; Bool prev_switch = tr_state->switched_off; GF_ChildNodeItem *l = children; tr_state->switched_off = 1; i=0; while (l) { if (i!=which_child) gf_node_traverse(l->node, rs); l = l->next; } tr_state->switched_off = prev_switch; } gf_node_traverse(gf_node_list_get_child(children, which_child), rs); }
GF_Err gf_bifs_enc_mf_field(GF_BifsEncoder *codec, GF_BitStream *bs, GF_Node *node, GF_FieldInfo *field) { GF_ChildNodeItem *list = NULL; GF_Err e; u32 nbBits, qp_local; Bool use_list, qp_on, initial_qp; u32 nbF, i; GF_FieldInfo sffield; nbF = 0; if (field->fieldType != GF_SG_VRML_MFNODE) { nbF = field->far_ptr ? ((GenMFField *)field->far_ptr)->count : 0; if (!nbF && (field->fieldType == GF_SG_VRML_MFSCRIPT)) nbF = 1; } else if (field->far_ptr) { list = *((GF_ChildNodeItem **)field->far_ptr); nbF = gf_node_list_get_count(list); } /*reserved*/ GF_BIFS_WRITE_INT(codec, bs, 0, 1, "reserved", NULL); if (!nbF) { /*is list*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "isList", NULL); /*end flag*/ GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); return GF_OK; } /*do we work in list or vector*/ use_list = GF_FALSE; nbBits = gf_get_bit_size(nbF); if (nbBits + 5 > nbF + 1) use_list = GF_TRUE; GF_BIFS_WRITE_INT(codec, bs, use_list, 1, "isList", NULL); if (!use_list) { GF_BIFS_WRITE_INT(codec, bs, nbBits, 5, "nbBits", NULL); GF_BIFS_WRITE_INT(codec, bs, nbF, nbBits, "length", NULL); } memset(&sffield, 0, sizeof(GF_FieldInfo)); sffield.fieldIndex = field->fieldIndex; sffield.fieldType = gf_sg_vrml_get_sf_type(field->fieldType); sffield.NDTtype = field->NDTtype; initial_qp = qp_on = GF_FALSE; qp_local = 0; initial_qp = codec->ActiveQP ? GF_TRUE : GF_FALSE; for (i=0; i<nbF; i++) { if (use_list) GF_BIFS_WRITE_INT(codec, bs, 0, 1, "end", NULL); if (field->fieldType != GF_SG_VRML_MFNODE) { gf_sg_vrml_mf_get_item(field->far_ptr, field->fieldType, &sffield.far_ptr, i); e = gf_bifs_enc_sf_field(codec, bs, node, &sffield); } else { assert(list); e = gf_bifs_enc_node(codec, list->node, field->NDTtype, bs, node); /*activate QP*/ if (list->node->sgprivate->tag == TAG_MPEG4_QuantizationParameter) { qp_local = ((M_QuantizationParameter *)list->node)->isLocal; if (qp_on) gf_bifs_enc_qp_remove(codec, GF_FALSE); e = gf_bifs_enc_qp_set(codec, list->node); if (e) return e; qp_on = GF_TRUE; if (qp_local) qp_local = 2; } list = list->next; } if (e) return e; if (qp_on && qp_local) { if (qp_local == 2) qp_local -= 1; else { gf_bifs_enc_qp_remove(codec, initial_qp); qp_local = qp_on = GF_FALSE; } } } if (use_list) GF_BIFS_WRITE_INT(codec, bs, 1, 1, "end", NULL); if (qp_on) gf_bifs_enc_qp_remove(codec, initial_qp); /*for QP14*/ gf_bifs_enc_qp14_set_length(codec, nbF); return GF_OK; }
static void TraverseSwitch(GF_Node *node, void *rs, Bool is_destroy) { GF_ChildNodeItem *l; u32 i; Bool prev_switch; GF_ChildNodeItem *children; s32 whichChoice; GF_Node *child; SwitchStack *st = (SwitchStack *)gf_node_get_private(node); GF_TraverseState *tr_state; tr_state = (GF_TraverseState *)rs; children = NULL; /* souchay : be sure to be initialized, -1 seems reasonable since we check if (whichChoice>=0) */ whichChoice = -1; if (is_destroy) { gf_sc_check_focus_upon_destroy(node); gf_free(st); return; } /*WARNING: X3D/MPEG4 NOT COMPATIBLE*/ switch (gf_node_get_tag(node)) { case TAG_MPEG4_Switch: children = ((M_Switch *)node)->choice; whichChoice = ((M_Switch *)node)->whichChoice; break; #ifndef GPAC_DISABLE_X3D case TAG_X3D_Switch: children = ((X_Switch *)node)->children; whichChoice = ((X_Switch *)node)->whichChoice; break; #endif } if (tr_state->traversing_mode!=TRAVERSE_GET_BOUNDS) { prev_switch = tr_state->switched_off; /*check changes in choice field*/ if ((gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) || (st->last_switch != whichChoice) ) { tr_state->switched_off = 1; i=0; l = children; while (l) { // if ((s32) i!=whichChoice) gf_node_traverse(l->node, tr_state); if ((s32) i == st->last_switch) gf_node_traverse(l->node, tr_state); l = l->next; i++; } tr_state->switched_off = 0; st->last_switch = whichChoice; } gf_node_dirty_clear(node, 0); /*no need to check for sensors since a sensor is active for the whole parent group, that is for switch itself CSQ: switch cannot be used to switch sensors, too bad...*/ tr_state->switched_off = prev_switch; } if (!children) return; if (whichChoice==-2) { #ifndef GPAC_DISABLE_3D if (tr_state->visual->autostereo_type) { u32 idx; u32 count = gf_node_list_get_count(children); /*this should be a bit more subtle (reusing views if missing, ...)...*/ idx = tr_state->visual->current_view % count; child = (GF_Node*)gf_node_list_get_child(children, idx); gf_node_traverse(child, tr_state); return; } else #endif //GPAC_DISABLE_3D { /*fallback to first view*/ whichChoice=0; } } if (whichChoice>=0) { child = (GF_Node*)gf_node_list_get_child(children, whichChoice); gf_node_traverse(child, tr_state); } }
static void RenderOrderedGroup(GF_Node *node, void *rs, Bool is_destroy) { u32 i, count; GF_Node *child; Bool split_text_backup, invalidate_backup; M_OrderedGroup *og; u32 count2; GF_List *sensor_backup; SensorHandler *hsens; OrderedGroupStack *ogs = (OrderedGroupStack *) gf_node_get_private(node); RenderEffect2D *eff = (RenderEffect2D *)rs; if (is_destroy) { DeleteGroupingNode2D((GroupingNode2D *)ogs); if (ogs->priorities) free(ogs->priorities); free(ogs); return; } og = (M_OrderedGroup *) ogs->owner; if (!og->order.count) { group2d_traverse((GroupingNode2D*)ogs, og->children, eff); return; } count = gf_node_list_get_count(og->children); invalidate_backup = eff->invalidate_all; /*check whether the OrderedGroup node has changed*/ if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) { if (ogs->priorities) free(ogs->priorities); ogs->priorities = (struct og_pos*)malloc(sizeof(struct og_pos)*count); for (i=0; i<count; i++) { ogs->priorities[i].position = i; ogs->priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0; } qsort(ogs->priorities, count, sizeof(struct og_pos), compare_priority); eff->invalidate_all = 1; } sensor_backup = NULL; if (gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY) { /*rebuild sensor list*/ if (gf_list_count(ogs->sensors)) { gf_list_del(ogs->sensors); ogs->sensors = gf_list_new(); } for (i=0; i<count; i++) { child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); if (!child || !is_sensor_node(child) ) continue; hsens = get_sensor_handler(child); if (hsens) gf_list_add(ogs->sensors, hsens); } } /*if we have an active sensor at this level discard all sensors in current render context (cf VRML)*/ count2 = gf_list_count(ogs->sensors); if (count2) { sensor_backup = eff->sensors; eff->sensors = gf_list_new(); /*add sensor to effects*/ for (i=0; i <count2; i++) { SensorHandler *hsens = (SensorHandler *)gf_list_get(ogs->sensors, i); effect_add_sensor(eff, hsens, &eff->transform); } } gf_node_dirty_clear(node, 0); if (eff->parent == (GroupingNode2D *) ogs) { for (i=0; i<count; i++) { group2d_start_child((GroupingNode2D *) ogs); child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); gf_node_render(child, eff); group2d_end_child((GroupingNode2D *) ogs); } } else { split_text_backup = eff->text_split_mode; if (count>1) eff->text_split_mode = 0; for (i=0; i<count; i++) { child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position); gf_node_render(child, eff); } eff->text_split_mode = split_text_backup; } /*restore effect*/ invalidate_backup = eff->invalidate_all; if (count2) { /*destroy current effect list and restore previous*/ effect_reset_sensors(eff); gf_list_del(eff->sensors); eff->sensors = sensor_backup; } }
GF_Node *CloneNodeForEditing(GF_SceneGraph *inScene, GF_Node *orig) //, GF_Node *cloned_parent) { u32 i, j, count; GF_Node *node, *child, *tmp; GF_ChildNodeItem *list, *list2; GF_FieldInfo field_orig, field; /*this is not a mistake*/ if (!orig) return NULL; /*check for DEF/USE if (orig->sgprivate->NodeID) { node = gf_sg_find_node(inScene, orig->sgprivate->NodeID); //node already created, USE if (node) { gf_node_register(node, cloned_parent); return node; } } */ /*create a node*/ /* if (orig->sgprivate->tag == TAG_MPEG4_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, gf_node_get_tag(orig)); // } count = gf_node_get_field_count(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 = CloneNodeForEditing(inScene, (GF_Node *) (* ((GF_Node **) field_orig.far_ptr)));//, node); *((GF_Node **) field.far_ptr) = child; break; case GF_SG_VRML_MFNODE: list = *( (GF_ChildNodeItem **) field_orig.far_ptr); list2 = *( (GF_ChildNodeItem **) field.far_ptr); for (j=0; j<gf_node_list_get_count(list); j++) { tmp = (GF_Node *)gf_node_list_get_child(list, j); child = CloneNodeForEditing(inScene, tmp);//, node); gf_node_list_add_child(&list2, child); } break; default: gf_sg_vrml_field_copy(field.far_ptr, field_orig.far_ptr, field.fieldType); break; } } /*register node if (orig->sgprivate->NodeID) { Node_SetID(node, orig->sgprivate->NodeID); gf_node_register(node, cloned_parent); }*/ /*init node before creating ISed routes so the eventIn handler are in place*/ if (gf_node_get_tag(node) != TAG_ProtoNode) gf_node_init(node); return node; }