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;
}
Example #2
0
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;
}
Example #3
0
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
}
Example #4
0
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;
		}
	}
}
Example #5
0
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;
}
Example #6
0
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;
		}
	}
}
Example #7
0
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;
}
Example #8
0
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
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #13
0
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;
}