Exemple #1
0
static void OnPlaneSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_PlaneSensor *ps = (M_PlaneSensor *)sh->owner;
	PSStack *stack = (PSStack *) gf_node_get_private(sh->owner);
	
	
	if (ps->isActive && (!ps->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) )) {
		if (ps->autoOffset) {
			ps->offset = ps->translation_changed;
			gf_node_event_out_str(sh->owner, "offset");
		}
		ps->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 0);
	}
	else if (!ps->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		gf_mx_copy(stack->initial_matrix, hit_info->local_to_world);
		gf_vec_diff(stack->start_drag, hit_info->local_point, ps->offset);
		stack->tracker.normal.x = stack->tracker.normal.y = 0; stack->tracker.normal.z = FIX_ONE;
		stack->tracker.d = - gf_vec_dot(stack->start_drag, stack->tracker.normal);
		ps->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(stack->compositor, 1);
	}
	else if (ps->isActive) {
		GF_Ray loc_ray;
		SFVec3f res;
		loc_ray = hit_info->world_ray;
		gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
		gf_plane_intersect_line(&stack->tracker, &loc_ray.orig, &loc_ray.dir, &res);
		ps->trackPoint_changed = res;
		gf_node_event_out_str(sh->owner, "trackPoint_changed");

		gf_vec_diff(res, res, stack->start_drag);
		/*clip*/
		if (ps->minPosition.x <= ps->maxPosition.x) {
			if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
			if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
		}
		if (ps->minPosition.y <= ps->maxPosition.y) {
			if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
			if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
		}
		ps->translation_changed = res;
		gf_node_event_out_str(sh->owner, "translation_changed");
	}
}
Exemple #2
0
static Bool OnCylinderSensor(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_CylinderSensor *cs = (M_CylinderSensor *)sh->sensor;
	CylinderSensorStack *st = (CylinderSensorStack *) gf_node_get_private(sh->sensor);

	if (cs->isActive && (!cs->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 (cs->autoOffset) {
			cs->offset = cs->rotation_changed.q;
			if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"offset"*/);
		}
		cs->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 6/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	}
	else if (is_mouse) {
		if (!cs->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
			GF_Ray r;
			SFVec3f yaxis;
			Fixed acute, reva;
			SFVec3f bearing;

			gf_mx_copy(st->init_matrix, compositor->hit_world_to_local);
			/*get initial angle & check disk mode*/
			r = compositor->hit_world_ray;
			gf_vec_add(r.dir, r.orig, r.dir);
			gf_mx_apply_vec(&compositor->hit_world_to_local, &r.orig);
			gf_mx_apply_vec(&compositor->hit_world_to_local, &r.dir);
			gf_vec_diff(bearing, r.orig, r.dir);
			gf_vec_norm(&bearing);
			yaxis.x = yaxis.z = 0;
			yaxis.y = FIX_ONE;
			acute = gf_vec_dot(bearing, yaxis);
			if (acute < -FIX_ONE) acute = -FIX_ONE;
			else if (acute > FIX_ONE) acute = FIX_ONE;
			acute = gf_acos(acute);
			reva = ABS(GF_PI - acute);
			if (reva<acute) acute = reva;
			st->disk_mode = (acute < cs->diskAngle) ? 1 : 0;

			st->grab_start = compositor->hit_local_point;
			/*cos we're lazy*/
			st->yplane.d = 0;
			st->yplane.normal.x = st->yplane.normal.z = st->yplane.normal.y = 0;
			st->zplane = st->xplane = st->yplane;
			st->xplane.normal.x = FIX_ONE;
			st->yplane.normal.y = FIX_ONE;
			st->zplane.normal.z = FIX_ONE;

			cs->rotation_changed.x = 0;
			cs->rotation_changed.y = FIX_ONE;
			cs->rotation_changed.z = 0;

			cs->isActive = 1;
			gf_node_event_out(sh->sensor, 6/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (cs->isActive) {
			GF_Ray r;
			Fixed radius, rot;
			SFVec3f dir1, dir2, cx;

			if (is_over) {
				cs->trackPoint_changed = compositor->hit_local_point;
				gf_node_event_out(sh->sensor, 8/*"trackPoint_changed"*/);
			} else {
				GF_Plane project_to;
				r = compositor->hit_world_ray;
				gf_mx_apply_ray(&st->init_matrix, &r);

				/*no intersection, use intersection with "main" fronting plane*/
				if ( ABS(r.dir.z) > ABS(r.dir.y)) {
					if (ABS(r.dir.z) > ABS(r.dir.x)) project_to = st->xplane;
					else project_to = st->yplane;
				} else {
					if (ABS(r.dir.z) > ABS(r.dir.x)) project_to = st->xplane;
					else project_to = st->zplane;
				}
				if (!gf_plane_intersect_line(&project_to, &r.orig, &r.dir, &compositor->hit_local_point)) return 0;
			}

			dir1.x = compositor->hit_local_point.x;
			dir1.y = 0;
			dir1.z = compositor->hit_local_point.z;
			if (st->disk_mode) {
				radius = FIX_ONE;
			} else {
				radius = gf_vec_len(dir1);
			}
			gf_vec_norm(&dir1);
			dir2.x = st->grab_start.x;
			dir2.y = 0;
			dir2.z = st->grab_start.z;
			gf_vec_norm(&dir2);
			cx = gf_vec_cross(dir2, dir1);
			gf_vec_norm(&cx);
			if (gf_vec_len(cx)<FIX_EPSILON) return 0;
			rot = gf_mulfix(radius, gf_acos(gf_vec_dot(dir2, dir1)) );
			if (fabs(cx.y + FIX_ONE) < FIX_EPSILON) rot = -rot;
			if (cs->autoOffset) rot += cs->offset;

			if (cs->minAngle < cs->maxAngle) {
				if (rot < cs->minAngle) rot = cs->minAngle;
				else if (rot > cs->maxAngle) rot = cs->maxAngle;
			}
			cs->rotation_changed.q = rot;
			gf_node_event_out(sh->sensor, 7/*"rotation_changed"*/);
			return 1;
		}
	} else {
		if (!cs->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			cs->isActive = 1;
			cs->rotation_changed.q = cs->offset;
			cs->rotation_changed.x = cs->rotation_changed.z = 0;
			cs->rotation_changed.y = FIX_ONE;
			gf_node_event_out(sh->sensor, 6/*"isActive"*/);
			return 1;
		}
		else if (cs->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFFloat res;
			Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? GF_PI/8 : GF_PI/64;

			res = cs->rotation_changed.q;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
				res -= diff;
				break;
			case GF_KEY_RIGHT:
				res += diff;
				break;
			case GF_KEY_HOME:
				res = cs->offset;
				break;
			default:
				return 0;
			}
			/*clip*/
			if (cs->minAngle <= cs->maxAngle) {
				if (res < cs->minAngle) res = cs->minAngle;
				if (res > cs->maxAngle) res = cs->maxAngle;
			}
			cs->rotation_changed.q = res;
			gf_node_event_out(sh->sensor, 7/*"rotation_changed"*/);
			return 1;
		}
	}
	return 0;
}
Exemple #3
0
static Bool OnPlaneSensor(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_PlaneSensor *ps = (M_PlaneSensor *)sh->sensor;
	PSStack *stack = (PSStack *) gf_node_get_private(sh->sensor);


	if (ps->isActive &&
	        ( /*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 (ps->autoOffset) {
			ps->offset = ps->translation_changed;
			if (!is_cancel) gf_node_event_out(sh->sensor, 4/*"offset"*/);
		}
		ps->isActive = 0;
		if (!is_cancel) gf_node_event_out(sh->sensor, 5/*"isActive"*/);
		sh->grabbed = 0;
		return is_cancel ? 0 : 1;
	}
	/*mouse*/
	else if (is_mouse) {
		if (!ps->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT) ) {
			gf_mx_copy(stack->initial_matrix, compositor->hit_local_to_world);
			gf_vec_diff(stack->start_drag, compositor->hit_local_point, ps->offset);
			stack->tracker.normal.x = stack->tracker.normal.y = 0;
			stack->tracker.normal.z = FIX_ONE;
			stack->tracker.d = - gf_vec_dot(stack->start_drag, stack->tracker.normal);
			ps->isActive = 1;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			sh->grabbed = 1;
			return 1;
		}
		else if (ps->isActive) {
			GF_Ray loc_ray;
			SFVec3f res;
			loc_ray = compositor->hit_world_ray;
			gf_mx_apply_ray(&stack->initial_matrix, &loc_ray);
			gf_plane_intersect_line(&stack->tracker, &loc_ray.orig, &loc_ray.dir, &res);
			ps->trackPoint_changed = res;
			gf_node_event_out(sh->sensor, 6/*"trackPoint_changed"*/);

			gf_vec_diff(res, res, stack->start_drag);
			/*clip*/
			if (ps->minPosition.x <= ps->maxPosition.x) {
				if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
				if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
			}
			if (ps->minPosition.y <= ps->maxPosition.y) {
				if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
				if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
			}
			ps->translation_changed = res;
			gf_node_event_out(sh->sensor, 7/*"translation_changed"*/);
			return 1;
		}
	} else {
		if (!ps->isActive && is_over && (ev->type==GF_EVENT_KEYDOWN) && (ev->key.key_code==GF_KEY_ENTER)) {
			ps->isActive = 1;
			stack->start_drag = ps->offset;
			gf_node_event_out(sh->sensor, 5/*"isActive"*/);
			return 1;
		}
		else if (ps->isActive && (ev->type==GF_EVENT_KEYDOWN)) {
			SFVec3f res;
			Fixed diff = (ev->key.flags & GF_KEY_MOD_SHIFT) ? 5*FIX_ONE : FIX_ONE;
			if (!gf_sg_use_pixel_metrics(gf_node_get_graph(sh->sensor)))
				diff = gf_divfix(diff, INT2FIX(compositor->vp_width/2));

			res = stack->start_drag;
			switch (ev->key.key_code) {
			case GF_KEY_LEFT:
				res.x -= diff;
				break;
			case GF_KEY_RIGHT:
				res.x += diff;
				break;
			case GF_KEY_UP:
				res.y += diff;
				break;
			case GF_KEY_DOWN:
				res.y -= diff;
				break;
			case GF_KEY_HOME:
				res = ps->offset;
				break;
			default:
				return 0;
			}
			/*clip*/
			if (ps->minPosition.x <= ps->maxPosition.x) {
				if (res.x < ps->minPosition.x) res.x = ps->minPosition.x;
				if (res.x > ps->maxPosition.x) res.x = ps->maxPosition.x;
			}
			if (ps->minPosition.y <= ps->maxPosition.y) {
				if (res.y < ps->minPosition.y) res.y = ps->minPosition.y;
				if (res.y > ps->maxPosition.y) res.y = ps->maxPosition.y;
			}
			stack->start_drag = res;
			ps->translation_changed = res;
			gf_node_event_out(sh->sensor, 7/*"translation_changed"*/);
			return 1;
		}
	}
	return 0;
}
Exemple #4
0
static void OnCylinderSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info)
{
	M_CylinderSensor *cs = (M_CylinderSensor *)sh->owner;
	CylinderSensorStack *st = (CylinderSensorStack *) gf_node_get_private(sh->owner);

	if (cs->isActive && (!cs->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT))) ) {
		if (cs->autoOffset) {
			cs->offset = cs->rotation_changed.q;
			gf_node_event_out_str(sh->owner, "offset");
		}
		cs->isActive = 0;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 0);
	}
	else if (!cs->isActive && (ev->type==GF_EVENT_MOUSEDOWN) && (ev->mouse.button==GF_MOUSE_LEFT)) {
		GF_Ray r;
		SFVec3f yaxis;
		Fixed acute, reva;
		SFVec3f bearing;

		gf_mx_copy(st->init_matrix, hit_info->world_to_local);
		/*get initial angle & check disk mode*/
		r = hit_info->world_ray;
		gf_vec_add(r.dir, r.orig, r.dir);
		gf_mx_apply_vec(&hit_info->world_to_local, &r.orig);
		gf_mx_apply_vec(&hit_info->world_to_local, &r.dir);
		gf_vec_diff(bearing, r.orig, r.dir);
		gf_vec_norm(&bearing);
		yaxis.x = yaxis.z = 0;
		yaxis.y = FIX_ONE;
		acute = gf_vec_dot(bearing, yaxis);
		if (acute < -FIX_ONE) acute = -FIX_ONE; 
		else if (acute > FIX_ONE) acute = FIX_ONE;
		acute = gf_acos(acute);
		reva = ABS(GF_PI - acute);
		if (reva<acute) acute = reva;
		st->disk_mode = (acute < cs->diskAngle) ? 1 : 0;

		st->grab_start = hit_info->local_point;
		/*cos we're lazy*/
		st->yplane.d = 0; st->yplane.normal.x = st->yplane.normal.z = st->yplane.normal.y = 0;
		st->zplane = st->xplane = st->yplane;
		st->xplane.normal.x = FIX_ONE;
		st->yplane.normal.y = FIX_ONE;
		st->zplane.normal.z = FIX_ONE;

		cs->rotation_changed.x = 0;
		cs->rotation_changed.y = FIX_ONE;
		cs->rotation_changed.z = 0;

		cs->isActive = 1;
		gf_node_event_out_str(sh->owner, "isActive");
		R3D_SetGrabbed(st->compositor, 1);
	}
	else if (cs->isActive) {
		GF_Ray r;
		Fixed radius, rot;
		SFVec3f dir1, dir2, cx;

		if (is_over) {
			cs->trackPoint_changed = hit_info->local_point;
			gf_node_event_out_str(sh->owner, "trackPoint_changed");
		} else {
			GF_Plane project_to;
			r = hit_info->world_ray;
			gf_mx_apply_ray(&st->init_matrix, &r);

			/*no intersection, use intersection with "main" fronting plane*/
			if ( ABS(r.dir.z) > ABS(r.dir.y)) {
				if (ABS(r.dir.x) > ABS(r.dir.x)) project_to = st->xplane;
				else project_to = st->zplane;
			} else project_to = st->yplane;
			if (!gf_plane_intersect_line(&project_to, &r.orig, &r.dir, &hit_info->local_point)) return;
		}

  		dir1.x = hit_info->local_point.x; dir1.y = 0; dir1.z = hit_info->local_point.z;
		if (st->disk_mode) {
			radius = FIX_ONE;
		} else {
			radius = gf_vec_len(dir1);
		}
		gf_vec_norm(&dir1);
       	dir2.x = st->grab_start.x; dir2.y = 0; dir2.z = st->grab_start.z;
		gf_vec_norm(&dir2);
		cx = gf_vec_cross(dir2, dir1);
		gf_vec_norm(&cx);
		if (gf_vec_len(cx)<FIX_EPSILON) return;
		rot = gf_mulfix(radius, gf_acos(gf_vec_dot(dir2, dir1)) );
		if (fabs(cx.y + FIX_ONE) < FIX_EPSILON) rot = -rot;
		if (cs->autoOffset) rot += cs->offset;

		if (cs->minAngle < cs->maxAngle) {
			if (rot < cs->minAngle) rot = cs->minAngle;
			else if (rot > cs->maxAngle) rot = cs->maxAngle;
		}
		cs->rotation_changed.q = rot;
		gf_node_event_out_str(sh->owner, "rotation_changed");
	}
}