static Bool OnSphereSensor(GF_SensorHandler *sh, Bool is_over, Bool is_cancel, GF_Event *ev, GF_Compositor *compositor) { Bool is_mouse = (ev->type<=GF_EVENT_MOUSEWHEEL) ? 1 : 0; M_SphereSensor *sphere = (M_SphereSensor *)sh->sensor; SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->sensor); if (sphere->isActive && (!sphere->enabled || /*mouse*/((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) || /*keyboar*/(!is_mouse && (!is_over|| ((ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)))) ) ) { if (sphere->autoOffset) { sphere->offset = sphere->rotation_changed; if (!is_cancel) gf_node_event_out(sh->sensor, 2/*"offset"*/); } sphere->isActive = 0; if (!is_cancel) gf_node_event_out(sh->sensor, 3/*"isActive"*/); sh->grabbed = 0; return is_cancel ? 0 : 1; } else if (is_mouse) { if (!sphere->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) { st->center.x = st->center.y = st->center.z = 0; gf_mx_apply_vec(&compositor->hit_local_to_world, &st->center); st->radius = gf_vec_len(compositor->hit_local_point); if (!st->radius) st->radius = FIX_ONE; st->grab_vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius)); sphere->isActive = 1; gf_node_event_out(sh->sensor, 3/*"isActive"*/); sh->grabbed = 1; return 1; } else if (sphere->isActive) { SFVec3f vec, axis; SFVec4f q1, q2; SFRotation r; Fixed cl; if (is_over) { sphere->trackPoint_changed = compositor->hit_local_point; gf_node_event_out(sh->sensor, 5/*"trackPoint_changed"*/); } else { GF_Ray r; r = compositor->hit_world_ray; gf_mx_apply_ray(&compositor->hit_world_to_local, &r); if (!gf_ray_hit_sphere(&r, NULL, st->radius, &compositor->hit_local_point)) { vec.x = vec.y = vec.z = 0; /*doesn't work properly...*/ compositor->hit_local_point = gf_closest_point_to_line(r.orig, r.dir, vec); } } vec = gf_vec_scale(compositor->hit_local_point, gf_invfix(st->radius)); axis = gf_vec_cross(st->grab_vec, vec); cl = gf_vec_len(axis); if (cl < -FIX_ONE) cl = -FIX_ONE; else if (cl > FIX_ONE) cl = FIX_ONE; r.q = gf_asin(cl); if (gf_vec_dot(st->grab_vec, vec) < 0) r.q += GF_PI / 2; gf_vec_norm(&axis); r.x = axis.x; r.y = axis.y; r.z = axis.z; q1 = gf_quat_from_rotation(r); if (sphere->autoOffset) { q2 = gf_quat_from_rotation(sphere->offset); q1 = gf_quat_multiply(&q1, &q2); } sphere->rotation_changed = gf_quat_to_rotation(&q1); gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/); return 1; } } else { if (!sphere->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) { sphere->isActive = 1; sphere->rotation_changed = sphere->offset; gf_node_event_out(sh->sensor, 3/*"isActive"*/); return 1; } else if (sphere->isActive && (ev->type==GF_EVENT_KEYDOWN)) { SFVec4f res, rot; Fixed diff = GF_PI/64; res = sphere->rotation_changed; switch (ev->key.key_code) { case GF_KEY_LEFT: diff = -diff; case GF_KEY_RIGHT: rot.x = 0; rot.y = FIX_ONE; rot.z = 0; rot.q = diff; res = gf_quat_from_rotation(res); rot = gf_quat_from_rotation(rot); rot = gf_quat_multiply(&rot, &res); res = gf_quat_to_rotation(&rot); break; case GF_KEY_DOWN: diff = -diff; case GF_KEY_UP: if (ev->key.flags & GF_KEY_MOD_SHIFT) { rot.x = 0; rot.z = FIX_ONE; } else { rot.x = FIX_ONE; rot.z = 0; } rot.y = 0; rot.q = diff; res = gf_quat_from_rotation(res); rot = gf_quat_from_rotation(rot); rot = gf_quat_multiply(&rot, &res); res = gf_quat_to_rotation(&rot); break; case GF_KEY_HOME: res = sphere->offset; break; default: return 0; } sphere->rotation_changed = res; gf_node_event_out(sh->sensor, 4/*"rotation_changed"*/); return 1; } } return 0; }
void envtest_evaluate(GF_Node *node, GF_Route *_route) { Bool smaller, larger, equal; Float ar, arft; u32 par; char par_value[50]; const char *opt; M_EnvironmentTest *envtest = (M_EnvironmentTest *)node; GF_Compositor *compositor = (GF_Compositor *)gf_node_get_private(node); if (envtest->parameterValue.buffer) gf_free(envtest->parameterValue.buffer); envtest->parameterValue.buffer=NULL; smaller = larger = equal = 0; switch (envtest->parameter) { /*screen aspect ratio*/ case 0: if (compositor->display_width>compositor->display_height) { ar = (Float) compositor->display_width; ar /= compositor->display_height; } else { ar = (Float) compositor->display_height; ar /= compositor->display_width; } if (envtest->compareValue.buffer && (sscanf(envtest->compareValue.buffer, "%f", &arft)==1)) { if (ar==arft) equal=1; else if (ar>arft) smaller=1; else larger=1; } sprintf(par_value, "%f", ar); break; /*screen is portrait */ case 1: equal = (compositor->display_width < compositor->display_height) ? 1 : 2; strcpy(par_value, (equal==1) ? "TRUE" : "FALSE"); break; /*screen width */ case 2: if (envtest->compareValue.buffer && (sscanf(envtest->compareValue.buffer, "%u", &par)==1)) { if (compositor->display_width==par) equal=1; else if (compositor->display_width>par) smaller=1; else larger=1; } sprintf(par_value, "%u", compositor->display_width); break; /*screen width */ case 3: if (envtest->compareValue.buffer && (sscanf(envtest->compareValue.buffer, "%u", &par)==1)) { if (compositor->display_height==par) equal=1; else if (compositor->display_height>par) smaller=1; else larger=1; } sprintf(par_value, "%u", compositor->display_height); break; /*screen dpi horizontal */ case 4: if (envtest->compareValue.buffer && (sscanf(envtest->compareValue.buffer, "%u", &par)==1)) { if (compositor->video_out->dpi_x==par) equal=1; else if (compositor->video_out->dpi_x>par) smaller=1; else larger=1; } sprintf(par_value, "%u", compositor->video_out->dpi_x); break; /*screen dpi vertical*/ case 5: if (envtest->compareValue.buffer && (sscanf(envtest->compareValue.buffer, "%u", &par)==1)) { if (compositor->video_out->dpi_y==par) equal=1; else if (compositor->video_out->dpi_y>par) smaller=1; else larger=1; } sprintf(par_value, "%u", compositor->video_out->dpi_y); break; /*automotive situation - fixme we should use a profile doc ?*/ case 6: opt = gf_cfg_get_key(compositor->user->config, "Profile", "Automotive"); equal = (opt && !strcmp(opt, "yes")) ? 1 : 2; strcpy(par_value, (equal==1) ? "TRUE" : "FALSE"); break; /*visually challenged - fixme we should use a profile doc ?*/ case 7: opt = gf_cfg_get_key(compositor->user->config, "Profile", "VisuallyChallenged"); equal = (opt && !strcmp(opt, "yes")) ? 1 : 2; strcpy(par_value, (equal==1) ? "TRUE" : "FALSE"); break; /*has touch - fixme we should find out by ourselves*/ case 8: opt = gf_cfg_get_key(compositor->user->config, "Profile", "HasTouchScreen"); equal = (!opt || !strcmp(opt, "yes")) ? 1 : 2; strcpy(par_value, (equal==1) ? "TRUE" : "FALSE"); break; /*has key - fixme we should find out by ourselves*/ case 9: opt = gf_cfg_get_key(compositor->user->config, "Profile", "HasKeyPad"); equal = (!opt || !strcmp(opt, "yes")) ? 1 : 2; strcpy(par_value, (equal==1) ? "TRUE" : "FALSE"); break; } if (equal) { envtest->valueEqual=(equal==1) ? 1 : 0; gf_node_event_out(node, 6/*"valueEqual"*/); } else if (smaller) { envtest->valueSmaller=1; gf_node_event_out(node, 7/*"valueSmaller"*/); } else if (larger) { envtest->valueLarger=1; gf_node_event_out(node, 5/*"valueLarger"*/); } envtest->parameterValue.buffer = gf_strdup(par_value); gf_node_event_out(node, 8/*"parameterValue"*/); }
static void timesensor_update_time(GF_TimeNode *st) { Double currentTime, cycleTime; Fixed newFraction; u32 inc; M_TimeSensor *TS = (M_TimeSensor *)st->udta; TimeSensorStack *stack = (TimeSensorStack *)gf_node_get_private(st->udta); if (! TS->enabled) { if (TS->isActive) { TS->cycleTime = gf_node_get_scene_time(st->udta); gf_node_event_out(st->udta, 5);//"cycleTime" timesensor_deactivate(stack, TS); } return; } if (stack->store_info) { stack->store_info = 0; stack->start_time = TS->startTime; stack->cycle_interval = TS->cycleInterval; } currentTime = gf_node_get_scene_time(st->udta); if (!TS->isActive) { if (currentTime < stack->start_time) return; /*special case: if we're greater than both start and stop time don't activate*/ if (!TS->isActive && (TS->stopTime > stack->start_time) && (currentTime >= TS->stopTime)) { stack->time_handle.needs_unregister = 1; return; } #ifndef GPAC_DISABLE_X3D if (stack->is_x3d && !TS->loop) { if (!stack->start_time) return; if (currentTime >= TS->startTime+stack->cycle_interval) return; } #endif } cycleTime = currentTime - stack->start_time - stack->num_cycles * stack->cycle_interval; newFraction = FLT2FIX ( fmod(cycleTime, stack->cycle_interval) / stack->cycle_interval ); if (TS->isActive) { TS->time = currentTime; gf_node_event_out(st->udta, 8);//"time" /*VRML: "f = fmod( (now - startTime) , cycleInterval) / cycleInterval if (f == 0.0 && now > startTime) fraction_changed = 1.0 else fraction_changed = f" */ if (!newFraction && (currentTime > stack->start_time ) ) newFraction = FIX_ONE; /*check for deactivation - if so generate a fraction_changed AS IF NOW WAS EXACTLY STOPTIME*/ if ((TS->stopTime > stack->start_time) && (currentTime >= TS->stopTime) ) { cycleTime = TS->stopTime - stack->start_time - stack->num_cycles * stack->cycle_interval; TS->fraction_changed = FLT2FIX( fmod(cycleTime, stack->cycle_interval) / stack->cycle_interval ); /*cf above*/ if (TS->fraction_changed < FIX_EPSILON) TS->fraction_changed = FIX_ONE; gf_node_event_out(st->udta, 6);//"fraction_changed" timesensor_deactivate(stack, TS); return; } if (! TS->loop) { if (cycleTime >= stack->cycle_interval) { TS->fraction_changed = FIX_ONE; gf_node_event_out(st->udta, 6);//"fraction_changed" timesensor_deactivate(stack, TS); return; } } if (newFraction != TS->fraction_changed) { TS->fraction_changed = newFraction; gf_node_event_out(st->udta, 6);//"fraction_changed" } } /*we're (about to be) active: VRML: "A time-dependent node is inactive until its startTime is reached. When time now becomes greater than or equal to startTime, an isActive TRUE event is generated and the time-dependent node becomes active */ if (!TS->isActive) { st->needs_unregister = 0; TS->isActive = 1; gf_node_event_out(st->udta, 7); //"isActive" TS->cycleTime = currentTime; gf_node_event_out(st->udta, 5);//"cycleTime" TS->fraction_changed = newFraction; gf_node_event_out(st->udta, 6);//"fraction_changed" } //compute cycle time if (TS->loop && (cycleTime >= stack->cycle_interval) ) { inc = 1 + (u32) ( (cycleTime - stack->cycle_interval ) / stack->cycle_interval ); stack->num_cycles += inc; cycleTime -= inc*stack->cycle_interval; TS->cycleTime = currentTime - cycleTime; gf_node_event_out(st->udta, 5);//"cycleTime" } }
GF_EXPORT GF_Err gf_sg_command_apply(GF_SceneGraph *graph, GF_Command *com, Double time_offset) { GF_Err e; GF_CommandField *inf; #ifndef GPAC_DISABLE_VRML GF_FieldInfo field; void *slot_ptr; GF_Node *def; #endif GF_Node *node; 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: /*unregister root*/ gf_node_unregister(graph->RootNode, NULL); /*remove all protos and routes*/ while (gf_list_count(graph->routes_to_activate)) gf_list_rem(graph->routes_to_activate, 0); if (!com->aggregated) { /*destroy all routes*/ while (gf_list_count(graph->Routes)) { GF_Route *r = (GF_Route *)gf_list_get(graph->Routes, 0); /*this will unregister the route from the graph, so don't delete the chain entry*/ gf_sg_route_del(r); } /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } } /*DO NOT TOUCH node registry*/ /*DO NOT TOUCH UNREGISTERED PROTOS*/ /*if no protos (previously aggregated command) create proto list*/ if (!graph->protos) graph->protos = gf_list_new(); /*move all protos in graph*/ 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); } /*assign new root (no need to register/unregister)*/ 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); if (inf->new_node) gf_node_register(inf->new_node, NULL); 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; /*reset dest*/ 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; } /*clone command list*/ 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: /*this is a regular field, reset it and clone - we cannot switch pointers since the original fields are NOT pointers*/ 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 MFNode remove the child and set new node*/ if (field.fieldType == GF_SG_VRML_MFNODE) { /*we must remove the node before in case the new node uses the same ID (not forbidden) and this command removes the last instance of the node with the same ID*/ 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); } /*erase the field item*/ else { if ((inf->pos < 0) || ((u32) inf->pos >= ((GenMFField *) field.far_ptr)->count) ) { inf->pos = ((GenMFField *)field.far_ptr)->count - 1; /*may happen with text and default value*/ 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); /*note we don't add time offset, since there's no MFTime*/ } 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; /*then we need special handling in case of a node*/ 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; } /*this is a regular MFField, just remove the item (gf_realloc)*/ e = gf_sg_vrml_mf_remove(field.far_ptr, field.fieldType, inf->pos); } /*deletion -> node has changed*/ 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; /*rescale the MFField and parse the SFField*/ 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: /*destroy all proto*/ 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++) { /*note this will check for unregistered protos, but since IDs are unique we are sure we will not destroy an unregistered one*/ 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: /*destroy all proto*/ while (gf_list_count(graph->protos)) { GF_Proto *p = (GF_Proto*)gf_list_get(graph->protos, 0); gf_list_rem(graph->protos, 0); /*this will unregister the proto from the graph, so don't delete the chain entry*/ gf_sg_proto_del(p); } /*DO NOT TOUCH UNREGISTERED PROTOS*/ 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; } } } /*override target node*/ 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; } /*indexed replacement*/ if (pos>=-1) { /*if MFNode remove the child and set new node*/ 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); } /*erase the field item*/ else { u32 sftype; if ((pos < 0) || ((u32) pos >= ((GenMFField *) field.far_ptr)->count) ) { pos = ((GenMFField *)field.far_ptr)->count - 1; /*may happen with text and default value*/ 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); /*note we don't add time offset, since there's no MFTime*/ } } 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; /*only used by BIFS*/ case GF_SG_GLOBAL_QUANTIZER: return GF_OK; #endif /*GPAC_DISABLE_VRML*/ #ifndef GPAC_DISABLE_SVG /*laser commands*/ case GF_SG_LSR_NEW_SCENE: /*DO NOT TOUCH node registry*/ /*assign new root (no need to register/unregister)*/ 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 { /*NOT SUPPORTED*/ 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 fieldIndex (eg attributeName) is set, this is children replacement*/ 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); } /*signal node modif*/ 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; } /*signal node modif*/ gf_node_changed(com->node, NULL); return GF_OK; } /*attribute modif*/ 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); } /*signal node modif*/ 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)); } /*signal node modif*/ 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); } /*signal node modif*/ 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); } /*signal node modif*/ 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 = *(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)); } } 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; }
static void TimeTrigger_setTrigger(GF_Node *n, GF_Route *route) { X_TimeTrigger *tt = (X_TimeTrigger *)n; tt->triggerTime = gf_node_get_scene_time(n); gf_node_event_out(n, 1/*"triggerTime"*/); }
static void BooleanTrigger_setTime(GF_Node *n, GF_Route *route) { X_BooleanTrigger *bt = (X_BooleanTrigger *)n; bt->triggerTrue = 1; gf_node_event_out(n, 1/*"triggerTrue"*/); }
void mediasensor_update_timing(GF_ObjectManager *odm, Bool is_eos) { GF_Segment *desc; u32 i, count, j, ms_count; Double time; ms_count = gf_list_count(odm->ms_stack); if (!ms_count) return; time = odm->media_current_time / 1000.0; //dirty hack to get timing of frame when very late (openhevc debug) if (odm->subscene && odm->subscene->dyn_ck && odm->subscene->dyn_ck->last_TS_rendered) time = odm->subscene->dyn_ck->last_TS_rendered / 1000.0; for (j=0; j<ms_count; j++) { MediaSensorStack *media_sens = (MediaSensorStack *)gf_list_get(odm->ms_stack, j); if (!media_sens->is_init) continue; count = gf_list_count(media_sens->seg); /*full object controled*/ if (!media_sens->active_seg && !count) { /*check for end of scene (MediaSensor on inline)*/ if (odm->subscene && odm->subscene->duration) { GF_Clock *ck = gf_odm_get_media_clock(odm); if (ck->has_seen_eos && (1000*time>=(Double) (s64)odm->subscene->duration)) { if (media_sens->sensor->isActive) { /*force notification of time (ntify the scene duration rather than the current clock*/ media_sens->sensor->mediaCurrentTime = (Double) odm->subscene->duration; media_sens->sensor->mediaCurrentTime /= 1000; gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/); media_sens->sensor->isActive = 0; gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor\n", odm->OD->objectDescriptorID)); } continue; } } if (!is_eos && !media_sens->sensor->isActive) { media_sens->sensor->isActive = 1; gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); if (odm->subscene) { media_sens->sensor->mediaDuration = (Double) (s64)odm->subscene->duration; } else { media_sens->sensor->mediaDuration = (Double) (s64)odm->duration; } if (media_sens->sensor->mediaDuration) media_sens->sensor->mediaDuration /= 1000; else media_sens->sensor->mediaDuration = -FIX_ONE; gf_node_event_out((GF_Node *) media_sens->sensor, 3/*"mediaDuration"*/); } if (is_eos && media_sens->sensor->isActive) { if (media_sens->sensor->mediaDuration>=0) { media_sens->sensor->mediaCurrentTime = media_sens->sensor->mediaDuration; } else { media_sens->sensor->mediaCurrentTime = time; } gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/); media_sens->sensor->isActive = 0; gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); } else { if (media_sens->sensor->isActive && (media_sens->sensor->mediaCurrentTime != time)) { media_sens->sensor->mediaCurrentTime = time; gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/); } } continue; } /*locate segment*/ for (i=media_sens->active_seg; i<count; i++) { desc = (GF_Segment*)gf_list_get(media_sens->seg, i); /*not controled*/ if (desc->startTime > time) { if (media_sens->sensor->isActive) { media_sens->sensor->isActive = 0; gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName)); } continue; } if (desc->startTime + desc->Duration < time) continue; if (desc->startTime + desc->Duration == time) { continue; } /*segment switch, force activation (isActive TRUE send at each seg)*/ if (media_sens->active_seg != i) { media_sens->active_seg = i; media_sens->sensor->isActive = 0; } if (!media_sens->sensor->isActive) { media_sensor_activate_segment(media_sens, desc); GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Activating media sensor time %g - segment %s\n", odm->OD->objectDescriptorID, time, desc->SegmentName)); } /*set media time - relative to segment start time*/ time -= desc->startTime; if (media_sens->sensor->mediaCurrentTime != time) { media_sens->sensor->mediaCurrentTime = time; gf_node_event_out((GF_Node *) media_sens->sensor, 1/*"mediaCurrentTime"*/); } break; } if (i==count) { /*we're after last segment, deactivate*/ if (media_sens->sensor->isActive) { media_sens->sensor->isActive = 0; gf_node_event_out((GF_Node *) media_sens->sensor, 4/*"isActive"*/); media_sens->active_seg = count; GF_LOG(GF_LOG_DEBUG, GF_LOG_INTERACT, ("[ODM%d] Deactivating media sensor at time %g: no more segments\n", odm->OD->objectDescriptorID, time)); } } } }