1334 lines
56 KiB
C++
1334 lines
56 KiB
C++
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup editors
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "BKE_attribute.h"
|
|
#include "BLI_utildefines.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
/* ********* exports for space_view3d/ module ********** */
|
|
struct ARegion;
|
|
struct BMEdge;
|
|
struct BMElem;
|
|
struct BMEditMesh;
|
|
struct BMFace;
|
|
struct BMVert;
|
|
struct BPoint;
|
|
struct Base;
|
|
struct BezTriple;
|
|
struct BoundBox;
|
|
struct Camera;
|
|
struct CustomData_MeshMasks;
|
|
struct Depsgraph;
|
|
struct EditBone;
|
|
struct GPUSelectResult;
|
|
struct ID;
|
|
struct Main;
|
|
struct MetaElem;
|
|
struct Nurb;
|
|
struct Object;
|
|
struct RV3DMatrixStore;
|
|
struct RegionView3D;
|
|
struct RenderEngineType;
|
|
struct Scene;
|
|
struct ScrArea;
|
|
struct SnapObjectContext;
|
|
struct View3D;
|
|
struct ViewContext;
|
|
struct ViewLayer;
|
|
struct ViewOpsData;
|
|
struct bContext;
|
|
struct bPoseChannel;
|
|
struct bScreen;
|
|
struct rctf;
|
|
struct rcti;
|
|
struct wmEvent;
|
|
struct wmGizmo;
|
|
struct wmKeyMapItem;
|
|
struct wmWindow;
|
|
struct wmWindowManager;
|
|
|
|
/* for derivedmesh drawing callbacks, for view3d_select, .... */
|
|
struct ViewContext {
|
|
bContext *C;
|
|
Main *bmain;
|
|
/* Dependency graph is uses for depth drawing, viewport camera matrix access, and also some areas
|
|
* are re-using this to access evaluated entities.
|
|
*
|
|
* Moral of the story: assign to a fully evaluated state. */
|
|
Depsgraph *depsgraph;
|
|
Scene *scene;
|
|
ViewLayer *view_layer;
|
|
Object *obact;
|
|
Object *obedit;
|
|
ARegion *region;
|
|
View3D *v3d;
|
|
wmWindow *win;
|
|
RegionView3D *rv3d;
|
|
BMEditMesh *em;
|
|
int mval[2];
|
|
};
|
|
|
|
struct ViewDepths {
|
|
unsigned short w, h;
|
|
/* only for temp use for sub-rectangles, added to `region->winx/winy`. */
|
|
short x, y;
|
|
float *depths;
|
|
double depth_range[2];
|
|
};
|
|
|
|
/* Rotate 3D cursor on placement. */
|
|
enum eV3DCursorOrient {
|
|
V3D_CURSOR_ORIENT_NONE = 0,
|
|
V3D_CURSOR_ORIENT_VIEW,
|
|
V3D_CURSOR_ORIENT_XFORM,
|
|
V3D_CURSOR_ORIENT_GEOM,
|
|
};
|
|
|
|
void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float r_color[3]);
|
|
bool ED_view3d_has_workbench_in_texture_color(const Scene *scene,
|
|
const Object *ob,
|
|
const View3D *v3d);
|
|
/**
|
|
* Cursor position in `r_cursor_co`, result in `r_cursor_co`, `mval` in region coords.
|
|
*
|
|
* \note cannot use `event->mval` here, called by #object_add().
|
|
*/
|
|
void ED_view3d_cursor3d_position(bContext *C,
|
|
const int mval[2],
|
|
bool use_depth,
|
|
float r_cursor_co[3]);
|
|
void ED_view3d_cursor3d_position_rotation(bContext *C,
|
|
const int mval[2],
|
|
bool use_depth,
|
|
enum eV3DCursorOrient orientation,
|
|
float r_cursor_co[3],
|
|
float r_cursor_quat[4]);
|
|
void ED_view3d_cursor3d_update(bContext *C,
|
|
const int mval[2],
|
|
bool use_depth,
|
|
enum eV3DCursorOrient orientation);
|
|
|
|
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d);
|
|
|
|
/**
|
|
* Calculate the view transformation matrix from RegionView3D input.
|
|
* The resulting matrix is equivalent to #RegionView3D.viewinv
|
|
* \param mat: The view 4x4 transformation matrix to calculate.
|
|
* \param ofs: The view offset, normally from #RegionView3D.ofs.
|
|
* \param quat: The view rotation, quaternion normally from #RegionView3D.viewquat.
|
|
* \param dist: The view distance from ofs, normally from #RegionView3D.dist.
|
|
*/
|
|
void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], float dist);
|
|
/**
|
|
* Set the view transformation from a 4x4 matrix.
|
|
*
|
|
* \param mat: The view 4x4 transformation matrix to assign.
|
|
* \param ofs: The view offset, normally from #RegionView3D.ofs.
|
|
* \param quat: The view rotation, quaternion normally from #RegionView3D.viewquat.
|
|
* \param dist: The view distance from `ofs`, normally from #RegionView3D.dist.
|
|
*/
|
|
void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], const float *dist);
|
|
|
|
/**
|
|
* Set the #RegionView3D members from an objects transformation and optionally lens.
|
|
* \param ob: The object to set the view to.
|
|
* \param ofs: The view offset to be set, normally from #RegionView3D.ofs.
|
|
* \param quat: The view rotation to be set, quaternion normally from #RegionView3D.viewquat.
|
|
* \param dist: The view distance from `ofs `to be set, normally from #RegionView3D.dist.
|
|
* \param lens: The view lens angle set for cameras and lights, normally from View3D.lens.
|
|
*/
|
|
void ED_view3d_from_object(
|
|
const Object *ob, float ofs[3], float quat[4], float *dist, float *lens);
|
|
/**
|
|
* Set the object transformation from #RegionView3D members.
|
|
* \param depsgraph: The depsgraph to get the evaluated object parent
|
|
* for the transformation calculation.
|
|
* \param ob: The object which has the transformation assigned.
|
|
* \param ofs: The view offset, normally from #RegionView3D.ofs.
|
|
* \param quat: The view rotation, quaternion normally from #RegionView3D.viewquat.
|
|
* \param dist: The view distance from `ofs`, normally from #RegionView3D.dist.
|
|
*/
|
|
void ED_view3d_to_object(
|
|
const Depsgraph *depsgraph, Object *ob, const float ofs[3], const float quat[4], float dist);
|
|
|
|
bool ED_view3d_camera_to_view_selected(Main *bmain,
|
|
Depsgraph *depsgraph,
|
|
const Scene *scene,
|
|
Object *camera_ob);
|
|
|
|
bool ED_view3d_camera_to_view_selected_with_set_clipping(Main *bmain,
|
|
Depsgraph *depsgraph,
|
|
const Scene *scene,
|
|
Object *camera_ob);
|
|
|
|
/**
|
|
* Use to store the last view, before entering camera view.
|
|
*/
|
|
void ED_view3d_lastview_store(RegionView3D *rv3d);
|
|
|
|
/* Depth buffer */
|
|
enum eV3DDepthOverrideMode {
|
|
/** Redraw viewport without Grease Pencil and Annotations. */
|
|
V3D_DEPTH_NO_GPENCIL = 0,
|
|
/** Redraw viewport with Grease Pencil and Annotations only. */
|
|
V3D_DEPTH_GPENCIL_ONLY,
|
|
/** Redraw viewport with active object only. */
|
|
V3D_DEPTH_OBJECT_ONLY,
|
|
|
|
};
|
|
/**
|
|
* Redraw the viewport depth buffer.
|
|
*/
|
|
void ED_view3d_depth_override(Depsgraph *depsgraph,
|
|
ARegion *region,
|
|
View3D *v3d,
|
|
Object *obact,
|
|
eV3DDepthOverrideMode mode,
|
|
ViewDepths **r_depths);
|
|
void ED_view3d_depths_free(ViewDepths *depths);
|
|
bool ED_view3d_depth_read_cached(const ViewDepths *vd,
|
|
const int mval[2],
|
|
int margin,
|
|
float *r_depth);
|
|
bool ED_view3d_depth_read_cached_normal(const ARegion *region,
|
|
const ViewDepths *depths,
|
|
const int mval[2],
|
|
float r_normal[3]);
|
|
bool ED_view3d_depth_unproject_v3(const ARegion *region,
|
|
const int mval[2],
|
|
double depth,
|
|
float r_location_world[3]);
|
|
|
|
/**
|
|
* Utilities to perform navigation.
|
|
* Call `ED_view3d_navigation_init` to create a context and `ED_view3d_navigation_do` to perform
|
|
* navigation in modal operators.
|
|
*
|
|
* \note modal map events can also be used in `ED_view3d_navigation_do`.
|
|
*/
|
|
ViewOpsData *ED_view3d_navigation_init(bContext *C, const wmKeyMapItem *kmi_merge);
|
|
bool ED_view3d_navigation_do(bContext *C,
|
|
ViewOpsData *vod,
|
|
const wmEvent *event,
|
|
const float depth_loc_override[3]);
|
|
void ED_view3d_navigation_free(bContext *C, ViewOpsData *vod);
|
|
|
|
/* Projection */
|
|
#define IS_CLIPPED 12000
|
|
|
|
/* return values for ED_view3d_project_...() */
|
|
enum eV3DProjStatus {
|
|
V3D_PROJ_RET_OK = 0,
|
|
/** can't avoid this when in perspective mode, (can't avoid) */
|
|
V3D_PROJ_RET_CLIP_NEAR = 1,
|
|
/** After clip_end. */
|
|
V3D_PROJ_RET_CLIP_FAR = 2,
|
|
/** so close to zero we can't apply a perspective matrix usefully */
|
|
V3D_PROJ_RET_CLIP_ZERO = 3,
|
|
/** bounding box clip - RV3D_CLIPPING */
|
|
V3D_PROJ_RET_CLIP_BB = 4,
|
|
/** outside window bounds */
|
|
V3D_PROJ_RET_CLIP_WIN = 5,
|
|
/** outside range (mainly for short), (can't avoid) */
|
|
V3D_PROJ_RET_OVERFLOW = 6,
|
|
};
|
|
ENUM_OPERATORS(eV3DProjStatus, V3D_PROJ_RET_OVERFLOW);
|
|
|
|
/* some clipping tests are optional */
|
|
enum eV3DProjTest {
|
|
V3D_PROJ_TEST_NOP = 0,
|
|
V3D_PROJ_TEST_CLIP_BB = (1 << 0),
|
|
V3D_PROJ_TEST_CLIP_WIN = (1 << 1),
|
|
V3D_PROJ_TEST_CLIP_NEAR = (1 << 2),
|
|
V3D_PROJ_TEST_CLIP_FAR = (1 << 3),
|
|
V3D_PROJ_TEST_CLIP_ZERO = (1 << 4),
|
|
/**
|
|
* Clip the contents of the data being iterated over.
|
|
* Currently this is only used to edges when projecting into screen space.
|
|
*
|
|
* Clamp the edge within the viewport limits defined by
|
|
* #V3D_PROJ_TEST_CLIP_WIN, #V3D_PROJ_TEST_CLIP_NEAR & #V3D_PROJ_TEST_CLIP_FAR.
|
|
* This resolves the problem of a visible edge having one of it's vertices
|
|
* behind the viewport. See: #32214.
|
|
*
|
|
* This is not default behavior as it may be important for the screen-space location
|
|
* of an edges vertex to represent that vertices location (instead of a location along the edge).
|
|
*
|
|
* \note Perspective views should enable #V3D_PROJ_TEST_CLIP_WIN along with
|
|
* #V3D_PROJ_TEST_CLIP_NEAR as the near-plane-clipped location of a point
|
|
* may become very large (even infinite) when projected into screen-space.
|
|
* Unless that point happens to coincide with the camera's point of view.
|
|
*
|
|
* Use #V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT instead of #V3D_PROJ_TEST_CLIP_CONTENT,
|
|
* to avoid accidentally enabling near clipping without clipping by window bounds.
|
|
*/
|
|
V3D_PROJ_TEST_CLIP_CONTENT = (1 << 5),
|
|
};
|
|
ENUM_OPERATORS(eV3DProjTest, V3D_PROJ_TEST_CLIP_CONTENT);
|
|
|
|
#define V3D_PROJ_TEST_CLIP_DEFAULT \
|
|
(V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR)
|
|
#define V3D_PROJ_TEST_ALL \
|
|
(V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_FAR | V3D_PROJ_TEST_CLIP_ZERO | \
|
|
V3D_PROJ_TEST_CLIP_CONTENT)
|
|
|
|
#define V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT \
|
|
(V3D_PROJ_TEST_CLIP_CONTENT | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_FAR | \
|
|
V3D_PROJ_TEST_CLIP_WIN)
|
|
|
|
/* `view3d_snap.cc` */
|
|
|
|
bool ED_view3d_snap_selected_to_location(bContext *C,
|
|
const float snap_target_global[3],
|
|
int pivot_point);
|
|
|
|
/* `view3d_cursor_snap.cc` */
|
|
|
|
#define USE_SNAP_DETECT_FROM_KEYMAP_HACK
|
|
enum eV3DSnapCursor {
|
|
V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE = 1 << 0,
|
|
V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE = 1 << 1,
|
|
V3D_SNAPCURSOR_OCCLUSION_ALWAYS_FALSE = 1 << 2, /* TODO. */
|
|
V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 3,
|
|
V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 4,
|
|
};
|
|
ENUM_OPERATORS(eV3DSnapCursor, V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE)
|
|
|
|
struct V3DSnapCursorData {
|
|
eSnapMode type_source;
|
|
eSnapMode type_target;
|
|
float loc[3];
|
|
float nor[3];
|
|
float obmat[4][4];
|
|
int elem_index[3];
|
|
float plane_omat[3][3];
|
|
bool is_snap_invert;
|
|
|
|
/** Enabled when snap is activated, even if it didn't find anything. */
|
|
bool is_enabled;
|
|
};
|
|
|
|
struct V3DSnapCursorState {
|
|
/* Setup. */
|
|
eV3DSnapCursor flag;
|
|
uchar source_color[4];
|
|
uchar target_color[4];
|
|
uchar color_box[4];
|
|
float *prevpoint;
|
|
float box_dimensions[3];
|
|
bool draw_point;
|
|
bool draw_plane;
|
|
bool draw_box;
|
|
|
|
bool (*poll)(ARegion *region, void *custom_poll_data);
|
|
void *poll_data;
|
|
};
|
|
|
|
void ED_view3d_cursor_snap_state_default_set(V3DSnapCursorState *state);
|
|
V3DSnapCursorState *ED_view3d_cursor_snap_state_active_get();
|
|
void ED_view3d_cursor_snap_state_active_set(V3DSnapCursorState *state);
|
|
V3DSnapCursorState *ED_view3d_cursor_snap_state_create();
|
|
void ED_view3d_cursor_snap_state_free(V3DSnapCursorState *state);
|
|
void ED_view3d_cursor_snap_state_prevpoint_set(V3DSnapCursorState *state,
|
|
const float prev_point[3]);
|
|
void ED_view3d_cursor_snap_data_update(V3DSnapCursorState *state, const bContext *C, int x, int y);
|
|
V3DSnapCursorData *ED_view3d_cursor_snap_data_get();
|
|
SnapObjectContext *ED_view3d_cursor_snap_context_ensure(Scene *scene);
|
|
void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d,
|
|
const float source_loc[3],
|
|
const float target_loc[3],
|
|
const eSnapMode source_type,
|
|
const eSnapMode target_type,
|
|
const uchar source_color[4],
|
|
const uchar target_color[4]);
|
|
|
|
/* view3d_iterators.cc */
|
|
|
|
/* foreach iterators */
|
|
|
|
void meshobject_foreachScreenVert(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
const float screen_co[2],
|
|
int index),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
void mesh_foreachScreenVert(
|
|
ViewContext *vc,
|
|
void (*func)(void *user_data, BMVert *eve, const float screen_co[2], int index),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
void mesh_foreachScreenEdge(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
BMEdge *eed,
|
|
const float screen_co_a[2],
|
|
const float screen_co_b[2],
|
|
int index),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
|
|
/**
|
|
* A version of #mesh_foreachScreenEdge that clips the segment when
|
|
* there is a clipping bounding box.
|
|
*/
|
|
void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
BMEdge *eed,
|
|
const float screen_co_a[2],
|
|
const float screen_co_b[2],
|
|
int index),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
|
|
void mesh_foreachScreenFace(
|
|
ViewContext *vc,
|
|
void (*func)(void *user_data, BMFace *efa, const float screen_co[2], int index),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
void nurbs_foreachScreenVert(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
Nurb *nu,
|
|
BPoint *bp,
|
|
BezTriple *bezt,
|
|
int beztindex,
|
|
bool handle_visible,
|
|
const float screen_co[2]),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
/**
|
|
* #ED_view3d_init_mats_rv3d must be called first.
|
|
*/
|
|
void mball_foreachScreenElem(ViewContext *vc,
|
|
void (*func)(void *user_data, MetaElem *ml, const float screen_co[2]),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
void lattice_foreachScreenVert(ViewContext *vc,
|
|
void (*func)(void *user_data, BPoint *bp, const float screen_co[2]),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
/**
|
|
* #ED_view3d_init_mats_rv3d must be called first.
|
|
*/
|
|
void armature_foreachScreenBone(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
EditBone *ebone,
|
|
const float screen_co_a[2],
|
|
const float screen_co_b[2]),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
|
|
/**
|
|
* ED_view3d_init_mats_rv3d must be called first.
|
|
*/
|
|
void pose_foreachScreenBone(ViewContext *vc,
|
|
void (*func)(void *user_data,
|
|
bPoseChannel *pchan,
|
|
const float screen_co_a[2],
|
|
const float screen_co_b[2]),
|
|
void *user_data,
|
|
eV3DProjTest clip_flag);
|
|
/* *** end iterators *** */
|
|
|
|
/* `view3d_project.cc` */
|
|
|
|
/**
|
|
* \note use #ED_view3d_ob_project_mat_get to get the projection matrix
|
|
*/
|
|
void ED_view3d_project_float_v2_m4(const ARegion *region,
|
|
const float co[3],
|
|
float r_co[2],
|
|
const float mat[4][4]);
|
|
/**
|
|
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
|
|
*/
|
|
void ED_view3d_project_float_v3_m4(const ARegion *region,
|
|
const float co[3],
|
|
float r_co[3],
|
|
const float mat[4][4]);
|
|
|
|
eV3DProjStatus ED_view3d_project_base(const ARegion *region, Base *base, float r_co[2]);
|
|
|
|
/* *** short *** */
|
|
eV3DProjStatus ED_view3d_project_short_ex(const ARegion *region,
|
|
float perspmat[4][4],
|
|
bool is_local,
|
|
const float co[3],
|
|
short r_co[2],
|
|
eV3DProjTest flag);
|
|
/* --- short --- */
|
|
eV3DProjStatus ED_view3d_project_short_global(const ARegion *region,
|
|
const float co[3],
|
|
short r_co[2],
|
|
eV3DProjTest flag);
|
|
/* object space, use ED_view3d_init_mats_rv3d before calling */
|
|
eV3DProjStatus ED_view3d_project_short_object(const ARegion *region,
|
|
const float co[3],
|
|
short r_co[2],
|
|
eV3DProjTest flag);
|
|
|
|
/* *** int *** */
|
|
eV3DProjStatus ED_view3d_project_int_ex(const ARegion *region,
|
|
float perspmat[4][4],
|
|
bool is_local,
|
|
const float co[3],
|
|
int r_co[2],
|
|
eV3DProjTest flag);
|
|
/* --- int --- */
|
|
eV3DProjStatus ED_view3d_project_int_global(const ARegion *region,
|
|
const float co[3],
|
|
int r_co[2],
|
|
eV3DProjTest flag);
|
|
/* object space, use ED_view3d_init_mats_rv3d before calling */
|
|
eV3DProjStatus ED_view3d_project_int_object(const ARegion *region,
|
|
const float co[3],
|
|
int r_co[2],
|
|
eV3DProjTest flag);
|
|
|
|
/* *** float *** */
|
|
eV3DProjStatus ED_view3d_project_float_ex(const ARegion *region,
|
|
float perspmat[4][4],
|
|
bool is_local,
|
|
const float co[3],
|
|
float r_co[2],
|
|
eV3DProjTest flag);
|
|
/* --- float --- */
|
|
eV3DProjStatus ED_view3d_project_float_global(const ARegion *region,
|
|
const float co[3],
|
|
float r_co[2],
|
|
eV3DProjTest flag);
|
|
/**
|
|
* Object space, use #ED_view3d_init_mats_rv3d before calling.
|
|
*/
|
|
eV3DProjStatus ED_view3d_project_float_object(const ARegion *region,
|
|
const float co[3],
|
|
float r_co[2],
|
|
eV3DProjTest flag);
|
|
|
|
float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]);
|
|
float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3]);
|
|
|
|
/**
|
|
* Calculate a depth value from \a co, use with #ED_view3d_win_to_delta.
|
|
*
|
|
* \param r_flip: Set to `zfac < 0.0` before the value is made signed.
|
|
* Since it's important in some cases to know if the value was flipped.
|
|
*
|
|
* \return The unsigned depth component of `co` multiplied by `rv3d->persmat` matrix,
|
|
* with additional sanitation to ensure the result is never negative
|
|
* as this isn't useful for tool-code.
|
|
*/
|
|
float ED_view3d_calc_zfac_ex(const RegionView3D *rv3d, const float co[3], bool *r_flip);
|
|
/** See #ED_view3d_calc_zfac_ex doc-string. */
|
|
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3]);
|
|
/**
|
|
* Calculate a depth value from `co` (result should only be used for comparison).
|
|
*/
|
|
float ED_view3d_calc_depth_for_comparison(const RegionView3D *rv3d, const float co[3]);
|
|
|
|
bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]);
|
|
/**
|
|
* Calculate a 3d viewpoint and direction vector from 2d window coordinates.
|
|
* This ray_start is located at the viewpoint, ray_normal is the direction towards mval.
|
|
* ray_start is clipped by the view near limit so points in front of it are always in view.
|
|
* In orthographic view the resulting ray_normal will match the view vector.
|
|
* \param region: The region (used for the window width and height).
|
|
* \param v3d: The 3d viewport (used for near clipping value).
|
|
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
|
|
* \param r_ray_start: The world-space point where the ray intersects the window plane.
|
|
* \param r_ray_normal: The normalized world-space direction of towards mval.
|
|
* \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes.
|
|
* \return success, false if the ray is totally clipped.
|
|
*/
|
|
bool ED_view3d_win_to_ray_clipped(Depsgraph *depsgraph,
|
|
const ARegion *region,
|
|
const View3D *v3d,
|
|
const float mval[2],
|
|
float r_ray_start[3],
|
|
float r_ray_normal[3],
|
|
bool do_clip_planes);
|
|
/**
|
|
* Calculate a 3d viewpoint and direction vector from 2d window coordinates.
|
|
* This ray_start is located at the viewpoint, ray_normal is the direction towards `mval`.
|
|
* ray_start is clipped by the view near limit so points in front of it are always in view.
|
|
* In orthographic view the resulting ray_normal will match the view vector.
|
|
* This version also returns the ray_co point of the ray on window plane, useful to fix precision
|
|
* issues especially with orthographic view, where default ray_start is set rather far away.
|
|
* \param region: The region (used for the window width and height).
|
|
* \param v3d: The 3d viewport (used for near clipping value).
|
|
* \param mval: The area relative 2d location (such as `event->mval`, converted into float[2]).
|
|
* \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes.
|
|
* \param r_ray_co: The world-space point where the ray intersects the window plane.
|
|
* \param r_ray_normal: The normalized world-space direction of towards mval.
|
|
* \param r_ray_start: The world-space starting point of the ray.
|
|
* \param r_ray_end: The world-space end point of the segment.
|
|
* \return success, false if the ray is totally clipped.
|
|
*/
|
|
bool ED_view3d_win_to_ray_clipped_ex(Depsgraph *depsgraph,
|
|
const ARegion *region,
|
|
const View3D *v3d,
|
|
const float mval[2],
|
|
const bool do_clip_planes,
|
|
float r_ray_co[3],
|
|
float r_ray_normal[3],
|
|
float r_ray_start[3],
|
|
float r_ray_end[3]);
|
|
/**
|
|
* Calculate a 3d viewpoint and direction vector from 2d window coordinates.
|
|
* This ray_start is located at the viewpoint, ray_normal is the direction towards `mval`.
|
|
* \param region: The region (used for the window width and height).
|
|
* \param mval: The area relative 2d location (such as `event->mval`, converted into float[2]).
|
|
* \param r_ray_start: The world-space point where the ray intersects the window plane.
|
|
* \param r_ray_normal: The normalized world-space direction of towards mval.
|
|
*
|
|
* \note Ignores view near/far clipping,
|
|
* to take this into account use #ED_view3d_win_to_ray_clipped.
|
|
*/
|
|
void ED_view3d_win_to_ray(const ARegion *region,
|
|
const float mval[2],
|
|
float r_ray_start[3],
|
|
float r_ray_normal[3]);
|
|
/**
|
|
* Calculate a normalized 3d direction vector from the viewpoint towards a global location.
|
|
* In orthographic view the resulting vector will match the view vector.
|
|
* \param rv3d: The region (used for the window width and height).
|
|
* \param coord: The world-space location.
|
|
* \param vec: The resulting normalized vector.
|
|
*/
|
|
void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3]);
|
|
/**
|
|
* Calculate a 3d location from 2d window coordinates.
|
|
* \param region: The region (used for the window width and height).
|
|
* \param depth_pt: The reference location used to calculate the Z depth.
|
|
* \param mval: The area relative location (such as `event->mval` converted to floats).
|
|
* \param r_out: The resulting world-space location.
|
|
*/
|
|
void ED_view3d_win_to_3d(const View3D *v3d,
|
|
const ARegion *region,
|
|
const float depth_pt[3],
|
|
const float mval[2],
|
|
float r_out[3]);
|
|
void ED_view3d_win_to_3d_int(const View3D *v3d,
|
|
const ARegion *region,
|
|
const float depth_pt[3],
|
|
const int mval[2],
|
|
float r_out[3]);
|
|
bool ED_view3d_win_to_3d_on_plane(const ARegion *region,
|
|
const float plane[4],
|
|
const float mval[2],
|
|
bool do_clip,
|
|
float r_out[3]);
|
|
/**
|
|
* A wrapper for #ED_view3d_win_to_3d_on_plane that projects onto \a plane_fallback
|
|
* then maps this back to \a plane.
|
|
*
|
|
* This is intended to be used when \a plane is orthogonal to the views Z axis where
|
|
* projecting the \a mval doesn't work well (or fail completely when exactly aligned).
|
|
*/
|
|
bool ED_view3d_win_to_3d_on_plane_with_fallback(const ARegion *region,
|
|
const float plane[4],
|
|
const float mval[2],
|
|
bool do_clip,
|
|
const float plane_fallback[4],
|
|
float r_out[3]);
|
|
bool ED_view3d_win_to_3d_on_plane_int(
|
|
const ARegion *region, const float plane[4], const int mval[2], bool do_clip, float r_out[3]);
|
|
/**
|
|
* Calculate a 3d difference vector from 2d window offset.
|
|
*
|
|
* \note that #ED_view3d_calc_zfac() must be called first to determine
|
|
* the depth used to calculate the delta.
|
|
*
|
|
* When the `zfac` is calculated based on a world-space location directly under the cursor,
|
|
* the value of `r_out` can be subtracted from #RegionView3D.ofs to pan the view
|
|
* with the contents following the cursor perfectly (without sliding).
|
|
*
|
|
* \param region: The region (used for the window width and height).
|
|
* \param xy_delta: 2D difference (in pixels) such as `event->mval[0] - other_x`.
|
|
* \param zfac: The depth result typically calculated by #ED_view3d_calc_zfac
|
|
* (see it's doc-string for details).
|
|
* \param r_out: The resulting world-space delta.
|
|
*/
|
|
void ED_view3d_win_to_delta(const ARegion *region,
|
|
const float xy_delta[2],
|
|
float zfac,
|
|
float r_out[3]);
|
|
/**
|
|
* Calculate a 3d origin from 2d window coordinates.
|
|
* \note Orthographic views have a less obvious origin,
|
|
* Since far clip can be a very large value resulting in numeric precision issues,
|
|
* the origin in this case is close to zero coordinate.
|
|
*
|
|
* \param region: The region (used for the window width and height).
|
|
* \param mval: The area relative 2d location (such as `event->mval` converted to float).
|
|
* \param r_out: The resulting normalized world-space direction vector.
|
|
*/
|
|
void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3]);
|
|
/**
|
|
* Calculate a 3d direction vector from 2d window coordinates.
|
|
* This direction vector starts and the view in the direction of the 2d window coordinates.
|
|
* In orthographic view all window coordinates yield the same vector.
|
|
*
|
|
* \note doesn't rely on #ED_view3d_calc_zfac
|
|
* for perspective view, get the vector direction to
|
|
* the mouse cursor as a normalized vector.
|
|
*
|
|
* \param region: The region (used for the window width and height).
|
|
* \param mval: The area relative 2d location (such as `event->mval` converted to float).
|
|
* \param r_out: The resulting normalized world-space direction vector.
|
|
*/
|
|
void ED_view3d_win_to_vector(const ARegion *region, const float mval[2], float r_out[3]);
|
|
/**
|
|
* Calculate a 3d segment from 2d window coordinates.
|
|
* This ray_start is located at the viewpoint, ray_end is a far point.
|
|
* ray_start and ray_end are clipped by the view near and far limits
|
|
* so points along this line are always in view.
|
|
* In orthographic view all resulting segments will be parallel.
|
|
* \param region: The region (used for the window width and height).
|
|
* \param v3d: The 3d viewport (used for near and far clipping range).
|
|
* \param mval: The area relative 2d location (such as event->mval, converted into float[2]).
|
|
* \param r_ray_start: The world-space starting point of the segment.
|
|
* \param r_ray_end: The world-space end point of the segment.
|
|
* \param do_clip_planes: Optionally clip the ray by the view clipping planes.
|
|
* \return success, false if the segment is totally clipped.
|
|
*/
|
|
bool ED_view3d_win_to_segment_clipped(const Depsgraph *depsgraph,
|
|
const ARegion *region,
|
|
const View3D *v3d,
|
|
const float mval[2],
|
|
float r_ray_start[3],
|
|
float r_ray_end[3],
|
|
bool do_clip_planes);
|
|
void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob, float r_pmat[4][4]);
|
|
void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d,
|
|
const float obmat[4][4],
|
|
float r_pmat[4][4]);
|
|
|
|
/**
|
|
* Convert between region relative coordinates (x,y) and depth component z and
|
|
* a point in world space.
|
|
*/
|
|
void ED_view3d_project_v3(const ARegion *region, const float world[3], float r_region_co[3]);
|
|
void ED_view3d_project_v2(const ARegion *region, const float world[3], float r_region_co[2]);
|
|
bool ED_view3d_unproject_v3(
|
|
const ARegion *region, float regionx, float regiony, float regionz, float world[3]);
|
|
|
|
/* end */
|
|
|
|
void ED_view3d_dist_range_get(const View3D *v3d, float r_dist_range[2]);
|
|
/**
|
|
* \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
|
|
*/
|
|
bool ED_view3d_clip_range_get(const Depsgraph *depsgraph,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
float *r_clipsta,
|
|
float *r_clipend,
|
|
bool use_ortho_factor);
|
|
bool ED_view3d_viewplane_get(Depsgraph *depsgraph,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
int winxi,
|
|
int winyi,
|
|
rctf *r_viewplane,
|
|
float *r_clipsta,
|
|
float *r_clipend,
|
|
float *r_pixsize);
|
|
|
|
/**
|
|
* Use instead of: `GPU_polygon_offset(rv3d->dist, ...)` see bug #37727.
|
|
*/
|
|
void ED_view3d_polygon_offset(const RegionView3D *rv3d, float dist);
|
|
|
|
void ED_view3d_calc_camera_border(const Scene *scene,
|
|
Depsgraph *depsgraph,
|
|
const ARegion *region,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
rctf *r_viewborder,
|
|
bool no_shift);
|
|
void ED_view3d_calc_camera_border_size(const Scene *scene,
|
|
Depsgraph *depsgraph,
|
|
const ARegion *region,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
float r_size[2]);
|
|
bool ED_view3d_calc_render_border(
|
|
const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *region, rcti *rect);
|
|
|
|
void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *clipbb, bool is_flip);
|
|
void ED_view3d_clipping_calc(
|
|
BoundBox *bb, float planes[4][4], const ARegion *region, const Object *ob, const rcti *rect);
|
|
/**
|
|
* Clamp min/max by the viewport clipping.
|
|
*
|
|
* \note This is an approximation, with the limitation that the bounding box from the (mix, max)
|
|
* calculation might not have any geometry inside the clipped region.
|
|
* Performing a clipping test on each vertex would work well enough for most cases,
|
|
* although it's not perfect either as edges/faces may intersect the clipping without having any
|
|
* of their vertices inside it.
|
|
* A more accurate result would be quite involved.
|
|
*
|
|
* \return True when the arguments were clamped.
|
|
*/
|
|
bool ED_view3d_clipping_clamp_minmax(const RegionView3D *rv3d, float min[3], float max[3]);
|
|
|
|
void ED_view3d_clipping_local(RegionView3D *rv3d, const float mat[4][4]);
|
|
/**
|
|
* Return true when `co` is hidden by the 3D views clipping planes.
|
|
*
|
|
* \param is_local: When true use local (object-space) #ED_view3d_clipping_local must run first,
|
|
* then all comparisons can be done in local-space.
|
|
* \return True when `co` is outside all clipping planes.
|
|
*
|
|
* \note Callers should check #RV3D_CLIPPING_ENABLED first.
|
|
*/
|
|
bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], bool is_local);
|
|
|
|
float ED_view3d_radius_to_dist_persp(float angle, float radius);
|
|
float ED_view3d_radius_to_dist_ortho(float lens, float radius);
|
|
/**
|
|
* Return a new #RegionView3D.dist value to fit the \a radius.
|
|
*
|
|
* \note Depth isn't taken into account, this will fit a flat plane exactly,
|
|
* but points towards the view (with a perspective projection),
|
|
* may be within the radius but outside the view. eg:
|
|
*
|
|
* <pre>
|
|
* +
|
|
* pt --> + /^ radius
|
|
* / |
|
|
* / |
|
|
* view + +
|
|
* \ |
|
|
* \ |
|
|
* \|
|
|
* +
|
|
* </pre>
|
|
*
|
|
* \param region: Can be NULL if \a use_aspect is false.
|
|
* \param persp: Allow the caller to tell what kind of perspective to use (ortho/view/camera)
|
|
* \param use_aspect: Increase the distance to account for non 1:1 view aspect.
|
|
* \param radius: The radius will be fitted exactly,
|
|
* typically pre-scaled by a margin (#VIEW3D_MARGIN).
|
|
*/
|
|
float ED_view3d_radius_to_dist(const View3D *v3d,
|
|
const ARegion *region,
|
|
const Depsgraph *depsgraph,
|
|
char persp,
|
|
bool use_aspect,
|
|
float radius);
|
|
|
|
/**
|
|
* Back-buffer select and draw support.
|
|
*/
|
|
void ED_view3d_backbuf_depth_validate(ViewContext *vc);
|
|
/**
|
|
* allow for small values [0.5 - 2.5],
|
|
* and large values, FLT_MAX by clamping by the area size
|
|
*/
|
|
int ED_view3d_backbuf_sample_size_clamp(ARegion *region, float dist);
|
|
|
|
void ED_view3d_select_id_validate(ViewContext *vc);
|
|
|
|
/** Check if the last auto-dist can be used. */
|
|
bool ED_view3d_autodist_last_check(wmWindow *win, const wmEvent *event);
|
|
/**
|
|
* \return true when `r_ofs` is set.
|
|
* \warning #ED_view3d_autodist_last_check should be called first to ensure the data is available.
|
|
*/
|
|
bool ED_view3d_autodist_last_get(wmWindow *win, float r_ofs[3]);
|
|
void ED_view3d_autodist_last_set(wmWindow *win,
|
|
const wmEvent *event,
|
|
const float ofs[3],
|
|
const bool has_depth);
|
|
/** Clear and free auto-dist data. */
|
|
void ED_view3d_autodist_last_clear(wmWindow *win);
|
|
|
|
/**
|
|
* Get the world-space 3d location from a screen-space 2d point.
|
|
* TODO: Implement #alphaoverride. We don't want to zoom into billboards.
|
|
*
|
|
* \param mval: Input screen-space pixel location.
|
|
* \param mouse_worldloc: Output world-space location.
|
|
* \param fallback_depth_pt: Use this points depth when no depth can be found.
|
|
*/
|
|
bool ED_view3d_autodist(Depsgraph *depsgraph,
|
|
ARegion *region,
|
|
View3D *v3d,
|
|
const int mval[2],
|
|
float mouse_worldloc[3],
|
|
bool alphaoverride,
|
|
const float fallback_depth_pt[3]);
|
|
|
|
/**
|
|
* No 4x4 sampling, run #ED_view3d_depth_override first.
|
|
*/
|
|
bool ED_view3d_autodist_simple(ARegion *region,
|
|
const int mval[2],
|
|
float mouse_worldloc[3],
|
|
int margin,
|
|
const float *force_depth);
|
|
bool ED_view3d_depth_read_cached_seg(
|
|
const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
|
|
|
|
/**
|
|
* The default value for the maximum number of elements that can be selected at once
|
|
* using view-port selection.
|
|
*
|
|
* \note in many cases this defines the size of fixed-size stack buffers,
|
|
* so take care increasing this value.
|
|
*/
|
|
#define MAXPICKELEMS 2500
|
|
|
|
enum eV3DSelectMode {
|
|
/* all elements in the region, ignore depth */
|
|
VIEW3D_SELECT_ALL = 0,
|
|
/* pick also depth sorts (only for small regions!) */
|
|
VIEW3D_SELECT_PICK_ALL = 1,
|
|
/* sorts and only returns visible objects (only for small regions!) */
|
|
VIEW3D_SELECT_PICK_NEAREST = 2,
|
|
};
|
|
|
|
enum eV3DSelectObjectFilter {
|
|
/** Don't exclude anything. */
|
|
VIEW3D_SELECT_FILTER_NOP = 0,
|
|
/** Don't select objects outside the current mode. */
|
|
VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1,
|
|
/** A version of #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK that allows pose-bone selection. */
|
|
VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK = 2,
|
|
};
|
|
|
|
eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const Scene *scene, const Object *obact);
|
|
|
|
/**
|
|
* Optionally cache data for multiple calls to #view3d_opengl_select
|
|
*
|
|
* just avoid GPU_select headers outside this file
|
|
*/
|
|
void view3d_opengl_select_cache_begin();
|
|
void view3d_opengl_select_cache_end();
|
|
|
|
/**
|
|
* \warning be sure to account for a negative return value
|
|
* This is an error, "Too many objects in select buffer"
|
|
* and no action should be taken (can crash blender) if this happens
|
|
*
|
|
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
|
|
*/
|
|
int view3d_opengl_select_ex(ViewContext *vc,
|
|
GPUSelectResult *buffer,
|
|
unsigned int buffer_len,
|
|
const rcti *input,
|
|
eV3DSelectMode select_mode,
|
|
eV3DSelectObjectFilter select_filter,
|
|
bool do_material_slot_selection);
|
|
int view3d_opengl_select(ViewContext *vc,
|
|
GPUSelectResult *buffer,
|
|
unsigned int buffer_len,
|
|
const rcti *input,
|
|
eV3DSelectMode select_mode,
|
|
eV3DSelectObjectFilter select_filter);
|
|
int view3d_opengl_select_with_id_filter(ViewContext *vc,
|
|
GPUSelectResult *buffer,
|
|
unsigned int buffer_len,
|
|
const rcti *input,
|
|
eV3DSelectMode select_mode,
|
|
eV3DSelectObjectFilter select_filter,
|
|
uint select_id);
|
|
|
|
/* view3d_select.cc */
|
|
|
|
float ED_view3d_select_dist_px();
|
|
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph);
|
|
|
|
/**
|
|
* Re-initialize `vc` with `obact` as if it's active object (with some differences).
|
|
*
|
|
* This is often used when operating on multiple objects in modes (edit, pose mode etc)
|
|
* where the `vc` is passed in as an argument which then references it's object data.
|
|
*
|
|
* \note members #ViewContext.obedit & #ViewContext.em are only initialized if they're already set,
|
|
* by #ED_view3d_viewcontext_init in most cases.
|
|
* This is necessary because the active object defines the current object-mode.
|
|
* When iterating over objects in object-mode it doesn't make sense to perform
|
|
* an edit-mode action on an object that happens to contain edit-mode data.
|
|
* In some cases these values are cleared allowing the owner of `vc` to explicitly
|
|
* disable edit-mode operation (to force object selection in edit-mode for e.g.).
|
|
* So object-mode specific values should remain cleared when initialized with another object.
|
|
*/
|
|
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact);
|
|
/**
|
|
* Use this call when executing an operator,
|
|
* event system doesn't set for each event the OpenGL drawing context.
|
|
*/
|
|
void view3d_operator_needs_opengl(const bContext *C);
|
|
void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *region);
|
|
|
|
/** XXX: should move to BLI_math */
|
|
bool edge_inside_circle(const float cent[2],
|
|
float radius,
|
|
const float screen_co_a[2],
|
|
const float screen_co_b[2]);
|
|
|
|
/**
|
|
* Get 3D region from context, also if mouse is in header or toolbar.
|
|
*/
|
|
RegionView3D *ED_view3d_context_rv3d(bContext *C);
|
|
/**
|
|
* Ideally would return an rv3d but in some cases the region is needed too
|
|
* so return that, the caller can then access the `region->regiondata`.
|
|
*/
|
|
bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region);
|
|
/**
|
|
* Similar to #ED_view3d_context_user_region() but does not use context. Always performs a lookup.
|
|
* Also works if \a v3d is not the active space.
|
|
*/
|
|
bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region);
|
|
bool ED_operator_rv3d_user_region_poll(bContext *C);
|
|
|
|
/**
|
|
* Most of the time this isn't needed since you could assume the view matrix was
|
|
* set while drawing, however when functions like mesh_foreachScreenVert are
|
|
* called by selection tools, we can't be sure this object was the last.
|
|
*
|
|
* for example, transparent objects are drawn after edit-mode and will cause
|
|
* the rv3d mat's to change and break selection.
|
|
*
|
|
* 'ED_view3d_init_mats_rv3d' should be called before
|
|
* view3d_project_short_clip and view3d_project_short_noclip in cases where
|
|
* these functions are not used during draw_object
|
|
*/
|
|
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d);
|
|
void ED_view3d_init_mats_rv3d_gl(const Object *ob, RegionView3D *rv3d);
|
|
#ifdef DEBUG
|
|
/**
|
|
* Ensure we correctly initialize.
|
|
*/
|
|
void ED_view3d_clear_mats_rv3d(RegionView3D *rv3d);
|
|
void ED_view3d_check_mats_rv3d(RegionView3D *rv3d);
|
|
#else
|
|
# define ED_view3d_clear_mats_rv3d(rv3d) (void)(rv3d)
|
|
# define ED_view3d_check_mats_rv3d(rv3d) (void)(rv3d)
|
|
#endif
|
|
|
|
RV3DMatrixStore *ED_view3d_mats_rv3d_backup(RegionView3D *rv3d);
|
|
void ED_view3d_mats_rv3d_restore(RegionView3D *rv3d, RV3DMatrixStore *rv3dmat);
|
|
|
|
RenderEngineType *ED_view3d_engine_type(const Scene *scene, int drawtype);
|
|
|
|
bool ED_view3d_context_activate(bContext *C);
|
|
/**
|
|
* Set the correct matrices
|
|
*/
|
|
void ED_view3d_draw_setup_view(const wmWindowManager *wm,
|
|
wmWindow *win,
|
|
Depsgraph *depsgraph,
|
|
Scene *scene,
|
|
ARegion *region,
|
|
View3D *v3d,
|
|
const float viewmat[4][4],
|
|
const float winmat[4][4],
|
|
const rcti *rect);
|
|
|
|
/**
|
|
* `mval` comes from event->mval, only use within region handlers.
|
|
*/
|
|
Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]);
|
|
Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2]);
|
|
Object *ED_view3d_give_material_slot_under_cursor(bContext *C,
|
|
const int mval[2],
|
|
int *r_material_slot);
|
|
bool ED_view3d_is_object_under_cursor(bContext *C, const int mval[2]);
|
|
/**
|
|
* 'clip' is used to know if our clip setting has changed.
|
|
*/
|
|
void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip);
|
|
/**
|
|
* \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore
|
|
*/
|
|
void ED_view3d_update_viewmat(Depsgraph *depsgraph,
|
|
const Scene *scene,
|
|
View3D *v3d,
|
|
ARegion *region,
|
|
const float viewmat[4][4],
|
|
const float winmat[4][4],
|
|
const rcti *rect,
|
|
bool offscreen);
|
|
bool ED_view3d_quat_from_axis_view(char view, char view_axis_roll, float r_quat[4]);
|
|
bool ED_view3d_quat_to_axis_view(const float viewquat[4],
|
|
float epsilon,
|
|
char *r_view,
|
|
char *r_view_axis_rotation);
|
|
/**
|
|
* A version of #ED_view3d_quat_to_axis_view that updates `viewquat`
|
|
* if it's within `epsilon` to an axis-view.
|
|
*
|
|
* \note Include the special case function since most callers need to perform these operations.
|
|
*/
|
|
bool ED_view3d_quat_to_axis_view_and_reset_quat(float viewquat[4],
|
|
float epsilon,
|
|
char *r_view,
|
|
char *r_view_axis_rotation);
|
|
|
|
char ED_view3d_lock_view_from_index(int index);
|
|
char ED_view3d_axis_view_opposite(char view);
|
|
bool ED_view3d_lock(RegionView3D *rv3d);
|
|
|
|
void ED_view3d_datamask(const Scene *scene,
|
|
ViewLayer *view_layer,
|
|
const View3D *v3d,
|
|
CustomData_MeshMasks *r_cddata_masks);
|
|
/**
|
|
* Goes over all modes and view3d settings.
|
|
*/
|
|
void ED_view3d_screen_datamask(const Scene *scene,
|
|
ViewLayer *view_layer,
|
|
const bScreen *screen,
|
|
CustomData_MeshMasks *r_cddata_masks);
|
|
|
|
bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d);
|
|
/**
|
|
* For viewport operators that exit camera perspective.
|
|
*
|
|
* \note This differs from simply setting `rv3d->persp = persp` because it
|
|
* sets the `ofs` and `dist` values of the viewport so it matches the camera,
|
|
* otherwise switching out of camera view may jump to a different part of the scene.
|
|
*/
|
|
void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph,
|
|
View3D *v3d,
|
|
RegionView3D *rv3d,
|
|
char persp);
|
|
/**
|
|
* Action to take when rotating the view,
|
|
* handle auto-perspective and logic for switching out of views.
|
|
*
|
|
* shared with NDOF.
|
|
*/
|
|
bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *region);
|
|
|
|
/* Camera view functions. */
|
|
|
|
/**
|
|
* Utility to scale zoom level when in camera-view #RegionView3D.camzoom and apply limits.
|
|
* \return true a change was made.
|
|
*/
|
|
bool ED_view3d_camera_view_zoom_scale(RegionView3D *rv3d, const float scale);
|
|
/**
|
|
* Utility to pan when in camera view.
|
|
* \param event_ofs: The offset the pan in screen (pixel) coordinates.
|
|
* \return true when a change was made.
|
|
*/
|
|
bool ED_view3d_camera_view_pan(ARegion *region, const float event_ofs[2]);
|
|
|
|
/* Camera lock functions */
|
|
|
|
/**
|
|
* \return true when the 3D Viewport is locked to its camera.
|
|
*/
|
|
bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d);
|
|
/**
|
|
* Copy the camera to the view before starting a view transformation.
|
|
*
|
|
* Apply the camera object transformation to the 3D Viewport.
|
|
* (needed so we can use regular 3D Viewport manipulation operators, that sync back to the camera).
|
|
*/
|
|
void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph,
|
|
View3D *v3d,
|
|
RegionView3D *rv3d,
|
|
bool calc_dist);
|
|
void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d);
|
|
/**
|
|
* Copy the view to the camera, return true if.
|
|
*
|
|
* Apply the 3D Viewport transformation back to the camera object.
|
|
*
|
|
* \return true if the camera (or one of it's parents) was moved.
|
|
*/
|
|
bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d);
|
|
|
|
bool ED_view3d_camera_autokey(
|
|
const Scene *scene, ID *id_key, bContext *C, bool do_rotate, bool do_translate);
|
|
/**
|
|
* Call after modifying a locked view.
|
|
*
|
|
* \note Not every view edit currently auto-keys (numeric-pad for eg),
|
|
* this is complicated because of smooth-view.
|
|
*/
|
|
bool ED_view3d_camera_lock_autokey(
|
|
View3D *v3d, RegionView3D *rv3d, bContext *C, bool do_rotate, bool do_translate);
|
|
|
|
void ED_view3d_lock_clear(View3D *v3d);
|
|
|
|
/**
|
|
* Check if creating an undo step should be performed if the viewport moves.
|
|
* \return true if #ED_view3d_camera_lock_undo_push would do an undo push.
|
|
*/
|
|
bool ED_view3d_camera_lock_undo_test(const View3D *v3d, const RegionView3D *rv3d, bContext *C);
|
|
|
|
/**
|
|
* Create an undo step when the camera is locked to the view.
|
|
* \param str: The name of the undo step (typically #wmOperatorType.name should be used).
|
|
*
|
|
* \return true when the call to push an undo step was made.
|
|
*/
|
|
bool ED_view3d_camera_lock_undo_push(const char *str,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
bContext *C);
|
|
|
|
/**
|
|
* A version of #ED_view3d_camera_lock_undo_push that performs a grouped undo push.
|
|
*
|
|
* \note use for actions that are likely to be repeated such as mouse wheel to zoom,
|
|
* where adding a separate undo step each time isn't desirable.
|
|
*/
|
|
bool ED_view3d_camera_lock_undo_grouped_push(const char *str,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
bContext *C);
|
|
|
|
#define VIEW3D_MARGIN 1.4f
|
|
#define VIEW3D_DIST_FALLBACK 1.0f
|
|
|
|
/**
|
|
* This function solves the problem of having to switch between camera and non-camera views.
|
|
*
|
|
* When viewing from the perspective of \a mat, and having the view center \a ofs,
|
|
* this calculates a distance from \a ofs to the matrix \a mat.
|
|
* Using \a fallback_dist when the distance would be too small.
|
|
*
|
|
* \param mat: A matrix use for the view-point (typically the camera objects matrix).
|
|
* \param ofs: Orbit center (negated), matching #RegionView3D.ofs, which is typically passed in.
|
|
* \param fallback_dist: The distance to use if the object is too near or in front of \a ofs.
|
|
* \returns A newly calculated distance or the fallback.
|
|
*/
|
|
float ED_view3d_offset_distance(const float mat[4][4], const float ofs[3], float fallback_dist);
|
|
/**
|
|
* Set the dist without moving the view (compensate with #RegionView3D.ofs)
|
|
*
|
|
* \note take care that #RegionView3d.viewinv is up to date, #ED_view3d_update_viewmat first.
|
|
*/
|
|
void ED_view3d_distance_set(RegionView3D *rv3d, float dist);
|
|
/**
|
|
* Change the distance & offset to match the depth of \a dist_co along the view axis.
|
|
*
|
|
* \param dist_co: A world-space location to use for the new depth.
|
|
* \param dist_min: Resulting distances below this will be ignored.
|
|
* \return Success if the distance was set.
|
|
*/
|
|
bool ED_view3d_distance_set_from_location(RegionView3D *rv3d,
|
|
const float dist_co[3],
|
|
float dist_min);
|
|
|
|
/**
|
|
* Could move this elsewhere, but tied into #ED_view3d_grid_scale
|
|
*/
|
|
float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit);
|
|
float ED_view3d_grid_scale(const Scene *scene, const View3D *v3d, const char **r_grid_unit);
|
|
void ED_view3d_grid_steps(const Scene *scene,
|
|
const View3D *v3d,
|
|
const RegionView3D *rv3d,
|
|
float r_grid_steps[8]);
|
|
/**
|
|
* Simulates the grid scale that is actually viewed.
|
|
* The actual code is seen in `object_grid_frag.glsl` (see `grid_res`).
|
|
* Currently the simulation is only done when RV3D_VIEW_IS_AXIS.
|
|
*/
|
|
float ED_view3d_grid_view_scale(Scene *scene,
|
|
View3D *v3d,
|
|
ARegion *region,
|
|
const char **r_grid_unit);
|
|
|
|
/**
|
|
* \note The info that this uses is updated in #ED_scene_fps_average_accumulate,
|
|
* which currently gets called during #SCREEN_OT_animation_step.
|
|
*/
|
|
void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset);
|
|
|
|
/* Render */
|
|
|
|
void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region);
|
|
void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area);
|
|
|
|
#define SHADING_XRAY_ALPHA(shading) \
|
|
(((shading).type == OB_WIRE) ? (shading).xray_alpha_wire : (shading).xray_alpha)
|
|
#define SHADING_XRAY_FLAG(shading) \
|
|
(((shading).type == OB_WIRE) ? V3D_SHADING_XRAY_WIREFRAME : V3D_SHADING_XRAY)
|
|
#define SHADING_XRAY_FLAG_ENABLED(shading) (((shading).flag & SHADING_XRAY_FLAG(shading)) != 0)
|
|
#define SHADING_XRAY_ENABLED(shading) \
|
|
(SHADING_XRAY_FLAG_ENABLED(shading) && (SHADING_XRAY_ALPHA(shading) < 1.0f))
|
|
#define SHADING_XRAY_ACTIVE(shading) \
|
|
(SHADING_XRAY_ENABLED(shading) && ((shading).type < OB_MATERIAL))
|
|
|
|
#define XRAY_ALPHA(v3d) SHADING_XRAY_ALPHA((v3d)->shading)
|
|
#define XRAY_FLAG(v3d) SHADING_XRAY_FLAG((v3d)->shading)
|
|
#define XRAY_FLAG_ENABLED(v3d) SHADING_XRAY_FLAG_ENABLED((v3d)->shading)
|
|
#define XRAY_ENABLED(v3d) SHADING_XRAY_ENABLED((v3d)->shading)
|
|
#define XRAY_ACTIVE(v3d) SHADING_XRAY_ACTIVE((v3d)->shading)
|
|
|
|
#define OVERLAY_RETOPOLOGY_ENABLED(overlay) \
|
|
(((overlay).edit_flag & V3D_OVERLAY_EDIT_RETOPOLOGY) != 0)
|
|
#ifdef __APPLE__
|
|
/* Apple silicon tile depth test requires a higher value to reduce drawing artifacts. */
|
|
# define OVERLAY_RETOPOLOGY_MIN_OFFSET 0.0015f
|
|
#else
|
|
# define OVERLAY_RETOPOLOGY_MIN_OFFSET FLT_EPSILON
|
|
#endif
|
|
|
|
#define OVERLAY_RETOPOLOGY_OFFSET(overlay) \
|
|
(OVERLAY_RETOPOLOGY_ENABLED(overlay) ? \
|
|
max_ff((overlay).retopology_offset, OVERLAY_RETOPOLOGY_MIN_OFFSET) : \
|
|
0.0f)
|
|
|
|
#define RETOPOLOGY_ENABLED(v3d) (OVERLAY_RETOPOLOGY_ENABLED((v3d)->overlay))
|
|
#define RETOPOLOGY_OFFSET(v3d) (OVERLAY_RETOPOLOGY_OFFSET((v3d)->overlay))
|
|
|
|
/* view3d_draw_legacy.c */
|
|
|
|
/**
|
|
* Try avoid using these more move out of legacy.
|
|
*/
|
|
void ED_view3d_draw_bgpic_test(const Scene *scene,
|
|
Depsgraph *depsgraph,
|
|
ARegion *region,
|
|
View3D *v3d,
|
|
bool do_foreground,
|
|
bool do_camera_frame);
|
|
|
|
/* view3d_gizmo_preselect_type.cc */
|
|
|
|
void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C,
|
|
wmGizmo *gz,
|
|
Base **r_base,
|
|
BMElem **r_ele);
|
|
void ED_view3d_gizmo_mesh_preselect_clear(wmGizmo *gz);
|
|
|
|
/* space_view3d.cc */
|
|
|
|
void ED_view3d_buttons_region_layout_ex(const bContext *C,
|
|
ARegion *region,
|
|
const char *category_override);
|
|
|
|
/* `view3d_view.cc` */
|
|
|
|
/**
|
|
* See if current UUID is valid, otherwise set a valid UUID to v3d,
|
|
* Try to keep the same UUID previously used to allow users to quickly toggle back and forth.
|
|
*/
|
|
bool ED_view3d_local_collections_set(Main *bmain, View3D *v3d);
|
|
void ED_view3d_local_collections_reset(bContext *C, bool reset_all);
|
|
|
|
#ifdef WITH_XR_OPENXR
|
|
void ED_view3d_xr_mirror_update(const ScrArea *area, const View3D *v3d, bool enable);
|
|
void ED_view3d_xr_shading_update(wmWindowManager *wm, const View3D *v3d, const Scene *scene);
|
|
bool ED_view3d_is_region_xr_mirror_active(const wmWindowManager *wm,
|
|
const View3D *v3d,
|
|
const ARegion *region);
|
|
#endif
|