2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2010-10-25 07:09:38 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
2018-06-01 18:19:39 +02:00
|
|
|
* of the License, or (at your option) any later version.
|
2010-10-25 07:09:38 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup spview3d
|
2020-08-02 18:08:46 +10:00
|
|
|
*
|
|
|
|
* Interactive fly navigation modal operator (flying around in space).
|
|
|
|
*
|
|
|
|
* \note Similar logic to `view3d_walk.c` changes here may apply there too.
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* defines VIEW3D_OT_fly modal operator */
|
|
|
|
|
2016-08-18 00:21:55 -04:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
|
|
|
//# define NDOF_FLY_DEBUG
|
2019-01-14 16:30:43 +11:00
|
|
|
/* is this needed for ndof? - commented so redraw doesn't thrash - campbell */
|
|
|
|
//# define NDOF_FLY_DRAW_TOOMUCH
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif /* WITH_INPUT_NDOF */
|
2013-11-28 15:01:53 +11:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
#include "BLI_blenlib.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_math.h"
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_report.h"
|
|
|
|
|
2015-08-16 17:32:01 +10:00
|
|
|
#include "BLT_translation.h"
|
2014-02-12 14:06:45 -02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "ED_space_api.h"
|
|
|
|
|
|
|
|
#include "PIL_time.h" /* smoothview */
|
|
|
|
|
2015-07-12 21:14:06 +02:00
|
|
|
#include "UI_interface.h"
|
2014-03-18 05:34:43 +11:00
|
|
|
#include "UI_resources.h"
|
|
|
|
|
2016-09-20 14:44:52 +00:00
|
|
|
#include "GPU_immediate.h"
|
|
|
|
|
2018-01-23 15:19:53 +11:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2012-04-02 06:26:52 +00:00
|
|
|
#include "view3d_intern.h" /* own include */
|
2013-11-28 15:01:53 +11:00
|
|
|
|
2020-06-18 12:40:38 +10:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Modal Key-map
|
|
|
|
* \{ */
|
|
|
|
|
2019-01-14 16:30:43 +11:00
|
|
|
/* NOTE: these defines are saved in keymap files,
|
|
|
|
* do not change values but just add new ones */
|
2011-09-25 04:47:46 +00:00
|
|
|
enum {
|
2012-03-10 06:46:23 +00:00
|
|
|
FLY_MODAL_CANCEL = 1,
|
2011-09-25 04:47:46 +00:00
|
|
|
FLY_MODAL_CONFIRM,
|
|
|
|
FLY_MODAL_ACCELERATE,
|
|
|
|
FLY_MODAL_DECELERATE,
|
|
|
|
FLY_MODAL_PAN_ENABLE,
|
|
|
|
FLY_MODAL_PAN_DISABLE,
|
|
|
|
FLY_MODAL_DIR_FORWARD,
|
|
|
|
FLY_MODAL_DIR_BACKWARD,
|
|
|
|
FLY_MODAL_DIR_LEFT,
|
|
|
|
FLY_MODAL_DIR_RIGHT,
|
|
|
|
FLY_MODAL_DIR_UP,
|
|
|
|
FLY_MODAL_DIR_DOWN,
|
|
|
|
FLY_MODAL_AXIS_LOCK_X,
|
|
|
|
FLY_MODAL_AXIS_LOCK_Z,
|
|
|
|
FLY_MODAL_PRECISION_ENABLE,
|
|
|
|
FLY_MODAL_PRECISION_DISABLE,
|
|
|
|
FLY_MODAL_FREELOOK_ENABLE,
|
2013-01-08 16:54:26 +00:00
|
|
|
FLY_MODAL_FREELOOK_DISABLE,
|
|
|
|
FLY_MODAL_SPEED, /* mousepan typically */
|
2011-09-25 04:47:46 +00:00
|
|
|
};
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-03-21 02:56:16 +00:00
|
|
|
/* relative view axis locking - xlock, zlock */
|
|
|
|
typedef enum eFlyPanState {
|
|
|
|
/* disabled */
|
|
|
|
FLY_AXISLOCK_STATE_OFF = 0,
|
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* enabled but not checking because mouse hasn't moved outside the margin since locking was
|
|
|
|
* checked an not needed when the mouse moves, locking is set to 2 so checks are done. */
|
2013-03-21 02:56:16 +00:00
|
|
|
FLY_AXISLOCK_STATE_IDLE = 1,
|
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* mouse moved and checking needed,
|
|
|
|
* if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */
|
2019-01-15 23:57:49 +11:00
|
|
|
FLY_AXISLOCK_STATE_ACTIVE = 2,
|
2013-03-21 02:56:16 +00:00
|
|
|
} eFlyPanState;
|
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* called in transform_ops.c, on each regeneration of keymaps */
|
|
|
|
void fly_modal_keymap(wmKeyConfig *keyconf)
|
|
|
|
{
|
2017-10-18 15:07:26 +11:00
|
|
|
static const EnumPropertyItem modal_items[] = {
|
2012-03-10 06:46:23 +00:00
|
|
|
{FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
|
2018-07-10 07:41:49 +02:00
|
|
|
{FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""},
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2018-07-10 07:41:49 +02:00
|
|
|
{FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""},
|
|
|
|
{FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""},
|
|
|
|
{FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""},
|
|
|
|
{FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""},
|
|
|
|
{FLY_MODAL_DIR_UP, "UP", 0, "Up", ""},
|
|
|
|
{FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""},
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2018-07-10 07:41:49 +02:00
|
|
|
{FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""},
|
|
|
|
{FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""},
|
|
|
|
|
|
|
|
{FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""},
|
|
|
|
{FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""},
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
{FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"},
|
|
|
|
{FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"},
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2018-07-10 07:41:49 +02:00
|
|
|
{FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""},
|
|
|
|
{FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""},
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2018-07-10 07:41:49 +02:00
|
|
|
{FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""},
|
|
|
|
{FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""},
|
2011-09-25 04:47:46 +00:00
|
|
|
|
2019-02-03 14:01:45 +11:00
|
|
|
{0, NULL, 0, NULL, NULL},
|
|
|
|
};
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2020-03-27 10:58:00 +11:00
|
|
|
wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal");
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* this function is called for each spacetype, only needs to add map once */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (keymap && keymap->modal_items) {
|
2012-03-10 06:46:23 +00:00
|
|
|
return;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2020-03-27 10:58:00 +11:00
|
|
|
keymap = WM_modalkeymap_ensure(keyconf, "View3D Fly Modal", modal_items);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* assign map to operators */
|
|
|
|
WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
|
|
|
|
}
|
|
|
|
|
2020-06-18 12:40:38 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Internal Fly Structs
|
|
|
|
* \{ */
|
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
typedef struct FlyInfo {
|
|
|
|
/* context stuff */
|
|
|
|
RegionView3D *rv3d;
|
|
|
|
View3D *v3d;
|
2020-03-06 16:56:42 +01:00
|
|
|
ARegion *region;
|
2018-04-06 12:07:27 +02:00
|
|
|
struct Depsgraph *depsgraph;
|
2010-10-25 07:09:38 +00:00
|
|
|
Scene *scene;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-11-25 00:55:11 +11:00
|
|
|
/** Needed for updating that isn't triggered by input. */
|
2019-08-11 22:41:04 +10:00
|
|
|
wmTimer *timer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
short state;
|
2013-03-20 23:14:18 +00:00
|
|
|
bool redraw;
|
|
|
|
bool use_precision;
|
2019-08-11 22:41:04 +10:00
|
|
|
/** If the user presses shift they can look about without moving the direction there looking. */
|
2013-03-20 23:14:18 +00:00
|
|
|
bool use_freelook;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-08-11 22:34:22 +10:00
|
|
|
/**
|
|
|
|
* Needed for auto-keyframing, when animation isn't playing, only keyframe on confirmation.
|
|
|
|
*
|
|
|
|
* Currently we can't cancel this operator usefully while recording on animation playback
|
|
|
|
* (this would need to un-key all previous frames).
|
|
|
|
*/
|
|
|
|
bool anim_playing;
|
2019-08-08 09:41:19 +02:00
|
|
|
|
2019-08-11 22:41:04 +10:00
|
|
|
/** Latest 2D mouse values. */
|
|
|
|
int mval[2];
|
|
|
|
/** Center mouse values. */
|
|
|
|
int center_mval[2];
|
|
|
|
/** Camera viewport dimensions. */
|
|
|
|
float width, height;
|
2016-08-18 00:21:55 -04:00
|
|
|
|
|
|
|
#ifdef WITH_INPUT_NDOF
|
2019-08-11 22:41:04 +10:00
|
|
|
/** Latest 3D mouse values. */
|
|
|
|
wmNDOFMotionData *ndof;
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* fly state state */
|
2019-08-11 22:41:04 +10:00
|
|
|
/** The speed the view is moving per redraw. */
|
|
|
|
float speed;
|
|
|
|
/** Axis index to move along by default Z to move along the view. */
|
|
|
|
short axis;
|
|
|
|
/** When true, pan the view instead of rotating. */
|
|
|
|
bool pan_view;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-03-21 02:56:16 +00:00
|
|
|
eFlyPanState xlock, zlock;
|
2019-08-11 22:41:04 +10:00
|
|
|
/** Nicer dynamics. */
|
|
|
|
float xlock_momentum, zlock_momentum;
|
|
|
|
/** World scale 1.0 default. */
|
|
|
|
float grid;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* compare between last state */
|
2020-07-10 11:41:14 +10:00
|
|
|
/** Used to accelerate when using the mouse-wheel a lot. */
|
2019-08-11 22:41:04 +10:00
|
|
|
double time_lastwheel;
|
|
|
|
/** Time between draws. */
|
|
|
|
double time_lastdraw;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
void *draw_handle_pixel;
|
|
|
|
|
|
|
|
/* use for some lag */
|
2019-08-11 22:41:04 +10:00
|
|
|
/** Keep the previous value to smooth transitions (use lag). */
|
|
|
|
float dvec_prev[3];
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-11-28 15:01:53 +11:00
|
|
|
struct View3DCameraControl *v3d_camera_control;
|
2013-06-06 19:04:56 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
} FlyInfo;
|
|
|
|
|
2020-06-18 12:40:38 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Internal Fly Drawing
|
|
|
|
* \{ */
|
|
|
|
|
2019-08-08 09:41:19 +02:00
|
|
|
/* prototypes */
|
2019-08-08 10:38:01 +02:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
2019-08-08 10:44:32 +02:00
|
|
|
static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm);
|
2019-08-08 10:38:01 +02:00
|
|
|
#endif /* WITH_INPUT_NDOF */
|
2020-09-04 20:59:13 +02:00
|
|
|
static int flyApply(bContext *C, struct FlyInfo *fly, bool is_confirm);
|
2019-08-08 09:41:19 +02:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
|
|
|
FlyInfo *fly = arg;
|
2013-12-10 12:14:31 -02:00
|
|
|
rctf viewborder;
|
|
|
|
int xoff, yoff;
|
|
|
|
float x1, x2, y1, y2;
|
|
|
|
|
2018-12-05 08:36:37 +11:00
|
|
|
if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) {
|
2018-01-18 15:58:02 +01:00
|
|
|
ED_view3d_calc_camera_border(
|
2020-03-06 16:56:42 +01:00
|
|
|
fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
|
2013-12-10 12:14:31 -02:00
|
|
|
xoff = viewborder.xmin;
|
|
|
|
yoff = viewborder.ymin;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
xoff = 0;
|
|
|
|
yoff = 0;
|
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* draws 4 edge brackets that frame the safe area where the
|
2012-03-03 16:31:46 +00:00
|
|
|
* mouse can move during fly mode without spinning the view */
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
x1 = xoff + 0.45f * fly->width;
|
|
|
|
y1 = yoff + 0.45f * fly->height;
|
|
|
|
x2 = xoff + 0.55f * fly->width;
|
|
|
|
y2 = yoff + 0.55f * fly->height;
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
GPUVertFormat *format = immVertexFormat();
|
|
|
|
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
2016-09-20 14:44:52 +00:00
|
|
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
|
|
|
|
2020-02-17 22:39:33 +01:00
|
|
|
immUniformThemeColor3(TH_VIEW_OVERLAY);
|
2016-09-20 14:44:52 +00:00
|
|
|
|
2018-07-18 00:12:21 +02:00
|
|
|
immBegin(GPU_PRIM_LINES, 16);
|
2016-09-20 14:44:52 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* bottom left */
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x1, y1);
|
|
|
|
immVertex2f(pos, x1, y1 + 5);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x1, y1);
|
|
|
|
immVertex2f(pos, x1 + 5, y1);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* top right */
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x2, y2);
|
|
|
|
immVertex2f(pos, x2, y2 - 5);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x2, y2);
|
|
|
|
immVertex2f(pos, x2 - 5, y2);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* top left */
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x1, y2);
|
|
|
|
immVertex2f(pos, x1, y2 - 5);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x1, y2);
|
|
|
|
immVertex2f(pos, x1 + 5, y2);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* bottom right */
|
2016-09-20 14:44:52 +00:00
|
|
|
immVertex2f(pos, x2, y1);
|
|
|
|
immVertex2f(pos, x2, y1 + 5);
|
|
|
|
|
|
|
|
immVertex2f(pos, x2, y1);
|
|
|
|
immVertex2f(pos, x2 - 5, y1);
|
2012-03-10 06:46:23 +00:00
|
|
|
|
2016-09-20 14:44:52 +00:00
|
|
|
immEnd();
|
|
|
|
immUnbindProgram();
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
|
2020-06-18 12:40:38 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Internal Fly Logic
|
|
|
|
* \{ */
|
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* FlyInfo->state */
|
2013-12-03 13:37:04 +11:00
|
|
|
enum {
|
|
|
|
FLY_RUNNING = 0,
|
|
|
|
FLY_CANCEL = 1,
|
|
|
|
FLY_CONFIRM = 2,
|
|
|
|
};
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-03-20 23:14:18 +00:00
|
|
|
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
2019-08-08 09:41:19 +02:00
|
|
|
wmWindowManager *wm = CTX_wm_manager(C);
|
2012-03-10 06:46:23 +00:00
|
|
|
wmWindow *win = CTX_wm_window(C);
|
2013-12-10 12:14:31 -02:00
|
|
|
rctf viewborder;
|
|
|
|
|
2012-04-02 06:26:52 +00:00
|
|
|
float upvec[3]; /* tmp */
|
2010-10-25 07:09:38 +00:00
|
|
|
float mat[3][3];
|
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->rv3d = CTX_wm_region_view3d(C);
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->v3d = CTX_wm_view3d(C);
|
2020-03-06 16:56:42 +01:00
|
|
|
fly->region = CTX_wm_region(C);
|
2019-07-25 16:36:22 +02:00
|
|
|
fly->depsgraph = CTX_data_expect_evaluated_depsgraph(C);
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->scene = CTX_data_scene(C);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
#ifdef NDOF_FLY_DEBUG
|
2011-07-14 21:20:45 +00:00
|
|
|
puts("\n-- fly begin --");
|
2011-08-02 08:12:50 +00:00
|
|
|
#endif
|
2011-07-14 21:20:45 +00:00
|
|
|
|
2012-10-10 08:46:52 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-11-06 17:17:10 +01:00
|
|
|
if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) {
|
2010-10-25 07:09:38 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library");
|
2013-03-20 23:14:18 +00:00
|
|
|
return false;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-05-03 07:29:25 +00:00
|
|
|
if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) {
|
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked");
|
2013-03-20 23:14:18 +00:00
|
|
|
return false;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) {
|
2010-10-25 07:09:38 +00:00
|
|
|
BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints");
|
2013-03-20 23:14:18 +00:00
|
|
|
return false;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->state = FLY_RUNNING;
|
|
|
|
fly->speed = 0.0f;
|
|
|
|
fly->axis = 2;
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->pan_view = false;
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_OFF;
|
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_OFF;
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->xlock_momentum = 0.0f;
|
|
|
|
fly->zlock_momentum = 0.0f;
|
|
|
|
fly->grid = 1.0f;
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->use_precision = false;
|
|
|
|
fly->use_freelook = false;
|
2019-08-08 09:41:19 +02:00
|
|
|
fly->anim_playing = ED_screen_animation_playing(wm);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2011-08-02 07:49:34 +00:00
|
|
|
#ifdef NDOF_FLY_DRAW_TOOMUCH
|
2012-03-25 23:54:33 +00:00
|
|
|
fly->redraw = 1;
|
2011-08-02 07:49:34 +00:00
|
|
|
#endif
|
2012-03-23 20:18:09 +00:00
|
|
|
zero_v3(fly->dvec_prev);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2011-11-07 01:38:32 +00:00
|
|
|
copy_v2_v2_int(fly->mval, event->mval);
|
2016-08-18 00:21:55 -04:00
|
|
|
|
|
|
|
#ifdef WITH_INPUT_NDOF
|
2011-07-14 21:20:45 +00:00
|
|
|
fly->ndof = NULL;
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->draw_handle_pixel = ED_region_draw_cb_activate(
|
2020-03-06 16:56:42 +01:00
|
|
|
fly->region->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-03 13:37:04 +11:00
|
|
|
fly->rv3d->rflag |= RV3D_NAVIGATING;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-06-25 22:58:23 +00:00
|
|
|
/* detect whether to start with Z locking */
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
copy_m3_m4(mat, fly->rv3d->viewinv);
|
|
|
|
mul_m3_v3(mat, upvec);
|
2012-07-21 15:27:40 +00:00
|
|
|
if (fabsf(upvec[2]) < 0.1f) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_IDLE;
|
2012-07-21 15:27:40 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-25 16:36:22 +02:00
|
|
|
fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
|
2020-11-05 16:08:00 -06:00
|
|
|
fly->depsgraph, fly->scene, fly->v3d, fly->rv3d);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
/* calculate center */
|
2018-12-05 08:36:37 +11:00
|
|
|
if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) {
|
2018-01-18 15:58:02 +01:00
|
|
|
ED_view3d_calc_camera_border(
|
2020-03-06 16:56:42 +01:00
|
|
|
fly->scene, fly->depsgraph, fly->region, fly->v3d, fly->rv3d, &viewborder, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
fly->width = BLI_rctf_size_x(&viewborder);
|
|
|
|
fly->height = BLI_rctf_size_y(&viewborder);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
fly->center_mval[0] = viewborder.xmin + fly->width / 2;
|
|
|
|
fly->center_mval[1] = viewborder.ymin + fly->height / 2;
|
|
|
|
}
|
|
|
|
else {
|
2020-03-06 16:56:42 +01:00
|
|
|
fly->width = fly->region->winx;
|
|
|
|
fly->height = fly->region->winy;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
fly->center_mval[0] = fly->width / 2;
|
|
|
|
fly->center_mval[1] = fly->height / 2;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* center the mouse, probably the UI mafia are against this but without its quite annoying */
|
2020-03-06 16:56:42 +01:00
|
|
|
WM_cursor_warp(win,
|
|
|
|
fly->region->winrct.xmin + fly->center_mval[0],
|
|
|
|
fly->region->winrct.ymin + fly->center_mval[1]);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int flyEnd(bContext *C, FlyInfo *fly)
|
|
|
|
{
|
2013-12-03 13:37:04 +11:00
|
|
|
wmWindow *win;
|
|
|
|
RegionView3D *rv3d;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->state == FLY_RUNNING) {
|
2010-10-25 07:09:38 +00:00
|
|
|
return OPERATOR_RUNNING_MODAL;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2020-07-03 17:18:56 +02:00
|
|
|
if (fly->state == FLY_CONFIRM) {
|
2019-08-08 09:41:19 +02:00
|
|
|
/* Needed for auto_keyframe. */
|
|
|
|
#ifdef WITH_INPUT_NDOF
|
|
|
|
if (fly->ndof) {
|
|
|
|
flyApply_ndof(C, fly, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif /* WITH_INPUT_NDOF */
|
|
|
|
{
|
|
|
|
flyApply(C, fly, true);
|
|
|
|
}
|
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
#ifdef NDOF_FLY_DEBUG
|
2011-07-14 21:20:45 +00:00
|
|
|
puts("\n-- fly end --");
|
2011-08-02 08:12:50 +00:00
|
|
|
#endif
|
2011-07-14 21:20:45 +00:00
|
|
|
|
2013-12-03 13:37:04 +11:00
|
|
|
win = CTX_wm_window(C);
|
|
|
|
rv3d = fly->rv3d;
|
|
|
|
|
|
|
|
WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2020-03-06 16:56:42 +01:00
|
|
|
ED_region_draw_cb_exit(fly->region->type, fly->draw_handle_pixel);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-11-28 15:01:53 +11:00
|
|
|
ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL);
|
2011-09-26 08:33:51 +00:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
rv3d->rflag &= ~RV3D_NAVIGATING;
|
|
|
|
|
2016-08-18 00:21:55 -04:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->ndof) {
|
2011-07-14 21:20:45 +00:00
|
|
|
MEM_freeN(fly->ndof);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif
|
2011-07-14 21:20:45 +00:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->state == FLY_CONFIRM) {
|
2010-10-25 07:09:38 +00:00
|
|
|
MEM_freeN(fly);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(fly);
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2019-06-07 13:01:37 +10:00
|
|
|
static void flyEvent(FlyInfo *fly, const wmEvent *event)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
2011-08-02 07:49:34 +00:00
|
|
|
if (event->type == TIMER && event->customdata == fly->timer) {
|
|
|
|
fly->redraw = 1;
|
|
|
|
}
|
|
|
|
else if (event->type == MOUSEMOVE) {
|
2011-11-07 01:38:32 +00:00
|
|
|
copy_v2_v2_int(fly->mval, event->mval);
|
2011-07-14 21:20:45 +00:00
|
|
|
}
|
2016-08-18 00:21:55 -04:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
2011-07-14 21:20:45 +00:00
|
|
|
else if (event->type == NDOF_MOTION) {
|
2012-04-02 06:26:52 +00:00
|
|
|
/* do these automagically get delivered? yes. */
|
2011-07-14 21:20:45 +00:00
|
|
|
// puts("ndof motion detected in fly mode!");
|
2012-08-26 11:35:43 +00:00
|
|
|
// static const char *tag_name = "3D mouse position";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-22 16:19:02 +11:00
|
|
|
const wmNDOFMotionData *incoming_ndof = event->customdata;
|
2011-08-02 08:12:50 +00:00
|
|
|
switch (incoming_ndof->progress) {
|
2011-07-14 21:20:45 +00:00
|
|
|
case P_STARTING:
|
2012-04-02 06:26:52 +00:00
|
|
|
/* start keeping track of 3D mouse position */
|
2016-08-18 00:21:55 -04:00
|
|
|
# ifdef NDOF_FLY_DEBUG
|
2011-07-14 21:20:45 +00:00
|
|
|
puts("start keeping track of 3D mouse position");
|
2016-08-18 00:21:55 -04:00
|
|
|
# endif
|
2013-07-21 08:16:37 +00:00
|
|
|
/* fall-through */
|
2011-07-14 21:20:45 +00:00
|
|
|
case P_IN_PROGRESS:
|
2012-04-02 06:26:52 +00:00
|
|
|
/* update 3D mouse position */
|
2016-08-18 00:21:55 -04:00
|
|
|
# ifdef NDOF_FLY_DEBUG
|
2011-07-14 21:20:45 +00:00
|
|
|
putchar('.');
|
|
|
|
fflush(stdout);
|
2016-08-18 00:21:55 -04:00
|
|
|
# endif
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->ndof == NULL) {
|
2011-07-14 21:20:45 +00:00
|
|
|
// fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
|
|
|
|
fly->ndof = MEM_dupallocN(incoming_ndof);
|
|
|
|
// fly->ndof = malloc(sizeof(wmNDOFMotionData));
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2011-07-14 21:20:45 +00:00
|
|
|
memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2011-07-14 21:20:45 +00:00
|
|
|
break;
|
|
|
|
case P_FINISHING:
|
2012-07-08 20:36:00 +00:00
|
|
|
/* stop keeping track of 3D mouse position */
|
2016-08-18 00:21:55 -04:00
|
|
|
# ifdef NDOF_FLY_DEBUG
|
2011-07-14 21:20:45 +00:00
|
|
|
puts("stop keeping track of 3D mouse position");
|
2016-08-18 00:21:55 -04:00
|
|
|
# endif
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->ndof) {
|
2011-07-14 21:20:45 +00:00
|
|
|
MEM_freeN(fly->ndof);
|
|
|
|
// free(fly->ndof);
|
|
|
|
fly->ndof = NULL;
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2011-07-19 22:40:22 +00:00
|
|
|
/* update the time else the view will jump when 2D mouse/timer resume */
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->time_lastdraw = PIL_check_seconds_timer();
|
2011-07-14 21:20:45 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-03-10 22:00:55 +00:00
|
|
|
break; /* should always be one of the above 3 */
|
2011-07-14 21:20:45 +00:00
|
|
|
}
|
2012-03-10 06:46:23 +00:00
|
|
|
}
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif /* WITH_INPUT_NDOF */
|
2011-07-14 21:20:45 +00:00
|
|
|
/* handle modal keymap first */
|
2010-10-25 07:09:38 +00:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-08 16:54:26 +00:00
|
|
|
/* speed adjusting with mousepan (trackpad) */
|
|
|
|
case FLY_MODAL_SPEED: {
|
|
|
|
float fac = 0.02f * (event->prevy - event->y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-08 16:54:26 +00:00
|
|
|
/* allowing to brake immediate */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fac > 0.0f && fly->speed < 0.0f) {
|
2013-01-08 16:54:26 +00:00
|
|
|
fly->speed = 0.0f;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
else if (fac < 0.0f && fly->speed > 0.0f) {
|
2013-01-08 16:54:26 +00:00
|
|
|
fly->speed = 0.0f;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
else {
|
2013-01-08 16:54:26 +00:00
|
|
|
fly->speed += fly->grid * fac;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-01-08 16:54:26 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
case FLY_MODAL_ACCELERATE: {
|
|
|
|
double time_currwheel;
|
|
|
|
float time_wheel;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-04 01:49:20 +00:00
|
|
|
/* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
|
|
|
|
if (fly->axis == -1) {
|
|
|
|
fly->axis = 2;
|
|
|
|
fly->speed = fabsf(fly->speed);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
time_currwheel = PIL_check_seconds_timer();
|
2010-10-25 07:09:38 +00:00
|
|
|
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
|
|
|
|
fly->time_lastwheel = time_currwheel;
|
2012-05-25 09:51:53 +00:00
|
|
|
/* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */
|
2019-01-15 23:24:20 +11:00
|
|
|
/* 0-0.5 -> 0-5.0 */
|
|
|
|
time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->speed < 0.0f) {
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->speed = 0.0f;
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
else {
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FLY_MODAL_DECELERATE: {
|
|
|
|
double time_currwheel;
|
|
|
|
float time_wheel;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-09-04 01:49:20 +00:00
|
|
|
/* not quite correct but avoids confusion WASD/arrow keys 'locking up' */
|
|
|
|
if (fly->axis == -1) {
|
|
|
|
fly->axis = 2;
|
|
|
|
fly->speed = -fabsf(fly->speed);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
time_currwheel = PIL_check_seconds_timer();
|
2010-10-25 07:09:38 +00:00
|
|
|
time_wheel = (float)(time_currwheel - fly->time_lastwheel);
|
|
|
|
fly->time_lastwheel = time_currwheel;
|
2019-01-15 23:24:20 +11:00
|
|
|
/* 0-0.5 -> 0-5.0 */
|
|
|
|
time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f)));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->speed > 0.0f) {
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->speed = 0;
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
else {
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FLY_MODAL_PAN_ENABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->pan_view = true;
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_PAN_DISABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->pan_view = false;
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
/* implement WASD keys,
|
|
|
|
* comments only for 'forward '*/
|
2010-10-25 07:09:38 +00:00
|
|
|
case FLY_MODAL_DIR_FORWARD:
|
2019-01-15 23:24:20 +11:00
|
|
|
if (fly->axis == 2 && fly->speed < 0.0f) {
|
|
|
|
/* reverse direction stops, tap again to continue */
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2020-07-10 11:41:14 +10:00
|
|
|
/* Flip speed rather than stopping, game like motion,
|
|
|
|
* else increase like mouse-wheel if we're already moving in that direction. */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed < 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 2) {
|
|
|
|
fly->speed += fly->grid;
|
|
|
|
}
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 2;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_DIR_BACKWARD:
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->axis == 2 && fly->speed > 0.0f) {
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed > 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 2) {
|
|
|
|
fly->speed -= fly->grid;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 2;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_DIR_LEFT:
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->axis == 0 && fly->speed < 0.0f) {
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed < 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 0) {
|
|
|
|
fly->speed += fly->grid;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 0;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_DIR_RIGHT:
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->axis == 0 && fly->speed > 0.0f) {
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed > 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 0) {
|
|
|
|
fly->speed -= fly->grid;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 0;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_DIR_DOWN:
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->axis == 1 && fly->speed < 0.0f) {
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed < 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 1) {
|
|
|
|
fly->speed += fly->grid;
|
|
|
|
}
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 1;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_DIR_UP:
|
2012-03-10 06:46:23 +00:00
|
|
|
if (fly->axis == 1 && fly->speed > 0.0f) {
|
2012-03-10 04:19:25 +00:00
|
|
|
fly->axis = -1;
|
|
|
|
}
|
|
|
|
else {
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->speed > 0.0f) {
|
|
|
|
fly->speed = -fly->speed;
|
|
|
|
}
|
|
|
|
else if (fly->axis == 1) {
|
|
|
|
fly->speed -= fly->grid;
|
|
|
|
}
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->axis = 1;
|
2012-03-10 04:19:25 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
case FLY_MODAL_AXIS_LOCK_X:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_OFF;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
else {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_ACTIVE;
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->xlock_momentum = 0.0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FLY_MODAL_AXIS_LOCK_Z:
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_OFF;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
else {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->zlock_momentum = 0.0;
|
|
|
|
}
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
case FLY_MODAL_PRECISION_ENABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->use_precision = true;
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_PRECISION_DISABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->use_precision = false;
|
2010-10-25 07:09:38 +00:00
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-25 04:47:46 +00:00
|
|
|
case FLY_MODAL_FREELOOK_ENABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->use_freelook = true;
|
2011-09-25 04:47:46 +00:00
|
|
|
break;
|
|
|
|
case FLY_MODAL_FREELOOK_DISABLE:
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->use_freelook = false;
|
2011-09-25 04:47:46 +00:00
|
|
|
break;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-08 09:41:19 +02:00
|
|
|
static void flyMoveCamera(bContext *C,
|
|
|
|
FlyInfo *fly,
|
|
|
|
const bool do_rotate,
|
|
|
|
const bool do_translate,
|
|
|
|
const bool is_confirm)
|
2011-07-31 03:06:00 +00:00
|
|
|
{
|
2019-08-08 09:41:19 +02:00
|
|
|
/* we only consider autokeying on playback or if user confirmed fly on the same frame
|
|
|
|
* otherwise we get a keyframe even if the user cancels. */
|
|
|
|
const bool use_autokey = is_confirm || fly->anim_playing;
|
|
|
|
ED_view3d_cameracontrol_update(fly->v3d_camera_control, use_autokey, C, do_rotate, do_translate);
|
2011-07-31 03:06:00 +00:00
|
|
|
}
|
|
|
|
|
2019-08-08 09:41:19 +02:00
|
|
|
static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
2013-09-04 01:49:20 +00:00
|
|
|
#define FLY_ROTATE_FAC 10.0f /* more is faster */
|
2011-04-29 04:43:36 +00:00
|
|
|
#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */
|
2010-10-25 07:09:38 +00:00
|
|
|
#define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */
|
2013-09-04 01:49:20 +00:00
|
|
|
#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-03 16:31:46 +00:00
|
|
|
/* fly mode - Shift+F
|
|
|
|
* a fly loop where the user can move move the view as if they are flying
|
|
|
|
*/
|
2012-03-10 06:46:23 +00:00
|
|
|
RegionView3D *rv3d = fly->rv3d;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* 3x3 copy of the view matrix so we can move along the view axis */
|
|
|
|
float mat[3][3];
|
|
|
|
/* this is the direction that's added to the view offset per redraw */
|
|
|
|
float dvec[3] = {0, 0, 0};
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
/* Camera Uprighting variables */
|
2012-03-25 23:54:33 +00:00
|
|
|
float moffset[2]; /* mouse offset from the views center */
|
|
|
|
float tmp_quat[4]; /* used for rotating the view */
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* x and y margin are define the safe area where the mouses movement wont rotate the view */
|
|
|
|
int xmargin, ymargin;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
#ifdef NDOF_FLY_DEBUG
|
2012-01-19 16:04:44 +00:00
|
|
|
{
|
2019-03-01 23:43:34 +11:00
|
|
|
static uint iteration = 1;
|
2012-01-19 16:04:44 +00:00
|
|
|
printf("fly timer %d\n", iteration++);
|
|
|
|
}
|
2011-08-02 08:12:50 +00:00
|
|
|
#endif
|
2011-07-14 21:20:45 +00:00
|
|
|
|
2013-12-10 12:14:31 -02:00
|
|
|
xmargin = fly->width / 20.0f;
|
|
|
|
ymargin = fly->height / 20.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* mouse offset from the center */
|
2013-12-10 12:14:31 -02:00
|
|
|
moffset[0] = fly->mval[0] - fly->center_mval[0];
|
|
|
|
moffset[1] = fly->mval[1] - fly->center_mval[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* enforce a view margin */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (moffset[0] > xmargin) {
|
|
|
|
moffset[0] -= xmargin;
|
|
|
|
}
|
|
|
|
else if (moffset[0] < -xmargin) {
|
|
|
|
moffset[0] += xmargin;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
moffset[0] = 0;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (moffset[1] > ymargin) {
|
|
|
|
moffset[1] -= ymargin;
|
|
|
|
}
|
|
|
|
else if (moffset[1] < -ymargin) {
|
|
|
|
moffset[1] += ymargin;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
moffset[1] = 0;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* scale the mouse movement by this value - scales mouse movement to the view size
|
2020-03-06 16:56:42 +01:00
|
|
|
* moffset[0] / (region->winx-xmargin * 2) - window size minus margin (same for y)
|
2010-10-25 07:09:38 +00:00
|
|
|
*
|
2012-03-18 07:38:51 +00:00
|
|
|
* the mouse moves isn't linear */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (moffset[0]) {
|
2013-12-10 12:14:31 -02:00
|
|
|
moffset[0] /= fly->width - (xmargin * 2);
|
2011-03-27 15:57:27 +00:00
|
|
|
moffset[0] *= fabsf(moffset[0]);
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (moffset[1]) {
|
2013-12-10 12:14:31 -02:00
|
|
|
moffset[1] /= fly->height - (ymargin * 2);
|
2011-03-27 15:57:27 +00:00
|
|
|
moffset[1] *= fabsf(moffset[1]);
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* Should we redraw? */
|
2012-03-10 06:46:23 +00:00
|
|
|
if ((fly->speed != 0.0f) || moffset[0] || moffset[1] ||
|
2013-03-21 02:56:16 +00:00
|
|
|
(fly->zlock != FLY_AXISLOCK_STATE_OFF) || (fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
|
2012-03-10 06:46:23 +00:00
|
|
|
dvec[0] || dvec[1] || dvec[2]) {
|
2010-10-25 07:09:38 +00:00
|
|
|
float dvec_tmp[3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
/* time how fast it takes for us to redraw,
|
2012-03-18 07:38:51 +00:00
|
|
|
* this is so simple scenes don't fly too fast */
|
2012-03-10 06:46:23 +00:00
|
|
|
double time_current;
|
2011-03-27 15:57:27 +00:00
|
|
|
float time_redraw;
|
2010-10-25 07:09:38 +00:00
|
|
|
float time_redraw_clamped;
|
2011-08-02 07:49:34 +00:00
|
|
|
#ifdef NDOF_FLY_DRAW_TOOMUCH
|
2012-03-25 23:54:33 +00:00
|
|
|
fly->redraw = 1;
|
2011-08-02 07:49:34 +00:00
|
|
|
#endif
|
2012-03-10 06:46:23 +00:00
|
|
|
time_current = PIL_check_seconds_timer();
|
|
|
|
time_redraw = (float)(time_current - fly->time_lastdraw);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* clamp redraw time to avoid jitter in roll correction */
|
|
|
|
time_redraw_clamped = min_ff(0.05f, time_redraw);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->time_lastdraw = time_current;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* Scale the time to use shift to scale the speed down- just like
|
2012-03-03 16:31:46 +00:00
|
|
|
* shift slows many other areas of blender down */
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->use_precision) {
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->speed = fly->speed * (1.0f - time_redraw_clamped);
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
copy_m3_m4(mat, rv3d->viewinv);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-20 23:14:18 +00:00
|
|
|
if (fly->pan_view == true) {
|
2010-10-25 07:09:38 +00:00
|
|
|
/* pan only */
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
if (fly->use_precision) {
|
2011-03-27 15:57:27 +00:00
|
|
|
dvec_tmp[0] *= 0.1f;
|
|
|
|
dvec_tmp[1] *= 0.1f;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, dvec_tmp);
|
2011-03-27 15:57:27 +00:00
|
|
|
mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid);
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-01-19 16:04:44 +00:00
|
|
|
float roll; /* similar to the angle between the camera's up and the Z-up,
|
2012-03-25 23:54:33 +00:00
|
|
|
* but its very rough so just roll */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* rotate about the X axis- look up/down */
|
|
|
|
if (moffset[1]) {
|
2015-10-23 03:08:17 +11:00
|
|
|
float upvec[3];
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2012-01-19 16:04:44 +00:00
|
|
|
/* Rotate about the relative up vec */
|
2015-04-04 14:45:54 +11:00
|
|
|
axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->xlock_momentum = 0.0f;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* rotate about the Y axis- look left/right */
|
|
|
|
if (moffset[0]) {
|
2015-10-23 03:08:17 +11:00
|
|
|
float upvec[3];
|
2010-10-25 07:09:38 +00:00
|
|
|
/* if we're upside down invert the moffset */
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (upvec[2] < 0.0f) {
|
2012-03-10 06:46:23 +00:00
|
|
|
moffset[0] = -moffset[0];
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* make the lock vectors */
|
|
|
|
if (fly->zlock) {
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-01-19 16:04:44 +00:00
|
|
|
/* Rotate about the relative up vec */
|
2015-04-04 14:45:54 +11:00
|
|
|
axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (fly->xlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
|
|
|
if (fly->zlock != FLY_AXISLOCK_STATE_OFF) {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_ACTIVE;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-21 02:56:16 +00:00
|
|
|
if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) {
|
2015-10-23 03:08:17 +11:00
|
|
|
float upvec[3];
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-02 06:26:52 +00:00
|
|
|
/* make sure we have some z rolling */
|
2011-03-27 15:57:27 +00:00
|
|
|
if (fabsf(upvec[2]) > 0.00001f) {
|
2012-03-10 06:46:23 +00:00
|
|
|
roll = upvec[2] * 5.0f;
|
2013-12-03 13:37:04 +11:00
|
|
|
/* rotate the view about this axis */
|
|
|
|
copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2012-01-19 16:04:44 +00:00
|
|
|
/* Rotate about the relative up vec */
|
|
|
|
axis_angle_to_quat(tmp_quat,
|
|
|
|
upvec,
|
2012-03-25 23:54:33 +00:00
|
|
|
roll * time_redraw_clamped * fly->zlock_momentum *
|
|
|
|
FLY_ZUP_CORRECT_FAC);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL;
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* don't check until the view rotates again */
|
|
|
|
fly->zlock = FLY_AXISLOCK_STATE_IDLE;
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->zlock_momentum = 0.0f;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-21 02:56:16 +00:00
|
|
|
/* only apply xcorrect when mouse isn't applying x rot */
|
|
|
|
if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) {
|
2015-10-23 03:08:17 +11:00
|
|
|
float upvec[3];
|
2013-12-03 13:37:04 +11:00
|
|
|
copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2012-04-02 06:26:52 +00:00
|
|
|
/* make sure we have some z rolling */
|
2011-08-19 16:21:29 +00:00
|
|
|
if (fabsf(upvec[2]) > 0.00001f) {
|
2012-03-10 06:46:23 +00:00
|
|
|
roll = upvec[2] * -5.0f;
|
2013-12-03 13:37:04 +11:00
|
|
|
/* rotate the view about this axis */
|
|
|
|
copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, upvec);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-01-19 16:04:44 +00:00
|
|
|
/* Rotate about the relative up vec */
|
2012-03-10 06:46:23 +00:00
|
|
|
axis_angle_to_quat(
|
|
|
|
tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f);
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
fly->xlock_momentum += 0.05f;
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-03-21 02:56:16 +00:00
|
|
|
fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->xlock_momentum = 0.0f;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2012-03-10 04:19:25 +00:00
|
|
|
if (fly->axis == -1) {
|
|
|
|
/* pause */
|
|
|
|
zero_v3(dvec_tmp);
|
|
|
|
}
|
2012-04-02 05:34:58 +00:00
|
|
|
else if (!fly->use_freelook) {
|
2010-10-25 07:09:38 +00:00
|
|
|
/* Normal operation */
|
|
|
|
/* define dvec, view direction vector */
|
2012-04-02 05:34:58 +00:00
|
|
|
zero_v3(dvec_tmp);
|
2010-10-25 07:09:38 +00:00
|
|
|
/* move along the current axis */
|
2012-03-10 06:46:23 +00:00
|
|
|
dvec_tmp[fly->axis] = 1.0f;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
mul_m3_v3(mat, dvec_tmp);
|
|
|
|
}
|
2011-09-25 04:47:46 +00:00
|
|
|
else {
|
|
|
|
normalize_v3_v3(dvec_tmp, fly->dvec_prev);
|
2012-02-22 16:52:06 +00:00
|
|
|
if (fly->speed < 0.0f) {
|
2011-09-25 04:47:46 +00:00
|
|
|
negate_v3(dvec_tmp);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2011-09-25 04:47:46 +00:00
|
|
|
mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f);
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* impose a directional lag */
|
2013-09-04 01:49:20 +00:00
|
|
|
interp_v3_v3v3(
|
|
|
|
dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC))));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
add_v3_v3(rv3d->ofs, dvec);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-21 02:56:16 +00:00
|
|
|
if (rv3d->persp == RV3D_CAMOB) {
|
|
|
|
const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) ||
|
|
|
|
(fly->zlock != FLY_AXISLOCK_STATE_OFF) ||
|
|
|
|
((moffset[0] || moffset[1]) && !fly->pan_view));
|
|
|
|
const bool do_translate = (fly->speed != 0.0f || fly->pan_view);
|
2019-08-08 09:41:19 +02:00
|
|
|
flyMoveCamera(C, fly, do_rotate, do_translate, is_confirm);
|
2013-03-21 02:56:16 +00:00
|
|
|
}
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* we're not redrawing but we need to update the time else the view will jump */
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->time_lastdraw = PIL_check_seconds_timer();
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
/* end drawing */
|
|
|
|
copy_v3_v3(fly->dvec_prev, dvec);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2016-08-18 00:21:55 -04:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
2019-08-08 10:38:01 +02:00
|
|
|
static void flyApply_ndof(bContext *C, FlyInfo *fly, bool is_confirm)
|
2011-07-14 21:20:45 +00:00
|
|
|
{
|
2014-02-19 21:19:13 +11:00
|
|
|
Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
|
|
|
|
bool has_translate, has_rotate;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-19 21:19:13 +11:00
|
|
|
view3d_ndof_fly(fly->ndof,
|
|
|
|
fly->v3d,
|
|
|
|
fly->rv3d,
|
|
|
|
fly->use_precision,
|
|
|
|
lock_ob ? lock_ob->protectflag : 0,
|
|
|
|
&has_translate,
|
|
|
|
&has_rotate);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-19 21:19:13 +11:00
|
|
|
if (has_translate || has_rotate) {
|
2013-03-20 23:14:18 +00:00
|
|
|
fly->redraw = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-19 21:19:13 +11:00
|
|
|
if (fly->rv3d->persp == RV3D_CAMOB) {
|
2019-08-08 10:38:01 +02:00
|
|
|
flyMoveCamera(C, fly, has_rotate, has_translate, is_confirm);
|
2011-07-19 22:40:22 +00:00
|
|
|
}
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2011-07-14 21:20:45 +00:00
|
|
|
}
|
2016-08-18 00:21:55 -04:00
|
|
|
#endif /* WITH_INPUT_NDOF */
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2020-06-18 12:40:38 +10:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Fly Operator
|
|
|
|
* \{ */
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
2012-03-10 06:46:23 +00:00
|
|
|
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
2010-10-25 07:09:38 +00:00
|
|
|
FlyInfo *fly;
|
|
|
|
|
VR: Initial Virtual Reality support - Milestone 1, Scene Inspection
NOTE: While most of the milestone 1 goals are there, a few smaller features and
improvements are still to be done.
Big picture of this milestone: Initial, OpenXR-based virtual reality support
for users and foundation for advanced use cases.
Maniphest Task: https://developer.blender.org/T71347
The tasks contains more information about this milestone.
To be clear: This is not a feature rich VR implementation, it's focused on the
initial scene inspection use case. We intentionally focused on that, further
features like controller support are part of the next milestone.
- How to use?
Instructions on how to use this are here:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/How_to_Test
These will be updated and moved to a more official place (likely the manual) soon.
Currently Windows Mixed Reality and Oculus devices are usable. Valve/HTC
headsets don't support the OpenXR standard yet and hence, do not work with this
implementation.
---------------
This is the C-side implementation of the features added for initial VR
support as per milestone 1. A "VR Scene Inspection" Add-on will be
committed separately, to expose the VR functionality in the UI. It also
adds some further features for milestone 1, namely a landmarking system
(stored view locations in the VR space)
Main additions/features:
* Support for rendering viewports to an HMD, with good performance.
* Option to sync the VR view perspective with a fully interactive,
regular 3D View (VR-Mirror).
* Option to disable positional tracking. Keeps the current position (calculated
based on the VR eye center pose) when enabled while a VR session is running.
* Some regular viewport settings for the VR view
* RNA/Python-API to query and set VR session state information.
* WM-XR: Layer tying Ghost-XR to the Blender specific APIs/data
* wmSurface API: drawable, non-window container (manages Ghost-OpenGL and GPU
context)
* DNA/RNA for management of VR session settings
* `--debug-xr` and `--debug-xr-time` commandline options
* Utility batch & config file for using the Oculus runtime on Windows.
* Most VR data is runtime only. The exception is user settings which are saved
to files (`XrSessionSettings`).
* VR support can be disabled through the `WITH_XR_OPENXR` compiler flag.
For architecture and code documentation, see
https://wiki.blender.org/wiki/Source/Interface/XR.
---------------
A few thank you's:
* A huge shoutout to Ray Molenkamp for his help during the project - it would
have not been that successful without him!
* Sebastian Koenig and Simeon Conzendorf for testing and feedback!
* The reviewers, especially Brecht Van Lommel!
* Dalai Felinto for pushing and managing me to get this done ;)
* The OpenXR working group for providing an open standard. I think we're the
first bigger application to adopt OpenXR. Congratulations to them and
ourselves :)
This project started as a Google Summer of Code 2019 project - "Core Support of
Virtual Reality Headsets through OpenXR" (see
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/).
Some further information, including ideas for further improvements can be found
in the final GSoC report:
https://wiki.blender.org/wiki/User:Severin/GSoC-2019/Final_Report
Differential Revisions: D6193, D7098
Reviewed by: Brecht Van Lommel, Jeroen Bakker
2020-03-17 20:20:55 +01:00
|
|
|
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) {
|
2010-10-25 07:09:38 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation");
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
op->customdata = fly;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2013-03-20 23:14:18 +00:00
|
|
|
if (initFlyInfo(C, fly, op, event) == false) {
|
2010-10-25 07:09:38 +00:00
|
|
|
MEM_freeN(op->customdata);
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2019-06-07 13:01:37 +10:00
|
|
|
flyEvent(fly, event);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
WM_event_add_modal_handler(C, op);
|
|
|
|
|
|
|
|
return OPERATOR_RUNNING_MODAL;
|
|
|
|
}
|
|
|
|
|
2013-10-30 23:08:53 +00:00
|
|
|
static void fly_cancel(bContext *C, wmOperator *op)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
|
|
|
FlyInfo *fly = op->customdata;
|
|
|
|
|
|
|
|
fly->state = FLY_CANCEL;
|
|
|
|
flyEnd(C, fly);
|
2012-03-10 06:46:23 +00:00
|
|
|
op->customdata = NULL;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
|
|
|
|
2013-03-13 09:03:46 +00:00
|
|
|
static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
2010-10-25 07:09:38 +00:00
|
|
|
{
|
|
|
|
int exit_code;
|
2013-03-20 23:14:18 +00:00
|
|
|
bool do_draw = false;
|
2012-03-10 06:46:23 +00:00
|
|
|
FlyInfo *fly = op->customdata;
|
|
|
|
RegionView3D *rv3d = fly->rv3d;
|
2013-11-28 15:01:53 +11:00
|
|
|
Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2012-03-10 06:46:23 +00:00
|
|
|
fly->redraw = 0;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2019-06-07 13:01:37 +10:00
|
|
|
flyEvent(fly, event);
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2016-08-18 00:21:55 -04:00
|
|
|
#ifdef WITH_INPUT_NDOF
|
2011-08-02 08:12:50 +00:00
|
|
|
if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */
|
2012-03-10 06:46:23 +00:00
|
|
|
if (event->type == NDOF_MOTION) {
|
2019-08-08 09:41:19 +02:00
|
|
|
flyApply_ndof(C, fly, false);
|
2011-07-14 21:20:45 +00:00
|
|
|
}
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2016-08-18 00:21:55 -04:00
|
|
|
else
|
|
|
|
#endif /* WITH_INPUT_NDOF */
|
|
|
|
if (event->type == TIMER && event->customdata == fly->timer) {
|
2019-08-08 09:41:19 +02:00
|
|
|
flyApply(C, fly, false);
|
2011-08-02 08:12:50 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
2010-10-25 07:12:29 +00:00
|
|
|
do_draw |= fly->redraw;
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
exit_code = flyEnd(C, fly);
|
|
|
|
|
2019-03-26 21:16:47 +11:00
|
|
|
if (exit_code != OPERATOR_RUNNING_MODAL) {
|
2013-03-20 23:14:18 +00:00
|
|
|
do_draw = true;
|
2019-03-26 21:16:47 +11:00
|
|
|
}
|
2010-11-24 16:54:18 +00:00
|
|
|
|
2011-08-02 08:12:50 +00:00
|
|
|
if (do_draw) {
|
2012-03-10 06:46:23 +00:00
|
|
|
if (rv3d->persp == RV3D_CAMOB) {
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, fly_object);
|
2010-10-25 07:12:29 +00:00
|
|
|
}
|
|
|
|
|
2011-08-02 07:49:34 +00:00
|
|
|
// puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now
|
2010-10-25 07:09:38 +00:00
|
|
|
ED_region_tag_redraw(CTX_wm_region(C));
|
2010-10-25 07:12:29 +00:00
|
|
|
}
|
2010-10-25 07:09:38 +00:00
|
|
|
|
|
|
|
return exit_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_fly(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-10 06:46:23 +00:00
|
|
|
ot->name = "Fly Navigation";
|
|
|
|
ot->description = "Interactively fly around the scene";
|
|
|
|
ot->idname = "VIEW3D_OT_fly";
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* api callbacks */
|
2012-03-10 06:46:23 +00:00
|
|
|
ot->invoke = fly_invoke;
|
|
|
|
ot->cancel = fly_cancel;
|
|
|
|
ot->modal = fly_modal;
|
2016-03-28 18:17:45 +02:00
|
|
|
ot->poll = ED_operator_region_view3d_active;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-10-25 07:09:38 +00:00
|
|
|
/* flags */
|
2012-03-10 06:46:23 +00:00
|
|
|
ot->flag = OPTYPE_BLOCKING;
|
2010-10-25 07:09:38 +00:00
|
|
|
}
|
2020-06-18 12:40:38 +10:00
|
|
|
|
|
|
|
/** \} */
|