Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c104
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c32
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c104
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c430
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c46
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h12
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c21
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c1153
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c362
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c68
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c75
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c30
18 files changed, 1952 insertions, 547 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index c7fe82e0cbb..f2536cfac62 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
view3d_header.c
view3d_iterators.c
view3d_ops.c
+ view3d_placement.c
view3d_project.c
view3d_select.c
view3d_snap.c
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index d469faac934..5daba238293 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -88,9 +88,9 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d == NULL) {
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_VIEW3D) {
- ARegion *region = BKE_area_find_region_active_win(sa);
+ ScrArea *area = CTX_wm_area(C);
+ if (area && area->spacetype == SPACE_VIEW3D) {
+ ARegion *region = BKE_area_find_region_active_win(area);
if (region) {
rv3d = region->regiondata;
}
@@ -101,27 +101,27 @@ 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_ar)
+bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_region)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
*r_v3d = NULL;
- *r_ar = NULL;
+ *r_region = NULL;
- if (sa && sa->spacetype == SPACE_VIEW3D) {
+ if (area && area->spacetype == SPACE_VIEW3D) {
ARegion *region = CTX_wm_region(C);
- View3D *v3d = (View3D *)sa->spacedata.first;
+ View3D *v3d = (View3D *)area->spacedata.first;
if (region) {
RegionView3D *rv3d;
if ((region->regiontype == RGN_TYPE_WINDOW) && (rv3d = region->regiondata) &&
(rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
*r_v3d = v3d;
- *r_ar = region;
+ *r_region = region;
return true;
}
else {
- if (ED_view3d_area_user_region(sa, v3d, r_ar)) {
+ if (ED_view3d_area_user_region(area, v3d, r_region)) {
*r_v3d = v3d;
return true;
}
@@ -136,23 +136,24 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
* 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 *sa, const View3D *v3d, ARegion **r_ar)
+bool ED_view3d_area_user_region(const ScrArea *area, const View3D *v3d, ARegion **r_region)
{
RegionView3D *rv3d = NULL;
- ARegion *ar_unlock_user = NULL;
- ARegion *ar_unlock = NULL;
- const ListBase *region_list = (v3d == sa->spacedata.first) ? &sa->regionbase : &v3d->regionbase;
+ ARegion *region_unlock_user = NULL;
+ ARegion *region_unlock = NULL;
+ const ListBase *region_list = (v3d == area->spacedata.first) ? &area->regionbase :
+ &v3d->regionbase;
BLI_assert(v3d->spacetype == SPACE_VIEW3D);
- for (ARegion *region = region_list->first; region; region = region->next) {
+ LISTBASE_FOREACH (ARegion *, region, region_list) {
/* find the first unlocked rv3d */
if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
rv3d = region->regiondata;
if ((rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
- ar_unlock = region;
+ region_unlock = region;
if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
- ar_unlock_user = region;
+ region_unlock_user = region;
break;
}
}
@@ -160,13 +161,13 @@ bool ED_view3d_area_user_region(const ScrArea *sa, const View3D *v3d, ARegion **
}
/* camera/perspective view get priority when the active region is locked */
- if (ar_unlock_user) {
- *r_ar = ar_unlock_user;
+ if (region_unlock_user) {
+ *r_region = region_unlock_user;
return true;
}
- if (ar_unlock) {
- *r_ar = ar_unlock;
+ if (region_unlock) {
+ *r_region = region_unlock;
return true;
}
@@ -237,16 +238,19 @@ void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *region)
RE_engine_free(rv3d->render_engine);
rv3d->render_engine = NULL;
}
+
+ /* A bit overkill but this make sure the viewport is reset completely. (fclem) */
+ WM_draw_region_free(region, false);
}
-void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area)
{
wmWindowManager *wm = bmain->wm.first;
if (v3d->shading.type != OB_RENDER) {
ARegion *region;
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if ((region->regiontype == RGN_TYPE_WINDOW) && region->regiondata) {
ED_view3d_stop_render_preview(wm, region);
break;
@@ -257,7 +261,7 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
/* ******************** default callbacks for view3d space ***************** */
-static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene)
+static SpaceLink *view3d_new(const ScrArea *UNUSED(area), const Scene *scene)
{
ARegion *region;
View3D *v3d;
@@ -336,7 +340,7 @@ static void view3d_free(SpaceLink *sl)
}
/* spacetype; init callback */
-static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area))
{
}
@@ -500,6 +504,8 @@ static void view3d_widgets(void)
WM_gizmogrouptype_append(VIEW3D_GGT_ruler);
WM_gizmotype_append(VIEW3D_GT_ruler_item);
+ WM_gizmogrouptype_append(VIEW3D_GGT_placement);
+
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate);
WM_gizmotype_append(VIEW3D_GT_navigate_rotate);
}
@@ -561,9 +567,9 @@ static void *view3d_main_region_duplicate(void *poin)
}
static void view3d_main_region_listener(
- wmWindow *UNUSED(win), ScrArea *sa, ARegion *region, wmNotifier *wmn, const Scene *scene)
+ wmWindow *UNUSED(win), ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
RegionView3D *rv3d = region->regiondata;
wmGizmoMap *gzmap = region->gizmo_map;
@@ -756,7 +762,7 @@ static void view3d_main_region_listener(
}
break;
case NC_LIGHTPROBE:
- ED_area_tag_refresh(sa);
+ ED_area_tag_refresh(area);
break;
case NC_IMAGE:
/* this could be more fine grained checks if we had
@@ -821,7 +827,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *sa,
+ struct ScrArea *area,
struct ARegion *region,
struct wmMsgBus *mbus)
{
@@ -899,7 +905,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
{
wmMsgSubscribeValue msg_sub_value_region_tag_refresh = {
.owner = region,
- .user_data = sa,
+ .user_data = area,
.notify = WM_toolsystem_do_msg_notify_tag_refresh,
};
WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh);
@@ -907,9 +913,19 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
}
}
-static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *region)
+/* concept is to retrieve cursor type context-less */
+static void view3d_main_region_cursor(wmWindow *win, ScrArea *area, ARegion *region)
{
- if (!WM_cursor_set_from_tool(win, sa, region)) {
+ if (WM_cursor_set_from_tool(win, area, region)) {
+ return;
+ }
+
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ if (obedit) {
+ WM_cursor_set(win, WM_CURSOR_EDIT);
+ }
+ else {
WM_cursor_set(win, WM_CURSOR_DEFAULT);
}
}
@@ -930,7 +946,7 @@ static void view3d_header_region_draw(const bContext *C, ARegion *region)
}
static void view3d_header_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
+ ScrArea *UNUSED(area),
ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
@@ -1003,7 +1019,7 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED
struct WorkSpace *UNUSED(workspace),
struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen),
- struct ScrArea *UNUSED(sa),
+ struct ScrArea *UNUSED(area),
struct ARegion *region,
struct wmMsgBus *mbus)
{
@@ -1147,7 +1163,7 @@ static void view3d_buttons_region_layout(const bContext *C, ARegion *region)
}
static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
- ScrArea *UNUSED(sa),
+ ScrArea *UNUSED(area),
ARegion *region,
wmNotifier *wmn,
const Scene *UNUSED(scene))
@@ -1270,11 +1286,11 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *region)
/* area (not region) level listener */
static void space_view3d_listener(wmWindow *UNUSED(win),
- ScrArea *sa,
+ ScrArea *area,
struct wmNotifier *wmn,
Scene *UNUSED(scene))
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
/* context changes */
switch (wmn->category) {
@@ -1282,7 +1298,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_WORLD:
if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1292,7 +1308,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
case ND_WORLD_DRAW:
case ND_WORLD:
if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1301,7 +1317,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
switch (wmn->data) {
case ND_NODES:
if (v3d->shading.type == OB_TEXTURE) {
- ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW);
+ ED_area_tag_redraw_regiontype(area, RGN_TYPE_WINDOW);
}
break;
}
@@ -1309,7 +1325,7 @@ static void space_view3d_listener(wmWindow *UNUSED(win),
}
}
-static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(sa))
+static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
{
Scene *scene = CTX_data_scene(C);
LightCache *lcache = scene->eevee.light_cache_data;
@@ -1367,7 +1383,7 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
return -1; /* found but not available */
}
-static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id)
+static void view3d_id_remap(ScrArea *area, SpaceLink *slink, ID *old_id, ID *new_id)
{
View3D *v3d;
ARegion *region;
@@ -1382,8 +1398,8 @@ static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_i
v3d->camera = (Object *)new_id;
if (!new_id) {
/* 3D view might be inactive, in that case needs to use slink->regionbase */
- ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase :
- &slink->regionbase;
+ ListBase *regionbase = (slink == area->spacedata.first) ? &area->regionbase :
+ &slink->regionbase;
for (region = regionbase->first; region; region = region->next) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = is_local ? ((RegionView3D *)region->regiondata)->localvd :
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 80ab18cd3db..cb87ddafea1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1005,7 +1005,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float
}
}
BKE_nurb_test_2d(nu);
- BKE_nurb_handles_test(nu, true); /* test for bezier too */
+ BKE_nurb_handles_test(nu, true, false); /* test for bezier too */
nu = nu->next;
}
@@ -1140,9 +1140,9 @@ static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
return false;
}
-static void view3d_panel_vgroup(const bContext *C, Panel *pa)
+static void view3d_panel_vgroup(const bContext *C, Panel *panel)
{
- uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
+ uiBlock *block = uiLayoutAbsoluteBlock(panel->layout);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = view_layer->basact->object;
@@ -1171,7 +1171,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL);
- bcol = uiLayoutColumn(pa->layout, true);
+ bcol = uiLayoutColumn(panel->layout, true);
row = uiLayoutRow(bcol, true); /* The filter button row */
RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr);
@@ -1269,7 +1269,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
yco -= 2;
- col = uiLayoutColumn(pa->layout, true);
+ col = uiLayoutColumn(panel->layout, true);
row = uiLayoutRow(col, true);
ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1);
@@ -1555,7 +1555,7 @@ static bool view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)
return (view_layer->basact != NULL);
}
-static void view3d_panel_transform(const bContext *C, Panel *pa)
+static void view3d_panel_transform(const bContext *C, Panel *panel)
{
uiBlock *block;
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -1563,10 +1563,10 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
Object *obedit = OBEDIT_FROM_OBACT(ob);
uiLayout *col;
- block = uiLayoutGetBlock(pa->layout);
+ block = uiLayoutGetBlock(panel->layout);
UI_block_func_handle_set(block, do_view3d_region_buttons, NULL);
- col = uiLayoutColumn(pa->layout, false);
+ col = uiLayoutColumn(panel->layout, false);
if (ob == obedit) {
if (ob->type == OB_ARMATURE) {
@@ -1577,9 +1577,7 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
}
else {
View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL));
- v3d_editvertex_buts(col, v3d, ob, lim);
+ v3d_editvertex_buts(col, v3d, ob, FLT_MAX);
}
}
else if (ob->mode & OB_MODE_POSE) {
@@ -1644,7 +1642,7 @@ static int view3d_object_mode_menu(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
- ED_object_mode_toggle(C, OB_MODE_POSE);
+ ED_object_mode_set(C, (ob->mode == OB_MODE_OBJECT) ? OB_MODE_POSE : OB_MODE_OBJECT);
return OPERATOR_CANCELLED;
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 694cb7ee7d4..fac378ae104 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -63,6 +63,7 @@
#include "ED_armature.h"
#include "ED_gpencil.h"
+#include "ED_info.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
@@ -101,6 +102,8 @@
#define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f
+#define VIEW3D_OVERLAY_LINEHEIGHT (0.9f * U.widget_unit)
+
/* -------------------------------------------------------------------- */
/** \name General Functions
* \{ */
@@ -1341,7 +1344,7 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y
UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr));
@@ -1473,7 +1476,7 @@ static void draw_selected_name(
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info));
BLF_disable(font_id, BLF_SHADOW);
@@ -1494,7 +1497,7 @@ static void draw_grid_unit_name(
BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
}
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
BLF_enable(font_id, BLF_SHADOW);
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
@@ -1515,6 +1518,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
wmWindowManager *wm = CTX_wm_manager(C);
+ Main *bmain = CTX_data_main(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
#ifdef WITH_INPUT_NDOF
if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) &&
@@ -1550,8 +1555,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
}
}
- int xoffset = rect->xmin + U.widget_unit;
- int yoffset = rect->ymax;
+ int xoffset = rect->xmin + (0.5f * U.widget_unit);
+ int yoffset = rect->ymax - (0.1f * U.widget_unit);
if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
@@ -1562,7 +1567,6 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
}
if (U.uiflag & USER_DRAWVIEWINFO) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
draw_selected_name(scene, view_layer, ob, xoffset, &yoffset);
}
@@ -1571,10 +1575,12 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
/* draw below the viewport name */
draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset);
}
+
+ DRW_draw_region_engine_info(xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
}
- if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
- DRW_draw_region_engine_info(xoffset, yoffset);
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) {
+ ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT);
}
BLF_batch_draw_end();
@@ -2217,7 +2223,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
GPUViewport *viewport = WM_draw_region_get_viewport(region);
- DRW_draw_depth_object(vc->region, vc->v3d, viewport, obact_eval);
+ DRW_draw_depth_object(vc->scene, vc->region, vc->v3d, viewport, obact_eval);
}
vc->v3d->flag &= ~V3D_INVALID_BACKBUF;
@@ -2396,9 +2402,9 @@ void ED_view3d_screen_datamask(const bContext *C,
CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH);
/* Check if we need tfaces & mcols due to view mode. */
- for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks);
+ LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
+ if (area->spacetype == SPACE_VIEW3D) {
+ ED_view3d_datamask(C, scene, area->spacedata.first, r_cddata_masks);
}
}
}
@@ -2493,7 +2499,7 @@ void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset)
BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f});
BLF_shadow_offset(font_id, 1, -1);
- *yoffset -= U.widget_unit;
+ *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT;
#ifdef WITH_INTERNATIONAL
BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable));
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 67dacca85ba..edd75d8e561 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -175,7 +175,7 @@ typedef struct ViewOpsData {
/** Context pointers (assigned by #viewops_data_alloc). */
Main *bmain;
Scene *scene;
- ScrArea *sa;
+ ScrArea *area;
ARegion *region;
View3D *v3d;
RegionView3D *rv3d;
@@ -277,9 +277,9 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
vod->bmain = CTX_data_main(C);
vod->depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
vod->scene = CTX_data_scene(C);
- vod->sa = CTX_wm_area(C);
+ vod->area = CTX_wm_area(C);
vod->region = CTX_wm_region(C);
- vod->v3d = vod->sa->spacedata.first;
+ vod->v3d = vod->area->spacedata.first;
vod->rv3d = vod->region->regiondata;
}
@@ -529,10 +529,10 @@ static void viewops_data_create(bContext *C,
negate_v3_v3(rv3d->ofs, dvec);
}
else {
- const float mval_ar_mid[2] = {(float)vod->region->winx / 2.0f,
- (float)vod->region->winy / 2.0f};
+ const float mval_region_mid[2] = {(float)vod->region->winx / 2.0f,
+ (float)vod->region->winy / 2.0f};
- ED_view3d_win_to_3d(vod->v3d, vod->region, vod->dyn_ofs, mval_ar_mid, rv3d->ofs);
+ ED_view3d_win_to_3d(vod->v3d, vod->region, vod->dyn_ofs, mval_region_mid, rv3d->ofs);
negate_v3(rv3d->ofs);
}
negate_v3(vod->dyn_ofs);
@@ -627,14 +627,14 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -1120,7 +1120,7 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
* often `!rv3d->is_persp` since it doesn't make sense to dolly in ortho.
*/
static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
- ScrArea *sa,
+ ScrArea *area,
ARegion *region,
const bool has_translate,
const bool has_zoom)
@@ -1161,7 +1161,7 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
/* all callers must check */
if (has_translate) {
- BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false);
+ BLI_assert(ED_view3d_offset_lock_check((View3D *)area->spacedata.first, rv3d) == false);
}
}
@@ -1178,18 +1178,18 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
sub_v3_v3(rv3d->ofs, pan_vec);
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, region);
+ view3d_boxview_sync(area, region);
}
}
}
static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
- ScrArea *sa,
+ ScrArea *area,
ARegion *region,
ViewOpsData *vod,
const bool apply_dyn_ofs)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
RegionView3D *rv3d = region->regiondata;
float view_inv[4];
@@ -1422,12 +1422,12 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->region, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->region, vod, true);
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, true);
xform_flag |= HAS_ROTATE;
}
}
@@ -1505,7 +1505,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d);
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->region, has_translate, true);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, true);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1535,7 +1535,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
if (!is_orbit_around_pivot) {
ED_view3d_distance_set(rv3d, 0.0f);
}
- view3d_ndof_orbit(ndof, vod->sa, vod->region, vod, is_orbit_around_pivot);
+ view3d_ndof_orbit(ndof, vod->area, vod->region, vod, is_orbit_around_pivot);
xform_flag |= HAS_ROTATE;
if (!is_orbit_around_pivot) {
ED_view3d_distance_set(rv3d, dist_backup);
@@ -1543,7 +1543,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, vod->sa, vod->region, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, vod->area, vod->region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1607,11 +1607,11 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e
ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false);
if (ndof->progress != P_FINISHING) {
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
if (has_translate || has_zoom) {
- view3d_ndof_pan_zoom(ndof, sa, region, has_translate, has_zoom);
+ view3d_ndof_pan_zoom(ndof, area, region, has_translate, has_zoom);
xform_flag |= HAS_TRANSLATE;
}
}
@@ -1702,14 +1702,14 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items);
/* items for modal map */
WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
@@ -1751,7 +1751,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
add_v3_v3(vod->rv3d->ofs, dvec);
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->region);
+ view3d_boxview_sync(vod->area, vod->region);
}
}
@@ -1901,14 +1901,14 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -2189,7 +2189,7 @@ static void viewzoom_apply_3d(ViewOpsData *vod,
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->region);
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
@@ -2280,7 +2280,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
- ScrArea *sa;
+ ScrArea *area;
ARegion *region;
bool use_cam_zoom;
float dist_range[2];
@@ -2291,15 +2291,15 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- sa = vod->sa;
+ area = vod->area;
region = vod->region;
}
else {
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
region = CTX_wm_region(C);
}
- v3d = sa->spacedata.first;
+ v3d = area->spacedata.first;
rv3d = region->regiondata;
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) &&
@@ -2342,7 +2342,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
}
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, region);
+ view3d_boxview_sync(area, region);
}
ED_view3d_depth_tag_update(rv3d);
@@ -2472,14 +2472,14 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items);
/* disabled mode switching for now, can re-implement better, later on */
#if 0
@@ -2538,7 +2538,7 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
}
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->region);
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
@@ -2603,7 +2603,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
{
View3D *v3d;
RegionView3D *rv3d;
- ScrArea *sa;
+ ScrArea *area;
ARegion *region;
float mousevec[3];
@@ -2612,18 +2612,18 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
if (op->customdata) {
ViewOpsData *vod = op->customdata;
- sa = vod->sa;
+ area = vod->area;
region = vod->region;
copy_v3_v3(mousevec, vod->init.mousevec);
}
else {
- sa = CTX_wm_area(C);
+ area = CTX_wm_area(C);
region = CTX_wm_region(C);
negate_v3_v3(mousevec, ((RegionView3D *)region->regiondata)->viewinv[2]);
normalize_v3(mousevec);
}
- v3d = sa->spacedata.first;
+ v3d = area->spacedata.first;
rv3d = region->regiondata;
const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
@@ -2636,7 +2636,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, region);
+ view3d_boxview_sync(area, region);
}
ED_view3d_depth_tag_update(rv3d);
@@ -2886,9 +2886,9 @@ static void view3d_from_minmax_multi(bContext *C,
const bool ok_dist,
const int smooth_viewtx)
{
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *region;
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
/* when using all regions, don't jump out of camera view,
@@ -2980,7 +2980,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_all(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View All";
+ ot->name = "Frame All";
ot->description = "View all objects in scene";
ot->idname = "VIEW3D_OT_view_all";
@@ -3349,7 +3349,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Camera Center Operator
+/** \name Frame Camera Bounds Operator
* \{ */
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
@@ -3386,8 +3386,8 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Camera Center";
- ot->description = "Center the camera view";
+ ot->name = "Frame Camera Bounds";
+ ot->description = "Center the camera view, resizing the view to fit its bounds";
ot->idname = "VIEW3D_OT_view_center_camera";
/* api callbacks */
@@ -4376,7 +4376,7 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
}
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(vod->sa, vod->region);
+ view3d_boxview_sync(vod->area, vod->region);
}
ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
@@ -5018,7 +5018,6 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
float cursor_co[3],
float cursor_quat[4])
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
@@ -5052,7 +5051,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
float ray_co[3];
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, scene, 0, region, v3d);
+ scene, 0, region, v3d);
float obmat[4][4];
Object *ob_dummy = NULL;
@@ -5279,7 +5278,7 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
int type = RNA_enum_get(op->ptr, "type");
if (type == OB_SOLID) {
@@ -5307,7 +5306,7 @@ static int toggle_shading_exec(bContext *C, wmOperator *op)
}
}
- ED_view3d_shade_update(bmain, v3d, sa);
+ ED_view3d_shade_update(bmain, v3d, area);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
@@ -5340,7 +5339,7 @@ void VIEW3D_OT_toggle_shading(wmOperatorType *ot)
static int toggle_xray_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
Object *obact = CTX_data_active_object(C);
if (obact && ((obact->mode & OB_MODE_POSE) ||
@@ -5362,7 +5361,7 @@ static int toggle_xray_exec(bContext *C, wmOperator *op)
}
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
return OPERATOR_FINISHED;
}
@@ -5372,6 +5371,7 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot)
/* identifiers */
ot->name = "Toggle X-Ray";
ot->idname = "VIEW3D_OT_toggle_xray";
+ ot->description = "Transparent scene display. Allow selecting through items";
/* api callbacks */
ot->exec = toggle_xray_exec;
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 563e1afa67e..06d1a033a0d 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -125,14 +125,14 @@ void fly_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Fly Modal", modal_items);
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly");
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index cc00037b1fb..533fba3795b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -321,14 +321,14 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
gz = navgroup->gz_array[GZ_INDEX_CAMERA];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
if (navgroup->state.rv3d.is_camera == false) {
gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
- gz->matrix_basis[3][0] = co[0];
- gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
+ gz->matrix_basis[3][0] = roundf(co[0]);
+ gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
index a8e8d8cee96..3ce4c8dc9a8 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c
@@ -197,8 +197,8 @@ static void axis_geom_draw(const wmGizmo *gz,
const bool select,
const struct AxisDrawInfo *draw_info)
{
-
- GPU_line_width(gz->line_width);
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
GPUVertFormat *format = immVertexFormat();
const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
@@ -341,8 +341,13 @@ static void axis_geom_draw(const wmGizmo *gz,
/* Axis Line. */
if (is_pos) {
float v_start[3];
- GPU_line_width(2.0f);
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+ immUniform2fv("viewportSize", &viewport[2]);
+ immUniform1f("lineWidth", 2.0f * U.pixelsize);
immUniformColor4fv(is_pos_color ? color_current : color_current_fade);
+
immBegin(GPU_PRIM_LINES, 2);
if (axis_align == -1) {
zero_v3(v_start);
@@ -358,6 +363,10 @@ static void axis_geom_draw(const wmGizmo *gz,
immVertex3fv(pos_id, v_start);
immVertex3fv(pos_id, v_final);
immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
}
/* Axis Ball. */
@@ -527,9 +536,12 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv
return -1;
}
-static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz))
+static int gizmo_axis_cursor_get(wmGizmo *gz)
{
- return WM_CURSOR_DEFAULT;
+ if (gz->highlight_part > 0) {
+ return WM_CURSOR_EDIT;
+ }
+ return WM_CURSOR_NSEW_SCROLL;
}
void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt)
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 4b194d6687d..f3bc0a8a15b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -40,6 +40,7 @@
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
+#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
@@ -57,10 +58,13 @@
#include "WM_toolsystem.h"
#include "WM_types.h"
+#include "DEG_depsgraph_query.h"
+
#include "view3d_intern.h" /* own include */
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
#include "GPU_state.h"
#include "BLF_api.h"
@@ -94,10 +98,6 @@ enum {
RULER_STATE_DRAG,
};
-enum {
- RULER_SNAP_OK = (1 << 0),
-};
-
struct RulerItem;
typedef struct RulerInfo {
@@ -106,19 +106,25 @@ typedef struct RulerInfo {
int snap_flag;
int state;
- struct SnapObjectContext *snap_context;
-
/* wm state */
+ wmWindowManager *wm;
wmWindow *win;
- ScrArea *sa;
+ ScrArea *area;
ARegion *region; /* re-assigned every modal update */
/* Track changes in state. */
struct {
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
bool do_snap;
+#endif
bool do_thickness;
} drag_state_prev;
+ struct {
+ wmGizmo *gizmo;
+ PropertyRNA *prop_prevpoint;
+ } snap_data;
+
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -269,26 +275,17 @@ static bool view3d_ruler_pick(wmGizmoGroup *gzgroup,
* Ensure the 'snap_context' is only cached while dragging,
* needed since the user may toggle modes between tool use.
*/
-static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
+static void ruler_state_set(RulerInfo *ruler_info, int state)
{
- Main *bmain = CTX_data_main(C);
if (state == ruler_info->state) {
return;
}
- /* always remove */
- if (ruler_info->snap_context) {
- ED_transform_snap_object_context_destroy(ruler_info->snap_context);
- ruler_info->snap_context = NULL;
- }
-
if (state == RULER_STATE_NORMAL) {
/* pass */
}
else if (state == RULER_STATE_DRAG) {
memset(&ruler_info->drag_state_prev, 0x0, sizeof(ruler_info->drag_state_prev));
- ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, CTX_data_scene(C), 0, ruler_info->region, CTX_wm_view3d(C));
}
else {
BLI_assert(0);
@@ -299,7 +296,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], const int xy[2])
{
- ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->region, r_co, xy, r_co);
+ ED_view3d_win_to_3d_int(ruler_info->area->spacedata.first, ruler_info->region, r_co, xy, r_co);
}
/* use for mousemove events */
@@ -307,13 +304,18 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
RulerInfo *ruler_info,
RulerItem *ruler_item,
const int mval[2],
- const bool do_thickness,
- const bool do_snap)
+ const bool do_thickness
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ const bool do_snap
+#endif
+)
{
+ wmGizmo *snap_gizmo = ruler_info->snap_data.gizmo;
const float eps_bias = 0.0002f;
float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
+ WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, true);
if (ruler_item) {
RulerInteraction *inter = ruler_item->gz.interaction_data;
@@ -322,8 +324,10 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
copy_v3_v3(co, inter->drag_start_co);
view3d_ruler_item_project(ruler_info, co, mval);
if (do_thickness && inter->co_index != 1) {
- // Scene *scene = CTX_data_scene(C);
- // View3D *v3d = ruler_info->sa->spacedata.first;
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ View3D *v3d = ruler_info->area->spacedata.first;
+ SnapObjectContext *snap_context = ED_gizmotypes_snap_3d_context_ensure(
+ scene, ruler_info->region, v3d, snap_gizmo);
const float mval_fl[2] = {UNPACK2(mval)};
float ray_normal[3];
float ray_start[3];
@@ -331,7 +335,7 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0];
- if (ED_transform_snap_object_project_view3d(ruler_info->snap_context,
+ if (ED_transform_snap_object_project_view3d(snap_context,
depsgraph,
SCE_SNAP_MODE_FACE,
&(const struct SnapObjectParams){
@@ -346,7 +350,7 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
negate_v3(ray_normal);
/* add some bias */
madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
- ED_transform_snap_object_project_ray(ruler_info->snap_context,
+ ED_transform_snap_object_project_ray(snap_context,
depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
@@ -359,7 +363,12 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
NULL);
}
}
- else if (do_snap) {
+ else
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ if (do_snap)
+#endif
+ {
+ View3D *v3d = ruler_info->area->spacedata.first;
const float mval_fl[2] = {UNPACK2(mval)};
float *prev_point = NULL;
@@ -374,23 +383,16 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
prev_point = ruler_item->co[0];
}
}
+ if (prev_point != NULL) {
+ RNA_property_float_set_array(
+ snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
+ }
- if (ED_transform_snap_object_project_view3d(
- ruler_info->snap_context,
- depsgraph,
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR),
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .use_object_edit_cage = true,
- .use_occlusion_test = true,
- },
- mval_fl,
- prev_point,
- &dist_px,
- co,
- NULL)) {
- ruler_info->snap_flag |= RULER_SNAP_OK;
+ short snap_elem = ED_gizmotypes_snap_3d_update(
+ snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl, co, NULL);
+
+ if (snap_elem) {
+ WM_gizmo_set_flag(snap_gizmo, WM_GIZMO_HIDDEN, false);
}
}
return true;
@@ -417,6 +419,15 @@ static bGPDlayer *view3d_ruler_layer_get(bGPdata *gpd)
return NULL;
}
+static RulerItem *gzgroup_ruler_item_first_get(wmGizmoGroup *gzgroup)
+{
+#ifndef NDEBUG
+ RulerInfo *ruler_info = gzgroup->customdata;
+ BLI_assert(gzgroup->gizmos.first == ruler_info->snap_data.gizmo);
+#endif
+ return (RulerItem *)((wmGizmo *)gzgroup->gizmos.first)->next;
+}
+
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
{
@@ -448,7 +459,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
BKE_gpencil_free_strokes(gpf);
- for (ruler_item = gzgroup->gizmos.first; ruler_item;
+ for (ruler_item = gzgroup_ruler_item_first_get(gzgroup); ruler_item;
ruler_item = (RulerItem *)ruler_item->gz.next) {
bGPDspoint *pt;
int j;
@@ -556,6 +567,12 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
uchar color_wire[3];
float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f};
+ /* Pixel Space. */
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_identity_set();
+ wmOrtho2_region_pixelspace(region);
+
/* anti-aliased lines for more consistent appearance */
GPU_line_smooth(true);
GPU_line_width(1.0f);
@@ -575,20 +592,30 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
const bool is_act = (ruler_info->item_active == ruler_item);
float dir_ruler[2];
float co_ss[3][2];
+ bool proj_ok[3];
int j;
- /* should these be checked? - ok for now not to */
+ /* Check if each corner is behind the near plane. If it is, we do not draw certain lines. */
for (j = 0; j < 3; j++) {
- ED_view3d_project_float_global(region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ eV3DProjStatus status = ED_view3d_project_float_global(
+ region, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_CLIP_NEAR);
+ proj_ok[j] = (status == V3D_PROJ_RET_OK);
}
+ /* 3d drawing. */
+
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+
GPU_blend(true);
- const uint shdr_pos = GPU_vertformat_attr_add(
- immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ const uint shdr_pos_3d = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
if (ruler_item->flag & RULERITEM_USE_ANGLE) {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
@@ -605,21 +632,20 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immBegin(GPU_PRIM_LINE_STRIP, 3);
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[1]);
- immVertex2fv(shdr_pos, co_ss[2]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[1]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
immEnd();
immUnbindProgram();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* arc */
{
float dir_tmp[3];
- float co_tmp[3];
- float arc_ss_coord[2];
+ float ar_coord[3];
float dir_a[3];
float dir_b[3];
@@ -648,16 +674,53 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1);
for (j = 0; j <= arc_steps; j++) {
- madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
- ED_view3d_project_float_global(region, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP);
+ madd_v3_v3v3fl(ar_coord, ruler_item->co[1], dir_tmp, px_scale);
mul_qt_v3(quat, dir_tmp);
- immVertex2fv(shdr_pos, arc_ss_coord);
+ immVertex3fv(shdr_pos_3d, ar_coord);
}
immEnd();
}
+ immUnbindProgram();
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+ immUniform1i("colors_len", 2); /* "advanced" mode */
+ const float *col = is_act ? color_act : color_base;
+ immUniformArray4fv(
+ "colors",
+ (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
+ 2);
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+
+ immVertex3fv(shdr_pos_3d, ruler_item->co[0]);
+ immVertex3fv(shdr_pos_3d, ruler_item->co[2]);
+
+ immEnd();
+
+ immUnbindProgram();
+ }
+
+ /* 2d drawing. */
+
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
+
+ const uint shdr_pos_2d = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* capping */
{
float rot_90_vec_a[2];
@@ -676,15 +739,15 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
GPU_blend(true);
- if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
+ if (proj_ok[1] && is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) {
GPU_line_width(3.0f);
immUniformColor3fv(color_act);
immBegin(GPU_PRIM_LINES, 4);
/* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
immEnd();
GPU_line_width(1.0f);
@@ -692,25 +755,33 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 8);
+ if (proj_ok[0] || proj_ok[2] || proj_ok[1]) {
+ immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2 + proj_ok[1] * 4);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[0]) {
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[2]) {
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- /* angle vertex */
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
- immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ /* angle vertex */
+ if (proj_ok[1]) {
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ immVertex2f(shdr_pos_2d, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ }
- immEnd();
+ immEnd();
+ }
GPU_blend(false);
}
@@ -729,10 +800,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
/* draw text (bg) */
- {
+ if (proj_ok[1]) {
immUniformColor4fv(color_back);
GPU_blend(true);
- immRectf(shdr_pos,
+ immRectf(shdr_pos_2d,
posit[0] - bg_margin,
posit[1] - bg_margin,
posit[0] + bg_margin + numstr_size[0],
@@ -743,7 +814,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUnbindProgram();
/* draw text */
- {
+ if (proj_ok[1]) {
BLF_color3ubv(blf_mono_font, color_text);
BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
BLF_rotation(blf_mono_font, 0.0f);
@@ -751,30 +822,6 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
}
}
else {
- immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
-
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
-
- immUniform1i("colors_len", 2); /* "advanced" mode */
- const float *col = is_act ? color_act : color_base;
- immUniformArray4fv(
- "colors",
- (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}},
- 2);
- immUniform1f("dash_width", 6.0f);
- immUniform1f("dash_factor", 0.5f);
-
- immBegin(GPU_PRIM_LINES, 2);
-
- immVertex2fv(shdr_pos, co_ss[0]);
- immVertex2fv(shdr_pos, co_ss[2]);
-
- immEnd();
-
- immUnbindProgram();
-
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
@@ -790,19 +837,25 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUniformColor3ubv(color_wire);
- immBegin(GPU_PRIM_LINES, 4);
+ if (proj_ok[0] || proj_ok[2]) {
+ immBegin(GPU_PRIM_LINES, proj_ok[0] * 2 + proj_ok[2] * 2);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[0]) {
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
- immVertex2fv(shdr_pos, cap);
- madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
- immVertex2fv(shdr_pos, cap);
+ if (proj_ok[2]) {
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ immVertex2fv(shdr_pos_2d, cap);
+ }
- immEnd();
+ immEnd();
+ }
GPU_blend(false);
}
@@ -824,10 +877,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
posit[1] -= numstr_size[1] / 2.0f;
/* draw text (bg) */
- {
+ if (proj_ok[0] && proj_ok[2]) {
immUniformColor4fv(color_back);
GPU_blend(true);
- immRectf(shdr_pos,
+ immRectf(shdr_pos_2d,
posit[0] - bg_margin,
posit[1] - bg_margin,
posit[0] + bg_margin + numstr_size[0],
@@ -838,7 +891,7 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
immUnbindProgram();
/* draw text */
- {
+ if (proj_ok[0] && proj_ok[2]) {
BLF_color3ubv(blf_mono_font, color_text);
BLF_position(blf_mono_font, posit[0], posit[1], 0.0f);
BLF_draw(blf_mono_font, numstr, sizeof(numstr));
@@ -849,27 +902,10 @@ static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz)
BLF_disable(blf_mono_font, BLF_ROTATION);
-#undef ARC_STEPS
-
- /* draw snap */
- if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG) &&
- (ruler_item->gz.interaction_data != NULL)) {
- RulerInteraction *inter = ruler_item->gz.interaction_data;
- /* size from drawSnapping */
- const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- float co_ss_snap[3];
- ED_view3d_project_float_global(
- region, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP);
-
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor3(TH_GIZMO_VIEW_ALIGN);
-
- imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32);
-
- immUnbindProgram();
- }
+#undef ARC_STEPS
}
static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2])
@@ -902,35 +938,36 @@ static int gizmo_ruler_modal(bContext *C,
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
ARegion *region = CTX_wm_region(C);
- bool do_cursor_update = false;
+ bool do_cursor_update = (event->val == KM_RELEASE) || (event->type == MOUSEMOVE);
ruler_info->region = region;
- switch (event->type) {
- case MOUSEMOVE: {
- do_cursor_update = true;
- break;
- }
- }
-
- const bool do_snap = tweak_flag & WM_GIZMO_TWEAK_SNAP;
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ const bool do_snap = !(tweak_flag & WM_GIZMO_TWEAK_SNAP);
+#endif
const bool do_thickness = tweak_flag & WM_GIZMO_TWEAK_PRECISE;
- if ((ruler_info->drag_state_prev.do_snap != do_snap) ||
- (ruler_info->drag_state_prev.do_thickness != do_thickness)) {
+ if ((ruler_info->drag_state_prev.do_thickness != do_thickness)) {
do_cursor_update = true;
}
if (do_cursor_update) {
if (ruler_info->state == RULER_STATE_DRAG) {
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- if (view3d_ruler_item_mousemove(
- depsgraph, ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
+ if (view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item,
+ event->mval,
+ do_thickness
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ do_snap
+#endif
+ )) {
do_draw = true;
}
}
}
- ruler_info->drag_state_prev.do_snap = do_snap;
ruler_info->drag_state_prev.do_thickness = do_thickness;
if (do_draw) {
@@ -957,7 +994,7 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
/* Add Center Point */
ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
inter->co_index = 1;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+ ruler_state_set(ruler_info, RULER_STATE_DRAG);
/* find the factor */
{
@@ -978,13 +1015,21 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
/* update the new location */
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- view3d_ruler_item_mousemove(
- depsgraph, ruler_info, ruler_item_pick, event->mval, false, false);
+ view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item_pick,
+ event->mval,
+ false
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ false
+#endif
+ );
}
}
else {
inter->co_index = gz->highlight_part;
- ruler_state_set(C, ruler_info, RULER_STATE_DRAG);
+ ruler_state_set(ruler_info, RULER_STATE_DRAG);
/* store the initial depth */
copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]);
@@ -997,6 +1042,28 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE;
}
+ {
+ /* Set Snap prev point. */
+ float *prev_point;
+ if (ruler_item_pick->flag & RULERITEM_USE_ANGLE) {
+ prev_point = (inter->co_index != 1) ? ruler_item_pick->co[1] : NULL;
+ }
+ else if (inter->co_index == 0) {
+ prev_point = ruler_item_pick->co[2];
+ }
+ else {
+ prev_point = ruler_item_pick->co[0];
+ }
+
+ if (prev_point) {
+ RNA_property_float_set_array(
+ ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
+ }
+ else {
+ RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
+ }
+ }
+
ruler_info->item_active = ruler_item_pick;
return OPERATOR_RUNNING_MODAL;
@@ -1009,10 +1076,9 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
if (!cancel) {
if (ruler_info->state == RULER_STATE_DRAG) {
- if (ruler_info->snap_flag & RULER_SNAP_OK) {
- ruler_info->snap_flag &= ~RULER_SNAP_OK;
- }
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ WM_gizmo_set_flag(ruler_info->snap_data.gizmo, WM_GIZMO_HIDDEN, false);
+ RNA_property_unset(ruler_info->snap_data.gizmo->ptr, ruler_info->snap_data.prop_prevpoint);
+ ruler_state_set(ruler_info, RULER_STATE_NORMAL);
}
/* We could convert only the current gizmo, for now just re-generate. */
view3d_ruler_to_gpencil(C, gzgroup);
@@ -1022,7 +1088,7 @@ static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel)
MEM_SAFE_FREE(gz->interaction_data);
}
- ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
+ ruler_state_set(ruler_info, RULER_STATE_NORMAL);
}
static int gizmo_ruler_cursor_get(wmGizmo *gz)
@@ -1059,16 +1125,39 @@ static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__);
+ wmGizmo *gizmo;
+ {
+ /* The gizmo snap has to be the first gizmo. */
+ const wmGizmoType *gzt_snap;
+ gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
+ gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
+ RNA_enum_set(gizmo->ptr,
+ "snap_elements_force",
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
+
+ WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+
+ wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_ruler_add", true);
+ WM_gizmo_operator_set(gizmo, 0, ot, NULL);
+ }
+
if (view3d_ruler_from_gpencil(C, gzgroup)) {
/* nop */
}
+ wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
+
+ ruler_info->wm = wm;
ruler_info->win = win;
- ruler_info->sa = sa;
+ ruler_info->area = area;
ruler_info->region = region;
+ ruler_info->snap_data.gizmo = gizmo;
+ ruler_info->snap_data.prop_prevpoint = RNA_struct_find_property(gizmo->ptr, "prev_point");
gzgroup->customdata = ruler_info;
}
@@ -1078,7 +1167,7 @@ void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt)
gzgt->name = "Ruler Widgets";
gzgt->idname = view3d_gzgt_ruler_id;
- gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
@@ -1132,8 +1221,20 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* snap the first point added, not essential but handy */
inter->co_index = 0;
- view3d_ruler_item_mousemove(depsgraph, ruler_info, ruler_item, event->mval, false, true);
+ view3d_ruler_item_mousemove(depsgraph,
+ ruler_info,
+ ruler_item,
+ event->mval,
+ false
+#ifndef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ ,
+ true
+#endif
+ );
copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]);
+ RNA_property_float_set_array(ruler_info->snap_data.gizmo->ptr,
+ ruler_info->snap_data.prop_prevpoint,
+ inter->drag_start_co);
}
else {
negate_v3_v3(inter->drag_start_co, rv3d->ofs);
@@ -1152,6 +1253,7 @@ void VIEW3D_OT_ruler_add(wmOperatorType *ot)
/* identifiers */
ot->name = "Ruler Add";
ot->idname = "VIEW3D_OT_ruler_add";
+ ot->description = "Add ruler";
ot->invoke = view3d_ruler_add_invoke;
ot->poll = view3d_ruler_poll;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 57989680705..829d793333e 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -77,7 +77,8 @@ static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op))
else {
Scene *scene = CTX_data_scene(C);
scene->display.shading.flag ^= V3D_SHADING_MATCAP_FLIP_X;
- WM_event_add_notifier(C, NC_SCENE | NA_EDITED, v3d);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
}
return OPERATOR_FINISHED;
@@ -105,7 +106,7 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
wmWindow *win = CTX_wm_window(C);
const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
- /* watch it: if sa->win does not exist, check that when calling direct drawing routines */
+ /* watch it: if area->win does not exist, check that when calling direct drawing routines */
switch (event) {
case B_SEL_VERT:
@@ -138,10 +139,11 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
if (obedit && (obedit->type == OB_MESH)) {
BMEditMesh *em = BKE_editmesh_from_object(obedit);
uiLayout *row;
+ uiBut *but;
row = uiLayoutRow(layout, true);
block = uiLayoutGetBlock(row);
- uiDefIconButBitS(
+ but = uiDefIconButBitS(
block,
UI_BTYPE_TOGGLE,
SCE_SELECT_VERTEX,
@@ -157,23 +159,26 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
0,
0,
TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
- uiDefIconButBitS(block,
- UI_BTYPE_TOGGLE,
- SCE_SELECT_EDGE,
- B_SEL_EDGE,
- ICON_EDGESEL,
- 0,
- 0,
- ceilf(UI_UNIT_X - U.pixelsize),
- UI_UNIT_Y,
- &em->selectmode,
- 1.0,
- 0.0,
- 0,
- 0,
- TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click "
- "expands/contracts selection"));
- uiDefIconButBitS(
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ but = uiDefIconButBitS(
+ block,
+ UI_BTYPE_TOGGLE,
+ SCE_SELECT_EDGE,
+ B_SEL_EDGE,
+ ICON_EDGESEL,
+ 0,
+ 0,
+ ceilf(UI_UNIT_X - U.pixelsize),
+ UI_UNIT_Y,
+ &em->selectmode,
+ 1.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Edge select - Shift-Click for multiple modes, "
+ "Ctrl-Click expands/contracts selection depending on the current mode"));
+ UI_but_flag_disable(but, UI_BUT_UNDO);
+ but = uiDefIconButBitS(
block,
UI_BTYPE_TOGGLE,
SCE_SELECT_FACE,
@@ -189,6 +194,7 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
0,
0,
TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
+ UI_but_flag_disable(but, UI_BUT_UNDO);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 610c40c37eb..50cd71d7edc 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -91,8 +91,8 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot);
-void view3d_boxview_copy(struct ScrArea *sa, struct ARegion *region);
-void view3d_boxview_sync(struct ScrArea *sa, struct ARegion *region);
+void view3d_boxview_copy(struct ScrArea *area, struct ARegion *region);
+void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region);
void view3d_orbit_apply_dyn_ofs(float r_ofs[3],
const float ofs_old[3],
@@ -181,7 +181,7 @@ typedef struct V3D_SmoothParams {
void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph,
struct wmWindowManager *wm,
struct wmWindow *win,
- struct ScrArea *sa,
+ struct ScrArea *area,
struct View3D *v3d,
struct ARegion *region,
const int smooth_viewtx,
@@ -213,6 +213,7 @@ void viewrotate_modal_keymap(struct wmKeyConfig *keyconf);
void viewmove_modal_keymap(struct wmKeyConfig *keyconf);
void viewzoom_modal_keymap(struct wmKeyConfig *keyconf);
void viewdolly_modal_keymap(struct wmKeyConfig *keyconf);
+void viewplace_modal_keymap(struct wmKeyConfig *keyconf);
/* view3d_buttons.c */
void VIEW3D_OT_object_mode_pie_or_toggle(struct wmOperatorType *ot);
@@ -243,6 +244,9 @@ void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_active(struct wmOperatorType *ot);
+/* view3d_placement.c */
+void VIEW3D_OT_interactive_add(struct wmOperatorType *ot);
+
/* space_view3d.c */
extern const char *view3d_context_dir[]; /* doc access */
@@ -268,6 +272,8 @@ void VIEW3D_OT_ruler_remove(struct wmOperatorType *ot);
void VIEW3D_GT_navigate_rotate(struct wmGizmoType *gzt);
+void VIEW3D_GGT_placement(struct wmGizmoGroupType *gzgt);
+
/* workaround for trivial but noticeable camera bug caused by imprecision
* between view border calculation in 2D/3D space, workaround for bug [#28037].
* without this define we get the old behavior which is to try and align them
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index d8e1c8c1c72..91e629147f4 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -126,7 +126,7 @@ void meshobject_foreachScreenVert(
Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph);
Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
- me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
+ me = mesh_get_eval_final(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -388,7 +388,7 @@ void mesh_foreachScreenFace(
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
- if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) {
+ if (BKE_modifiers_uses_subsurf_facedots(vc->scene, vc->obedit)) {
BKE_mesh_foreach_mapped_subdiv_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}
@@ -406,6 +406,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co_b[2]),
void *userData,
const eV3DProjTest clip_flag)
@@ -414,6 +415,8 @@ void nurbs_foreachScreenVert(ViewContext *vc,
Nurb *nu;
int i;
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ /* If no point in the triple is selected, the handles are invisible. */
+ const bool only_selected = (vc->v3d->overlay.handle_display == CURVE_HANDLE_SELECTED);
ED_view3d_check_mats_rv3d(vc->rv3d);
@@ -427,15 +430,17 @@ void nurbs_foreachScreenVert(ViewContext *vc,
BezTriple *bezt = &nu->bezt[i];
if (bezt->hide == 0) {
+ const bool handles_visible = (vc->v3d->overlay.handle_display != CURVE_HANDLE_NONE) &&
+ (!only_selected || BEZT_ISSEL_ANY(bezt));
float screen_co[2];
- if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+ if (!handles_visible) {
if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 1, screen_co);
+ func(userData, nu, NULL, bezt, 1, false, screen_co);
}
}
else {
@@ -444,21 +449,21 @@ void nurbs_foreachScreenVert(ViewContext *vc,
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 0, screen_co);
+ func(userData, nu, NULL, bezt, 0, true, screen_co);
}
if (ED_view3d_project_float_object(vc->region,
bezt->vec[1],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 1, screen_co);
+ func(userData, nu, NULL, bezt, 1, true, screen_co);
}
if (ED_view3d_project_float_object(vc->region,
bezt->vec[2],
screen_co,
V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, NULL, bezt, 2, screen_co);
+ func(userData, nu, NULL, bezt, 2, true, screen_co);
}
}
}
@@ -473,7 +478,7 @@ void nurbs_foreachScreenVert(ViewContext *vc,
if (ED_view3d_project_float_object(
vc->region, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) ==
V3D_PROJ_RET_OK) {
- func(userData, nu, bp, NULL, -1, screen_co);
+ func(userData, nu, bp, NULL, -1, false, screen_co);
}
}
}
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index a53262df267..0770bac1313 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -47,6 +47,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_transform.h"
@@ -117,6 +118,7 @@ static int view3d_pastebuffer_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_WINDOW, NULL);
+ ED_outliner_select_sync_from_object_tag(C);
BKE_reportf(op->reports, RPT_INFO, "%d object(s) pasted", num_pasted);
@@ -209,6 +211,8 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active);
+ WM_operatortype_append(VIEW3D_OT_interactive_add);
+
WM_operatortype_append(VIEW3D_OT_toggle_shading);
WM_operatortype_append(VIEW3D_OT_toggle_xray);
WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip);
@@ -232,4 +236,5 @@ void view3d_keymap(wmKeyConfig *keyconf)
viewmove_modal_keymap(keyconf);
viewzoom_modal_keymap(keyconf);
viewdolly_modal_keymap(keyconf);
+ viewplace_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
new file mode 100644
index 00000000000..f2b78bc2aaf
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -0,0 +1,1153 @@
+/*
+ * 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
+ * of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/** \file
+ * \ingroup spview3d
+ *
+ * Operator to interactively place data.
+ *
+ * Currently only adds meshes, but could add other kinds of data
+ * including library assets & non-mesh types.
+ */
+
+#include "BLI_math_vector.h"
+#include "MEM_guardedalloc.h"
+
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_vfont_types.h"
+
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_main.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_toolsystem.h"
+#include "WM_types.h"
+
+#include "ED_gizmo_library.h"
+#include "ED_gizmo_utils.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
+#include "GPU_state.h"
+
+#include "view3d_intern.h"
+
+static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
+
+/* -------------------------------------------------------------------- */
+/** \name Local Types
+ * \{ */
+
+enum ePlace_PrimType {
+ PLACE_PRIMITIVE_TYPE_CUBE = 1,
+ PLACE_PRIMITIVE_TYPE_CYLINDER = 2,
+ PLACE_PRIMITIVE_TYPE_CONE = 3,
+ PLACE_PRIMITIVE_TYPE_SPHERE_UV = 4,
+ PLACE_PRIMITIVE_TYPE_SPHERE_ICO = 5,
+};
+
+enum ePlace_Origin {
+ PLACE_ORIGIN_BASE = 1,
+ PLACE_ORIGIN_CENTER = 2,
+};
+
+enum ePlace_Depth {
+ PLACE_DEPTH_SURFACE = 1,
+ PLACE_DEPTH_CURSOR_PLANE = 2,
+ PLACE_DEPTH_CURSOR_VIEW = 3,
+};
+
+struct InteractivePlaceData {
+ /* Window manager variables (set these even when waiting for input). */
+ Scene *scene;
+ ScrArea *area;
+ View3D *v3d;
+ ARegion *region;
+
+ /** Draw object preview region draw callback. */
+ void *draw_handle_view;
+
+ float co_src[3];
+
+ /** Primary & secondary steps. */
+ struct {
+ bool is_centered;
+ bool is_fixed_aspect;
+ float plane[4];
+ float co_dst[3];
+ } step[2];
+
+ float matrix_orient[3][3];
+ int orient_axis;
+
+ /** The tool option, if we start centered, invert toggling behavior. */
+ bool is_centered_init;
+
+ bool use_snap, is_snap_found, is_snap_invert;
+ float snap_co[3];
+
+ /** Can index into #InteractivePlaceData.step. */
+ enum {
+ STEP_BASE = 0,
+ STEP_DEPTH = 1,
+ } step_index;
+
+ enum ePlace_PrimType primitive_type;
+
+ /** Activated from the tool-system. */
+ bool use_tool;
+
+ /** Event used to start the operator. */
+ short launch_event;
+
+ /** When activated without a tool. */
+ bool wait_for_input;
+
+ /** Optional snap gizmo, needed for snapping. */
+ wmGizmo *snap_gizmo;
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
+
+/* On-screen snap distance. */
+#define MVAL_MAX_PX_DIST 12.0f
+
+static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
+{
+ if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
+ PropertyRNA *prop_location = RNA_struct_find_property(gz->ptr, "location");
+ RNA_property_float_get_array(gz->ptr, prop_location, r_location);
+ return true;
+ }
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Primitive Drawing (Cube, Cone, Cylinder...)
+ * \{ */
+
+static void draw_line_loop(float coords[][3], int coords_len, const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, coords_len);
+
+ for (int i = 0; i < coords_len; i++) {
+ GPU_vertbuf_attr_set(vert, pos, i, coords[i]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static void draw_line_pairs(float coords_a[][3],
+ float coords_b[][3],
+ int coords_len,
+ const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, coords_len * 2);
+
+ for (int i = 0; i < coords_len; i++) {
+ GPU_vertbuf_attr_set(vert, pos, i * 2, coords_a[i]);
+ GPU_vertbuf_attr_set(vert, pos, (i * 2) + 1, coords_b[i]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINES, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static void draw_line_bounds(const BoundBox *bounds, const float color[4])
+{
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ int edges[12][2] = {
+ /* First side. */
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 0},
+ /* Second side. */
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 4},
+ /* Edges between. */
+ {0, 4},
+ {1, 5},
+ {2, 6},
+ {3, 7},
+ };
+
+ GPUVertBuf *vert = GPU_vertbuf_create_with_format(format);
+ GPU_vertbuf_data_alloc(vert, ARRAY_SIZE(edges) * 2);
+
+ for (int i = 0, j = 0; i < ARRAY_SIZE(edges); i++) {
+ GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][0]]);
+ GPU_vertbuf_attr_set(vert, pos, j++, bounds->vec[edges[i][1]]);
+ }
+
+ GPU_blend(true);
+ GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_LINES, vert, NULL, GPU_BATCH_OWNS_VBO);
+ GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR);
+
+ GPU_batch_bind(batch);
+
+ GPU_batch_uniform_4fv(batch, "color", color);
+
+ float viewport[4];
+ GPU_viewport_size_get_f(viewport);
+ GPU_batch_uniform_2fv(batch, "viewportSize", &viewport[2]);
+ GPU_batch_uniform_1f(batch, "lineWidth", U.pixelsize);
+
+ GPU_batch_draw(batch);
+
+ GPU_batch_program_use_end(batch);
+
+ GPU_batch_discard(batch);
+ GPU_blend(false);
+}
+
+static bool calc_bbox(struct InteractivePlaceData *ipd, BoundBox *bounds)
+{
+ memset(bounds, 0x0, sizeof(*bounds));
+
+ if (compare_v3v3(ipd->co_src, ipd->step[0].co_dst, FLT_EPSILON)) {
+ return false;
+ }
+
+ float matrix_orient_inv[3][3];
+ invert_m3_m3(matrix_orient_inv, ipd->matrix_orient);
+
+ const int x_axis = (ipd->orient_axis + 1) % 3;
+ const int y_axis = (ipd->orient_axis + 2) % 3;
+
+ float quad_base[4][3];
+ float quad_secondary[4][3];
+
+ copy_v3_v3(quad_base[0], ipd->co_src);
+ copy_v3_v3(quad_base[2], ipd->step[0].co_dst);
+
+ /* Only set when we have a fixed aspect. */
+ float fixed_aspect_dimension;
+
+ /* *** Primary *** */
+
+ {
+ float delta_local[3];
+ float delta_a[3];
+ float delta_b[3];
+
+ sub_v3_v3v3(delta_local, ipd->step[0].co_dst, ipd->co_src);
+ mul_m3_v3(matrix_orient_inv, delta_local);
+
+ copy_v3_v3(delta_a, delta_local);
+ copy_v3_v3(delta_b, delta_local);
+ delta_a[ipd->orient_axis] = 0.0f;
+ delta_b[ipd->orient_axis] = 0.0f;
+
+ delta_a[x_axis] = 0.0f;
+ delta_b[y_axis] = 0.0f;
+
+ /* Assign here in case secondary */
+ fixed_aspect_dimension = max_ff(fabsf(delta_a[y_axis]), fabsf(delta_b[x_axis]));
+
+ if (ipd->step[0].is_fixed_aspect) {
+ delta_a[y_axis] = copysignf(fixed_aspect_dimension, delta_a[y_axis]);
+ delta_b[x_axis] = copysignf(fixed_aspect_dimension, delta_b[x_axis]);
+ }
+
+ mul_m3_v3(ipd->matrix_orient, delta_a);
+ mul_m3_v3(ipd->matrix_orient, delta_b);
+
+ if (ipd->step[0].is_fixed_aspect) {
+ /* Recalculate the destination point. */
+ copy_v3_v3(quad_base[2], ipd->co_src);
+ add_v3_v3(quad_base[2], delta_a);
+ add_v3_v3(quad_base[2], delta_b);
+ }
+
+ add_v3_v3v3(quad_base[1], ipd->co_src, delta_a);
+ add_v3_v3v3(quad_base[3], ipd->co_src, delta_b);
+ }
+
+ if (ipd->step[0].is_centered) {
+ /* Use a copy in case aspect was applied to the quad. */
+ float base_co_dst[3];
+ copy_v3_v3(base_co_dst, quad_base[2]);
+ for (int i = 0; i < 4; i++) {
+ sub_v3_v3(quad_base[i], base_co_dst);
+ mul_v3_fl(quad_base[i], 2.0f);
+ add_v3_v3(quad_base[i], base_co_dst);
+ }
+ }
+
+ /* *** Secondary *** */
+
+ float delta_local[3];
+ if (ipd->step_index == STEP_DEPTH) {
+ sub_v3_v3v3(delta_local, ipd->step[1].co_dst, ipd->step[0].co_dst);
+ }
+ else {
+ zero_v3(delta_local);
+ }
+
+ if (ipd->step[1].is_fixed_aspect) {
+ if (!is_zero_v3(delta_local)) {
+ normalize_v3_length(delta_local, fixed_aspect_dimension);
+ }
+ }
+
+ if (ipd->step[1].is_centered) {
+ for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
+ sub_v3_v3(quad_base[i], delta_local);
+ }
+ mul_v3_fl(delta_local, 2.0f);
+ }
+
+ if ((ipd->step_index == STEP_DEPTH) &&
+ (compare_v3v3(ipd->step[0].co_dst, ipd->step[1].co_dst, FLT_EPSILON) == false)) {
+
+ for (int i = 0; i < ARRAY_SIZE(quad_base); i++) {
+ add_v3_v3v3(quad_secondary[i], quad_base[i], delta_local);
+ }
+ }
+ else {
+ copy_v3_v3(quad_secondary[0], quad_base[0]);
+ copy_v3_v3(quad_secondary[1], quad_base[1]);
+ copy_v3_v3(quad_secondary[2], quad_base[2]);
+ copy_v3_v3(quad_secondary[3], quad_base[3]);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ copy_v3_v3(bounds->vec[i], quad_base[i]);
+ copy_v3_v3(bounds->vec[i + 4], quad_secondary[i]);
+ }
+
+ return true;
+}
+
+static void draw_circle_in_quad(const float v1[2],
+ const float v2[2],
+ const float v3[2],
+ const float v4[2],
+ const int resolution,
+ const float color[4])
+{
+ /* This isn't so efficient. */
+ const float quad[4][2] = {
+ {-1, -1},
+ {+1, -1},
+ {+1, +1},
+ {-1, +1},
+ };
+
+ float(*coords)[3] = MEM_mallocN(sizeof(float[3]) * (resolution + 1), __func__);
+ for (int i = 0; i <= resolution; i++) {
+ float theta = ((2.0f * M_PI) * ((float)i / (float)resolution)) + 0.01f;
+ float x = cosf(theta);
+ float y = sinf(theta);
+ float pt[2] = {x, y};
+ float w[4];
+ barycentric_weights_v2_quad(UNPACK4(quad), pt, w);
+
+ float *co = coords[i];
+ zero_v3(co);
+ madd_v3_v3fl(co, v1, w[0]);
+ madd_v3_v3fl(co, v2, w[1]);
+ madd_v3_v3fl(co, v3, w[2]);
+ madd_v3_v3fl(co, v4, w[3]);
+ }
+ draw_line_loop(coords, resolution + 1, color);
+ MEM_freeN(coords);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Drawing Callbacks
+ * \{ */
+
+static void draw_primitive_view_impl(const struct bContext *C,
+ struct InteractivePlaceData *ipd,
+ const float color[4])
+{
+ UNUSED_VARS(C);
+
+ BoundBox bounds;
+ calc_bbox(ipd, &bounds);
+ draw_line_bounds(&bounds, color);
+
+ if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CUBE) {
+ /* pass */
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
+ draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
+ draw_circle_in_quad(UNPACK4((&bounds.vec[4])), 32, color);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
+ draw_circle_in_quad(UNPACK4(bounds.vec), 32, color);
+
+ float center[3];
+ mid_v3_v3v3v3v3(center, UNPACK4((&bounds.vec[4])));
+
+ float coords_a[4][3];
+ float coords_b[4][3];
+
+ for (int i = 0; i < 4; i++) {
+ copy_v3_v3(coords_a[i], center);
+ mid_v3_v3v3(coords_b[i], bounds.vec[i], bounds.vec[(i + 1) % 4]);
+ }
+
+ draw_line_pairs(coords_a, coords_b, 4, color);
+ }
+ else if (ELEM(ipd->primitive_type,
+ PLACE_PRIMITIVE_TYPE_SPHERE_UV,
+ PLACE_PRIMITIVE_TYPE_SPHERE_ICO)) {
+ /* See bound-box diagram for reference. */
+
+ /* Primary Side. */
+ float v01[3], v12[3], v23[3], v30[3];
+ mid_v3_v3v3(v01, bounds.vec[0], bounds.vec[1]);
+ mid_v3_v3v3(v12, bounds.vec[1], bounds.vec[2]);
+ mid_v3_v3v3(v23, bounds.vec[2], bounds.vec[3]);
+ mid_v3_v3v3(v30, bounds.vec[3], bounds.vec[0]);
+ /* Secondary Side. */
+ float v45[3], v56[3], v67[3], v74[3];
+ mid_v3_v3v3(v45, bounds.vec[4], bounds.vec[5]);
+ mid_v3_v3v3(v56, bounds.vec[5], bounds.vec[6]);
+ mid_v3_v3v3(v67, bounds.vec[6], bounds.vec[7]);
+ mid_v3_v3v3(v74, bounds.vec[7], bounds.vec[4]);
+ /* Edges between. */
+ float v04[3], v15[3], v26[3], v37[3];
+ mid_v3_v3v3(v04, bounds.vec[0], bounds.vec[4]);
+ mid_v3_v3v3(v15, bounds.vec[1], bounds.vec[5]);
+ mid_v3_v3v3(v26, bounds.vec[2], bounds.vec[6]);
+ mid_v3_v3v3(v37, bounds.vec[3], bounds.vec[7]);
+
+ draw_circle_in_quad(v01, v45, v67, v23, 32, color);
+ draw_circle_in_quad(v30, v12, v56, v74, 32, color);
+ draw_circle_in_quad(v04, v15, v26, v37, 32, color);
+ }
+}
+
+static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region), void *arg)
+{
+ struct InteractivePlaceData *ipd = arg;
+ float color[4];
+ UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, color);
+
+ const bool use_depth = !XRAY_ENABLED(ipd->v3d);
+ const bool depth_test_enabled = GPU_depth_test_enabled();
+
+ if (use_depth) {
+ GPU_depth_test(false);
+ color[3] = 0.15f;
+ draw_primitive_view_impl(C, ipd, color);
+ }
+
+ if (use_depth) {
+ GPU_depth_test(true);
+ }
+ color[3] = 1.0f;
+ draw_primitive_view_impl(C, ipd, color);
+
+ if (use_depth) {
+ if (depth_test_enabled == false) {
+ GPU_depth_test(false);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Object Modal Operator
+ * \{ */
+
+/**
+ *
+ * */
+static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
+{
+
+ const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
+ const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
+ const enum ePlace_Origin plane_origin = RNA_enum_get(op->ptr, "plane_origin");
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ RegionView3D *rv3d = ipd->region->regiondata;
+
+ ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
+
+ ED_transform_calc_orientation_from_type(C, ipd->matrix_orient);
+
+ ipd->orient_axis = plane_axis;
+ ipd->is_centered_init = (plane_origin == PLACE_ORIGIN_CENTER);
+ ipd->step[0].is_centered = ipd->is_centered_init;
+ ipd->step[1].is_centered = ipd->is_centered_init;
+ ipd->step_index = STEP_BASE;
+
+ /* Assign snap gizmo which is may be used as part of the tool. */
+ {
+ wmGizmoMap *gzmap = ipd->region->gizmo_map;
+ wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
+ if ((gzgroup != NULL) && gzgroup->gizmos.first) {
+ ipd->snap_gizmo = gzgroup->gizmos.first;
+ }
+ }
+
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "primitive_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ ipd->primitive_type = RNA_property_enum_get(op->ptr, prop);
+ ipd->use_tool = false;
+ }
+ else {
+ ipd->use_tool = true;
+
+ /* Get from the tool, a bit of a non-standard way of operating. */
+ const bToolRef *tref = ipd->area->runtime.tool;
+ if (tref && STREQ(tref->idname, "builtin.primitive_cube_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CUBE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_cylinder_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CYLINDER;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_cone_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CONE;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_uv_sphere_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_SPHERE_UV;
+ }
+ else if (tref && STREQ(tref->idname, "builtin.primitive_ico_sphere_add")) {
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_SPHERE_ICO;
+ }
+ else {
+ /* If the user runs this as an operator they should set the 'primitive_type',
+ * however running from operator search will end up at this point. */
+ ipd->primitive_type = PLACE_PRIMITIVE_TYPE_CUBE;
+ ipd->use_tool = false;
+ }
+ }
+ }
+
+ UNUSED_VARS(C, event);
+
+ ipd->draw_handle_view = ED_region_draw_cb_activate(
+ ipd->region->type, draw_primitive_view, ipd, REGION_DRAW_POST_VIEW);
+
+ ED_region_tag_redraw(ipd->region);
+
+ plane_from_point_normal_v3(
+ ipd->step[0].plane, ipd->scene->cursor.location, ipd->matrix_orient[ipd->orient_axis]);
+
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ const bool is_snap_found = ipd->snap_gizmo ?
+ idp_snap_point_from_gizmo(ipd->snap_gizmo, ipd->co_src) :
+ false;
+ ipd->is_snap_invert = ipd->snap_gizmo ? ED_gizmotypes_snap_3d_invert_snap_get(ipd->snap_gizmo) :
+ false;
+ {
+ const ToolSettings *ts = ipd->scene->toolsettings;
+ ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
+ }
+
+ if (is_snap_found) {
+ /* pass */
+ }
+ else {
+ bool use_depth_fallback = true;
+ if (plane_depth == PLACE_DEPTH_CURSOR_VIEW) {
+ /* View plane. */
+ ED_view3d_win_to_3d(
+ ipd->v3d, ipd->region, ipd->scene->cursor.location, mval_fl, ipd->co_src);
+ use_depth_fallback = false;
+ }
+ else if (plane_depth == PLACE_DEPTH_SURFACE) {
+ SnapObjectContext *snap_context =
+ (ipd->snap_gizmo ? ED_gizmotypes_snap_3d_context_ensure(
+ ipd->scene, ipd->region, ipd->v3d, ipd->snap_gizmo) :
+ NULL);
+ if ((snap_context != NULL) &&
+ ED_transform_snap_object_project_view3d(snap_context,
+ CTX_data_ensure_evaluated_depsgraph(C),
+ SCE_SNAP_MODE_FACE,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ .use_object_edit_cage = true,
+ },
+ mval_fl,
+ NULL,
+ NULL,
+ ipd->co_src,
+ NULL)) {
+ use_depth_fallback = false;
+ }
+ }
+
+ /* Use as fallback to surface. */
+ if (use_depth_fallback || (plane_depth == PLACE_DEPTH_CURSOR_PLANE)) {
+ /* Cursor plane. */
+ float plane[4];
+ plane_from_point_normal_v3(
+ plane, ipd->scene->cursor.location, ipd->matrix_orient[ipd->orient_axis]);
+ if (ED_view3d_win_to_3d_on_plane(ipd->region, plane, mval_fl, false, ipd->co_src)) {
+ use_depth_fallback = false;
+ }
+ /* Even if the calculation works, it's possible the point found is behind the view. */
+ if (rv3d->is_persp) {
+ float dir[3];
+ sub_v3_v3v3(dir, rv3d->viewinv[3], ipd->co_src);
+ if (dot_v3v3(dir, rv3d->viewinv[2]) < ipd->v3d->clip_start) {
+ use_depth_fallback = true;
+ }
+ }
+ }
+
+ if (use_depth_fallback) {
+ float co_depth[3];
+ /* Fallback to view center. */
+ negate_v3_v3(co_depth, rv3d->ofs);
+ ED_view3d_win_to_3d(ipd->v3d, ipd->region, co_depth, mval_fl, ipd->co_src);
+ }
+ }
+
+ plane_from_point_normal_v3(
+ ipd->step[0].plane, ipd->co_src, ipd->matrix_orient[ipd->orient_axis]);
+
+ copy_v3_v3(ipd->step[0].co_dst, ipd->co_src);
+}
+
+static int view3d_interactive_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const bool wait_for_input = RNA_boolean_get(op->ptr, "wait_for_input");
+
+ struct InteractivePlaceData *ipd = MEM_callocN(sizeof(*ipd), __func__);
+ op->customdata = ipd;
+
+ ipd->scene = CTX_data_scene(C);
+ ipd->area = CTX_wm_area(C);
+ ipd->region = CTX_wm_region(C);
+ ipd->v3d = CTX_wm_view3d(C);
+
+ if (wait_for_input) {
+ ipd->wait_for_input = true;
+ /* TODO: support snapping when not using with tool. */
+#if 0
+ WM_gizmo_group_type_ensure(view3d_gzgt_placement_id);
+#endif
+ }
+ else {
+ view3d_interactive_add_begin(C, op, event);
+ }
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
+{
+ UNUSED_VARS(C);
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ ED_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view);
+
+ ED_region_tag_redraw(ipd->region);
+
+ MEM_freeN(ipd);
+}
+
+static void view3d_interactive_add_cancel(bContext *C, wmOperator *op)
+{
+ view3d_interactive_add_exit(C, op);
+}
+
+enum {
+ PLACE_MODAL_SNAP_ON,
+ PLACE_MODAL_SNAP_OFF,
+ PLACE_MODAL_FIXED_ASPECT_ON,
+ PLACE_MODAL_FIXED_ASPECT_OFF,
+ PLACE_MODAL_PIVOT_CENTER_ON,
+ PLACE_MODAL_PIVOT_CENTER_OFF,
+};
+
+void viewplace_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {PLACE_MODAL_SNAP_ON, "SNAP_ON", 0, "Snap On", ""},
+ {PLACE_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""},
+ {PLACE_MODAL_FIXED_ASPECT_ON, "FIXED_ASPECT_ON", 0, "Fixed Aspect On", ""},
+ {PLACE_MODAL_FIXED_ASPECT_OFF, "FIXED_ASPECT_OFF", 0, "Fixed Aspect Off", ""},
+ {PLACE_MODAL_PIVOT_CENTER_ON, "PIVOT_CENTER_ON", 0, "Center Pivot On", ""},
+ {PLACE_MODAL_PIVOT_CENTER_OFF, "PIVOT_CENTER_OFF", 0, "Center Pivot Off", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ const char *keymap_name = "View3D Placement Modal Map";
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name);
+
+ /* This function is called for each space-type, only needs to add map once. */
+ if (keymap && keymap->modal_items) {
+ return;
+ }
+
+ keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items);
+
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_interactive_add");
+}
+
+static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ UNUSED_VARS(C, op);
+
+ struct InteractivePlaceData *ipd = op->customdata;
+
+ ARegion *region = ipd->region;
+ bool do_redraw = false;
+ bool do_cursor_update = false;
+
+ /* Handle modal key-map. */
+ if (event->type == EVT_MODAL_MAP) {
+ bool is_fallthrough = false;
+ switch (event->val) {
+ case PLACE_MODAL_FIXED_ASPECT_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_FIXED_ASPECT_OFF: {
+ ipd->step[ipd->step_index].is_fixed_aspect = is_fallthrough;
+ do_redraw = true;
+ break;
+ }
+ case PLACE_MODAL_PIVOT_CENTER_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_PIVOT_CENTER_OFF: {
+ ipd->step[ipd->step_index].is_centered = is_fallthrough;
+ do_redraw = true;
+ break;
+ }
+ case PLACE_MODAL_SNAP_ON: {
+ is_fallthrough = true;
+ ATTR_FALLTHROUGH;
+ }
+ case PLACE_MODAL_SNAP_OFF: {
+ const ToolSettings *ts = ipd->scene->toolsettings;
+ ipd->is_snap_invert = is_fallthrough;
+ ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
+ do_cursor_update = true;
+ break;
+ }
+ }
+ }
+
+ if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
+ view3d_interactive_add_exit(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ else if (event->type == MOUSEMOVE) {
+ do_cursor_update = true;
+ }
+
+ if (ipd->wait_for_input) {
+ if (ELEM(event->type, LEFTMOUSE)) {
+ if (event->val == KM_PRESS) {
+ view3d_interactive_add_begin(C, op, event);
+ ipd->wait_for_input = false;
+ return OPERATOR_RUNNING_MODAL;
+ }
+ }
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ if (ipd->step_index == STEP_BASE) {
+ if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
+ if (event->val == KM_RELEASE) {
+ /* Set secondary plane. */
+
+ /* Create normal. */
+ {
+ RegionView3D *rv3d = region->regiondata;
+ float no_temp[3];
+ float no[3];
+ cross_v3_v3v3(no_temp, ipd->step[0].plane, rv3d->viewinv[2]);
+ cross_v3_v3v3(no, no_temp, ipd->step[0].plane);
+ normalize_v3(no);
+
+ plane_from_point_normal_v3(ipd->step[1].plane, ipd->step[0].co_dst, no);
+ }
+
+ copy_v3_v3(ipd->step[1].co_dst, ipd->step[0].co_dst);
+ ipd->step_index = STEP_DEPTH;
+
+ /* Keep these values from the previous step. */
+ ipd->step[1].is_centered = ipd->step[0].is_centered;
+ ipd->step[1].is_fixed_aspect = ipd->step[0].is_fixed_aspect;
+ }
+ }
+ }
+ else if (ipd->step_index == STEP_DEPTH) {
+ if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) {
+ if (event->val == KM_PRESS) {
+
+ BoundBox bounds;
+ calc_bbox(ipd, &bounds);
+
+ float location[3];
+ float rotation[3];
+ float scale[3];
+
+ float matrix_orient_axis[3][3];
+ copy_m3_m3(matrix_orient_axis, ipd->matrix_orient);
+ if (ipd->orient_axis != 2) {
+ swap_v3_v3(matrix_orient_axis[2], matrix_orient_axis[ipd->orient_axis]);
+ swap_v3_v3(matrix_orient_axis[0], matrix_orient_axis[1]);
+ }
+ /* Needed for shapes where the sign matters (cone for eg). */
+ {
+ float delta[3];
+ sub_v3_v3v3(delta, bounds.vec[0], bounds.vec[4]);
+ if (dot_v3v3(ipd->matrix_orient[ipd->orient_axis], delta) > 0.0f) {
+ negate_v3(matrix_orient_axis[2]);
+
+ /* Only flip Y so we don't flip a single axis which causes problems. */
+ negate_v3(matrix_orient_axis[1]);
+ }
+ }
+
+ mat3_to_eul(rotation, matrix_orient_axis);
+
+ mid_v3_v3v3(location, bounds.vec[0], bounds.vec[6]);
+ const int cube_verts[3] = {3, 1, 4};
+ for (int i = 0; i < 3; i++) {
+ scale[i] = len_v3v3(bounds.vec[0], bounds.vec[cube_verts[i]]);
+ }
+
+ wmOperatorType *ot = NULL;
+ PointerRNA op_props;
+ if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CUBE) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cube_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CYLINDER) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cylinder_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_CONE) {
+ ot = WM_operatortype_find("MESH_OT_primitive_cone_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_SPHERE_UV) {
+ ot = WM_operatortype_find("MESH_OT_primitive_uv_sphere_add", false);
+ }
+ else if (ipd->primitive_type == PLACE_PRIMITIVE_TYPE_SPHERE_ICO) {
+ ot = WM_operatortype_find("MESH_OT_primitive_ico_sphere_add", false);
+ }
+
+ if (ot != NULL) {
+ WM_operator_properties_create_ptr(&op_props, ot);
+
+ if (ipd->use_tool) {
+ bToolRef *tref = ipd->area->runtime.tool;
+ PointerRNA temp_props;
+ WM_toolsystem_ref_properties_init_for_keymap(tref, &temp_props, &op_props, ot);
+ SWAP(PointerRNA, temp_props, op_props);
+ WM_operator_properties_free(&temp_props);
+ }
+
+ RNA_float_set_array(&op_props, "rotation", rotation);
+ RNA_float_set_array(&op_props, "location", location);
+ RNA_float_set_array(&op_props, "scale", scale);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props);
+ WM_operator_properties_free(&op_props);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ view3d_interactive_add_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ if (do_cursor_update) {
+ const float mval_fl[2] = {UNPACK2(event->mval)};
+
+ /* Calculate the snap location on mouse-move or when toggling snap. */
+ bool is_snap_found_prev = ipd->is_snap_found;
+ ipd->is_snap_found = false;
+ if (ipd->use_snap) {
+ if (ipd->snap_gizmo != NULL) {
+ ED_gizmotypes_snap_3d_toggle_set(ipd->snap_gizmo, ipd->use_snap);
+ if (ED_gizmotypes_snap_3d_update(ipd->snap_gizmo,
+ CTX_data_ensure_evaluated_depsgraph(C),
+ ipd->region,
+ ipd->v3d,
+ NULL,
+ mval_fl,
+ ipd->snap_co,
+ NULL)) {
+ ipd->is_snap_found = true;
+ }
+ ED_gizmotypes_snap_3d_toggle_clear(ipd->snap_gizmo);
+ }
+ }
+
+ /* Workaround because test_select doesn't run at the same time as the modal operator. */
+ if (is_snap_found_prev != ipd->is_snap_found) {
+ wmGizmoMap *gzmap = ipd->region->gizmo_map;
+ WM_gizmo_highlight_set(gzmap, ipd->is_snap_found ? ipd->snap_gizmo : NULL);
+ }
+
+ if (ipd->step_index == STEP_BASE) {
+ if (ipd->is_snap_found) {
+ closest_to_plane_normalized_v3(ipd->step[0].co_dst, ipd->step[0].plane, ipd->snap_co);
+ }
+ else {
+ if (ED_view3d_win_to_3d_on_plane(
+ region, ipd->step[0].plane, mval_fl, false, ipd->step[0].co_dst)) {
+ /* pass */
+ }
+ }
+ }
+ else if (ipd->step_index == STEP_DEPTH) {
+ if (ipd->is_snap_found) {
+ closest_to_plane_normalized_v3(ipd->step[1].co_dst, ipd->step[1].plane, ipd->snap_co);
+ }
+ else {
+ if (ED_view3d_win_to_3d_on_plane(
+ region, ipd->step[1].plane, mval_fl, false, ipd->step[1].co_dst)) {
+ /* pass */
+ }
+ }
+
+ /* Correct the point so it's aligned with the 'ipd->step[0].co_dst'. */
+ float close[3], delta[3];
+ closest_to_plane_normalized_v3(close, ipd->step[0].plane, ipd->step[1].co_dst);
+ sub_v3_v3v3(delta, close, ipd->step[0].co_dst);
+ sub_v3_v3(ipd->step[1].co_dst, delta);
+ }
+ do_redraw = true;
+ }
+
+ if (do_redraw) {
+ ED_region_tag_redraw(region);
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static bool view3d_interactive_add_poll(bContext *C)
+{
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+ return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH);
+}
+
+void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Primitive Object";
+ ot->description = "Interactively add an object";
+ ot->idname = "VIEW3D_OT_interactive_add";
+
+ /* api callbacks */
+ ot->invoke = view3d_interactive_add_invoke;
+ ot->modal = view3d_interactive_add_modal;
+ ot->cancel = view3d_interactive_add_cancel;
+ ot->poll = view3d_interactive_add_poll;
+
+ /* Note, let the operator we call handle undo and registering it's self. */
+ /* flags */
+ ot->flag = 0;
+
+ /* properties */
+ PropertyRNA *prop;
+
+ /* Normally not accessed directly, leave unset and check the active tool. */
+ static const EnumPropertyItem primitive_type[] = {
+ {PLACE_PRIMITIVE_TYPE_CUBE, "CUBE", 0, "Cube", ""},
+ {PLACE_PRIMITIVE_TYPE_CYLINDER, "CYLINDER", 0, "Cylinder", ""},
+ {PLACE_PRIMITIVE_TYPE_CONE, "CONE", 0, "Cone", ""},
+ {PLACE_PRIMITIVE_TYPE_SPHERE_UV, "SPHERE_UV", 0, "UV Sphere", ""},
+ {PLACE_PRIMITIVE_TYPE_SPHERE_ICO, "SPHERE_ICO", 0, "ICO Sphere", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "primitive_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Primitive", "");
+ RNA_def_property_enum_items(prop, primitive_type);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_property(ot->srna, "plane_axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Plane Axis", "The axis used for placing the base region");
+ RNA_def_property_enum_default(prop, 2);
+ RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ static const EnumPropertyItem plane_depth_items[] = {
+ {PLACE_DEPTH_SURFACE,
+ "SURFACE",
+ 0,
+ "Surface",
+ "Start placing on the surface, using the 3D cursor position as a fallback"},
+ {PLACE_DEPTH_CURSOR_PLANE,
+ "CURSOR_PLANE",
+ 0,
+ "3D Cursor Plane",
+ "Start placement using a point projected onto the selected axis at the 3D cursor position"},
+ {PLACE_DEPTH_CURSOR_VIEW,
+ "CURSOR_VIEW",
+ 0,
+ "3D Cursor View",
+ "Start placement using the mouse cursor projected onto the view plane"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "plane_depth", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Position", "The initial depth used when placing the cursor");
+ RNA_def_property_enum_default(prop, PLACE_DEPTH_SURFACE);
+ RNA_def_property_enum_items(prop, plane_depth_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ static const EnumPropertyItem origin_items[] = {
+ {PLACE_ORIGIN_BASE, "BASE", 0, "Base", "Start placing the corner position"},
+ {PLACE_ORIGIN_CENTER, "CENTER", 0, "Center", "Start placing the center position"},
+ {0, NULL, 0, NULL, NULL},
+ };
+ prop = RNA_def_property(ot->srna, "plane_origin", PROP_ENUM, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Origin", "The initial position for placement");
+ RNA_def_property_enum_default(prop, PLACE_ORIGIN_BASE);
+ RNA_def_property_enum_items(prop, origin_items);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ /* When not accessed via a tool. */
+ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Placement Gizmo Group
+ *
+ * This is currently only used for snapping before the tool is initialized,
+ * we could show a placement plane here.
+ * \{ */
+
+static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+{
+ wmGizmo *gizmo;
+
+ {
+ /* The gizmo snap has to be the first gizmo. */
+ const wmGizmoType *gzt_snap;
+ gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
+ gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
+ RNA_enum_set(gizmo->ptr,
+ "snap_elements_force",
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
+
+ WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+
+ /* Don't handle any events, this is for display only. */
+ gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP;
+ }
+}
+
+void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
+{
+ gzgt->name = "Placement Widget";
+ gzgt->idname = view3d_gzgt_placement_id;
+
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_placement_setup;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 8fdef585fa2..8c60e36a141 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -157,7 +157,7 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d)
{
bool changed = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->flag & BASE_SELECTED) {
if (BASE_SELECTABLE(v3d, base)) {
ED_object_base_select(base, BA_DESELECT);
@@ -172,7 +172,7 @@ static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d)
static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
{
bool changed = false;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
if (base->flag & BASE_SELECTED) {
if (b != base) {
ED_object_base_select(base, BA_DESELECT);
@@ -408,9 +408,10 @@ typedef struct LassoSelectUserData {
const rcti *rect;
const rctf *rect_fl;
rctf _rect_fl;
- const int (*mcords)[2];
- int moves;
+ const int (*mcoords)[2];
+ int mcoords_len;
eSelectOp sel_op;
+ eBezTriple_Flag select_flag;
/* runtime */
int pass;
@@ -421,8 +422,8 @@ typedef struct LassoSelectUserData {
static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
ViewContext *vc,
const rcti *rect,
- const int (*mcords)[2],
- const int moves,
+ const int (*mcoords)[2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
r_data->vc = vc;
@@ -431,9 +432,11 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data,
r_data->rect_fl = &r_data->_rect_fl;
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
- r_data->mcords = mcords;
- r_data->moves = moves;
+ r_data->mcoords = mcoords;
+ r_data->mcoords_len = mcoords_len;
r_data->sel_op = sel_op;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
/* runtime */
r_data->pass = 0;
@@ -527,7 +530,8 @@ static void do_lasso_select_pose__do_tag(void *userData,
if (screen_co_a[0] != IS_CLIPPED) {
points_proj_tot++;
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) {
is_point_done = true;
}
}
@@ -536,22 +540,28 @@ static void do_lasso_select_pose__do_tag(void *userData,
if (screen_co_b[0] != IS_CLIPPED) {
points_proj_tot++;
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) {
is_point_done = true;
}
}
/* if one of points selected, we skip the bone itself */
- if ((is_point_done == true) ||
- ((is_point_done == false) && (points_proj_tot == 2) &&
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) {
+ if ((is_point_done == true) || ((is_point_done == false) && (points_proj_tot == 2) &&
+ BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ INT_MAX))) {
pchan->bone->flag |= BONE_DONE;
}
data->is_changed |= is_point_done;
}
}
-static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves)
+static void do_lasso_tag_pose(ViewContext *vc,
+ Object *ob,
+ const int mcoords[][2],
+ const int mcoords_len)
{
ViewContext vc_tmp;
LassoSelectUserData data;
@@ -564,9 +574,9 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2]
vc_tmp = *vc;
vc_tmp.obact = ob;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, 0);
ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
@@ -574,8 +584,8 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2]
}
static bool do_lasso_select_objects(ViewContext *vc,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
View3D *v3d = vc->v3d;
@@ -591,7 +601,7 @@ static bool do_lasso_select_objects(ViewContext *vc,
const bool is_select = base->flag & BASE_SELECTED;
const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) &&
BLI_lasso_is_point_inside(
- mcords, moves, base->sx, base->sy, IS_CLIPPED));
+ mcoords, mcoords_len, base->sx, base->sy, IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
@@ -617,7 +627,7 @@ static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len)
FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) {
Object *ob_iter = base_iter->object;
bArmature *arm = ob_iter->data;
- for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
Bone *bone = pchan->bone;
bone->flag &= ~BONE_DONE;
}
@@ -659,7 +669,7 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const
}
bool changed = true;
- for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob_iter->pose->chanbase) {
Bone *bone = pchan->bone;
if ((bone->flag & BONE_UNSELECTABLE) == 0) {
const bool is_select = bone->flag & BONE_SELECTED;
@@ -685,8 +695,8 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const
}
static bool do_lasso_select_pose(ViewContext *vc,
- const int mcords[][2],
- const short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
uint bases_len;
@@ -695,7 +705,7 @@ static bool do_lasso_select_pose(ViewContext *vc,
for (int i = 0; i < bases_len; i++) {
Base *base_iter = bases[i];
Object *ob_iter = base_iter->object;
- do_lasso_tag_pose(vc, ob_iter, mcords, moves);
+ do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len);
}
const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
@@ -715,9 +725,10 @@ static void do_lasso_select_mesh__doSelectVert(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_vert_select_set(data->vc->em->bm, eve, sel_op_result);
@@ -746,8 +757,10 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data,
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
const bool is_inside =
(is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), IS_CLIPPED) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -770,8 +783,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data,
}
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords,
- data->moves,
+ const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
UNPACK2(screen_co_a),
UNPACK2(screen_co_b),
IS_CLIPPED));
@@ -789,9 +802,10 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_face_select_set(data->vc->em->bm, efa, sel_op_result);
@@ -801,8 +815,8 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
static bool do_lasso_select_mesh(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
@@ -812,9 +826,9 @@ static bool do_lasso_select_mesh(ViewContext *vc,
/* set editmesh */
vc->em = BKE_editmesh_from_object(vc->obedit);
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
if (vc->em->bm->totvertsel) {
@@ -836,7 +850,7 @@ static bool do_lasso_select_mesh(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
}
@@ -892,27 +906,28 @@ static void do_lasso_select_curve__doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co[2])
{
LassoSelectUserData *data = userData;
const bool is_inside = BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED);
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED);
if (bp) {
const bool is_select = bp->f1 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
+ if (!handles_visible) {
+ /* can only be (beztindex == 1) here since handles are hidden */
const bool is_select = bezt->f2 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, data->select_flag);
}
bezt->f1 = bezt->f3 = bezt->f2;
data->is_changed = true;
@@ -922,7 +937,7 @@ static void do_lasso_select_curve__doSelect(void *userData,
const bool is_select = *flag_p & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
@@ -930,24 +945,35 @@ static void do_lasso_select_curve__doSelect(void *userData,
}
static bool do_lasso_select_curve(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
+ const bool deselect_all = (sel_op == SEL_OP_SET);
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *)vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
}
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
if (data.is_changed) {
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
}
@@ -958,9 +984,10 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const
{
LassoSelectUserData *data = userData;
const bool is_select = bp->f1 & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
@@ -968,16 +995,16 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const
}
}
static bool do_lasso_select_lattice(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= ED_lattice_flags_set(vc->obedit, 0);
@@ -1002,7 +1029,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (screen_co_a[0] != IS_CLIPPED) {
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) {
is_inside_flag |= BONESEL_ROOT;
}
}
@@ -1012,7 +1040,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (screen_co_b[0] != IS_CLIPPED) {
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
- BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) {
is_inside_flag |= BONESEL_TIP;
}
}
@@ -1022,8 +1051,11 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
if (is_ignore_flag == 0) {
if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) {
+ BLI_lasso_is_edge_inside(data->mcoords,
+ data->mcoords_len,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ INT_MAX)) {
is_inside_flag |= BONESEL_BONE;
}
}
@@ -1033,16 +1065,16 @@ static void do_lasso_select_armature__doSelectBone(void *userData,
}
static bool do_lasso_select_armature(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
rcti rect;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit);
@@ -1071,9 +1103,10 @@ static void do_lasso_select_mball__doSelectElem(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = ml->flag & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], INT_MAX));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT);
@@ -1081,8 +1114,8 @@ static void do_lasso_select_mball__doSelectElem(void *userData,
}
}
static bool do_lasso_select_meta(ViewContext *vc,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
LassoSelectUserData data;
@@ -1090,9 +1123,9 @@ static bool do_lasso_select_meta(ViewContext *vc,
MetaBall *mb = (MetaBall *)vc->obedit->data;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
data.is_changed |= BKE_mball_deselect_all(mb);
@@ -1113,9 +1146,10 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
{
LassoSelectUserData *data = userData;
const bool is_select = mv->flag & SELECT;
- const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
- BLI_lasso_is_point_inside(
- data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
+ const bool is_inside =
+ (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
+ BLI_lasso_is_point_inside(
+ data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
@@ -1124,8 +1158,8 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
}
static bool do_lasso_select_paintvert(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
@@ -1143,7 +1177,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (use_zbuf) {
@@ -1151,7 +1185,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
}
@@ -1163,7 +1197,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
else {
LassoSelectUserData data;
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
+ view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
@@ -1185,8 +1219,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
}
static bool do_lasso_select_paintface(ViewContext *vc,
wmGenericUserData *wm_userdata,
- const int mcords[][2],
- short moves,
+ const int mcoords[][2],
+ const int mcoords_len,
const eSelectOp sel_op)
{
Object *ob = vc->obact;
@@ -1203,14 +1237,14 @@ static bool do_lasso_select_paintface(ViewContext *vc,
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (esel == NULL) {
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE);
esel = wm_userdata->data;
esel->select_bitmap = DRW_select_buffer_bitmap_from_poly(
- vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL);
+ vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL);
}
if (esel->select_bitmap) {
@@ -1224,9 +1258,9 @@ static bool do_lasso_select_paintface(ViewContext *vc,
}
#if 0
-static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op)
+static void do_lasso_select_node(int mcoords[][2], const int mcoords_len, const eSelectOp sel_op)
{
- SpaceNode *snode = sa->spacedata.first;
+ SpaceNode *snode = area->spacedata.first;
bNode *node;
rcti rect;
@@ -1234,7 +1268,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
float node_centf[2];
bool changed = false;
- BLI_lasso_boundbox(&rect, mcords, moves);
+ BLI_lasso_boundbox(&rect, mcoords, mcoords_len);
/* store selection in temp test flag */
for (node = snode->edittree->nodes.first; node; node = node->next) {
@@ -1244,7 +1278,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
const bool is_select = node->flag & SELECT;
const bool is_inside = (BLI_rcti_isect_pt_v(&rect, node_cent) &&
- BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1]));
+ BLI_lasso_is_point_inside(mcoords, mcoords_len, node_cent[0], node_cent[1]));
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT);
@@ -1257,8 +1291,11 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s
}
#endif
-static bool view3d_lasso_select(
- bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
+static bool view3d_lasso_select(bContext *C,
+ ViewContext *vc,
+ const int mcoords[][2],
+ const int mcoords_len,
+ const eSelectOp sel_op)
{
Object *ob = CTX_data_active_object(C);
bool changed_multi = false;
@@ -1268,26 +1305,26 @@ static bool view3d_lasso_select(
if (vc->obedit == NULL) { /* Object Mode */
if (BKE_paint_select_face_test(ob)) {
- changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcoords, mcoords_len, sel_op);
}
else if (BKE_paint_select_vert_test(ob)) {
- changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, mcoords_len, sel_op);
}
else if (ob &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
/* pass */
}
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- changed_multi |= PE_lasso_select(C, mcords, moves, sel_op);
+ changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op);
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
- changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op);
if (changed_multi) {
ED_outliner_select_sync_from_pose_bone_tag(C);
}
}
else {
- changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op);
if (changed_multi) {
ED_outliner_select_sync_from_object_tag(C);
}
@@ -1300,23 +1337,23 @@ static bool view3d_lasso_select(
switch (vc->obedit->type) {
case OB_MESH:
- changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op);
+ changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op);
break;
case OB_CURVE:
case OB_SURF:
- changed = do_lasso_select_curve(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_curve(vc, mcoords, mcoords_len, sel_op);
break;
case OB_LATTICE:
- changed = do_lasso_select_lattice(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_lattice(vc, mcoords, mcoords_len, sel_op);
break;
case OB_ARMATURE:
- changed = do_lasso_select_armature(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_armature(vc, mcoords, mcoords_len, sel_op);
if (changed) {
ED_outliner_select_sync_from_edit_bone_tag(C);
}
break;
case OB_MBALL:
- changed = do_lasso_select_meta(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op);
break;
default:
BLI_assert(!"lasso select on incorrect object type");
@@ -1342,10 +1379,10 @@ static bool view3d_lasso_select(
static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
{
ViewContext vc;
- int mcords_tot;
- const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
+ int mcoords_len;
+ const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len);
- if (mcords) {
+ if (mcoords) {
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
view3d_operator_needs_opengl(C);
BKE_object_update_select_id(CTX_data_main(C));
@@ -1354,9 +1391,9 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
ED_view3d_viewcontext_init(C, &vc, depsgraph);
eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
- bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
+ bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op);
- MEM_freeN((void *)mcords);
+ MEM_freeN((void *)mcoords);
if (changed_multi) {
return OPERATOR_FINISHED;
@@ -1663,20 +1700,31 @@ static int selectbuffer_ret_hits_5(uint *buffer,
/**
* Populate a select buffer with objects and bones, if there are any.
* Checks three selection levels and compare.
+ *
+ * \param do_nearest_xray_if_supported: When set, read in hits that don't stop
+ * at the nearest surface. The hit's must still be ordered by depth.
+ * Needed so we can step to the next, non-active object when it's already selected, see: T76445.
*/
static int mixed_bones_object_selectbuffer(ViewContext *vc,
uint *buffer,
const int mval[2],
eV3DSelectObjectFilter select_filter,
- bool do_nearest)
+ bool do_nearest,
+ bool do_nearest_xray_if_supported)
{
rcti rect;
int hits15, hits9 = 0, hits5 = 0;
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
- const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
int hits = 0;
+ if (do_nearest_xray_if_supported) {
+ if ((U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0) {
+ select_mode = VIEW3D_SELECT_PICK_ALL;
+ }
+ }
+
/* we _must_ end cache before return, use 'goto finally' */
view3d_opengl_select_cache_begin();
@@ -1780,7 +1828,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
do_nearest = do_nearest && !enumerate;
- int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest);
+ int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest, true);
return hits;
}
@@ -1912,7 +1960,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
const int hits = mixed_bones_object_selectbuffer(
- &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest);
+ &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1971,7 +2019,7 @@ static bool ed_object_select_pick(bContext *C,
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc, depsgraph);
- ARegion *region = CTX_wm_region(C);
+ const ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -2526,6 +2574,7 @@ typedef struct BoxSelectUserData {
const rctf *rect_fl;
rctf _rect_fl;
eSelectOp sel_op;
+ eBezTriple_Flag select_flag;
/* runtime */
bool is_done;
@@ -2544,6 +2593,8 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data,
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
r_data->sel_op = sel_op;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
/* runtime */
r_data->is_done = false;
@@ -2674,6 +2725,7 @@ static void do_nurbs_box_select__doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool handles_visible,
const float screen_co[2])
{
BoxSelectUserData *data = userData;
@@ -2683,17 +2735,17 @@ static void do_nurbs_box_select__doSelect(void *userData,
const bool is_select = bp->f1 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
+ if (!handles_visible) {
+ /* can only be (beztindex == 1) here since handles are hidden */
const bool is_select = bezt->f2 & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, data->select_flag);
data->is_changed = true;
}
bezt->f1 = bezt->f3 = bezt->f2;
@@ -2703,7 +2755,7 @@ static void do_nurbs_box_select__doSelect(void *userData,
const bool is_select = *flag_p & SELECT;
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
+ SET_FLAG_FROM_TEST(*flag_p, sel_op_result, data->select_flag);
data->is_changed = true;
}
}
@@ -2711,17 +2763,28 @@ static void do_nurbs_box_select__doSelect(void *userData,
}
static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
+ const bool deselect_all = (sel_op == SEL_OP_SET);
BoxSelectUserData data;
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = (Curve *)vc->obedit->data;
- data.is_changed |= ED_curve_deselect_all(curve->editnurb);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
}
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
return data.is_changed;
@@ -3076,7 +3139,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
const int hits = view3d_opengl_select(
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
- for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
@@ -3092,7 +3155,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
goto finally;
}
- for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
+ LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
if (BASE_SELECTABLE(v3d, base)) {
if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
BLI_array_append(bases, base);
@@ -3104,9 +3167,9 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
- Bone *bone;
- Base *base = ED_armature_base_and_bone_from_select_buffer(
- bases, BLI_array_len(bases), *col, &bone);
+ bPoseChannel *pchan_dummy;
+ Base *base = ED_armature_base_and_pchan_from_select_buffer(
+ bases, BLI_array_len(bases), *col, &pchan_dummy);
if (base != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
}
@@ -3360,6 +3423,7 @@ typedef struct CircleSelectUserData {
float mval_fl[2];
float radius;
float radius_squared;
+ eBezTriple_Flag select_flag;
/* runtime */
bool is_changed;
@@ -3380,6 +3444,9 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data,
r_data->radius = rad;
r_data->radius_squared = rad * rad;
+ /* SELECT by default, but can be changed if needed (only few cases use and respect this). */
+ r_data->select_flag = SELECT;
+
/* runtime */
r_data->is_changed = false;
}
@@ -3617,29 +3684,24 @@ static void nurbscurve_circle_doSelect(void *userData,
BPoint *bp,
BezTriple *bezt,
int beztindex,
+ bool UNUSED(handles_visible),
const float screen_co[2])
{
CircleSelectUserData *data = userData;
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
if (bp) {
- bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
+ SET_FLAG_FROM_TEST(bp->f1, data->select, data->select_flag);
}
else {
- if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
- /* can only be (beztindex == 0) here since handles are hidden */
- bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
+ if (beztindex == 0) {
+ SET_FLAG_FROM_TEST(bezt->f1, data->select, data->select_flag);
+ }
+ else if (beztindex == 1) {
+ SET_FLAG_FROM_TEST(bezt->f2, data->select, data->select_flag);
}
else {
- if (beztindex == 0) {
- bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
- }
- else if (beztindex == 1) {
- bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
- }
- else {
- bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
- }
+ SET_FLAG_FROM_TEST(bezt->f3, data->select, data->select_flag);
}
}
data->is_changed = true;
@@ -3650,18 +3712,30 @@ static bool nurbscurve_circle_select(ViewContext *vc,
const int mval[2],
float rad)
{
+ const bool select = (sel_op != SEL_OP_SUB);
+ const bool deselect_all = (sel_op == SEL_OP_SET);
CircleSelectUserData data;
bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- Curve *curve = vc->obedit->data;
- changed |= ED_curve_deselect_all(curve->editnurb);
- }
- const bool select = (sel_op != SEL_OP_SUB);
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ Curve *curve = (Curve *)vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(curve);
+
+ /* For deselect all, items to be selected are tagged with temp flag. Clear that first. */
+ if (deselect_all) {
+ BKE_nurbList_flag_set(nurbs, BEZT_FLAG_TEMP_TAG, false);
+ data.select_flag = BEZT_FLAG_TEMP_TAG;
+ }
+
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
+
+ /* Deselect items that were not added to selection (indicated by temp flag). */
+ if (deselect_all) {
+ BKE_nurbList_flag_set_from_flag(nurbs, BEZT_FLAG_TEMP_TAG, SELECT);
+ }
+
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
return changed || data.is_changed;
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 2637fb6d1db..377e8c58ba3 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -86,6 +86,26 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float
UI_GetThemeColor3fv(TH_BACK, r_color);
}
+bool ED_view3d_has_workbench_in_texture_color(const Scene *scene,
+ const Object *ob,
+ const View3D *v3d)
+{
+ if (v3d->shading.type == OB_SOLID) {
+ if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
+ return true;
+ }
+ if (ob->mode == OB_MODE_TEXTURE_PAINT) {
+ return true;
+ }
+ }
+ else if (v3d->shading.type == OB_RENDER) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_WORKBENCH)) {
+ return scene->display.shading.color_type == V3D_SHADING_TEXTURE_COLOR;
+ }
+ }
+ return false;
+}
+
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
{
/* establish the camera object,
@@ -228,26 +248,26 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
bool ED_view3d_context_activate(bContext *C)
{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = CTX_wm_area(C);
ARegion *region;
- /* sa can be NULL when called from python */
- if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
- sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
+ /* area can be NULL when called from python */
+ if (area == NULL || area->spacetype != SPACE_VIEW3D) {
+ area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
}
- if (sa == NULL) {
+ if (area == NULL) {
return false;
}
- region = BKE_area_find_region_active_win(sa);
+ region = BKE_area_find_region_active_win(area);
if (region == NULL) {
return false;
}
/* bad context switch .. */
- CTX_wm_area_set(C, sa);
+ CTX_wm_area_set(C, area);
CTX_wm_region_set(C, region);
return true;
@@ -666,7 +686,7 @@ bool ED_view3d_camera_lock_autokey(View3D *v3d,
* Use with quad-split so each view is clipped by the bounds of each view axis.
* \{ */
-static void view3d_boxview_clip(ScrArea *sa)
+static void view3d_boxview_clip(ScrArea *area)
{
ARegion *region;
BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
@@ -675,7 +695,7 @@ static void view3d_boxview_clip(ScrArea *sa)
int val;
/* create bounding box */
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
@@ -747,7 +767,7 @@ static void view3d_boxview_clip(ScrArea *sa)
}
/* create bounding box */
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
@@ -812,13 +832,13 @@ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_
}
/* sync center/zoom view of region to others, for view transforms */
-void view3d_boxview_sync(ScrArea *sa, ARegion *region)
+void view3d_boxview_sync(ScrArea *area, ARegion *region)
{
ARegion *artest;
RegionView3D *rv3d = region->regiondata;
short clip = 0;
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ for (artest = area->regionbase.first; artest; artest = artest->next) {
if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3dtest = artest->regiondata;
@@ -833,18 +853,18 @@ void view3d_boxview_sync(ScrArea *sa, ARegion *region)
}
if (clip) {
- view3d_boxview_clip(sa);
+ view3d_boxview_clip(area);
}
}
/* for home, center etc */
-void view3d_boxview_copy(ScrArea *sa, ARegion *region)
+void view3d_boxview_copy(ScrArea *area, ARegion *region)
{
ARegion *artest;
RegionView3D *rv3d = region->regiondata;
bool clip = false;
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ for (artest = area->regionbase.first; artest; artest = artest->next) {
if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3dtest = artest->regiondata;
@@ -859,14 +879,14 @@ void view3d_boxview_copy(ScrArea *sa, ARegion *region)
}
if (clip) {
- view3d_boxview_clip(sa);
+ view3d_boxview_clip(area);
}
}
/* 'clip' is used to know if our clip setting has changed */
-void ED_view3d_quadview_update(ScrArea *sa, ARegion *region, bool do_clip)
+void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip)
{
- ARegion *ar_sync = NULL;
+ ARegion *region_sync = NULL;
RegionView3D *rv3d = region->regiondata;
short viewlock;
/* this function copies flags from the first of the 3 other quadview
@@ -892,21 +912,21 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *region, bool do_clip)
rv3d->rflag &= ~RV3D_BOXCLIP;
}
- /* use ar_sync so we sync with one of the aligned views below
+ /* use region_sync so we sync with one of the aligned views below
* else the view jumps on changing view settings like 'clip'
* since it copies from the perspective view */
- ar_sync = region;
+ region_sync = region;
}
}
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
+ view3d_boxview_sync(area, region_sync ? region_sync : area->regionbase.last);
}
/* ensure locked regions have an axis, locked user views don't make much sense */
if (viewlock & RV3D_LOCK_ROTATION) {
int index_qsplit = 0;
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if (region->alignment == RGN_ALIGN_QSPLIT) {
rv3d = region->regiondata;
if (rv3d->viewlock) {
@@ -922,7 +942,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *region, bool do_clip)
}
}
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 30587e6084d..fe77ca05a04 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -128,7 +128,7 @@ void ED_view3d_smooth_view_ex(
const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
- ScrArea *sa,
+ ScrArea *area,
View3D *v3d,
ARegion *region,
const int smooth_viewtx,
@@ -293,7 +293,7 @@ void ED_view3d_smooth_view_ex(
}
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
- view3d_boxview_copy(sa, region);
+ view3d_boxview_copy(area, region);
}
ED_region_tag_redraw(region);
@@ -309,9 +309,9 @@ void ED_view3d_smooth_view(bContext *C,
const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
- ED_view3d_smooth_view_ex(depsgraph, wm, win, sa, v3d, region, smooth_viewtx, sview);
+ ED_view3d_smooth_view_ex(depsgraph, wm, win, area, v3d, region, smooth_viewtx, sview);
}
/* only meant for timer usage */
@@ -615,17 +615,18 @@ static void sync_viewport_camera_smoothview(bContext *C,
if (v3d->scenelock) {
ListBase *lb = (space_link == area->spacedata.first) ? &area->regionbase :
&space_link->regionbase;
- for (ARegion *other_ar = lb->first; other_ar != NULL; other_ar = other_ar->next) {
- if (other_ar->regiontype == RGN_TYPE_WINDOW) {
- if (other_ar->regiondata) {
- RegionView3D *other_rv3d = other_ar->regiondata;
+ for (ARegion *other_region = lb->first; other_region != NULL;
+ other_region = other_region->next) {
+ if (other_region->regiontype == RGN_TYPE_WINDOW) {
+ if (other_region->regiondata) {
+ RegionView3D *other_rv3d = other_region->regiondata;
if (other_rv3d->persp == RV3D_CAMOB) {
Object *other_camera_old = other_v3d->camera;
other_v3d->camera = ob;
ED_view3d_lastview_store(other_rv3d);
ED_view3d_smooth_view(C,
other_v3d,
- other_ar,
+ other_region,
smooth_viewtx,
&(const V3D_SmoothParams){
.camera_old = other_camera_old,
@@ -704,9 +705,9 @@ static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
bool ED_operator_rv3d_user_region_poll(bContext *C)
{
View3D *v3d_dummy;
- ARegion *ar_dummy;
+ ARegion *region_dummy;
- return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy);
+ return ED_view3d_context_user_region(C, &v3d_dummy, &region_dummy);
}
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
@@ -1061,7 +1062,7 @@ int view3d_opengl_select(ViewContext *vc,
* the number of items is nearly always 1, maybe 2..3 in rare cases. */
LinkNode *ob_pose_list = NULL;
VirtualModifierData virtualModifierData;
- const ModifierData *md = modifiers_getVirtualModifierList(obact, &virtualModifierData);
+ const ModifierData *md = BKE_modifiers_get_virtual_modifierlist(obact, &virtualModifierData);
for (; md; md = md->next) {
if (md->type == eModifierType_Armature) {
ArmatureModifierData *amd = (ArmatureModifierData *)md;
@@ -1199,16 +1200,16 @@ finally:
static uint free_localview_bit(Main *bmain)
{
- ScrArea *sa;
- bScreen *sc;
+ ScrArea *area;
+ bScreen *screen;
ushort local_view_bits = 0;
/* sometimes we loose a localview: when an area is closed */
/* check all areas: which localviews are in use? */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ SpaceLink *sl = area->spacedata.first;
for (; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
@@ -1234,12 +1235,12 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
wmWindow *win,
Main *bmain,
ViewLayer *view_layer,
- ScrArea *sa,
+ ScrArea *area,
const bool frame_selected,
const int smooth_viewtx,
ReportList *reports)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
Base *base;
float min[3], max[3], box[3];
float size = 0.0f;
@@ -1301,7 +1302,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
memcpy(v3d->localvd, v3d, sizeof(View3D));
v3d->local_view_uuid = local_view_bit;
- for (region = sa->regionbase.first; region; region = region->next) {
+ for (region = area->regionbase.first; region; region = region->next) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
bool ok_dist = true;
@@ -1342,7 +1343,7 @@ static bool view3d_localview_init(const Depsgraph *depsgraph,
ED_view3d_smooth_view_ex(depsgraph,
wm,
win,
- sa,
+ area,
v3d,
region,
smooth_viewtx,
@@ -1364,11 +1365,11 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
wmWindowManager *wm,
wmWindow *win,
ViewLayer *view_layer,
- ScrArea *sa,
+ ScrArea *area,
const bool frame_selected,
const int smooth_viewtx)
{
- View3D *v3d = sa->spacedata.first;
+ View3D *v3d = area->spacedata.first;
if (v3d->localvd == NULL) {
return;
@@ -1389,7 +1390,7 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
MEM_freeN(v3d->localvd);
v3d->localvd = NULL;
- for (ARegion *region = sa->regionbase.first; region; region = region->next) {
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
@@ -1410,7 +1411,7 @@ static void view3d_localview_exit(const Depsgraph *depsgraph,
ED_view3d_smooth_view_ex(depsgraph,
wm,
win,
- sa,
+ area,
v3d,
region,
smooth_viewtx,
@@ -1438,23 +1439,23 @@ static int localview_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- ScrArea *sa = CTX_wm_area(C);
+ ScrArea *area = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
bool frame_selected = RNA_boolean_get(op->ptr, "frame_selected");
bool changed;
if (v3d->localvd) {
- view3d_localview_exit(depsgraph, wm, win, view_layer, sa, frame_selected, smooth_viewtx);
+ view3d_localview_exit(depsgraph, wm, win, view_layer, area, frame_selected, smooth_viewtx);
changed = true;
}
else {
changed = view3d_localview_init(
- depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports);
+ depsgraph, wm, win, bmain, view_layer, area, frame_selected, smooth_viewtx, op->reports);
}
if (changed) {
DEG_id_type_tag(bmain, ID_OB);
- ED_area_tag_redraw(sa);
+ ED_area_tag_redraw(area);
/* Unselected objects become selected when exiting. */
if (v3d->localvd == NULL) {
@@ -1555,19 +1556,17 @@ void VIEW3D_OT_localview_remove_from(wmOperatorType *ot)
/** \name Local Collections
* \{ */
-static uint free_localcollection_bit(Main *bmain,
- unsigned short local_collections_uuid,
- bool *r_reset)
+static uint free_localcollection_bit(Main *bmain, ushort local_collections_uuid, bool *r_reset)
{
- ScrArea *sa;
- bScreen *sc;
+ ScrArea *area;
+ bScreen *screen;
ushort local_view_bits = 0;
/* Check all areas: which localviews are in use? */
- for (sc = bmain->screens.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl = sa->spacedata.first;
+ for (screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (area = screen->areabase.first; area; area = area->next) {
+ SpaceLink *sl = area->spacedata.first;
for (; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
@@ -1596,7 +1595,7 @@ static uint free_localcollection_bit(Main *bmain,
}
static void local_collections_reset_uuid(LayerCollection *layer_collection,
- const unsigned short local_view_bit)
+ const ushort local_view_bit)
{
if (layer_collection->flag & LAYER_COLLECTION_HIDE) {
layer_collection->local_collections_bits &= ~local_view_bit;
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 89b5618075a..7aefd173953 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -160,14 +160,14 @@ void walk_modal_keymap(wmKeyConfig *keyconf)
{0, NULL, 0, NULL, NULL},
};
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal");
+ wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal");
/* this function is called for each spacetype, only needs to add map once */
if (keymap && keymap->modal_items) {
return;
}
- keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items);
+ keymap = WM_modalkeymap_ensure(keyconf, "View3D Walk Modal", modal_items);
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk");
@@ -374,16 +374,19 @@ static bool walk_floor_distance_get(RegionView3D *rv3d,
mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
add_v3_v3(ray_start, dvec_tmp);
- ret = ED_transform_snap_object_project_ray(walk->snap_context,
- walk->depsgraph,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- ray_start,
- ray_normal,
- r_distance,
- r_location,
- r_normal_dummy);
+ ret = ED_transform_snap_object_project_ray(
+ walk->snap_context,
+ walk->depsgraph,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ /* Avoid having to convert the edit-mesh to a regular mesh. */
+ .use_object_edit_cage = true,
+ },
+ ray_start,
+ ray_normal,
+ r_distance,
+ r_location,
+ r_normal_dummy);
/* artificially scale the distance to the scene size */
*r_distance /= walk->grid;
@@ -449,7 +452,6 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
- Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
walk->rv3d = CTX_wm_region_view3d(C);
@@ -553,7 +555,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- bmain, walk->scene, 0, walk->region, walk->v3d);
+ walk->scene, 0, walk->region, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
walk->depsgraph,