int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event) { int redraw = TREDRAW_NOTHING; switch (event->type) { case LEFTSHIFTKEY: case RIGHTSHIFTKEY: if (event->val == KM_PRESS) { t->modifiers |= MOD_PRECISION; /* shift is modifier for higher precision transform * store the mouse position where the normal movement ended */ copy_v2_v2_int(mi->precision_mval, event->mval); mi->precision = 1; redraw = TREDRAW_HARD; } else if (event->val == KM_RELEASE) { t->modifiers &= ~MOD_PRECISION; mi->precision = 0; redraw = TREDRAW_HARD; } break; } return redraw; }
static int paintcurve_slide_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Paint *p = BKE_paint_get_active_from_context(C); const float loc_fl[2] = {UNPACK2(event->mval)}; char select; int i; bool do_select = RNA_boolean_get(op->ptr, "select"); bool align = RNA_boolean_get(op->ptr, "align"); Brush *br = p->brush; PaintCurve *pc = br->paint_curve; PaintCurvePoint *pcp; if (!pc) { return OPERATOR_PASS_THROUGH; } if (do_select) { pcp = paintcurve_point_get_closest(pc, loc_fl, align, PAINT_CURVE_SELECT_THRESHOLD, &select); } else { pcp = NULL; /* just find first selected point */ for (i = 0; i < pc->tot_points; i++) { if ((select = paintcurve_point_side_index(&pc->points[i].bez, i == 0, SEL_F3))) { pcp = &pc->points[i]; break; } } } if (pcp) { ARegion *ar = CTX_wm_region(C); wmWindow *window = CTX_wm_window(C); PointSlideData *psd = MEM_mallocN(sizeof(PointSlideData), "PointSlideData"); copy_v2_v2_int(psd->initial_loc, event->mval); psd->event = event->type; psd->pcp = pcp; psd->select = paintcurve_point_co_index(select); for (i = 0; i < 3; i++) { copy_v2_v2(psd->point_initial_loc[i], pcp->bez.vec[i]); } psd->align = align; op->customdata = psd; /* first, clear all selection from points */ for (i = 0; i < pc->tot_points; i++) { pc->points[i].bez.f1 = pc->points[i].bez.f3 = pc->points[i].bez.f2 = 0; } /* only select the active point */ PAINT_CURVE_POINT_SELECT(pcp, psd->select); BKE_paint_curve_clamp_endpoint_add_index(pc, pcp - pc->points); WM_event_add_modal_handler(C, op); WM_paint_cursor_tag_redraw(window, ar); return OPERATOR_RUNNING_MODAL; } return OPERATOR_PASS_THROUGH; }
static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) { #define WALK_ROTATE_FAC 2.2f /* more is faster */ #define WALK_TOP_LIMIT DEG2RADF(85.0f) #define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) /* walk mode - Ctrl+Shift+F * a walk loop where the user can move move the view as if they are in a walk game */ RegionView3D *rv3d = walk->rv3d; ARegion *ar = walk->ar; float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */ float dvec[3] = {0.0f, 0.0f, 0.0f}; /* this is the direction that's added to the view offset per redraw */ /* Camera Uprighting variables */ float upvec[3] = {0.0f, 0.0f, 0.0f}; /* stores the view's up vector */ int moffset[2]; /* mouse offset from the views center */ float tmp_quat[4]; /* used for rotating the view */ #ifdef NDOF_WALK_DEBUG { static unsigned int iteration = 1; printf("walk timer %d\n", iteration++); } #endif { /* mouse offset from the center */ copy_v2_v2_int(moffset, walk->moffset); /* apply moffset so we can re-accumulate */ walk->moffset[0] = 0; walk->moffset[1] = 0; /* revert mouse */ if (walk->is_reversed) { moffset[1] = -moffset[1]; } /* Should we redraw? */ if ((walk->active_directions) || moffset[0] || moffset[1] || walk->teleport.state == WALK_TELEPORT_STATE_ON || walk->gravity_state != WALK_GRAVITY_STATE_OFF) { float dvec_tmp[3]; /* time how fast it takes for us to redraw, * this is so simple scenes don't walk too fast */ double time_current; float time_redraw; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - walk->time_lastdraw); walk->time_lastdraw = time_current; /* base speed in m/s */ walk->speed = WALK_MOVE_SPEED; if (walk->is_fast) { walk->speed *= WALK_BOOST_FACTOR; } else if (walk->is_slow) { walk->speed *= 1.0f / WALK_BOOST_FACTOR; } copy_m3_m4(mat, rv3d->viewinv); { /* rotate about the X axis- look up/down */ if (moffset[1]) { float angle; float y; /* relative offset */ y = (float) moffset[1] / ar->winy; /* speed factor */ y *= WALK_ROTATE_FAC; /* user adjustement factor */ y *= walk->mouse_speed; /* clamp the angle limits */ /* it ranges from 90.0f to -90.0f */ angle = -asinf(rv3d->viewmat[2][2]); if (angle > WALK_TOP_LIMIT && y > 0.0f) y = 0.0f; else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) y = 0.0f; copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); mul_m3_v3(mat, upvec); /* Rotate about the relative up vec */ axis_angle_to_quat(tmp_quat, upvec, -y); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } /* rotate about the Y axis- look left/right */ if (moffset[0]) { float x; /* if we're upside down invert the moffset */ copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); mul_m3_v3(mat, upvec); if (upvec[2] < 0.0f) moffset[0] = -moffset[0]; /* relative offset */ x = (float) moffset[0] / ar->winx; /* speed factor */ x *= WALK_ROTATE_FAC; /* user adjustement factor */ x *= walk->mouse_speed; copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); /* Rotate about the relative up vec */ axis_angle_normalized_to_quat(tmp_quat, upvec, x); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } } /* WASD - 'move' translation code */ if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) { short direction; zero_v3(dvec); if ((walk->active_directions & WALK_BIT_FORWARD) || (walk->active_directions & WALK_BIT_BACKWARD)) { direction = 0; if ((walk->active_directions & WALK_BIT_FORWARD)) direction += 1; if ((walk->active_directions & WALK_BIT_BACKWARD)) direction -= 1; copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); mul_m3_v3(mat, dvec_tmp); if (walk->navigation_mode == WALK_MODE_GRAVITY) { dvec_tmp[2] = 0.0f; } normalize_v3(dvec_tmp); add_v3_v3(dvec, dvec_tmp); } if ((walk->active_directions & WALK_BIT_LEFT) || (walk->active_directions & WALK_BIT_RIGHT)) { direction = 0; if ((walk->active_directions & WALK_BIT_LEFT)) direction += 1; if ((walk->active_directions & WALK_BIT_RIGHT)) direction -= 1; dvec_tmp[0] = direction * rv3d->viewinv[0][0]; dvec_tmp[1] = direction * rv3d->viewinv[0][1]; dvec_tmp[2] = 0.0f; normalize_v3(dvec_tmp); add_v3_v3(dvec, dvec_tmp); } if ((walk->active_directions & WALK_BIT_UP) || (walk->active_directions & WALK_BIT_DOWN)) { if (walk->navigation_mode == WALK_MODE_FREE) { direction = 0; if ((walk->active_directions & WALK_BIT_UP)) direction -= 1; if ((walk->active_directions & WALK_BIT_DOWN)) direction = 1; copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); add_v3_v3(dvec, dvec_tmp); } } /* apply movement */ mul_v3_fl(dvec, walk->speed * time_redraw); } /* stick to the floor */ if (walk->navigation_mode == WALK_MODE_GRAVITY && ELEM(walk->gravity_state, WALK_GRAVITY_STATE_OFF, WALK_GRAVITY_STATE_START)) { bool ret; float ray_distance; float difference = -100.0f; float fall_distance; ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance); if (ret) { difference = walk->view_height - ray_distance; } /* the distance we would fall naturally smoothly enough that we * can manually drop the object without activating gravity */ fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR; if (fabsf(difference) < fall_distance) { /* slope/stairs */ dvec[2] -= difference; /* in case we switched from FREE to GRAVITY too close to the ground */ if (walk->gravity_state == WALK_GRAVITY_STATE_START) walk->gravity_state = WALK_GRAVITY_STATE_OFF; } else { /* hijack the teleport variables */ walk->teleport.initial_time = PIL_check_seconds_timer(); walk->gravity_state = WALK_GRAVITY_STATE_ON; walk->teleport.duration = 0.0f; copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); copy_v2_v2(walk->teleport.direction, dvec); } } /* Falling or jumping) */ if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) { float t; float z_cur, z_new; bool ret; float ray_distance, difference = -100.0f; /* delta time */ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); /* keep moving if we were moving */ copy_v2_v2(dvec, walk->teleport.direction); z_cur = walk->rv3d->viewinv[3][2]; z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; /* jump */ z_new += t * walk->speed_jump * walk->grid; /* duration is the jump duration */ if (t > walk->teleport.duration) { /* check to see if we are landing */ ret = walk_floor_distance_get(C, rv3d, walk, dvec, &ray_distance); if (ret) { difference = walk->view_height - ray_distance; } if (difference > 0.0f) { /* quit falling, lands at "view_height" from the floor */ dvec[2] -= difference; walk->gravity_state = WALK_GRAVITY_STATE_OFF; walk->speed_jump = 0.0f; } else { /* keep falling */ dvec[2] = z_cur - z_new; } } else { /* keep going up (jump) */ dvec[2] = z_cur - z_new; } } /* Teleport */ else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) { float t; /* factor */ float new_loc[3]; float cur_loc[3]; /* linear interpolation */ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); t /= walk->teleport.duration; /* clamp so we don't go past our limit */ if (t >= 1.0f) { t = 1.0f; walk->teleport.state = WALK_TELEPORT_STATE_OFF; walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode); } mul_v3_v3fl(new_loc, walk->teleport.direction, t); add_v3_v3(new_loc, walk->teleport.origin); copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]); sub_v3_v3v3(dvec, cur_loc, new_loc); } if (rv3d->persp == RV3D_CAMOB) { Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0f; if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0f; if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0f; } /* scale the movement to the scene size */ mul_v3_v3fl(dvec_tmp, dvec, walk->grid); add_v3_v3(rv3d->ofs, dvec_tmp); if (rv3d->persp == RV3D_CAMOB) { const bool do_rotate = (moffset[0] || moffset[1]); const bool do_translate = (walk->speed != 0.0f); walkMoveCamera(C, walk, do_rotate, do_translate); } } else { /* we're not redrawing but we need to update the time else the view will jump */ walk->time_lastdraw = PIL_check_seconds_timer(); } /* end drawing */ copy_v3_v3(walk->dvec_prev, dvec); } return OPERATOR_FINISHED; #undef WALK_ROTATE_FAC #undef WALK_ZUP_CORRECT_FAC #undef WALK_ZUP_CORRECT_ACCEL #undef WALK_SMOOTH_FAC #undef WALK_TOP_LIMIT #undef WALK_BOTTOM_LIMIT #undef WALK_MOVE_SPEED #undef WALK_BOOST_FACTOR }
static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event) { if (event->type == TIMER && event->customdata == walk->timer) { walk->redraw = true; } else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_first) { /* wait until we get the 'warp' event */ if ((walk->center_mval[0] == event->mval[0]) && (walk->center_mval[1] == event->mval[1])) { walk->is_cursor_first = false; } else { /* note, its possible the system isn't giving us the warp event * ideally we shouldn't have to worry about this, see: T45361 */ wmWindow *win = CTX_wm_window(C); WM_cursor_warp(win, walk->ar->winrct.xmin + walk->center_mval[0], walk->ar->winrct.ymin + walk->center_mval[1]); } return; } if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) { walk->is_cursor_absolute = true; copy_v2_v2_int(walk->prev_mval, event->mval); copy_v2_v2_int(walk->center_mval, event->mval); /* without this we can't turn 180d */ CLAMP_MIN(walk->mouse_speed, 4.0f); } #endif /* USE_TABLET_SUPPORT */ walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; copy_v2_v2_int(walk->prev_mval, event->mval); if ((walk->center_mval[0] != event->mval[0]) || (walk->center_mval[1] != event->mval[1])) { walk->redraw = true; #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { /* pass */ } else #endif if (wm_event_is_last_mousemove(event)) { wmWindow *win = CTX_wm_window(C); #ifdef __APPLE__ if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) || (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2)) #endif { WM_cursor_warp(win, walk->ar->winrct.xmin + walk->center_mval[0], walk->ar->winrct.ymin + walk->center_mval[1]); copy_v2_v2_int(walk->prev_mval, walk->center_mval); } } } } else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in walk mode!"); // static const char *tag_name = "3D mouse position"; const wmNDOFMotionData *incoming_ndof = event->customdata; switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ #ifdef NDOF_WALK_DEBUG puts("start keeping track of 3D mouse position"); #endif /* fall-through */ case P_IN_PROGRESS: /* update 3D mouse position */ #ifdef NDOF_WALK_DEBUG putchar('.'); fflush(stdout); #endif if (walk->ndof == NULL) { // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); walk->ndof = MEM_dupallocN(incoming_ndof); // walk->ndof = malloc(sizeof(wmNDOFMotionData)); } else { memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); } break; case P_FINISHING: /* stop keeping track of 3D mouse position */ #ifdef NDOF_WALK_DEBUG puts("stop keeping track of 3D mouse position"); #endif if (walk->ndof) { MEM_freeN(walk->ndof); // free(walk->ndof); walk->ndof = NULL; } /* update the time else the view will jump when 2D mouse/timer resume */ walk->time_lastdraw = PIL_check_seconds_timer(); break; default: break; /* should always be one of the above 3 */ } } /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { case WALK_MODAL_CANCEL: walk->state = WALK_CANCEL; break; case WALK_MODAL_CONFIRM: walk->state = WALK_CONFIRM; break; case WALK_MODAL_ACCELERATE: base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f); break; case WALK_MODAL_DECELERATE: base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f); break; /* implement WASD keys */ case WALK_MODAL_DIR_FORWARD: walk->active_directions |= WALK_BIT_FORWARD; break; case WALK_MODAL_DIR_BACKWARD: walk->active_directions |= WALK_BIT_BACKWARD; break; case WALK_MODAL_DIR_LEFT: walk->active_directions |= WALK_BIT_LEFT; break; case WALK_MODAL_DIR_RIGHT: walk->active_directions |= WALK_BIT_RIGHT; break; case WALK_MODAL_DIR_UP: walk->active_directions |= WALK_BIT_UP; break; case WALK_MODAL_DIR_DOWN: walk->active_directions |= WALK_BIT_DOWN; break; case WALK_MODAL_DIR_FORWARD_STOP: walk->active_directions &= ~WALK_BIT_FORWARD; break; case WALK_MODAL_DIR_BACKWARD_STOP: walk->active_directions &= ~WALK_BIT_BACKWARD; break; case WALK_MODAL_DIR_LEFT_STOP: walk->active_directions &= ~WALK_BIT_LEFT; break; case WALK_MODAL_DIR_RIGHT_STOP: walk->active_directions &= ~WALK_BIT_RIGHT; break; case WALK_MODAL_DIR_UP_STOP: walk->active_directions &= ~WALK_BIT_UP; break; case WALK_MODAL_DIR_DOWN_STOP: walk->active_directions &= ~WALK_BIT_DOWN; break; case WALK_MODAL_FAST_ENABLE: walk->is_fast = true; break; case WALK_MODAL_FAST_DISABLE: walk->is_fast = false; break; case WALK_MODAL_SLOW_ENABLE: walk->is_slow = true; break; case WALK_MODAL_SLOW_DISABLE: walk->is_slow = false; break; #define JUMP_SPEED_MIN 1.0f #define JUMP_TIME_MAX 0.2f /* s */ #define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height) case WALK_MODAL_JUMP_STOP: if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) { float t; /* delta time */ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); /* reduce the veolocity, if JUMP wasn't hold for long enough */ t = min_ff(t, JUMP_TIME_MAX); walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; /* when jumping, duration is how long it takes before we start going down */ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); /* no more increase of jump speed */ walk->gravity_state = WALK_GRAVITY_STATE_ON; } break; case WALK_MODAL_JUMP: if ((walk->navigation_mode == WALK_MODE_GRAVITY) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF) && (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) { /* no need to check for ground, * walk->gravity wouldn't be off * if we were over a hole */ walk->gravity_state = WALK_GRAVITY_STATE_JUMP; walk->speed_jump = JUMP_SPEED_MAX; walk->teleport.initial_time = PIL_check_seconds_timer(); copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); /* using previous vec because WASD keys are not called when SPACE is */ copy_v2_v2(walk->teleport.direction, walk->dvec_prev); /* when jumping, duration is how long it takes before we start going down */ walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); } break; case WALK_MODAL_TELEPORT: { float loc[3], nor[3]; float distance; bool ret = walk_ray_cast(C, walk->rv3d, walk, loc, nor, &distance); /* in case we are teleporting middle way from a jump */ walk->speed_jump = 0.0f; if (ret) { WalkTeleport *teleport = &walk->teleport; teleport->state = WALK_TELEPORT_STATE_ON; teleport->initial_time = PIL_check_seconds_timer(); teleport->duration = U.walk_navigation.teleport_time; teleport->navigation_mode = walk->navigation_mode; walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); /* stop the camera from a distance (camera height) */ normalize_v3(nor); mul_v3_fl(nor, walk->view_height); add_v3_v3(loc, nor); sub_v3_v3v3(teleport->direction, loc, teleport->origin); } else { walk->teleport.state = WALK_TELEPORT_STATE_OFF; } break; } #undef JUMP_SPEED_MAX #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN case WALK_MODAL_TOGGLE: if (walk->navigation_mode == WALK_MODE_GRAVITY) { walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); } else { /* WALK_MODE_FREE */ walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); } break; } } }
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) { wmWindow *win = CTX_wm_window(C); walk->rv3d = CTX_wm_region_view3d(C); walk->v3d = CTX_wm_view3d(C); walk->ar = CTX_wm_region(C); walk->scene = CTX_data_scene(C); #ifdef NDOF_WALK_DEBUG puts("\n-- walk begin --"); #endif /* sanity check: for rare but possible case (if lib-linking the camera fails) */ if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { walk->rv3d->persp = RV3D_PERSP; } if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); return false; } if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); return false; } if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); return false; } walk->state = WALK_RUNNING; if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { base_speed = U.walk_navigation.walk_speed; userdef_speed = U.walk_navigation.walk_speed; } walk->speed = 0.0f; walk->is_fast = false; walk->is_slow = false; walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length; /* user preference settings */ walk->teleport.duration = U.walk_navigation.teleport_time; walk->mouse_speed = U.walk_navigation.mouse_speed; if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); else walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); walk->view_height = U.walk_navigation.view_height; walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; walk->gravity_state = WALK_GRAVITY_STATE_OFF; if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); } else { walk->gravity = 9.80668f; /* m/s2 */ } walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); #ifdef USE_TABLET_SUPPORT walk->is_cursor_first = true; walk->is_cursor_absolute = false; #endif walk->active_directions = 0; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif zero_v3(walk->dvec_prev); walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); walk->ndof = NULL; walk->time_lastdraw = PIL_check_seconds_timer(); walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); walk->rv3d->rflag |= RV3D_NAVIGATING; walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( walk->scene, walk->v3d, walk->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* center the mouse */ walk->center_mval[0] = walk->ar->winx * 0.5f; walk->center_mval[1] = walk->ar->winy * 0.5f; #ifdef USE_PIXELSIZE_NATIVE_SUPPORT walk->center_mval[0] += walk->ar->winrct.xmin; walk->center_mval[1] += walk->ar->winrct.ymin; WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); walk->center_mval[0] -= walk->ar->winrct.xmin; walk->center_mval[1] -= walk->ar->winrct.ymin; #endif copy_v2_v2_int(walk->prev_mval, walk->center_mval); WM_cursor_warp(win, walk->ar->winrct.xmin + walk->center_mval[0], walk->ar->winrct.ymin + walk->center_mval[1]); /* remove the mouse cursor temporarily */ WM_cursor_modal_set(win, CURSOR_NONE); return 1; }
static void flyEvent(FlyInfo *fly, const wmEvent *event) { if (event->type == TIMER && event->customdata == fly->timer) { fly->redraw = 1; } else if (event->type == MOUSEMOVE) { copy_v2_v2_int(fly->mval, event->mval); } else if (event->type == NDOF_MOTION) { /* do these automagically get delivered? yes. */ // puts("ndof motion detected in fly mode!"); // static const char *tag_name = "3D mouse position"; wmNDOFMotionData *incoming_ndof = (wmNDOFMotionData *)event->customdata; switch (incoming_ndof->progress) { case P_STARTING: /* start keeping track of 3D mouse position */ #ifdef NDOF_FLY_DEBUG puts("start keeping track of 3D mouse position"); #endif /* fall through... */ case P_IN_PROGRESS: /* update 3D mouse position */ #ifdef NDOF_FLY_DEBUG putchar('.'); fflush(stdout); #endif if (fly->ndof == NULL) { // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); fly->ndof = MEM_dupallocN(incoming_ndof); // fly->ndof = malloc(sizeof(wmNDOFMotionData)); } else { memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); } break; case P_FINISHING: /* stop keeping track of 3D mouse position */ #ifdef NDOF_FLY_DEBUG puts("stop keeping track of 3D mouse position"); #endif if (fly->ndof) { MEM_freeN(fly->ndof); // free(fly->ndof); fly->ndof = NULL; } /* update the time else the view will jump when 2D mouse/timer resume */ fly->time_lastdraw = PIL_check_seconds_timer(); break; default: break; /* should always be one of the above 3 */ } } /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { case FLY_MODAL_CANCEL: fly->state = FLY_CANCEL; break; case FLY_MODAL_CONFIRM: fly->state = FLY_CONFIRM; break; /* speed adjusting with mousepan (trackpad) */ case FLY_MODAL_SPEED: { float fac = 0.02f * (event->prevy - event->y); /* allowing to brake immediate */ if (fac > 0.0f && fly->speed < 0.0f) fly->speed = 0.0f; else if (fac < 0.0f && fly->speed > 0.0f) fly->speed = 0.0f; else fly->speed += fly->grid * fac; break; } case FLY_MODAL_ACCELERATE: { double time_currwheel; float time_wheel; time_currwheel = PIL_check_seconds_timer(); time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */ time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ if (fly->speed < 0.0f) { fly->speed = 0.0f; } else { fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); } break; } case FLY_MODAL_DECELERATE: { double time_currwheel; float time_wheel; time_currwheel = PIL_check_seconds_timer(); time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ if (fly->speed > 0.0f) { fly->speed = 0; } else { fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); } break; } case FLY_MODAL_PAN_ENABLE: fly->pan_view = true; break; case FLY_MODAL_PAN_DISABLE: //XXX2.5 WM_cursor_warp(CTX_wm_window(C), cent_orig[0], cent_orig[1]); fly->pan_view = false; break; /* implement WASD keys, * comments only for 'forward '*/ case FLY_MODAL_DIR_FORWARD: if (fly->axis == 2 && fly->speed < 0.0f) { /* reverse direction stops, tap again to continue */ fly->axis = -1; } else { /* flip speed rather than stopping, game like motion, * else increase like mousewheel if were already moving in that direction */ if (fly->speed < 0.0f) fly->speed = -fly->speed; else if (fly->axis == 2) fly->speed += fly->grid; fly->axis = 2; } break; case FLY_MODAL_DIR_BACKWARD: if (fly->axis == 2 && fly->speed > 0.0f) { fly->axis = -1; } else { if (fly->speed > 0.0f) fly->speed = -fly->speed; else if (fly->axis == 2) fly->speed -= fly->grid; fly->axis = 2; } break; case FLY_MODAL_DIR_LEFT: if (fly->axis == 0 && fly->speed < 0.0f) { fly->axis = -1; } else { if (fly->speed < 0.0f) fly->speed = -fly->speed; else if (fly->axis == 0) fly->speed += fly->grid; fly->axis = 0; } break; case FLY_MODAL_DIR_RIGHT: if (fly->axis == 0 && fly->speed > 0.0f) { fly->axis = -1; } else { if (fly->speed > 0.0f) fly->speed = -fly->speed; else if (fly->axis == 0) fly->speed -= fly->grid; fly->axis = 0; } break; case FLY_MODAL_DIR_DOWN: if (fly->axis == 1 && fly->speed < 0.0f) { fly->axis = -1; } else { if (fly->speed < 0.0f) fly->speed = -fly->speed; else if (fly->axis == 1) fly->speed += fly->grid; fly->axis = 1; } break; case FLY_MODAL_DIR_UP: if (fly->axis == 1 && fly->speed > 0.0f) { fly->axis = -1; } else { if (fly->speed > 0.0f) fly->speed = -fly->speed; else if (fly->axis == 1) fly->speed -= fly->grid; fly->axis = 1; } break; case FLY_MODAL_AXIS_LOCK_X: if (fly->xlock != FLY_AXISLOCK_STATE_OFF) fly->xlock = FLY_AXISLOCK_STATE_OFF; else { fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; fly->xlock_momentum = 0.0; } break; case FLY_MODAL_AXIS_LOCK_Z: if (fly->zlock != FLY_AXISLOCK_STATE_OFF) fly->zlock = FLY_AXISLOCK_STATE_OFF; else { fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; fly->zlock_momentum = 0.0; } break; case FLY_MODAL_PRECISION_ENABLE: fly->use_precision = true; break; case FLY_MODAL_PRECISION_DISABLE: fly->use_precision = false; break; case FLY_MODAL_FREELOOK_ENABLE: fly->use_freelook = true; break; case FLY_MODAL_FREELOOK_DISABLE: fly->use_freelook = false; break; } } }
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); float upvec[3]; /* tmp */ float mat[3][3]; fly->rv3d = CTX_wm_region_view3d(C); fly->v3d = CTX_wm_view3d(C); fly->ar = CTX_wm_region(C); fly->scene = CTX_data_scene(C); #ifdef NDOF_FLY_DEBUG puts("\n-- fly begin --"); #endif /* sanity check: for rare but possible case (if lib-linking the camera fails) */ if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { fly->rv3d->persp = RV3D_PERSP; } if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return false; } if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) { BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked"); return false; } if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); return false; } fly->state = FLY_RUNNING; fly->speed = 0.0f; fly->axis = 2; fly->pan_view = false; fly->xlock = FLY_AXISLOCK_STATE_OFF; fly->zlock = FLY_AXISLOCK_STATE_OFF; fly->xlock_momentum = 0.0f; fly->zlock_momentum = 0.0f; fly->grid = 1.0f; fly->use_precision = false; fly->use_freelook = false; #ifdef NDOF_FLY_DRAW_TOOMUCH fly->redraw = 1; #endif zero_v3(fly->dvec_prev); fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); copy_v2_v2_int(fly->mval, event->mval); fly->ndof = NULL; fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL); fly->rv3d->rflag |= RV3D_NAVIGATING; /* so we draw the corner margins */ /* detect weather to start with Z locking */ upvec[0] = 1.0f; upvec[1] = 0.0f; upvec[2] = 0.0f; copy_m3_m4(mat, fly->rv3d->viewinv); mul_m3_v3(mat, upvec); if (fabsf(upvec[2]) < 0.1f) { fly->zlock = FLY_AXISLOCK_STATE_IDLE; } upvec[0] = 0; upvec[1] = 0; upvec[2] = 0; fly->persp_backup = fly->rv3d->persp; fly->dist_backup = fly->rv3d->dist; /* check for flying ortho camera - which we cant support well * we _could_ also check for an ortho camera but this is easier */ if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->rv3d->is_persp == false)) { ((Camera *)fly->v3d->camera->data)->type = CAM_PERSP; fly->is_ortho_cam = true; } if (fly->rv3d->persp == RV3D_CAMOB) { Object *ob_back; if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (fly->root_parent = fly->v3d->camera->parent)) { while (fly->root_parent->parent) fly->root_parent = fly->root_parent->parent; ob_back = fly->root_parent; } else { ob_back = fly->v3d->camera; } /* store the original camera loc and rot */ fly->obtfm = BKE_object_tfm_backup(ob_back); BKE_object_where_is_calc(fly->scene, fly->v3d->camera); negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); fly->rv3d->dist = 0.0; } else { /* perspective or ortho */ if (fly->rv3d->persp == RV3D_ORTHO) fly->rv3d->persp = RV3D_PERSP; /* if ortho projection, make perspective */ copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat); copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs); /* the dist defines a vector that is infront of the offset * to rotate the view about. * this is no good for fly mode because we * want to rotate about the viewers center. * but to correct the dist removal we must * alter offset so the view doesn't jump. */ fly->rv3d->dist = 0.0f; upvec[2] = fly->dist_backup; /* x and y are 0 */ mul_m3_v3(mat, upvec); sub_v3_v3(fly->rv3d->ofs, upvec); /* Done with correcting for the dist */ } /* center the mouse, probably the UI mafia are against this but without its quite annoying */ WM_cursor_warp(win, fly->ar->winrct.xmin + fly->ar->winx / 2, fly->ar->winrct.ymin + fly->ar->winy / 2); return 1; }
static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len, unsigned char *fg, unsigned char *bg) { #define STEP_SEL(value) cdc->sel[0] += (value); cdc->sel[1] += (value) int rct_ofs= cdc->lheight/4; int tot_lines = (str_len/cdc->console_width)+1; /* total number of lines for wrapping */ int y_next = (str_len > cdc->console_width) ? cdc->xy[1]+cdc->lheight*tot_lines : cdc->xy[1]+cdc->lheight; const int mono= blf_mono_font; /* just advance the height */ if(cdc->draw==0) { if(cdc->pos_pick && (cdc->mval[1] != INT_MAX)) { if(cdc->xy[1] <= cdc->mval[1]) { if((y_next >= cdc->mval[1])) { int ofs = (int)floor(((float)cdc->mval[0] / (float)cdc->cwidth)); /* wrap */ if(str_len > cdc->console_width) ofs += (cdc->console_width * ((int)((((float)(y_next - cdc->mval[1]) / (float)(y_next-cdc->xy[1])) * tot_lines)))); CLAMP(ofs, 0, str_len); *cdc->pos_pick += str_len - ofs; } else *cdc->pos_pick += str_len + 1; } } cdc->xy[1]= y_next; return 1; } else if (y_next-cdc->lheight < cdc->ymin) { /* have not reached the drawable area so don't break */ cdc->xy[1]= y_next; /* adjust selection even if not drawing */ if(cdc->sel[0] != cdc->sel[1]) { STEP_SEL(-(str_len + 1)); } return 1; } if(str_len > cdc->console_width) { /* wrap? */ const int initial_offset= ((tot_lines-1) * cdc->console_width); const char *line_stride= str + initial_offset; /* advance to the last line and draw it first */ int sel_orig[2]; copy_v2_v2_int(sel_orig, cdc->sel); /* invert and swap for wrapping */ cdc->sel[0] = str_len - sel_orig[1]; cdc->sel[1] = str_len - sel_orig[0]; if(bg) { glColor3ubv(bg); glRecti(0, cdc->xy[1]-rct_ofs, cdc->winx, (cdc->xy[1]+(cdc->lheight*tot_lines))+rct_ofs); } glColor3ubv(fg); /* last part needs no clipping */ BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); BLF_draw(mono, line_stride, str_len - initial_offset); if(cdc->sel[0] != cdc->sel[1]) { STEP_SEL(-initial_offset); // glColor4ub(255, 0, 0, 96); // debug console_draw_sel(cdc->sel, cdc->xy, str_len % cdc->console_width, cdc->cwidth, cdc->lheight); STEP_SEL(cdc->console_width); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; line_stride -= cdc->console_width; for(; line_stride >= str; line_stride -= cdc->console_width) { BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); BLF_draw(mono, line_stride, cdc->console_width); if(cdc->sel[0] != cdc->sel[1]) { // glColor4ub(0, 255, 0, 96); // debug console_draw_sel(cdc->sel, cdc->xy, cdc->console_width, cdc->cwidth, cdc->lheight); STEP_SEL(cdc->console_width); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; /* check if were out of view bounds */ if(cdc->xy[1] > cdc->ymax) return 0; } copy_v2_v2_int(cdc->sel, sel_orig); STEP_SEL(-(str_len + 1)); } else { /* simple, no wrap */ if(bg) { glColor3ubv(bg); glRecti(0, cdc->xy[1]-rct_ofs, cdc->winx, cdc->xy[1]+cdc->lheight-rct_ofs); } glColor3ubv(fg); BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); BLF_draw(mono, str, str_len); if(cdc->sel[0] != cdc->sel[1]) { int isel[2]; isel[0]= str_len - cdc->sel[1]; isel[1]= str_len - cdc->sel[0]; // glColor4ub(255, 255, 0, 96); // debug console_draw_sel(isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight); STEP_SEL(-(str_len + 1)); } cdc->xy[1] += cdc->lheight; if(cdc->xy[1] > cdc->ymax) return 0; } return 1; #undef STEP_SEL }
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); rctf viewborder; float upvec[3]; /* tmp */ float mat[3][3]; fly->rv3d = CTX_wm_region_view3d(C); fly->v3d = CTX_wm_view3d(C); fly->ar = CTX_wm_region(C); fly->scene = CTX_data_scene(C); #ifdef NDOF_FLY_DEBUG puts("\n-- fly begin --"); #endif /* sanity check: for rare but possible case (if lib-linking the camera fails) */ if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { fly->rv3d->persp = RV3D_PERSP; } if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return false; } if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) { BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked"); return false; } if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); return false; } fly->state = FLY_RUNNING; fly->speed = 0.0f; fly->axis = 2; fly->pan_view = false; fly->xlock = FLY_AXISLOCK_STATE_OFF; fly->zlock = FLY_AXISLOCK_STATE_OFF; fly->xlock_momentum = 0.0f; fly->zlock_momentum = 0.0f; fly->grid = 1.0f; fly->use_precision = false; fly->use_freelook = false; #ifdef NDOF_FLY_DRAW_TOOMUCH fly->redraw = 1; #endif zero_v3(fly->dvec_prev); fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); copy_v2_v2_int(fly->mval, event->mval); #ifdef WITH_INPUT_NDOF fly->ndof = NULL; #endif fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL); fly->rv3d->rflag |= RV3D_NAVIGATING; /* detect whether to start with Z locking */ copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); copy_m3_m4(mat, fly->rv3d->viewinv); mul_m3_v3(mat, upvec); if (fabsf(upvec[2]) < 0.1f) { fly->zlock = FLY_AXISLOCK_STATE_IDLE; } fly->v3d_camera_control = ED_view3d_cameracontrol_acquire( fly->scene, fly->v3d, fly->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* calculate center */ if (fly->scene->camera) { ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); fly->width = BLI_rctf_size_x(&viewborder); fly->height = BLI_rctf_size_y(&viewborder); fly->center_mval[0] = viewborder.xmin + fly->width / 2; fly->center_mval[1] = viewborder.ymin + fly->height / 2; } else { fly->width = fly->ar->winx; fly->height = fly->ar->winy; fly->center_mval[0] = fly->width / 2; fly->center_mval[1] = fly->height / 2; } /* center the mouse, probably the UI mafia are against this but without its quite annoying */ WM_cursor_warp(win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]); fly_update_header(C, op, fly); return 1; }
uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg, void (*arg_free)(void *arg)) { wmWindow *window = CTX_wm_window(C); uiBut *activebut = UI_context_active_but_get(C); static ARegionType type; ARegion *ar; uiBlock *block; uiPopupBlockHandle *handle; /* disable tooltips from buttons below */ if (activebut) { UI_but_tooltip_timer_remove(C, activebut); } /* standard cursor by default */ WM_cursor_set(window, CURSOR_STD); /* create handle */ handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle"); /* store context for operator */ handle->ctx_area = CTX_wm_area(C); handle->ctx_region = CTX_wm_region(C); /* store vars to refresh popup (RGN_DRAW_REFRESH_UI) */ handle->popup_create_vars.create_func = create_func; handle->popup_create_vars.handle_create_func = handle_create_func; handle->popup_create_vars.arg = arg; handle->popup_create_vars.arg_free = arg_free; handle->popup_create_vars.but = but; handle->popup_create_vars.butregion = but ? butregion : NULL; copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x); /* don't allow by default, only if popup type explicitly supports it */ handle->can_refresh = false; /* create area region */ ar = ui_region_temp_add(CTX_wm_screen(C)); handle->region = ar; memset(&type, 0, sizeof(ARegionType)); type.draw = ui_block_region_draw; type.layout = ui_block_region_refresh; type.regionid = RGN_TYPE_TEMPORARY; ar->type = &type; UI_region_handlers_add(&ar->handlers); block = ui_popup_block_refresh(C, handle, butregion, but); handle = block->handle; /* keep centered on window resizing */ if (block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) { type.listener = ui_block_region_popup_window_listener; } return handle; }
static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; struct { Object *ob; BMElem *ele; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int vert_index; int edge_index; int face_index; } prev = { .base_index = gz_ele->base_index, .vert_index = gz_ele->vert_index, .edge_index = gz_ele->edge_index, .face_index = gz_ele->face_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ele->bases); gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ele->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); { /* TODO: support faces. */ int base_index = -1; BMVert *eve_test; BMEdge *eed_test; if (EDBM_unified_findnearest_from_raycast(&vc, gz_ele->bases, gz_ele->bases_len, true, &base_index, &eve_test, &eed_test, NULL)) { Base *base = gz_ele->bases[base_index]; best.ob = base->object; if (eve_test) { best.ele = (BMElem *)eve_test; } else if (eed_test) { best.ele = (BMElem *)eed_test; } else { BLI_assert(0); } best.base_index = base_index; /* Check above should never fail, if it does it's an internal error. */ BLI_assert(best.base_index != -1); } } BMesh *bm = NULL; gz_ele->base_index = -1; gz_ele->vert_index = -1; gz_ele->edge_index = -1; gz_ele->face_index = -1; if (best.ele) { gz_ele->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, best.ele->head.htype); if (best.ele->head.htype == BM_VERT) { gz_ele->vert_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_EDGE) { gz_ele->edge_index = BM_elem_index_get(best.ele); } else if (best.ele->head.htype == BM_FACE) { gz_ele->face_index = BM_elem_index_get(best.ele); } } if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) && (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) { /* pass (only recalculate on change) */ } else { if (best.ele) { const float(*coords)[3] = NULL; { Object *ob = gz_ele->bases[gz_ele->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); } else { EDBM_preselect_elem_clear(gz_ele->psel); } RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_elem_setup(wmGizmo *gz) { MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; if (gz_ele->psel == NULL) { gz_ele->psel = EDBM_preselect_elem_create(); } gz_ele->base_index = -1; }
static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; struct { Object *ob; BMEdge *eed; float dist; int base_index; } best = { .dist = ED_view3d_select_dist_px(), }; struct { int base_index; int edge_index; } prev = { .base_index = gz_ring->base_index, .edge_index = gz_ring->edge_index, }; { ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) { MEM_SAFE_FREE(gz_ring->bases); gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( view_layer, v3d, &gz_ring->bases_len); } } ViewContext vc; em_setup_viewcontext(C, &vc); copy_v2_v2_int(vc.mval, mval); uint base_index; BMEdge *eed_test = EDBM_edge_find_nearest_ex( &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index); if (eed_test) { best.ob = gz_ring->bases[base_index]->object; best.eed = eed_test; best.base_index = base_index; } BMesh *bm = NULL; if (best.eed) { gz_ring->base_index = best.base_index; bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm; BM_mesh_elem_index_ensure(bm, BM_EDGE); gz_ring->edge_index = BM_elem_index_get(best.eed); } else { gz_ring->base_index = -1; gz_ring->edge_index = -1; } if ((prev.base_index == gz_ring->base_index) && (prev.edge_index == gz_ring->edge_index)) { /* pass (only recalculate on change) */ } else { if (best.eed) { const float(*coords)[3] = NULL; { Object *ob = gz_ring->bases[gz_ring->base_index]->object; Depsgraph *depsgraph = CTX_data_depsgraph(C); Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); if (me_eval->runtime.edit_data) { coords = me_eval->runtime.edit_data->vertexCos; } } EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords); } else { EDBM_preselect_edgering_clear(gz_ring->psel); } RNA_int_set(gz->ptr, "object_index", gz_ring->base_index); RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } // return best.eed ? 0 : -1; return -1; } static void gizmo_preselect_edgering_setup(wmGizmo *gz) { MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; if (gz_ring->psel == NULL) { gz_ring->psel = EDBM_preselect_edgering_create(); } gz_ring->base_index = -1; }
static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len, const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4]) { int tot_lines; /* total number of lines for wrapping */ int *offsets; /* offsets of line beginnings for wrapping */ int y_next; str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets); y_next = cdc->xy[1] + cdc->lheight * tot_lines; /* just advance the height */ if (cdc->draw == 0) { if (cdc->pos_pick && cdc->mval[1] != INT_MAX && cdc->xy[1] <= cdc->mval[1]) { if (y_next >= cdc->mval[1]) { int ofs = 0; /* wrap */ if (tot_lines > 1) { int iofs = (int)((float)(y_next - cdc->mval[1]) / cdc->lheight); ofs += offsets[MIN2(iofs, tot_lines - 1)]; } /* last part */ ofs += txt_utf8_column_to_offset(str + ofs, (int)floor((float)cdc->mval[0] / cdc->cwidth)); CLAMP(ofs, 0, str_len); *cdc->pos_pick += str_len - ofs; } else *cdc->pos_pick += str_len + 1; } cdc->xy[1] = y_next; MEM_freeN(offsets); return 1; } else if (y_next < cdc->ymin) { /* have not reached the drawable area so don't break */ cdc->xy[1] = y_next; /* adjust selection even if not drawing */ if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -(str_len + 1)); } MEM_freeN(offsets); return 1; } if (tot_lines > 1) { /* wrap? */ const int initial_offset = offsets[tot_lines - 1]; size_t len = str_len - initial_offset; const char *s = str + initial_offset; int i; int sel_orig[2]; copy_v2_v2_int(sel_orig, cdc->sel); /* invert and swap for wrapping */ cdc->sel[0] = str_len - sel_orig[1]; cdc->sel[1] = str_len - sel_orig[0]; if (bg) { glColor3ubv(bg); glRecti(0, cdc->xy[1], cdc->winx, (cdc->xy[1] + (cdc->lheight * tot_lines))); } glColor3ubv(fg); /* last part needs no clipping */ BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -initial_offset); // glColor4ub(255, 0, 0, 96); // debug console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; for (i = tot_lines - 1; i > 0; i--) { len = offsets[i] - offsets[i - 1]; s = str + offsets[i - 1]; BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); BLF_draw_mono(cdc->font_id, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, len); // glColor4ub(0, 255, 0, 96); // debug console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; /* check if were out of view bounds */ if (cdc->xy[1] > cdc->ymax) { MEM_freeN(offsets); return 0; } } copy_v2_v2_int(cdc->sel, sel_orig); console_step_sel(cdc, -(str_len + 1)); } else { /* simple, no wrap */ if (bg) { glColor3ubv(bg); glRecti(0, cdc->xy[1], cdc->winx, cdc->xy[1] + cdc->lheight); } glColor3ubv(fg); BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0); BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { int isel[2]; isel[0] = str_len - cdc->sel[1]; isel[1] = str_len - cdc->sel[0]; // glColor4ub(255, 255, 0, 96); // debug console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, -(str_len + 1)); } cdc->xy[1] += cdc->lheight; if (cdc->xy[1] > cdc->ymax) { MEM_freeN(offsets); return 0; } } MEM_freeN(offsets); return 1; }