Bool compositor_compositetexture_handle_event(GF_Compositor *compositor, GF_Node *composite_appear, GF_Event *ev, Bool is_flush)
{
	GF_Ray ray;
	Fixed dist;
	Bool had_text_sel=0;
	GF_Matrix mx;
	GF_TraverseState *tr_state;
	GF_ChildNodeItem *children, *l;
	Bool res;
	SFVec3f txcoord, loc_pt, world_pt;
	GF_Matrix l2w_mx, w2l_mx;
	CompositeTextureStack *stack;
	GF_Node *appear, *prev_appear;
	M_Appearance *ap = (M_Appearance *)composite_appear;
	assert(ap && ap->texture);

	if (ev->type > GF_EVENT_MOUSEMOVE) return 0;
	stack = gf_node_get_private(ap->texture);
	if (!stack->txh.tx_io) return 0;

    tr_state = NULL;
    children = NULL;


	if (!is_flush) {
		txcoord.x = compositor->hit_texcoords.x;
		txcoord.y = compositor->hit_texcoords.y;
		txcoord.z = 0;
		if (gf_sc_texture_get_transform(&stack->txh, ap->textureTransform, &mx, 1)) {
			/*tx coords are inverted when mapping, thus applying directly the matrix will give us the
			untransformed coords*/
			gf_mx_apply_vec(&mx, &txcoord);
			while (txcoord.x<0) txcoord.x += FIX_ONE; while (txcoord.x>FIX_ONE) txcoord.x -= FIX_ONE;
			while (txcoord.y<0) txcoord.y += FIX_ONE; while (txcoord.y>FIX_ONE) txcoord.y -= FIX_ONE;
		}

		/*convert to tx space*/
		ev->mouse.x = FIX2INT( (txcoord.x - FIX_ONE/2) * stack->visual->width + FIX_ONE/2);
		ev->mouse.y = FIX2INT( (txcoord.y - FIX_ONE/2) * stack->visual->height + FIX_ONE/2);


		GF_SAFEALLOC(tr_state, GF_TraverseState);
		tr_state->vrml_sensors = gf_list_new();
		tr_state->visual = stack->visual;
		tr_state->traversing_mode = TRAVERSE_PICK;
		tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(ap->texture));
		tr_state->vp_size.x = INT2FIX(stack->txh.width);
		tr_state->vp_size.y = INT2FIX(stack->txh.height);
		tr_state->color_mat.identity = 1;

		gf_mx2d_init(tr_state->transform);
#ifndef GPAC_DISABLE_3D
		gf_mx_init(tr_state->model_matrix);
#endif
		/*collect sensors*/
		l = children = ((M_CompositeTexture2D*)ap->texture)->children;
		while (l) {
			GF_SensorHandler *hsens = compositor_mpeg4_get_sensor_handler(l->node);
			if (hsens) gf_list_add(tr_state->vrml_sensors, hsens);
			l = l->next;
		}
	}

	stack->temp_sensors = compositor->sensors;
	stack->temp_previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->sensors;
	compositor->previous_sensors = stack->previous_sensors;

	ray = compositor->hit_world_ray;
	dist = compositor->hit_square_dist;
	prev_appear = compositor->prev_hit_appear;

	/*protect against destrucion in case of self-destroy*/
	if (prev_appear) {
		gf_node_register(prev_appear, NULL);
	}
	compositor->prev_hit_appear = stack->prev_hit_appear;
	appear = compositor->hit_appear;
	compositor->hit_appear = NULL;

	/*also backup current hit state in case we hit a node in the texture but don't consume the event*/
	loc_pt = compositor->hit_local_point;
	world_pt = compositor->hit_world_point;
	gf_mx_copy(l2w_mx, compositor->hit_local_to_world);
	gf_mx_copy(w2l_mx, compositor->hit_world_to_local);
	
	if (compositor->text_selection) had_text_sel=1;

	if (is_flush) {
		res = 0;
		gf_list_reset(stack->sensors);
		gf_sc_exec_event_vrml(compositor, ev);
	} else {
		res = visual_execute_event(stack->visual, tr_state, ev, children);
	}

	if (!had_text_sel && compositor->edited_text) {
		stack->visual->has_text_edit = 1;
	} else if (!compositor->text_selection) {
		stack->visual->has_text_edit = 0;
	}

	if (!res) {
		compositor->hit_local_point = loc_pt;
		gf_mx_copy(compositor->hit_local_to_world, l2w_mx);
		gf_mx_copy(compositor->hit_world_to_local, w2l_mx);
	}

	stack->prev_hit_appear = compositor->prev_hit_appear;

	if (prev_appear) {
		if (prev_appear->sgprivate->num_instances>1) {
			compositor->prev_hit_appear = prev_appear;
			compositor->hit_appear = appear;
		} else {
			compositor->prev_hit_appear = NULL;
			compositor->hit_appear = NULL;
		}
		gf_node_unregister(prev_appear, NULL);
	} else {
		compositor->prev_hit_appear = prev_appear;
		compositor->hit_appear = appear;
	}

	compositor->hit_world_point = world_pt;
	compositor->hit_world_ray = ray;
	compositor->hit_square_dist = dist;

	stack->sensors = compositor->sensors;
	stack->previous_sensors = compositor->previous_sensors;
	compositor->sensors = stack->temp_sensors;
	stack->temp_sensors = NULL;
	compositor->previous_sensors = stack->temp_previous_sensors;
	stack->temp_previous_sensors = NULL;


	if (!is_flush) {
		gf_list_del(tr_state->vrml_sensors);
#ifndef GPAC_DISABLE_3D
		if (tr_state->layer3d) compositor->traverse_state->layer3d = tr_state->layer3d;
#endif
		gf_free(tr_state);
	}
	return res;
}
Example #2
0
Bool compositor_mpeg4_is_sensor_node(GF_Node *node)
{
	GF_SensorHandler *sh = compositor_mpeg4_get_sensor_handler(node);
	if (sh && sh->IsEnabled(node)) return 1;
	return 0;
}