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; }
static Bool compositor_handle_navigation_2d(GF_VisualManager *visual, GF_Event *ev) { Fixed x, y, dx, dy, key_trans, key_rot, zoom, new_zoom; u32 navigation_mode; s32 key_inv; Bool is_pixel_metrics = visual->compositor->traverse_state->pixel_metrics; u32 keys = visual->compositor->key_states; zoom = visual->compositor->zoom; navigation_mode = visual->compositor->navigate_mode; #ifndef GPAC_DISABLE_3D if (visual->type_3d) navigation_mode = visual->camera.navigate_mode; #endif if (navigation_mode==GF_NAVIGATE_NONE) return 0; if (!navigation_mode && !(keys & GF_KEY_MOD_ALT) ) return 0; x = y = 0; /*renorm between -1, 1*/ if (ev->type<=GF_EVENT_MOUSEWHEEL) { x = INT2FIX(ev->mouse.x); y = INT2FIX(ev->mouse.y); } dx = x - visual->compositor->grab_x; if (visual->center_coords) { dy = visual->compositor->grab_y - y; } else { dy = y - visual->compositor->grab_y; } if (!is_pixel_metrics) { dx /= visual->width; dy /= visual->height; } key_inv = 1; key_trans = INT2FIX(2); key_rot = GF_PI/100; if (keys & GF_KEY_MOD_SHIFT) { dx *= 4; dy *= 4; key_rot *= 4; key_trans*=4; } if (!is_pixel_metrics) { key_trans /= visual->width; } switch (ev->type) { case GF_EVENT_MOUSEDOWN: /*left*/ if (ev->mouse.button==GF_MOUSE_LEFT) { visual->compositor->grab_x = x; visual->compositor->grab_y = y; visual->compositor->navigation_state = 1; /*update zoom center*/ if (keys & GF_KEY_MOD_CTRL) { visual->compositor->trans_x -= visual->compositor->grab_x - INT2FIX(visual->width)/2; visual->compositor->trans_y += INT2FIX(visual->height)/2 - visual->compositor->grab_y; nav_set_zoom_trans_2d(visual, visual->compositor->zoom, 0, 0); } return 0; } break; case GF_EVENT_MOUSEUP: if (ev->mouse.button==GF_MOUSE_LEFT) { visual->compositor->navigation_state = 0; return 0; } break; case GF_EVENT_MOUSEWHEEL: switch (navigation_mode) { case GF_NAVIGATE_SLIDE: new_zoom = zoom + INT2FIX(ev->mouse.wheel_pos)/10; nav_set_zoom_trans_2d(visual, new_zoom, 0, 0); return 1; case GF_NAVIGATE_EXAMINE: if (ev->mouse.wheel_pos>0) visual->compositor->rotation += gf_asin( GF_PI / 10); else visual->compositor->rotation -= gf_asin( GF_PI / 10); nav_set_zoom_trans_2d(visual, zoom, 0, 0); return 1; } return 0; case GF_EVENT_MOUSEMOVE: if (!visual->compositor->navigation_state) return 0; visual->compositor->navigation_state++; switch (navigation_mode) { case GF_NAVIGATE_SLIDE: if (keys & GF_KEY_MOD_CTRL) { if (dy) { new_zoom = zoom; if (new_zoom > FIX_ONE) new_zoom += dy/20; else new_zoom += dy/80; nav_set_zoom_trans_2d(visual, new_zoom, 0, 0); } } else { nav_set_zoom_trans_2d(visual, zoom, dx, dy); } break; case GF_NAVIGATE_EXAMINE: { Fixed sin = gf_mulfix(GF_PI, dy) / visual->height; //truncate in [-1;1] for arcsin() if (sin < -FIX_ONE) sin = -FIX_ONE; if (sin > FIX_ONE) sin = FIX_ONE; visual->compositor->rotation += gf_asin(sin); nav_set_zoom_trans_2d(visual, zoom, 0, 0); } break; } visual->compositor->grab_x = x; visual->compositor->grab_y = y; return 1; case GF_EVENT_KEYDOWN: switch (ev->key.key_code) { case GF_KEY_BACKSPACE: gf_sc_reset_graphics(visual->compositor); return 1; case GF_KEY_HOME: if (!visual->compositor->navigation_state) { visual->compositor->trans_x = visual->compositor->trans_y = 0; visual->compositor->rotation = 0; visual->compositor->zoom = FIX_ONE; nav_set_zoom_trans_2d(visual, FIX_ONE, 0, 0); } return 1; case GF_KEY_LEFT: key_inv = -1; case GF_KEY_RIGHT: if (navigation_mode == GF_NAVIGATE_SLIDE) { nav_set_zoom_trans_2d(visual, zoom, key_inv*key_trans, 0); } else { visual->compositor->rotation -= key_inv * key_rot; nav_set_zoom_trans_2d(visual, zoom, 0, 0); } return 1; case GF_KEY_DOWN: key_inv = -1; case GF_KEY_UP: if (navigation_mode == GF_NAVIGATE_SLIDE) { if (keys & GF_KEY_MOD_CTRL) { Fixed new_zoom = zoom; if (new_zoom > FIX_ONE) new_zoom += key_inv*FIX_ONE/10; else new_zoom += key_inv*FIX_ONE/20; nav_set_zoom_trans_2d(visual, new_zoom, 0, 0); } else { nav_set_zoom_trans_2d(visual, zoom, 0, key_inv*key_trans); } } else { visual->compositor->rotation += key_inv*key_rot; nav_set_zoom_trans_2d(visual, zoom, 0, 0); } return 1; } break; } return 0; }
static void OnSphereSensor(SensorHandler *sh, Bool is_over, GF_Event *ev, RayHitInfo *hit_info) { M_SphereSensor *sphere = (M_SphereSensor *)sh->owner; SphereSensorStack *st = (SphereSensorStack *) gf_node_get_private(sh->owner); if (sphere->isActive && (!sphere->enabled || ((ev->type==GF_EVENT_MOUSEUP) && (ev->mouse.button==GF_MOUSE_LEFT)) ) ) { if (sphere->autoOffset) { sphere->offset = sphere->rotation_changed; gf_node_event_out_str(sh->owner, "offset"); } sphere->isActive = 0; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(st->compositor, 0); } else 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(&hit_info->local_to_world, &st->center); st->radius = gf_vec_len(hit_info->local_point); if (!st->radius) st->radius = FIX_ONE; st->grab_vec = gf_vec_scale(hit_info->local_point, gf_invfix(st->radius)); sphere->isActive = 1; gf_node_event_out_str(sh->owner, "isActive"); R3D_SetGrabbed(st->compositor, 1); } else if (sphere->isActive) { SFVec3f vec, axis; SFVec4f q1, q2; SFRotation r; Fixed cl; if (is_over) { sphere->trackPoint_changed = hit_info->local_point; gf_node_event_out_str(sh->owner, "trackPoint_changed"); } else { GF_Ray r; r = hit_info->world_ray; gf_mx_apply_ray(&hit_info->world_to_local, &r); if (!gf_ray_hit_sphere(&r, NULL, st->radius, &hit_info->local_point)) { vec.x = vec.y = vec.z = 0; /*doesn't work properly...*/ hit_info->local_point = gf_closest_point_to_line(r.orig, r.dir, vec); } } vec = gf_vec_scale(hit_info->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_str(sh->owner, "rotation_changed"); } }