From 5a9ab10b83debfec59294a1e094240c2aac39289 Mon Sep 17 00:00:00 2001 From: bla BLA Date: Wed, 27 Mar 2024 00:23:40 -0700 Subject: [PATCH 1/6] Custom build for 4.1 release, many selection options, also camera and ui --- intern/ghost/GHOST_Types.h | 6 + intern/ghost/intern/GHOST_WindowWin32.cc | 18 + .../blender_icons16/icon16_auto_xray.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_select_through.dat | Bin 0 -> 1048 bytes .../blender_icons32/icon32_auto_xray.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_select_through.dat | Bin 0 -> 4120 bytes release/datafiles/userdef/userdef_default.c | 2 + release/windows/icons/cursors/blank.cur | Bin 0 -> 30894 bytes release/windows/icons/cursors/box.cur | Bin 0 -> 30894 bytes release/windows/icons/cursors/boxdot.cur | Bin 0 -> 30894 bytes release/windows/icons/cursors/boxpointer.cur | Bin 0 -> 30894 bytes release/windows/icons/cursors/crossd.cur | Bin 0 -> 30894 bytes release/windows/icons/cursors/pointera.cur | Bin 0 -> 30894 bytes release/windows/icons/winblender.rc | 7 +- scripts/modules/rna_keymap_ui.py | 19 +- scripts/startup/bl_operators/userpref.py | 110 + .../startup/bl_ui/space_toolsystem_toolbar.py | 12 + scripts/startup/bl_ui/space_userpref.py | 18 + scripts/startup/bl_ui/space_view3d.py | 207 +- scripts/startup/bl_ui/space_view3d_toolbar.py | 36 +- source/blender/blenlib/BLI_lasso_2d.h | 3 +- source/blender/blenlib/intern/lasso_2d.c | 36 +- .../blenloader/intern/versioning_defaults.cc | 21 + .../blenloader/intern/versioning_userdef.cc | 10 +- .../draw/engines/overlay/overlay_edit_mesh.cc | 6 +- .../draw/engines/select/select_draw_utils.cc | 4 +- .../editors/curves/intern/curves_selection.cc | 3 +- .../editors/gpencil_legacy/gpencil_select.cc | 18 +- source/blender/editors/include/UI_icons.hh | 4 +- source/blender/editors/interface/resources.cc | 2 +- .../blender/editors/mesh/editmesh_select.cc | 37 +- source/blender/editors/screen/screen_ops.cc | 57 + .../blender/editors/space_node/node_select.cc | 36 +- .../editors/space_view3d/view3d_edit.cc | 245 ++ .../editors/space_view3d/view3d_intern.h | 3 + .../editors/space_view3d/view3d_navigate.cc | 19 + .../editors/space_view3d/view3d_navigate.hh | 2 + .../space_view3d/view3d_navigate_view_all.cc | 20 +- .../space_view3d/view3d_navigate_view_zoom.cc | 20 +- .../editors/space_view3d/view3d_ops.cc | 3 + .../editors/space_view3d/view3d_select.cc | 2266 ++++++++++++++--- .../blender/editors/uvedit/uvedit_select.cc | 21 +- source/blender/makesdna/DNA_scene_defaults.h | 19 + source/blender/makesdna/DNA_scene_types.h | 107 +- source/blender/makesdna/DNA_userdef_types.h | 154 +- source/blender/makesdna/DNA_view3d_types.h | 1 + source/blender/makesrna/intern/rna_scene.cc | 252 ++ source/blender/makesrna/intern/rna_space.cc | 10 + source/blender/makesrna/intern/rna_userdef.cc | 194 ++ source/blender/makesrna/intern/rna_wm_api.cc | 60 + source/blender/windowmanager/WM_api.hh | 1 + source/blender/windowmanager/WM_types.hh | 1 + .../windowmanager/intern/wm_cursors.cc | 274 +- .../windowmanager/intern/wm_event_query.cc | 55 +- .../windowmanager/intern/wm_event_system.cc | 5 + .../windowmanager/intern/wm_gesture.cc | 51 +- .../windowmanager/intern/wm_gesture_ops.cc | 105 +- .../windowmanager/intern/wm_operator_props.cc | 156 ++ 58 files changed, 4267 insertions(+), 449 deletions(-) create mode 100644 release/datafiles/blender_icons16/icon16_auto_xray.dat create mode 100644 release/datafiles/blender_icons16/icon16_select_through.dat create mode 100644 release/datafiles/blender_icons32/icon32_auto_xray.dat create mode 100644 release/datafiles/blender_icons32/icon32_select_through.dat create mode 100644 release/windows/icons/cursors/blank.cur create mode 100644 release/windows/icons/cursors/box.cur create mode 100644 release/windows/icons/cursors/boxdot.cur create mode 100644 release/windows/icons/cursors/boxpointer.cur create mode 100644 release/windows/icons/cursors/crossd.cur create mode 100644 release/windows/icons/cursors/pointera.cur diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index a45c505d4cb..5f25f3ea6db 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -329,12 +329,18 @@ typedef enum { GHOST_kStandardCursorCrosshairA, GHOST_kStandardCursorCrosshairB, GHOST_kStandardCursorCrosshairC, + GHOST_kStandardCursorCrosshairD, + GHOST_kStandardCursorBlank, + GHOST_kStandardCursorBox, + GHOST_kStandardCursorBoxDot, + GHOST_kStandardCursorBoxPointer, GHOST_kStandardCursorPencil, GHOST_kStandardCursorUpArrow, GHOST_kStandardCursorDownArrow, GHOST_kStandardCursorVerticalSplit, GHOST_kStandardCursorHorizontalSplit, GHOST_kStandardCursorEraser, + GHOST_kStandardCursorPointer, GHOST_kStandardCursorKnife, GHOST_kStandardCursorEyedropper, GHOST_kStandardCursorZoomIn, diff --git a/intern/ghost/intern/GHOST_WindowWin32.cc b/intern/ghost/intern/GHOST_WindowWin32.cc index d6c5e184705..2dec3b141bd 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cc +++ b/intern/ghost/intern/GHOST_WindowWin32.cc @@ -728,6 +728,9 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const case GHOST_kStandardCursorHorizontalSplit: cursor = ::LoadImage(module, "splith_cursor", IMAGE_CURSOR, cx, cy, flags); break; + case GHOST_kStandardCursorPointer: + cursor = ::LoadImage(module, "pointer_cursor", IMAGE_CURSOR, cx, cy, flags); + break; case GHOST_kStandardCursorKnife: cursor = ::LoadImage(module, "knife_cursor", IMAGE_CURSOR, cx, cy, flags); break; @@ -773,6 +776,21 @@ HCURSOR GHOST_WindowWin32::getStandardCursor(GHOST_TStandardCursor shape) const case GHOST_kStandardCursorCrosshairC: cursor = ::LoadImage(module, "crossC_cursor", IMAGE_CURSOR, cx, cy, flags); break; /* Minimal Crosshair C */ + case GHOST_kStandardCursorCrosshairD: + cursor = ::LoadImage(module, "crossD_cursor", IMAGE_CURSOR, cx, cy, flags); + break; /* Open Crosshair D */ + case GHOST_kStandardCursorBlank: + cursor = ::LoadImage(module, "blank_cursor", IMAGE_CURSOR, cx, cy, flags); + break; /* Blank */ + case GHOST_kStandardCursorBox: + cursor = ::LoadImage(module, "box_cursor", IMAGE_CURSOR, cx, cy, flags); + break; /* Box */ + case GHOST_kStandardCursorBoxDot: + cursor = ::LoadImage(module, "boxdot_cursor", IMAGE_CURSOR, cx, cy, flags); + break; /* Box Dot */ + case GHOST_kStandardCursorBoxPointer: + cursor = ::LoadImage(module, "boxpointer_cursor", IMAGE_CURSOR, cx, cy, flags); + break; /* Box Pointer */ case GHOST_kStandardCursorBottomSide: case GHOST_kStandardCursorUpDown: cursor = ::LoadImage(module, "movens_cursor", IMAGE_CURSOR, cx, cy, flags); diff --git a/release/datafiles/blender_icons16/icon16_auto_xray.dat b/release/datafiles/blender_icons16/icon16_auto_xray.dat new file mode 100644 index 0000000000000000000000000000000000000000..09c5685b63a8632eca9d3cb56241b921fd62649f GIT binary patch literal 1048 zcmbu8ze)o^5XSd{l@W3l3V8+*%k)0RHF*O|D~m0C02?8B2Js#80=7w+N=R&?U?b=6 zJ8qWo{(&0!v9mMt&F!~K@(@A}4_OEoP>e!|BF2AFmgN{e;8nB!us=cb4##$udd3;+ z*3I4}quxYNJB zAq`An11lU%zM1jt$ax4MhgBBBJB&La6rw0zqAbfd_=SyfJ+jk!==-pTp8G6EY!9Vzf4ax9 z@?p>66DF=rHGZG&=sIu&trPs*U~RS3f7QF^!d}1`W-x#es7IaM-dTLrzsE**mH$b* zeybb$jJmnk;H;W;e!utqKYp}r{WtQP=Bq8g)oRR^y8`s~ABr(e{k<)A-9J9f?*Ljp zzb$9Y!)Gb`+rKB>@h#yGrrC%+Qizf+c9#ACK?^%On^cyz+XMn>g^)jxCP`-@*7^^2 zF`b>FLQs(42f9A5WMuBi++^-LyNw4P?#wx7&O3AOot?eo&be`z>~n6h=G=Neow{?4 zM&rTLZnsC_D4-eMmmb7lq7mA@(eG9KfJr=uVWVIB<5x^fz%TfzJgzogHvTQSvaEzZgt5?H4ecl;!8vr=H*c zg?*n}ADuUFw{LuXe9`yP$L*E;O7B1U)9?jOL1y3o?D}X7!3wm%TG#XuvTK$0K7523 zbug=+ye}DBhfgYkox^*Gt@R531}s2b&ycHhl>5{^)6_m=KZCW)z_CaB1H4YHnVLsU ztzB!j_SafdYgWla^f6pmar&()b!;xzpWYe z(HwzIkZDh@ns^qSu%>OJ*#`}{2H95_w0Yg`qd5o1AlredZfn~5XzG7z6J#eaZ*$bg zpS=HLUC`KQV80e)&+ z+5C`d|L6KX@;P>rZ=sttSk8QIjLx&i`3uiKd|jYxct<_}ooJ29ljBz({9U`zkL*9= zSBd`@$7cZIv8mh*^N;L*lFHpLcU?T<`|mMx zkh{ve7uD{*KW!~mhHDCV`LlGDAE%bTj7)|jC(8~xd%u;HC(7isKIEALhu{@FgFVo; zK6PbyO7*|+<11&u&0B@Xu9Z0Lo87$EEI1$)yhTRd$tQb7|jc@>exLgYcW&5OvFmaSGIkGjp@L_XADt~R=hXt7Mv zUm|O@BS8QH5P$##AOL{^2n4M|Tj`_vVZYzIrK)pp=l2{a)|d0AnDJn%vrTPZ_v5K@ z_!EB`7qJiak%+&;^{g?=|LA|-F+eNZTl-hXvTM3WH)d967cxvh$|0&;@=f8nKAK0{A3~F$`U`sk1Jp@ zW8#PS$wI=FP4VNMCvOe}@t3{sG!$|C)m*F$zht_s} z({Y~GN@cBL^Rz_Qnvoy?0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U< z00Izz00ba#Wdyp;t!lG>NeEqQWa65bI*Ie;>VC6wbv(_MDhNRGe~9`-2KZlI`*&Su z)iicWZGZev-^Xm)jIHfx|1z(C#Q!kyKk|I~x_;Yvok`t+^K$$jbv<(49G0j3o!|2{ za9+*$$M~l)Q{4Z5jQ@=P-fLMKd&Ymp|69KP5&y(L@qfGbKlJ}{`+vL#ZX&S_P0rby p-LWpQ|5tUgcQZq1J!Kh5KUP3GK|ot)8jDRYL->yQOV{R)>0evxoBRL( literal 0 HcmV?d00001 diff --git a/release/windows/icons/cursors/boxdot.cur b/release/windows/icons/cursors/boxdot.cur new file mode 100644 index 0000000000000000000000000000000000000000..8b2562b7775e92e4bdbe97bd7650bcb2da7f0de4 GIT binary patch literal 30894 zcmeI5y>8nu5P&bu5OgW}2FX$&W2R08Ec8k88l9@CuhBKH;+JT;1RdSg@DF=On}IEu zktiz?!+vKR&ZJJ_-A7V3WJ(r!Czo<_BXXs$hmRtkMda>IU*Gq!ji>5I;{T{^TR)pUl9AeX%jNRqI2)<`sq;T#epnbO|HCGa-qZf@=Raeb zqS_%gH-?Zf$NJc_+jj$qTsUVsTOR9|Z_Wj6ZVUU^bqc+dA@{1!*D3Ux1_A*HKmY;| zfB*y_009U<00Izz00bZa0SG_<0&j*upX=MPeWpm-Z8n>;biH1Od?ty1|GQD|wk?0% z*>nm?{++fNB=I+iB$eUM_)i)z4d=G;^QiuIZZUgOGM~TE^%5bO%;SIS`~&8w&76NU z?y!OQ1BqU??flbvQ24hZddZ;({wZsOn!ZzyAMG6bd>ukx>gQM4wp*s8!Fws!id<`k zhHz(R?x!zzw%2?ArcFFfXg^q6r&X!es$rd$=)GnL1Rwwb2tWV=5P$##AOHafKmY;| zfB*y_009U<00Izz00bZa0SG_<0uX=z1PUWC#QLh#W8{P|=^h!oCnl!0UM{vR)NA5? zwNyp`eEws^V+_bYzy3e>KC7-{C)fTbfB$^KuHD$%kN(f|{KxnoXZ%mRo<25j&%Vzg zcHm}xA^BIDSAC#X?j!}|UumMX>XWK{moroER`81!;-D0tDX05Dh^{rCC z=U=T!`rKEmmA6(_wfa^mB>(@p|10g}TD8~wFQET5_2=7)jDu;V+DQsH|8>eU=0yIJ zK93~UEqwpm{Xa>J&tUb8f5yKKCi}jWlQ938|D%k_oX>yFXCK7MmP62(PpA)mhgK*4 zD6A7sFc#0)nh@UWy6VFUkP`%y`ju4&J9F-jmCv?+zweIod)Cbc|AE>M`2_n9`Jvv* literal 0 HcmV?d00001 diff --git a/release/windows/icons/cursors/boxpointer.cur b/release/windows/icons/cursors/boxpointer.cur new file mode 100644 index 0000000000000000000000000000000000000000..e9fcb9333122897a195c0cfd995b20d23817f0c9 GIT binary patch literal 30894 zcmeI5yHeXg6owC>VA3Rc1Jh(e2US`i4Fw%fkj@1qO**J}jkMI6p`c496%7pxGc;*K z1v5b5442J0$6B$HCE07qTFLs?bG)n7N_+lqFS=rg-q0c~FB2{C=ja2`XChi#BYMl9 zqmM*?IB#Qv=pBDnz7QR9ffX*pn-FKyf~JTLxEulqfB*=900^{cj_+N7tACWJ@o=IAJFyaud{{g=eU!$aH_?3;{>I)l%B?YOKfK-xh15j!nb_PMXG zcJuP`GS=)fYKg^98v^?-TGe+?(dvH6chMChOy$4p`^CkD?K`dU-|g?VPla%v>zsWB2+sxdp9b_FZG?iaan}gk=E3IwsBU`eY(tM)#8m|v}Iq~;lzL`x-)YJXjSl-jxU^`&5?`aYLtr-FcfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfPgmvv$?q`&uiQI9=o^T)COj6Z_j1$jn~)x z{%^{qS{KdP*_m2LIhgzVdvkq#ttKow#(|&3zlH)1^ExJ8#Yd^TySu#pQ0u^~sj?CM zl3^Lx@xZ>wF=8IWi2fYyI}H$D=Dn)iZCwBj)-L$zQ`+L$l>o__|n%(?FT{M?S0j7@@N%|yQ(^HcNujvX7plx9~v6a8uJ zQgxT~%lR%#7K@K@UDBV{&dXhDe~~*9I@JCn+9d<}hv!C_aKdHIV*bxmgZ4-JbI0hy z`7io^1_8OIY-0P%#af2Dm1lKbf8f6d&udS;R?k~mWj^!|e`BRerWNd~w)XG(`A<{l zzvy=oD(FhZyXd<9uJ?b;|J|Pdo810-5RATLJ``VFlRP)r=S6OrNzyz+)^e_0JQF9@ z+G~03peyBlW{x3EfM-M3nnK8GCmg9I)O0P%TXT+bP T_5CRRJB&>uW7e}I{@M6HKQ}#J literal 0 HcmV?d00001 diff --git a/release/windows/icons/cursors/crossd.cur b/release/windows/icons/cursors/crossd.cur new file mode 100644 index 0000000000000000000000000000000000000000..1b623879cd706b16333041f7a4957150e2b6355f GIT binary patch literal 30894 zcmeI4%}(1u5XXl`YNZ}ZPgRdxDskk*8TCo}CUEMpsBggoBmt2Raq2TfLXdz>lK*7*8k%VaWfqtVDMInQ0M*K>ox zV3oFJzeo&4+M0dp%_m^v3>`v}KmR%v1&#u&lZ|CT;#&n(ixY+$iZll0ZVifZ|R{uBR z_&^Uvbcg-jy zKmsH{0wh2JBtQZrKmsH{0wh2Jr4e|mJz*W@P7BuJq46E{Dafe?nO#S-&!|s9{%Me| z*=)MY%S+d2G%SA9ryxFF+%vbLK^p_czx@O_{yN`n?n86_r?>y(H!`en{L>r%g!g}+ z{~+%{{!_2l?f92U{*!wCoBH+7_GfsEkOWA81W14cNFZhc$kmXq`kY<0lOIz-fXcojLdu8Xj6rFU(V0ZpVrRcNA^0} z{JOZfu<QfMZEs1;)IWzKE4H_kt`#(NjyKaJhj2}7$Vf;GZv!a7;b0C@VXZ+6uIR2df zk8^m_uq1OGWzdN#eVg H$JEY$4_y{@ literal 0 HcmV?d00001 diff --git a/release/windows/icons/cursors/pointera.cur b/release/windows/icons/cursors/pointera.cur new file mode 100644 index 0000000000000000000000000000000000000000..7127a53365fcdb79e434d9ae79054266e29a15fa GIT binary patch literal 30894 zcmeI5!H(K65Qe?oLyzqnz@^gOx~B@b1Xbb%`UJgj0)e>owtMQc^jw|-#542);sgk| zf|$-Ywq+7!r4=H<__s7n9GrOmFLuHvj#sG<>QU9}N~b@cmHNg@&(9|RMX7(huH8=a zPv4dL%>|w~TW4#tJ?JH+Ub!3+2!H?xfB*=900@8p2vkgfI-L%241d|aRuBt~$7AYt zyH&+OtJO+dMRCySbkbH3$F&cMt6$>S@Ar-cS1j$~+Ucx*VIaqWD-|oFJ-YfUs9V^& zV_&jvsasO^c$dLEtvUTH`*{0x%W|1*EnByuE2K}n&qp@dxo;0<{YUmvrp6}sDdbkh zPd0a-g70Y{fdB}A00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2t+}Ek|dF5B~?8q zz7#TzMk8OtFWzC<&$=$rK(pCQTcA2veMG;Fuq zA|1D=As4@|!L}#vU}cRPcyC|M#c%m%V*l~p9hX%8EdIb^7ep@p0AqLY2O7JMKj7GP z{Bq6@q_0Z6*%Wf@qDB8+5YKk2=SYdODA{pFA;xaTDKUJV;`1_Iibqo^8CNAf1;IWs z`I_;%Ag{OHu20POFUE`G{m7Usf4?#|OY*k9n#s#Jtv1^$n;oa6_+2w35C8!X009sH z0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI5C8!X009sH0T2KI z5CDOo2~eZakP*tEzNdL9e40!q)bIDH*=$-4p}p&Q2?N?}HndnQG>2ZVN3B*XCJuVU zynOf^q&-B!!RfaPJ_l(JUcb1-_dG9Y`?9T-o%4}!$m!0mDBy4@_gmRME0+$3gEsqx zuYWKY$hlGMUXqpRyy&-Syq!k=6D>dgM&@M=Fx@AQq+O__o{yv>f zX*e9({(etw-tP)@JRV&eu;;o+w4b&A2(>%?k!siaBi63<%in$x^>@+ir 0) { - return true; - } - for (uint a = 0; a < mcoords_len - 1; a++) { - if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) { + if (!fully_inside) { + /* check points in lasso */ + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) { return true; } + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) { + return true; + } + + /* no points in lasso, so we have to intersect with lasso edge */ + + if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) { + return true; + } + for (unsigned int a = 0; a < mcoords_len - 1; a++) { + if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) { + return true; + } + } } return false; diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index cb25dfeffc0..0fc2a6be3b8 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -203,6 +203,8 @@ static void blo_update_defaults_screen(bScreen *screen, /* Disable Curve Normals. */ v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; v3d->overlay.normals_constant_screen_size = 7.0f; + /* Show xray facedots */ + v3d->overlay.edit_flag |= V3D_OVERLAY_EDIT_FACE_DOT_XRAY; } else if (area->spacetype == SPACE_CLIP) { SpaceClip *sclip = static_cast(area->spacedata.first); @@ -392,6 +394,25 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) if (ts->unified_paint_settings.input_samples == 0) { ts->unified_paint_settings.input_samples = 1; } + + /* X-Ray. */ + ts->xray_button = true; + ts->auto_xray_object = true; + ts->auto_xray_edit = true; + ts->auto_xray_box = true; + ts->auto_xray_lasso = true; + ts->auto_xray_circle = true; + ts->select_through = true; + ts->select_through_object = true; + ts->select_through_box = true; + ts->select_through_lasso = true; + ts->select_through_circle = true; + + /* Viewport-Facing Select */ + ts->viewport_facing_select_mode = 1; + ts->viewport_facing_select_vert = 1; + ts->viewport_facing_select_edge = 1; + ts->viewport_facing_select_face = 1; } void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) diff --git a/source/blender/blenloader/intern/versioning_userdef.cc b/source/blender/blenloader/intern/versioning_userdef.cc index 855bb4b52a4..9029ab621ce 100644 --- a/source/blender/blenloader/intern/versioning_userdef.cc +++ b/source/blender/blenloader/intern/versioning_userdef.cc @@ -490,9 +490,8 @@ void blo_do_versions_userdef(UserDef *userdef) if (!USER_VERSION_ATLEAST(278, 6)) { /* Clear preference flags for re-use. */ - userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | (1 << 2) | USER_FLAG_UNUSED_3 | - USER_FLAG_UNUSED_6 | USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 | - USER_DEVELOPER_UI); + userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | (1 << 2) | USER_FLAG_UNUSED_6 | + USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 | USER_DEVELOPER_UI); userdef->uiflag &= ~(USER_HEADER_BOTTOM); userdef->transopts &= ~(USER_TR_UNUSED_3 | USER_TR_UNUSED_4 | USER_TR_UNUSED_6 | USER_TR_UNUSED_7); @@ -581,8 +580,6 @@ void blo_do_versions_userdef(UserDef *userdef) copy_v3_fl3(userdef->light_ambient, 0.025000, 0.025000, 0.025000); - userdef->flag &= ~(USER_FLAG_UNUSED_4); - userdef->uiflag &= ~(USER_HEADER_FROM_PREF | USER_REGISTER_ALL_USERS); } @@ -921,6 +918,9 @@ void blo_do_versions_userdef(UserDef *userdef) STRNCPY(km->idname, "NLA Tracks"); } } + + userdef->header_highlight = 5; + userdef->selection_radius = 75.0f; } /** diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.cc b/source/blender/draw/engines/overlay/overlay_edit_mesh.cc index 3060c66ea77..9a89cb2c12d 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.cc @@ -61,8 +61,10 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) bool select_face = pd->edit_mesh.select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0; bool select_edge = pd->edit_mesh.select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0; - bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 || - pd->edit_mesh.do_zbufclip; + bool show_face_dots = !XRAY_FLAG_ENABLED(draw_ctx->v3d) && + v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT || + XRAY_FLAG_ENABLED(draw_ctx->v3d) && + v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT_XRAY; bool show_retopology = RETOPOLOGY_ENABLED(v3d); float retopology_offset = RETOPOLOGY_OFFSET(v3d); diff --git a/source/blender/draw/engines/select/select_draw_utils.cc b/source/blender/draw/engines/select/select_draw_utils.cc index b79310ccbe9..d5d82444177 100644 --- a/source/blender/draw/engines/select/select_draw_utils.cc +++ b/source/blender/draw/engines/select/select_draw_utils.cc @@ -59,7 +59,9 @@ static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawTyp { if (select_mode & SCE_SELECT_FACE) { if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) { - return true; + if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT_XRAY) { + return true; + } } if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) { return true; diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index 8844b0bc30f..252461864b6 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -832,7 +832,8 @@ bool select_lasso(const ViewContext &vc, int(pos1_proj.y), int(pos2_proj.x), int(pos2_proj.y), - IS_CLIPPED)) + IS_CLIPPED, + false)) { apply_selection_operation_at_index(selection.span, curve_i, sel_op); changed = true; diff --git a/source/blender/editors/gpencil_legacy/gpencil_select.cc b/source/blender/editors/gpencil_legacy/gpencil_select.cc index 2f13a9a0859..759c337c077 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_select.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_select.cc @@ -1490,7 +1490,8 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd, const float diff_mat[4][4], const int selectmode, const float scale, - const bool is_curve_edit) + const bool is_curve_edit, + const bool square) { bGPDspoint *pt = nullptr; int x0 = 0, y0 = 0; @@ -1510,7 +1511,9 @@ static bool gpencil_stroke_do_circle_sel(bGPdata *gpd, /* do boundbox check first */ if (!ELEM(V2D_IS_CLIPPED, x0, y0) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ - if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) { + if (square ? BLI_rcti_isect_pt(rect, x0, y0) : + ((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) + { hit = true; /* change selection */ @@ -1581,7 +1584,8 @@ static bool gpencil_do_curve_circle_sel(bContext *C, const bool select, rcti *rect, const float diff_mat[4][4], - const int selectmode) + const int selectmode, + const bool square) { ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); @@ -1629,7 +1633,7 @@ static bool gpencil_do_curve_circle_sel(bContext *C, int dist_x = screen_co[0] - mx; int dist_y = screen_co[1] - my; int dist = dist_x * dist_x + dist_y * dist_y; - if (dist <= radius * radius) { + if (square ? BLI_rcti_isect_pt(rect, screen_co[0], screen_co[1]) : dist <= radius * radius) { hit = true; /* change selection */ if (select) { @@ -1674,6 +1678,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); const bool is_curve_edit = bool(GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)); + const bool square = ts->square_select; int selectmode; if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL_LEGACY) { @@ -1729,7 +1734,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) GP_EDITABLE_CURVES_BEGIN(gps_iter, C, gpl, gps, gpc) { changed |= gpencil_do_curve_circle_sel( - C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode); + C, gps, gpc, mx, my, radius, select, &rect, gps_iter.diff_mat, selectmode, square); } GP_EDITABLE_CURVES_END(gps_iter); } @@ -1758,7 +1763,8 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) gpstroke_iter.diff_mat, selectmode, scale, - is_curve_edit); + is_curve_edit, + square); } GP_EVALUATED_STROKES_END(gpstroke_iter); } diff --git a/source/blender/editors/include/UI_icons.hh b/source/blender/editors/include/UI_icons.hh index 49a7e34acef..462dc25cf59 100644 --- a/source/blender/editors/include/UI_icons.hh +++ b/source/blender/editors/include/UI_icons.hh @@ -448,8 +448,8 @@ DEF_ICON_BLANK(705) DEF_ICON_BLANK(706) DEF_ICON_BLANK(707) DEF_ICON_BLANK(708) -DEF_ICON_BLANK(709) -DEF_ICON_BLANK(710) +DEF_ICON(AUTO_XRAY) +DEF_ICON(SELECT_THROUGH) DEF_ICON(SELECT_SET) DEF_ICON(SELECT_EXTEND) DEF_ICON(SELECT_SUBTRACT) diff --git a/source/blender/editors/interface/resources.cc b/source/blender/editors/interface/resources.cc index 66eb3b8a3dd..24cafb88dee 100644 --- a/source/blender/editors/interface/resources.cc +++ b/source/blender/editors/interface/resources.cc @@ -248,7 +248,7 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_HEADER_ACTIVE: { cp = ts->header; - const int factor = 5; + const int factor = U.header_highlight; /* Lighten the header color when editor is active. */ header_active[0] = cp[0] > 245 ? cp[0] - factor : cp[0] + factor; header_active[1] = cp[1] > 245 ? cp[1] - factor : cp[1] + factor; diff --git a/source/blender/editors/mesh/editmesh_select.cc b/source/blender/editors/mesh/editmesh_select.cc index 5b84b92b22f..3cfbd6435e8 100644 --- a/source/blender/editors/mesh/editmesh_select.cc +++ b/source/blender/editors/mesh/editmesh_select.cc @@ -246,7 +246,9 @@ static void findnearestvert__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && + data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) + { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -455,7 +457,9 @@ static void find_nearest_edge__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && + data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) + { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -688,7 +692,9 @@ static void findnearestface__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && + data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) + { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -724,27 +730,27 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, uint base_index = 0; if (!XRAY_FLAG_ENABLED(vc->v3d)) { - float dist_test; + float dist_test = 0.0f; uint index; BMFace *efa; + uint dist_px_manhattan_test = 0; { - uint dist_px_manhattan_test = 0; - if (*dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) { - dist_px_manhattan_test = uint( - ED_view3d_backbuf_sample_size_clamp(vc->region, *dist_px_manhattan_p)); + if (U.flag & USER_ADJUSTABLE_CLICK_SELECT || + *dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) + { + dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, + *dist_px_manhattan_p); } DRW_select_buffer_context_create(vc->depsgraph, bases, SCE_SELECT_FACE); - if (dist_px_manhattan_test == 0) { + if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_px_manhattan_test == 0) { index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval); - dist_test = 0.0f; } else { index = DRW_select_buffer_find_nearest_to_point( vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test); - dist_test = dist_px_manhattan_test; } if (index) { @@ -778,7 +784,14 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, /* end exception */ if (efa) { - if (dist_test < *dist_px_manhattan_p) { + if (U.flag & USER_ADJUSTABLE_CLICK_SELECT && dist_px_manhattan_test < *dist_px_manhattan_p) { + if (r_base_index) { + *r_base_index = base_index; + } + *dist_px_manhattan_p = dist_px_manhattan_test; + return efa; + } + else if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_test < *dist_px_manhattan_p) { if (r_base_index) { *r_base_index = base_index; } diff --git a/source/blender/editors/screen/screen_ops.cc b/source/blender/editors/screen/screen_ops.cc index 332da569b0a..8badfc931e2 100644 --- a/source/blender/editors/screen/screen_ops.cc +++ b/source/blender/editors/screen/screen_ops.cc @@ -3982,6 +3982,62 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Invoke Last Operator + * \{ */ + +static int invoke_last_exec(bContext *C, wmOperator * /*op*/) +{ + wmWindowManager *wm = CTX_wm_manager(C); + wmOperator *lastop = static_cast(wm->operators.last); + + /* Seek last registered operator */ + while (lastop) { + if (lastop->type->flag & OPTYPE_REGISTER) { + if (STREQ(lastop->idname, "MESH_OT_delete") || STREQ(lastop->idname, "MESH_OT_select_all") || + STREQ(lastop->idname, "MESH_OT_select_mode") || + STREQ(lastop->idname, "OBJECT_OT_editmode_toggle") || + STREQ(lastop->idname, "OBJECT_OT_select_all") || + STREQ(lastop->idname, "TRANSFORM_OT_resize") || + STREQ(lastop->idname, "TRANSFORM_OT_rotate") || + STREQ(lastop->idname, "TRANSFORM_OT_trackball") || + STREQ(lastop->idname, "TRANSFORM_OT_translate")) + { + lastop = lastop->prev; + } + else { + // printf(lastop->idname, "\n"); + break; + } + } + else { + lastop = lastop->prev; + } + } + + if (lastop) { + WM_operator_free_all_after(wm, lastop); + WM_operator_invoke_last(C, lastop); + } + + return OPERATOR_CANCELLED; +} + +static void SCREEN_OT_invoke_last(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Invoke Last"; + ot->description = "Invoke last operation"; + ot->idname = "SCREEN_OT_invoke_last"; + + /* api callbacks */ + ot->exec = invoke_last_exec; + + ot->poll = ED_operator_screenactive; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Redo Operator * \{ */ @@ -5863,6 +5919,7 @@ void ED_operatortypes_screen() WM_operatortype_append(SCREEN_OT_actionzone); WM_operatortype_append(SCREEN_OT_repeat_last); WM_operatortype_append(SCREEN_OT_repeat_history); + WM_operatortype_append(SCREEN_OT_invoke_last); WM_operatortype_append(SCREEN_OT_redo_last); /* Screen tools. */ diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index a4243711d9f..93e280e7dd5 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -875,9 +875,12 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); bNodeTree &node_tree = *snode->edittree; + ToolSettings *ts = CTX_data_tool_settings(C); + const bool square = ts->square_select; int x, y, radius; float2 offset; + rctf rectf; float zoom = float(BLI_rcti_size_x(®ion->winrct)) / float(BLI_rctf_size_x(®ion->v2d.cur)); @@ -896,6 +899,11 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(®ion->v2d, x, y, &offset.x, &offset.y); + if (square) { + BLI_rctf_init(&rectf, x - radius, x + radius, y - radius, y + radius); + UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); + } + for (bNode *node : node_tree.all_nodes()) { switch (node->type) { case NODE_FRAME: { @@ -904,16 +912,32 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) rctf frame_inside = node_frame_rect_inside(*snode, *node); const float radius_adjusted = float(radius) / zoom; BLI_rctf_pad(&frame_inside, -2.0f * radius_adjusted, -2.0f * radius_adjusted); - if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius_adjusted) && - !BLI_rctf_isect_circle(&frame_inside, offset, radius_adjusted)) - { - nodeSetSelected(node, select); + if (square) { + if (BLI_rctf_isect(&rectf, &node->runtime->totr, nullptr) && + !BLI_rctf_inside_rctf(&frame_inside, &rectf)) + { + nodeSetSelected(node, select); + } + } + else { + if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius_adjusted) && + !BLI_rctf_isect_circle(&frame_inside, offset, radius_adjusted)) + { + nodeSetSelected(node, select); + } } break; } default: { - if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius / zoom)) { - nodeSetSelected(node, select); + if (square) { + if (BLI_rctf_isect(&rectf, &node->runtime->totr, nullptr)) { + nodeSetSelected(node, select); + } + } + else { + if (BLI_rctf_isect_circle(&node->runtime->totr, offset, radius / zoom)) { + nodeSetSelected(node, select); + } } break; } diff --git a/source/blender/editors/space_view3d/view3d_edit.cc b/source/blender/editors/space_view3d/view3d_edit.cc index 161e0a97b21..6dacf24879e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.cc +++ b/source/blender/editors/space_view3d/view3d_edit.cc @@ -1243,3 +1243,248 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Automatic XRay + * \{ */ + +static int toggle_auto_xray_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + bToolRef *tref = area->runtime.tool; + const bool mode_match = obedit ? ts->auto_xray_edit : ts->auto_xray_object; + + if (STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box")) + { + if (mode_match && ts->auto_xray && ts->auto_xray_box) { + ts->auto_xray ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->auto_xray_edit ^= true; + } + else { + ts->auto_xray_object ^= true; + } + } + + if (!ts->auto_xray) { + ts->auto_xray ^= true; + } + + if (!ts->auto_xray_box) { + ts->auto_xray_box ^= true; + } + } + } + else if (STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso")) + { + if (mode_match && ts->auto_xray && ts->auto_xray_lasso) { + ts->auto_xray ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->auto_xray_edit ^= true; + } + else { + ts->auto_xray_object ^= true; + } + } + + if (!ts->auto_xray) { + ts->auto_xray ^= true; + } + + if (!ts->auto_xray_lasso) { + ts->auto_xray_lasso ^= true; + } + } + } + else if (STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle")) + { + if (mode_match && ts->auto_xray && ts->auto_xray_circle) { + ts->auto_xray ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->auto_xray_edit ^= true; + } + else { + ts->auto_xray_object ^= true; + } + } + + if (!ts->auto_xray) { + ts->auto_xray ^= true; + } + + if (!ts->auto_xray_circle) { + ts->auto_xray_circle ^= true; + } + } + } + + ED_area_tag_redraw(area); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_toggle_auto_xray(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Automatic X-Ray"; + ot->idname = "VIEW3D_OT_toggle_auto_xray"; + ot->description = "Transparent scene display during box, lasso, and circle select"; + + /* api callbacks */ + ot->exec = toggle_auto_xray_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Select Through + * \{ */ + +static int toggle_select_through_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + bToolRef *tref = area->runtime.tool; + const bool mode_match = obedit ? ts->select_through_edit : ts->select_through_object; + + if (STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box")) + { + if (mode_match && ts->select_through && ts->select_through_box) { + ts->select_through ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->select_through_edit ^= true; + } + else { + ts->select_through_object ^= true; + } + } + + if (!ts->select_through) { + ts->select_through ^= true; + } + + if (!ts->select_through_box) { + ts->select_through_box ^= true; + } + } + } + else if (STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso")) + { + if (mode_match && ts->select_through && ts->select_through_lasso) { + ts->select_through ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->select_through_edit ^= true; + } + else { + ts->select_through_object ^= true; + } + } + + if (!ts->select_through) { + ts->select_through ^= true; + } + + if (!ts->select_through_lasso) { + ts->select_through_lasso ^= true; + } + } + } + else if (STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle")) + { + if (mode_match && ts->select_through && ts->select_through_circle) { + ts->select_through ^= true; + } + else { + if (!mode_match) { + if (obedit) { + ts->select_through_edit ^= true; + } + else { + ts->select_through_object ^= true; + } + } + + if (!ts->select_through) { + ts->select_through ^= true; + } + + if (!ts->select_through_circle) { + ts->select_through_circle ^= true; + } + } + } + + ED_area_tag_redraw(area); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_toggle_select_through(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Select Through"; + ot->idname = "VIEW3D_OT_toggle_select_through"; + ot->description = "Select occluded objects and mesh elements with box, lasso, and circle select"; + + /* api callbacks */ + ot->exec = toggle_select_through_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Facedots + * \{ */ + +static int toggle_facedots_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + View3D *v3d = CTX_wm_view3d(C); + if (!XRAY_FLAG_ENABLED(v3d)) { + v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT; + } + else { + v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT_XRAY; + } + ED_area_tag_redraw(area); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_toggle_facedots(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Toggle Facedots"; + ot->idname = "VIEW3D_OT_toggle_facedots"; + ot->description = "Show face center dots in the current shading mode"; + /* api callbacks */ + ot->exec = toggle_facedots_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 695025cf726..1c3a2b1b725 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -61,6 +61,9 @@ void VIEW3D_OT_render_border(struct wmOperatorType *ot); void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot); void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot); void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_auto_xray(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_select_through(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_facedots(struct wmOperatorType *ot); /* `view3d_draw.cc` */ diff --git a/source/blender/editors/space_view3d/view3d_navigate.cc b/source/blender/editors/space_view3d/view3d_navigate.cc index dca57939fc0..6e9c740174f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.cc +++ b/source/blender/editors/space_view3d/view3d_navigate.cc @@ -663,6 +663,25 @@ void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPro if (flag & V3D_OP_PROP_USE_MOUSE_INIT) { WM_operator_properties_use_cursor_init(ot); } + + if (flag & V3D_OP_PROP_FRAME_SELECTED_DISTANCE) { + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, + "frame_selected_distance", + 0, + 0, + 1000, + "Camera Offset", + "Distance to put camera from selected", + 0, + 1000); + } + + if (flag & V3D_OP_PROP_ZOOM_SPEED) { + PropertyRNA *prop; + prop = RNA_def_float( + ot->srna, "zoom_speed", 1.2f, 1.001, 10, "Zoom Speed", "Speed to zoom camera", 1.001f, 10); + } } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_navigate.hh b/source/blender/editors/space_view3d/view3d_navigate.hh index 2318dd546cd..ea5ea8b3f7f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate.hh +++ b/source/blender/editors/space_view3d/view3d_navigate.hh @@ -41,6 +41,8 @@ enum eV3D_OpPropFlag { V3D_OP_PROP_DELTA = (1 << 1), V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2), V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3), + V3D_OP_PROP_FRAME_SELECTED_DISTANCE = (1 << 4), + V3D_OP_PROP_ZOOM_SPEED = (1 << 5), }; ENUM_OPERATORS(eV3D_OpPropFlag, V3D_OP_PROP_USE_MOUSE_INIT); diff --git a/source/blender/editors/space_view3d/view3d_navigate_view_all.cc b/source/blender/editors/space_view3d/view3d_navigate_view_all.cc index e357332d4d3..73baba9cb55 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_view_all.cc +++ b/source/blender/editors/space_view3d/view3d_navigate_view_all.cc @@ -91,7 +91,8 @@ static void view3d_from_minmax(bContext *C, const float min[3], const float max[3], bool ok_dist, - const int smooth_viewtx) + const int smooth_viewtx, + const int view_dist) { RegionView3D *rv3d = static_cast(region->regiondata); float afm[3]; @@ -134,7 +135,7 @@ static void view3d_from_minmax(bContext *C, v3d, region, depsgraph, persp, true, (size / 2) * VIEW3D_MARGIN); if (rv3d->is_persp) { /* don't zoom closer than the near clipping plane */ - new_dist = max_ff(new_dist, v3d->clip_start * 1.5f); + new_dist = max_ff(new_dist, v3d->clip_start * 1.5f + view_dist); } } } @@ -166,7 +167,8 @@ static void view3d_from_minmax_multi(bContext *C, const float min[3], const float max[3], const bool ok_dist, - const int smooth_viewtx) + const int smooth_viewtx, + const int view_dist) { ScrArea *area = CTX_wm_area(C); LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { @@ -175,7 +177,7 @@ static void view3d_from_minmax_multi(bContext *C, /* when using all regions, don't jump out of camera view, * but _do_ allow locked cameras to be moved */ if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { - view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx); + view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx, view_dist); } } } @@ -263,10 +265,10 @@ static int view3d_all_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view_undo_begin(C, area); if (use_all_regions) { - view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx); + view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx, 0); } else { - view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx); + view3d_from_minmax(C, v3d, region, min, max, true, smooth_viewtx, 0); } ED_view3d_smooth_view_undo_end(C, area, op->type->name, false); @@ -328,6 +330,7 @@ static int viewselected_exec(bContext *C, wmOperator *op) /* any one of the regions may be locked */ (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA)); const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + const int view_dist = RNA_int_get(op->ptr, "frame_selected_distance"); INIT_MINMAX(min, max); if (is_face_map) { @@ -454,10 +457,10 @@ static int viewselected_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view_undo_begin(C, area); if (use_all_regions) { - view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx); + view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx, view_dist); } else { - view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx); + view3d_from_minmax(C, v3d, region, min, max, ok_dist, smooth_viewtx, view_dist); } ED_view3d_smooth_view_undo_end(C, area, op->type->name, false); @@ -481,6 +484,7 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot) /* properties */ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS); + view3d_operator_properties_common(ot, V3D_OP_PROP_FRAME_SELECTED_DISTANCE); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_navigate_view_zoom.cc b/source/blender/editors/space_view3d/view3d_navigate_view_zoom.cc index ff4feb5da89..207f9666cf0 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_view_zoom.cc +++ b/source/blender/editors/space_view3d/view3d_navigate_view_zoom.cc @@ -389,7 +389,8 @@ static void view_zoom_apply_step(bContext *C, ScrArea *area, ARegion *region, const int delta, - const int zoom_xy[2]) + const int zoom_xy[2], + const float zoom_speed) { View3D *v3d = static_cast(area->spacedata.first); RegionView3D *rv3d = static_cast(region->regiondata); @@ -402,7 +403,8 @@ static void view_zoom_apply_step(bContext *C, ED_view3d_dist_range_get(v3d, dist_range); if (delta < 0) { - const float step = 1.2f; + const float step = zoom_speed; + if (use_cam_zoom) { view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy); } @@ -413,7 +415,7 @@ static void view_zoom_apply_step(bContext *C, } } else { - const float step = 1.0f / 1.2f; + const float step = 1.0f / zoom_speed; if (use_cam_zoom) { view_zoom_to_window_xy_camera(scene, depsgraph, v3d, region, step, zoom_xy); } @@ -446,6 +448,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op) RegionView3D *rv3d = static_cast(region->regiondata); const int delta = RNA_int_get(op->ptr, "delta"); + const float zoom_speed = RNA_float_get(op->ptr, "zoom_speed"); const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init"); int zoom_xy_buf[2]; @@ -459,7 +462,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op) zoom_xy = zoom_xy_buf; } - view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy); + view_zoom_apply_step(C, depsgraph, scene, area, region, delta, zoom_xy, zoom_speed); ED_view3d_camera_lock_undo_grouped_push(op->type->name, v3d, rv3d, C); return OPERATOR_FINISHED; @@ -481,6 +484,7 @@ static int viewzoom_invoke_impl(bContext *C, prop = RNA_struct_find_property(ptr, "delta"); const int delta = RNA_property_is_set(ptr, prop) ? RNA_property_int_get(ptr, prop) : 0; + const float zoom_speed = RNA_float_get(ptr, "zoom_speed"); if (delta) { const bool do_zoom_to_mouse_pos = (vod->viewops_flag & VIEWOPS_FLAG_ZOOM_TO_MOUSE) != 0; @@ -490,7 +494,8 @@ static int viewzoom_invoke_impl(bContext *C, vod->area, vod->region, delta, - do_zoom_to_mouse_pos ? xy : nullptr); + do_zoom_to_mouse_pos ? xy : nullptr, + zoom_speed); return OPERATOR_FINISHED; } @@ -545,8 +550,9 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_XY; /* properties */ - view3d_operator_properties_common( - ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT); + view3d_operator_properties_common(ot, + V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | + V3D_OP_PROP_USE_MOUSE_INIT | V3D_OP_PROP_ZOOM_SPEED); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_ops.cc b/source/blender/editors/space_view3d/view3d_ops.cc index 1bc6e5c0aee..c6017358431 100644 --- a/source/blender/editors/space_view3d/view3d_ops.cc +++ b/source/blender/editors/space_view3d/view3d_ops.cc @@ -223,6 +223,9 @@ void view3d_operatortypes() WM_operatortype_append(VIEW3D_OT_toggle_shading); WM_operatortype_append(VIEW3D_OT_toggle_xray); WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip); + WM_operatortype_append(VIEW3D_OT_toggle_auto_xray); + WM_operatortype_append(VIEW3D_OT_toggle_select_through); + WM_operatortype_append(VIEW3D_OT_toggle_facedots); WM_operatortype_append(VIEW3D_OT_ruler_add); WM_operatortype_append(VIEW3D_OT_ruler_remove); diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 2ab147bb96e..66064b5c151 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -30,6 +30,7 @@ #include "BLI_listbase.h" #include "BLI_math_bits.h" #include "BLI_math_geom.h" +#include "BLI_math_matrix.h" #include "BLI_rect.h" #include "BLI_span.hh" #include "BLI_string.h" @@ -107,6 +108,7 @@ // #include "BLI_time_utildefines.h" using blender::Vector; +using namespace blender; /* -------------------------------------------------------------------- */ /** \name Public Utilities @@ -114,7 +116,12 @@ using blender::Vector; float ED_view3d_select_dist_px() { - return 75.0f * U.pixelsize; + if (U.flag & USER_ADJUSTABLE_CLICK_SELECT) { + return U.selection_radius * U.pixelsize; + } + else { + return 75.0f * U.pixelsize; + } } ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph) @@ -154,6 +161,347 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) /** \name Internal Object Utilities * \{ */ +/* helper also for box_select and lasso */ +static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) +{ + return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2); +} + +static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) +{ + int d1, d2, d3, d4; + + /* check points in rect */ + if (edge_fully_inside_rect(rect, v1, v2)) { + return true; + } + + /* check points completely out rect */ + if (v1[0] < rect->xmin && v2[0] < rect->xmin) { + return false; + } + if (v1[0] > rect->xmax && v2[0] > rect->xmax) { + return false; + } + if (v1[1] < rect->ymin && v2[1] < rect->ymin) { + return false; + } + if (v1[1] > rect->ymax && v2[1] > rect->ymax) { + return false; + } + + /* simple check lines intersecting. */ + d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); + d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); + d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); + d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); + + if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) { + return false; + } + if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) { + return false; + } + + return true; +} + +const bool object_filter(ViewContext *vc, + Base *base, + const int style, + const int mcoords[][2], + const int mcoords_len, + rctf *rectf, + const int circle_data[3], + const bool square_select) +{ + Mesh *me = BKE_object_to_mesh(nullptr, base->object, false); + ED_view3d_init_mats_rv3d(base->object, vc->rv3d); + float radius_squared, point[2], v1co[2], v2co[2]; + const bool lasso = mcoords != nullptr; + const bool box = rectf != nullptr && !square_select; + const bool square = rectf != nullptr && square_select; + const bool circle = circle_data != nullptr; + bool in_bounds = false; + bool touch_bounds = false; + bool inside = false; + + if (lasso) { + point[0] = static_cast(mcoords[0][0]); + point[1] = static_cast(mcoords[0][1]); + } + else if (box || square) { + point[0] = rectf->xmin; + point[1] = rectf->ymin; + } + else if (circle) { + radius_squared = float(circle_data[2]) * float(circle_data[2]); + point[0] = float(circle_data[0]); + point[1] = float(circle_data[1]); + } + + /* bounds check for touch & non-circle enclose */ + if (style == 1 || box || lasso) { + const std::optional> bounds = me->bounds_min_max(); + float boundsv2[4][2] = {}; + float boundsv3[8][3] = {bounds->min[0], bounds->min[1], bounds->min[2], bounds->min[0], + bounds->min[1], bounds->max[2], bounds->min[0], bounds->max[1], + bounds->min[2], bounds->min[0], bounds->max[1], bounds->max[2], + bounds->max[0], bounds->max[1], bounds->min[2], bounds->max[0], + bounds->max[1], bounds->max[2], bounds->max[0], bounds->min[1], + bounds->min[2], bounds->max[0], bounds->min[1], bounds->max[2]}; + ED_view3d_project_float_object( + vc->region, boundsv3[0], v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + boundsv2[0][0] = boundsv2[1][0] = boundsv2[2][0] = boundsv2[3][0] = v1co[0]; + boundsv2[0][1] = boundsv2[1][1] = boundsv2[2][1] = boundsv2[3][1] = v1co[1]; + + for (int i = 1; i < 8; i++) { + ED_view3d_project_float_object( + vc->region, boundsv3[i], v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + if (v1co[0] < boundsv2[0][0]) { + boundsv2[0][0] = boundsv2[1][0] = v1co[0]; + } + else if (v1co[0] > boundsv2[2][0]) { + boundsv2[2][0] = boundsv2[3][0] = v1co[0]; + } + if (v1co[1] < boundsv2[0][1]) { + boundsv2[0][1] = boundsv2[3][1] = v1co[1]; + } + else if (v1co[1] > boundsv2[1][1]) { + boundsv2[1][1] = boundsv2[2][1] = v1co[1]; + } + } + + if (style == 1) { + in_bounds = isect_point_poly_v2(point, boundsv2, 4); + + for (int i = 0; i < 4; i++) { + if (lasso) { + if (i == 3) { + touch_bounds = BLI_lasso_is_edge_inside(mcoords, + mcoords_len, + (int)boundsv2[3][0], + (int)boundsv2[3][1], + (int)boundsv2[0][0], + (int)boundsv2[0][1], + IS_CLIPPED, + false); + } + else { + touch_bounds = BLI_lasso_is_edge_inside(mcoords, + mcoords_len, + (int)boundsv2[i][0], + (int)boundsv2[i][1], + (int)boundsv2[i + 1][0], + (int)boundsv2[i + 1][1], + IS_CLIPPED, + false); + } + } + else if (box || square) { + if (i == 3) { + touch_bounds = edge_inside_rect(rectf, boundsv2[3], boundsv2[0]); + } + else { + touch_bounds = edge_inside_rect(rectf, boundsv2[i], boundsv2[i + 1]); + } + } + else if (circle) { + if (i == 3) { + touch_bounds = edge_inside_circle(point, circle_data[2], boundsv2[3], boundsv2[0]); + } + else { + touch_bounds = edge_inside_circle(point, circle_data[2], boundsv2[i], boundsv2[i + 1]); + } + } + if (touch_bounds) { + break; + } + } + + if (!in_bounds && !touch_bounds) { + return false; + } + } + else { + for (int i = 0; i < 4; i++) { + if (lasso) { + if (i == 3) { + inside = BLI_lasso_is_edge_inside(mcoords, + mcoords_len, + (int)boundsv2[3][0], + (int)boundsv2[3][1], + (int)boundsv2[0][0], + (int)boundsv2[0][1], + IS_CLIPPED, + true); + } + else { + inside = BLI_lasso_is_edge_inside(mcoords, + mcoords_len, + (int)boundsv2[i][0], + (int)boundsv2[i][1], + (int)boundsv2[i + 1][0], + (int)boundsv2[i + 1][1], + IS_CLIPPED, + true); + } + } + else if (box) { + if (i == 3) { + inside = edge_fully_inside_rect(rectf, boundsv2[3], boundsv2[0]); + } + else { + inside = edge_fully_inside_rect(rectf, boundsv2[i], boundsv2[i + 1]); + } + } + if (!inside) { + break; + } + } + if (inside) { + return true; + } + } + } + + /* touch */ + const Span positions = me->vert_positions(); + if (style == 1) { + for (int i = 0; i < me->verts_num; i++) { + ED_view3d_project_float_object( + vc->region, positions[i], v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + + if (lasso) { + inside = BLI_lasso_is_point_inside(mcoords, + mcoords_len, + int(v1co[0]), + int(v1co[1]), + /* Dummy value. */ + INT_MAX); + } + else if (box || square) { + inside = BLI_rctf_isect_pt_v(rectf, v1co); + } + else if (circle) { + inside = len_squared_v2v2(point, v1co) <= radius_squared; + } + if (inside) { + return true; + } + } + + const blender::Span edges = me->edges(); + for (int i = 0; i < me->edges_num; i++) { + ED_view3d_project_float_object(vc->region, + positions[edges[i][0]], + v1co, + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + ED_view3d_project_float_object(vc->region, + positions[edges[i][1]], + v2co, + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + if (lasso) { + inside = BLI_lasso_is_edge_inside(mcoords, + mcoords_len, + (int)v1co[0], + (int)v1co[1], + (int)v2co[0], + (int)v2co[1], + IS_CLIPPED, + false); + } + else if (box || square) { + inside = edge_inside_rect(rectf, v1co, v2co); + } + else if (circle) { + inside = edge_inside_circle(point, circle_data[2], v1co, v2co); + } + if (inside) { + break; + } + } + /* skip checks that can't succeed after vert & edge failure */ + if (!inside && !touch_bounds && in_bounds) { + const blender::OffsetIndices faces = me->faces(); + const Span corner_verts = me->corner_verts(); + + for (const int i : faces.index_range()) { + const Span polyverts = corner_verts.slice(faces[i]); + const int size = polyverts.size(); + + if (size == 3) { + float tri[3][2] = {}; + for (int i = 0; i < 3; i++) { + ED_view3d_project_float_object(vc->region, + positions[polyverts[i]], + v1co, + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + tri[i][0] = v1co[0]; + tri[i][1] = v1co[1]; + } + inside = isect_point_poly_v2(point, tri, 3); + } + else if (size == 4) { + float quad[4][2] = {}; + for (int i = 0; i < 4; i++) { + ED_view3d_project_float_object(vc->region, + positions[polyverts[i]], + v1co, + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + quad[i][0] = v1co[0]; + quad[i][1] = v1co[1]; + } + inside = isect_point_poly_v2(point, quad, 4); + } + else { + float(*ngon)[2] = static_cast( + MEM_mallocN(sizeof(float) * 2 * size, __func__)); + for (int i = 0; i < size; i++) { + ED_view3d_project_float_object(vc->region, + positions[polyverts[i]], + v1co, + V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + ngon[i][0] = v1co[0]; + ngon[i][1] = v1co[1]; + } + inside = isect_point_poly_v2(point, ngon, size); + MEM_freeN(ngon); + } + if (inside) { + break; + } + } + } + } + /* enclose */ + else { + for (int i = 0; i < me->verts_num; i++) { + ED_view3d_project_float_object( + vc->region, positions[i], v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + + if (lasso) { + inside = BLI_lasso_is_point_inside(mcoords, + mcoords_len, + int(v1co[0]), + int(v1co[1]), + /* Dummy value. */ + INT_MAX); + } + else if (box || square) { + inside = BLI_rctf_isect_pt_v(rectf, v1co); + } + else if (circle) { + inside = len_squared_v2v2(point, v1co) <= radius_squared; + } + if (!inside) { + break; + } + } + } + return inside; +} + static bool object_deselect_all_visible(const Scene *scene, ViewLayer *view_layer, View3D *v3d) { bool changed = false; @@ -248,15 +596,580 @@ static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *w /** \name Internal Edit-Mesh Utilities * \{ */ -static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, +struct BoxSelectUserData { + ViewContext *vc; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + eSelectOp sel_op; + eBezTriple_Flag select_flag; + int edge_style; + int face_style; + bool check_mesh_direction; + + /* runtime */ + bool is_done; + bool is_changed; +}; + +struct LassoSelectUserData { + ViewContext *vc; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + const int (*mcoords)[2]; + int mcoords_len; + eSelectOp sel_op; + eBezTriple_Flag select_flag; + int edge_style; + int face_style; + bool check_mesh_direction; + + /* runtime */ + int pass; + bool is_done; + bool is_changed; +}; + +struct CircleSelectUserData { + ViewContext *vc; + bool select; + int mval[2]; + float mval_fl[2]; + float radius; + float radius_squared; + eBezTriple_Flag select_flag; + int edge_style; + int face_style; + bool check_mesh_direction; + + /* runtime */ + bool is_changed; +}; + +void edbm_vert_orientation(const BMVert *eve, float normal[3], float plane[3], float meshmat[3][3]) +{ + float vec[3] = {}; + float tangent[3] = {0.0f, 0.0f, 1.0f}; + copy_v3_v3(normal, eve->no); + + if (eve->e) { + float v1co[3] = {eve->e->v1->co[0], eve->e->v1->co[1], eve->e->v1->co[2]}; + float v2co[3] = {eve->e->v2->co[0], eve->e->v2->co[1], eve->e->v2->co[2]}; + sub_v3_v3v3(plane, v2co, v1co); + } + else { + if (eve->no[0] < 0.5f) { + vec[0] = 1.0f; + } + else if (eve->no[1] < 0.5f) { + vec[1] = 1.0f; + } + else { + vec[2] = 1.0f; + } + cross_v3_v3v3(plane, eve->no, vec); + } + normalize_v3(plane); + copy_v3_v3(meshmat[2], normal); + cross_v3_v3v3(meshmat[0], meshmat[2], tangent); + + if (is_zero_v3(meshmat[0])) { + tangent[0] = 1.0f; + tangent[1] = tangent[2] = 0.0f; + cross_v3_v3v3(meshmat[0], tangent, meshmat[2]); + } + cross_v3_v3v3(meshmat[1], meshmat[2], meshmat[0]); +} + +void edbm_edge_orientation(const BMEdge *eed, float normal[3], float plane[3]) +{ + float eed_plane[3] = {}; + float vec[3] = {}; + add_v3_v3v3(normal, eed->v1->no, eed->v2->no); + sub_v3_v3v3(eed_plane, eed->v2->co, eed->v1->co); + cross_v3_v3v3(vec, normal, eed_plane); + cross_v3_v3v3(normal, eed_plane, vec); + normalize_v3(normal); + + if (BM_edge_is_boundary(eed)) { + sub_v3_v3v3(plane, eed->l->v->co, eed->l->next->v->co); + } + else { + if (eed->v2->co[1] > eed->v1->co[1]) { + sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); + } + else { + sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); + } + } + normalize_v3(plane); +} + +bool edbm_normal_facing_viewport(ViewContext *vc, + struct BMVert *eve, + struct BMEdge *eed, + struct BMFace *efa, + bool use_direction) +{ + ToolSettings *ts = vc->scene->toolsettings; + float normal[3], plane[3], meshcol3[3], viewcol3[3], meshmat[3][3]; + int direction = eve != nullptr ? ts->viewport_facing_select_vert : + eed != nullptr ? ts->viewport_facing_select_edge : + ts->viewport_facing_select_face; + bool backface = use_direction && (direction == 4 || direction == 8); + + if (eve != nullptr) { + edbm_vert_orientation(eve, normal, plane, meshmat); + } + else { + if (eed != nullptr) { + edbm_edge_orientation(eed, normal, plane); + } + else if (efa != nullptr) { + copy_v3_v3(normal, efa->no); + BM_face_calc_tangent_auto(efa, plane); + } + normalize_v3_v3(meshmat[2], normal); + negate_v3_v3(meshmat[1], plane); + + if (is_zero_v3(meshmat[1])) { + meshmat[1][2] = 1.0f; + } + cross_v3_v3v3(meshmat[0], meshmat[2], meshmat[1]); + cross_v3_v3v3(meshmat[1], meshmat[2], meshmat[0]); + normalize_v3(meshmat[1]); + } + normalize_m3(meshmat); + invert_m3(meshmat); + meshcol3[0] = meshmat[0][2]; + meshcol3[1] = meshmat[1][2]; + meshcol3[2] = meshmat[2][2]; + viewcol3[0] = vc->rv3d->viewmat[0][2]; + viewcol3[1] = vc->rv3d->viewmat[1][2]; + viewcol3[2] = vc->rv3d->viewmat[2][2]; + + bool mesh_facing = false; + if (backface) { + mesh_facing = dot_v3v3(meshcol3, viewcol3) < -ts->viewport_facing_select_threshold; + } + else { + mesh_facing = dot_v3v3(meshcol3, viewcol3) > ts->viewport_facing_select_threshold; + } + return mesh_facing; +} + +bool edbm_facing_viewport_precheck(ToolSettings *ts, int style, bool xray) +{ + if (!ts->viewport_facing_select) { + return false; + } + const bool mode_match = xray ? ts->viewport_facing_select_mode == 1 || + ts->viewport_facing_select_mode == 4 : + ts->viewport_facing_select_mode < 4; + const bool check_mesh_facing = mode_match && style > 0 && style < 16; + return check_mesh_facing; +} + +bool edbm_facing_viewport(ViewContext *vc, BMVert *eve, BMEdge *eed, BMFace *efa, int style) +{ + BMIter iter; + bool mesh_facing = false; + if (eve != nullptr) { + /* viewport-facing or rear-facing vert */ + mesh_facing = edbm_normal_facing_viewport(vc, eve, nullptr, nullptr, true); + if (!mesh_facing && eve->e && eve->e->l && (style == 2 || style == 8)) { + BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { + const bool eve_efa_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, false); + /* vert of a viewport-facing face */ + if (style == 2) { + if (eve_efa_facing) { + mesh_facing = true; + break; + } + } + /* vert of a rear-facing face */ + else if (!eve_efa_facing) { + mesh_facing = true; + break; + } + } + } + } + else if (eed != nullptr) { + /* viewport-facing or rear-facing edge */ + mesh_facing = edbm_normal_facing_viewport(vc, nullptr, eed, nullptr, true); + if (!mesh_facing && eed->l && (style == 2 || style == 8)) { + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + const bool eed_efa_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, false); + /* edge of a viewport-facing face */ + if (style == 2) { + if (eed_efa_facing) { + mesh_facing = true; + break; + } + } + /* edge of a rear-facing face */ + else if (!eed_efa_facing) { + mesh_facing = true; + break; + } + } + } + } + else if (efa != nullptr) { + /* viewport-facing or rear-facing face */ + mesh_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, true); + if (!mesh_facing && (style == 2 || style == 8)) { + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + const bool efa_eve_facing = edbm_normal_facing_viewport(vc, eve, nullptr, nullptr, false); + /* face has a viewport-facing vert */ + if (style == 2) { + if (efa_eve_facing) { + mesh_facing = true; + break; + } + } + /* face has a rear-facing vert */ + else if (!efa_eve_facing) { + mesh_facing = true; + break; + } + } + } + } + return mesh_facing; +} + +static void mesh_filter( + ViewContext *vc, void *box_data, void *lasso_data, void *circle_data, eSelectOp sel_op) +{ + BMVert *eve; + BoxSelectUserData *data = static_cast(box_data); + LassoSelectUserData *ldata = static_cast(lasso_data); + CircleSelectUserData *cdata = static_cast(circle_data); + const BMesh *bm = vc->em->bm; + const bool box = box_data != nullptr; + const bool lasso = lasso_data != nullptr; + const bool circle = circle_data != nullptr; + const bool enclose = box ? data->face_style == 4 : + lasso ? ldata->face_style == 4 : + cdata->face_style == 4; + const bool check_direction = box ? data->check_mesh_direction : + lasso ? ldata->check_mesh_direction : + cdata->check_mesh_direction; + int totvert = bm->totvert; + float v1co[2], v2co[2]; + float(*vco)[2] = static_cast(MEM_mallocN(sizeof(int) * 2 * totvert, __func__)); + + /* store 2d vert co */ + for (int i = 0; i < bm->totvert; i++) { + eve = BM_vert_at_index(vc->em->bm, i); + if (ED_view3d_project_float_object( + vc->region, eve->co, v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB) == + V3D_PROJ_RET_OK) + { + vco[i][0] = v1co[0]; + vco[i][1] = v1co[1]; + } + /* invalid vco */ + else { + vco[i][0] = 0.0f; + vco[i][1] = 0.0f; + } + } + + for (int i = 0; i < bm->totface; i++) { + BMFace *efa = BM_face_at_index(vc->em->bm, i); + bool inside = false; + bool mesh_facing = true; + + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + BMLoop *l_first, *l_iter; + rctf facetmp; + rctf *face = &facetmp; + BLI_rctf_init_minmax(face); + bool skip = false; + + /* out of range check */ + if (bm->totvert > totvert) { + MEM_freeN(vco); + totvert = bm->totvert; + vco = static_cast(MEM_mallocN(sizeof(float) * 2 * totvert, __func__)); + + for (int i = 0; i < bm->totvert; i++) { + eve = BM_vert_at_index(vc->em->bm, i); + if (ED_view3d_project_float_object( + vc->region, eve->co, v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB) == + V3D_PROJ_RET_OK) + { + vco[i][0] = v1co[0]; + vco[i][1] = v1co[1]; + } + else { + vco[i][0] = 0.0f; + vco[i][1] = 0.0f; + } + } + } + + /* skip invalid */ + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + if (vco[BM_elem_index_get(l_iter->v)][0] == 0.0f && + vco[BM_elem_index_get(l_iter->v)][1] == 0.0f) + { + skip = true; + break; + } + BLI_rctf_do_minmax_v(face, vco[BM_elem_index_get(l_iter->v)]); + } while ((l_iter = l_iter->next) != l_first); + + /* skip non-intersect, not enough on its own, selects too many things */ + if (!skip) { + if (box && !BLI_rctf_isect(face, data->rect_fl, nullptr) || + lasso && !BLI_rctf_isect(face, ldata->rect_fl, nullptr) || + circle && !BLI_rctf_isect_circle(face, cdata->mval_fl, cdata->radius)) + { + skip ^= true; + } + } + + if (!skip) { + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + if (circle && enclose) { + do { + v1co[0] = vco[BM_elem_index_get(l_iter->v)][0]; + v1co[1] = vco[BM_elem_index_get(l_iter->v)][1]; + inside = len_squared_v2v2(cdata->mval_fl, v1co) <= cdata->radius_squared; + + if (!inside) { + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { + do { + v1co[0] = vco[BM_elem_index_get(l_iter->e->v1)][0]; + v1co[1] = vco[BM_elem_index_get(l_iter->e->v1)][1]; + v2co[0] = vco[BM_elem_index_get(l_iter->e->v2)][0]; + v2co[1] = vco[BM_elem_index_get(l_iter->e->v2)][1]; + + if (box) { + inside = enclose ? edge_fully_inside_rect(data->rect_fl, v1co, v2co) : + edge_inside_rect(data->rect_fl, v1co, v2co); + } + else if (lasso) { + inside = BLI_lasso_is_edge_inside(ldata->mcoords, + ldata->mcoords_len, + int(v1co[0]), + int(v1co[1]), + int(v2co[0]), + int(v2co[1]), + IS_CLIPPED, + enclose); + } + else if (circle) { + inside = edge_inside_circle(cdata->mval_fl, cdata->radius, v1co, v2co); + } + + if (!enclose && inside) { + break; + } + else if (enclose && !inside) { + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + + /* touch face interior */ + if (!enclose && !inside) { + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + int vcount = 0; + float point[2]; + + if (box) { + point[0] = data->rect_fl->xmin; + point[1] = data->rect_fl->ymin; + } + else if (lasso) { + point[0] = static_cast(ldata->mcoords[0][0]); + point[1] = static_cast(ldata->mcoords[0][1]); + } + else if (circle) { + point[0] = cdata->mval_fl[0]; + point[1] = cdata->mval_fl[1]; + } + + if (efa->len == 3) { + float tri[3][2]; + do { + tri[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; + tri[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + vcount++; + } while ((l_iter = l_iter->next) != l_first); + + inside = isect_point_tri_v2(point, tri[0], tri[1], tri[2]); + } + else if (efa->len == 4) { + float quad[4][2]; + do { + quad[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; + quad[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + vcount++; + } while ((l_iter = l_iter->next) != l_first); + + inside = isect_point_quad_v2(point, quad[0], quad[1], quad[2], quad[3]); + } + else { + float(*ngon)[2] = static_cast( + MEM_mallocN(sizeof(float) * 2 * efa->len, __func__)); + do { + ngon[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; + ngon[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + vcount++; + } while ((l_iter = l_iter->next) != l_first); + + inside = isect_point_poly_v2(point, ngon, efa->len); + MEM_freeN(ngon); + } + } + + if (inside && check_direction) { + mesh_facing = edbm_facing_viewport( + vc, nullptr, nullptr, efa, vc->scene->toolsettings->viewport_facing_select_face); + } + } + } + + const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); + const int sel_op_result = ED_select_op_action_deselected( + sel_op, is_select, inside && mesh_facing); + + if (sel_op_result != -1) { + BM_face_select_set(vc->em->bm, efa, sel_op_result); + if (box) { + data->is_changed = true; + } + else if (lasso) { + ldata->is_changed = true; + } + else if (circle) { + cdata->is_changed = true; + } + } + } + MEM_freeN(vco); +} + +bool edbm_circle_enclose_mesh(BMEdge *eed, BMFace *efa, struct CircleSelectUserData *data) +{ + BMVert *eve; + BMIter iter; + bool enclose = false; + + if (eed != nullptr) { + BM_ITER_ELEM (eve, &iter, eed, BM_VERTS_OF_EDGE) { + float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; + float vertv2[2] = {}; + ED_view3d_project_float_object( + data->vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + enclose = len_squared_v2v2(data->mval_fl, vertv2) <= data->radius_squared; + if (!enclose) { + break; + } + } + } + else if (efa != nullptr) { + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + float vertv3[3] = {eve->co[0], eve->co[1], eve->co[2]}; + float vertv2[2] = {}; + ED_view3d_project_float_object( + data->vc->region, vertv3, vertv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + enclose = len_squared_v2v2(data->mval_fl, vertv2) <= data->radius_squared; + if (!enclose) { + break; + } + } + } + return enclose; +} + +bool edbm_center_face(ViewContext *vc, + BMFace *efa, + const rctf *rect, + struct LassoSelectUserData *ldata, + struct CircleSelectUserData *cdata) +{ + BMVert *eve; + BMIter iter; + float centerv3[3], centerv2[2]; + int vcount = 0; + bool center_face = false; + + if (efa->len == 3) { + float tri[3][3]; + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + tri[vcount][0] = eve->co[0]; + tri[vcount][1] = eve->co[1]; + tri[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3v3v3(centerv3, tri[0], tri[1], tri[2]); + } + else if (efa->len == 4) { + float quad[4][3]; + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + quad[vcount][0] = eve->co[0]; + quad[vcount][1] = eve->co[1]; + quad[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3v3v3v3(centerv3, quad[0], quad[1], quad[2], quad[3]); + } + else { + float(*ngon)[3] = static_cast( + MEM_mallocN(sizeof(float) * 3 * efa->len, __func__)); + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + ngon[vcount][0] = eve->co[0]; + ngon[vcount][1] = eve->co[1]; + ngon[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3_array(centerv3, ngon, efa->len); + MEM_freeN(ngon); + } + + ED_view3d_project_float_object( + vc->region, centerv3, centerv2, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB); + + if (ldata != nullptr) { + center_face = BLI_rctf_isect_pt_v(rect, centerv2) && + BLI_lasso_is_point_inside( + ldata->mcoords, ldata->mcoords_len, centerv2[0], centerv2[1], IS_CLIPPED); + } + else if (cdata != nullptr) { + center_face = (len_squared_v2v2(cdata->mval_fl, centerv2) <= cdata->radius_squared); + } + else { + center_face = BLI_rctf_isect_pt_v(rect, centerv2); + } + return center_face; +} + +static bool edbm_backbuf_check_and_select_verts(ViewContext *vc, + EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) { + ToolSettings *ts = vc->scene->toolsettings; BMVert *eve; BMIter iter; bool changed = false; + const int style = ts->viewport_facing_select_vert; + const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); @@ -269,7 +1182,12 @@ static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + bool mesh_facing = true; + if (is_inside && check_mesh_facing) { + mesh_facing = edbm_facing_viewport(vc, eve, nullptr, nullptr, style); + } + const int sel_op_result = ED_select_op_action_deselected( + sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_vert_select_set(em->bm, eve, sel_op_result); changed = true; @@ -280,15 +1198,20 @@ static bool edbm_backbuf_check_and_select_verts(EditSelectBuf_Cache *esel, return changed; } -static bool edbm_backbuf_check_and_select_edges(EditSelectBuf_Cache *esel, +static bool edbm_backbuf_check_and_select_edges(void *userData, + EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, const eSelectOp sel_op) { + CircleSelectUserData *data = static_cast(userData); + ToolSettings *ts = data->vc->scene->toolsettings; BMEdge *eed; BMIter iter; bool changed = false; + const int style = ts->viewport_facing_select_edge; + const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); @@ -301,7 +1224,19 @@ static bool edbm_backbuf_check_and_select_edges(EditSelectBuf_Cache *esel, if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + bool enclose_edge = true; + bool mesh_facing = true; + + if (data->edge_style == 4 && is_inside) { + enclose_edge = edbm_circle_enclose_mesh(eed, nullptr, data); + } + + if (check_mesh_facing && is_inside) { + mesh_facing = edbm_facing_viewport(data->vc, nullptr, eed, nullptr, style); + } + + const int sel_op_result = ED_select_op_action_deselected( + sel_op, is_select, is_inside && enclose_edge && mesh_facing); if (sel_op_result != -1) { BM_edge_select_set(em->bm, eed, sel_op_result); changed = true; @@ -312,28 +1247,74 @@ static bool edbm_backbuf_check_and_select_edges(EditSelectBuf_Cache *esel, return changed; } -static bool edbm_backbuf_check_and_select_faces(EditSelectBuf_Cache *esel, +static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, + EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, - const eSelectOp sel_op) + const eSelectOp sel_op, + const rcti *rect, + const int face_style, + void *lasso_data, + void *circle_data) { + ToolSettings *ts = vc->scene->toolsettings; + BMIter iter, viter; BMFace *efa; - BMIter iter; + BMVert *eve; + rctf rectf; bool changed = false; - + const int style = ts->viewport_facing_select_face; + const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); const BLI_bitmap *select_bitmap = esel->select_bitmap; + LassoSelectUserData *ldata = static_cast(lasso_data); + CircleSelectUserData *cdata = static_cast(circle_data); uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_FACE); - if (index == 0) { + uint vindex = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); + + if (rect != nullptr) { + BLI_rctf_rcti_copy(&rectf, rect); + } + + if (index == 0 || vindex == 0) { return false; } index -= 1; + vindex -= 1; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + bool enclose_face = true; + bool center_face = true; + bool mesh_facing = true; + + if (face_style > 2 && is_inside) { + if (face_style == 4) { + if (cdata != nullptr) { + enclose_face = edbm_circle_enclose_mesh(nullptr, efa, cdata); + } + else { + BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { + enclose_face = BLI_BITMAP_TEST_BOOL(select_bitmap, vindex + BM_elem_index_get(eve)); + if (!enclose_face) { + break; + } + } + } + } + else { + center_face = edbm_center_face(vc, efa, &rectf, ldata, cdata); + } + } + + if (check_mesh_facing && is_inside) { + mesh_facing = edbm_facing_viewport(vc, nullptr, nullptr, efa, style); + } + + const int sel_op_result = ED_select_op_action_deselected( + sel_op, is_select, is_inside && enclose_face && center_face && mesh_facing); if (sel_op_result != -1) { BM_face_select_set(em->bm, efa, sel_op_result); changed = true; @@ -412,28 +1393,14 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *mesh, /** \name Lasso Select * \{ */ -struct LassoSelectUserData { - ViewContext *vc; - const rcti *rect; - const rctf *rect_fl; - rctf _rect_fl; - const int (*mcoords)[2]; - int mcoords_len; - eSelectOp sel_op; - eBezTriple_Flag select_flag; - - /* runtime */ - int pass; - bool is_done; - bool is_changed; -}; - static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, ViewContext *vc, const rcti *rect, const int (*mcoords)[2], const int mcoords_len, - const eSelectOp sel_op) + const eSelectOp sel_op, + const int edge_style, + const int face_style) { r_data->vc = vc; @@ -446,6 +1413,9 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, 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 = (eBezTriple_Flag)SELECT; + r_data->edge_style = edge_style; + r_data->face_style = face_style; + r_data->check_mesh_direction = false; /* runtime */ r_data->pass = 0; @@ -484,51 +1454,6 @@ static bool view3d_selectable_data(bContext *C) return true; } -/* helper also for box_select */ -static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) -{ - return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2); -} - -static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2]) -{ - int d1, d2, d3, d4; - - /* check points in rect */ - if (edge_fully_inside_rect(rect, v1, v2)) { - return true; - } - - /* check points completely out rect */ - if (v1[0] < rect->xmin && v2[0] < rect->xmin) { - return false; - } - if (v1[0] > rect->xmax && v2[0] > rect->xmax) { - return false; - } - if (v1[1] < rect->ymin && v2[1] < rect->ymin) { - return false; - } - if (v1[1] > rect->ymax && v2[1] > rect->ymax) { - return false; - } - - /* simple check lines intersecting. */ - d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); - d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); - d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax); - d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin); - - if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) { - return false; - } - if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) { - return false; - } - - return true; -} - static void do_lasso_select_pose__do_tag(void *user_data, bPoseChannel *pchan, const float screen_co_a[2], @@ -541,8 +1466,12 @@ static void do_lasso_select_pose__do_tag(void *user_data, } if (BLI_rctf_isect_segment(data->rect_fl, screen_co_a, screen_co_b) && - BLI_lasso_is_edge_inside( - data->mcoords, data->mcoords_len, 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, + false)) { pchan->bone->flag |= BONE_DONE; data->is_changed = true; @@ -560,7 +1489,7 @@ static void do_lasso_tag_pose(ViewContext *vc, const int mcoords[][2], const int BLI_lasso_boundbox(&rect, mcoords, mcoords_len); view3d_userdata_lassoselect_init( - &data, vc, &rect, mcoords, mcoords_len, static_cast(0)); + &data, vc, &rect, mcoords, mcoords_len, static_cast(0), 0, 0); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); @@ -571,41 +1500,175 @@ static void do_lasso_tag_pose(ViewContext *vc, const int mcoords[][2], const int V3D_PROJ_TEST_CLIP_DEFAULT | V3D_PROJ_TEST_CLIP_CONTENT_DEFAULT); } +/** + * Compare result of 'GPU_select': 'GPUSelectResult', + * Needed for stable sorting, so cycling through all items near the cursor behaves predictably. + */ +static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b_p) +{ + GPUSelectResult *a = (GPUSelectResult *)sel_a_p; + GPUSelectResult *b = (GPUSelectResult *)sel_b_p; + + if (a->depth < b->depth) { + return -1; + } + if (a->depth > b->depth) { + return 1; + } + + /* Depths match, sort by id. */ + uint sel_a = a->id; + uint sel_b = b->id; + +#ifdef __BIG_ENDIAN__ + BLI_endian_switch_uint32(&sel_a); + BLI_endian_switch_uint32(&sel_b); +#endif + + if (sel_a < sel_b) { + return -1; + } + if (sel_a > sel_b) { + return 1; + } + return 0; +} + static bool do_lasso_select_objects(ViewContext *vc, const int mcoords[][2], const int mcoords_len, - const eSelectOp sel_op) + const eSelectOp sel_op, + wmOperator *op) { View3D *v3d = vc->v3d; - + ToolSettings *ts = vc->scene->toolsettings; bool changed = false; + float region_co[2]; + const int object_style = RNA_enum_get(op->ptr, "object_type"); + const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); + changed |= object_deselect_all_visible(vc->scene, vc->view_layer, v3d); } - BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); - LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { - if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */ - float region_co[2]; - const bool is_select = base->flag & BASE_SELECTED; - const bool is_inside = (ED_view3d_project_base(vc->region, base, region_co) == - V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcoords, - mcoords_len, - int(region_co[0]), - int(region_co[1]), - /* Dummy value. */ - INT_MAX); - 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); - changed = true; + + if (wireless_touch) { + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { + if (BASE_SELECTABLE(v3d, base)) { + const bool is_select = base->flag & BASE_SELECTED; + bool is_inside = false; + if (base->object->type == OB_MESH) { + is_inside = object_filter( + vc, base, object_style, mcoords, mcoords_len, nullptr, nullptr, false); + } + else { + is_inside = (ED_view3d_project_base(vc->region, base, region_co) == -V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside(mcoords, + mcoords_len, + int(region_co[0]), + int(region_co[1]), + /* Dummy value. */ + INT_MAX); + } + 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); + changed = true; + } } } - } - if (changed) { - DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); - WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); + if (changed) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); + } + } + else { + int hits = 0; + GPUSelectBuffer buffer; + rcti rect; + blender::Vector bases; + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); + const bool select_through = XRAY_FLAG_ENABLED(v3d) || + (ts->select_through && ts->select_through_object && + ts->select_through_lasso); + const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, + vc->obact); + + if (select_through) { + hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_PICK_ALL, select_filter); + } + else { + hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_PICK_NEAREST, select_filter); + } + + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { + base->object->id.tag &= ~LIB_TAG_DOIT; + } + ListBase *object_bases = BKE_view_layer_object_bases_get(vc->view_layer); + + if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { + goto finally; + } + + LISTBASE_FOREACH (Base *, base, object_bases) { + if (BASE_SELECTABLE(v3d, base)) { + if ((base->object->runtime->select_id & 0x0000FFFF) != 0) { + bases.append(base); + } + } + } + + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(buffer.storage.data(), hits, sizeof(GPUSelectResult), gpu_select_buffer_depth_id_cmp); + for (const GPUSelectResult *buf_iter = buffer.storage.data(), *buf_end = buf_iter + hits; + buf_iter < buf_end; + buf_iter++) + { + bPoseChannel *pchan_dummy; + Base *base = ED_armature_base_and_pchan_from_select_buffer( + bases, buf_iter->id, &pchan_dummy); + + if (base != nullptr) { + base->object->id.tag |= LIB_TAG_DOIT; + } + } + + for (Base *base = static_cast(object_bases->first); base && hits; base = base->next) { + if (BASE_SELECTABLE(v3d, base)) { + const bool is_select = base->flag & BASE_SELECTED; + bool is_inside = false; + if (base->object->type == OB_MESH && (object_style == 1 || object_style == 2)) { + is_inside = base->object->id.tag & LIB_TAG_DOIT && + object_filter( + vc, base, object_style, mcoords, mcoords_len, nullptr, nullptr, false); + } + else { + is_inside = base->object->id.tag & LIB_TAG_DOIT && + (ED_view3d_project_base(vc->region, base, region_co) == -V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside(mcoords, + mcoords_len, + int(region_co[0]), + int(region_co[1]), + /* Dummy value. */ + INT_MAX); + } + + 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); + changed = true; + } + } + } + + finally: + if (changed) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(vc->C, NC_SCENE | ND_OB_SELECT, vc->scene); + } } return changed; } @@ -739,7 +1802,18 @@ static void do_lasso_select_mesh__doSelectVert(void *user_data, (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); + bool mesh_facing = true; + + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + eve, + nullptr, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_vert); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_vert_select_set(data->vc->em->bm, eve, sel_op_result); data->is_changed = true; @@ -760,6 +1834,7 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, user_data); LassoSelectUserData *data = data_for_edge->data; bool is_visible = true; + bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); @@ -772,7 +1847,17 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, 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 (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + eed, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_edge); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); data->is_done = true; @@ -789,6 +1874,7 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, user_data); LassoSelectUserData *data = data_for_edge->data; bool is_visible = true; + bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); @@ -799,8 +1885,17 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), - IS_CLIPPED)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + IS_CLIPPED, + false)); + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + eed, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_edge); + } + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); data->is_changed = true; @@ -818,7 +1913,18 @@ static void do_lasso_select_mesh__doSelectFace(void *user_data, (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); + bool mesh_facing = true; + + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + nullptr, + efa, + data->vc->scene->toolsettings->viewport_facing_select_face); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_face_select_set(data->vc->em->bm, efa, sel_op_result); data->is_changed = true; @@ -829,7 +1935,8 @@ static bool do_lasso_select_mesh(ViewContext *vc, wmGenericUserData *wm_userdata, const int mcoords[][2], const int mcoords_len, - const eSelectOp sel_op) + const eSelectOp sel_op, + wmOperator *op) { LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; @@ -840,7 +1947,14 @@ static bool do_lasso_select_mesh(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data, + vc, + &rect, + mcoords, + mcoords_len, + sel_op, + RNA_enum_get(op->ptr, "edge_type"), + RNA_enum_get(op->ptr, "face_type")); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -854,12 +1968,23 @@ static bool do_lasso_select_mesh(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + const bool select_through = ts->select_through && ts->select_through_edit && + ts->select_through_lasso; + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); if (use_zbuf) { if (wm_userdata->data == nullptr) { - editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); + /* for near enclose face */ + if (data.face_style == 4 && ts->selectmode & SCE_SELECT_FACE && + !(ts->selectmode & SCE_SELECT_VERTEX)) + { + editselect_buf_cache_init_with_generic_userdata( + wm_userdata, vc, ts->selectmode | SCE_SELECT_VERTEX); + } + else { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); + } esel = static_cast(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, nullptr); @@ -869,9 +1994,12 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( - esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_vert, true); + mesh_foreachScreenVert( vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -887,12 +2015,20 @@ static bool do_lasso_select_mesh(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); - /* Fully inside. */ - mesh_foreachScreenEdge_clip_bb_segment( - vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); - if (data.is_done == false) { - /* Fall back to partially inside. - * Clip content to account for edges partially behind the view. */ + + data.check_mesh_direction = use_zbuf ? + edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_edge, false) : + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_edge, true); + + /* Fully inside */ + if (data.edge_style != 2) { + mesh_foreachScreenEdge_clip_bb_segment( + vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, clip_flag); + } + /* Partially inside */ + if (data.edge_style == 2 || data.edge_style == 1 && data.is_done == false) { mesh_foreachScreenEdge_clip_bb_segment(vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, @@ -902,12 +2038,30 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces( - esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces(vc, + esel, + vc->depsgraph, + vc->obedit, + vc->em, + sel_op, + &rect, + data.face_style, + &data, + nullptr); } else { - mesh_foreachScreenFace( - vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_face, true); + + /* center */ + if (data.face_style == 1 || data.face_style == 8) { + mesh_foreachScreenFace( + vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + /* touch & enclose */ + else { + mesh_filter(vc, nullptr, &data, nullptr, sel_op); + } } } @@ -971,7 +2125,7 @@ static bool do_lasso_select_curve(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); Curve *curve = (Curve *)vc->obedit->data; ListBase *nurbs = BKE_curve_editNurbs_get(curve); @@ -1022,7 +2176,7 @@ static bool do_lasso_select_lattice(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); @@ -1050,7 +2204,9 @@ static void do_lasso_select_armature__doSelectBone(void *user_data, if (screen_co_a[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX), + false) { is_inside_flag |= BONESEL_ROOT; } @@ -1061,7 +2217,9 @@ static void do_lasso_select_armature__doSelectBone(void *user_data, if (screen_co_b[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX), + false) { is_inside_flag |= BONESEL_TIP; } @@ -1072,8 +2230,12 @@ static void do_lasso_select_armature__doSelectBone(void *user_data, if (is_ignore_flag == 0) { if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || - BLI_lasso_is_edge_inside( - data->mcoords, data->mcoords_len, 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, + false)) { is_inside_flag |= BONESEL_BONE; } @@ -1102,8 +2264,12 @@ static void do_lasso_select_armature__doSelectBone_clip_content(void *user_data, return; } - if (BLI_lasso_is_edge_inside( - data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) + if (BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX, + false)) { is_inside_flag |= BONESEL_BONE; } @@ -1121,7 +2287,7 @@ static bool do_lasso_select_armature(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); @@ -1181,7 +2347,7 @@ static bool do_lasso_select_meta(ViewContext *vc, BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= BKE_mball_deselect_all(mb); @@ -1313,7 +2479,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc, LassoSelectUserData_ForMeshVert data; data.select_vert = select_vert.span; - view3d_userdata_lassoselect_init(&data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op); + view3d_userdata_lassoselect_init( + &data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op, 0, 0); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); @@ -1378,7 +2545,8 @@ static bool view3d_lasso_select(bContext *C, ViewContext *vc, const int mcoords[][2], const int mcoords_len, - const eSelectOp sel_op) + const eSelectOp sel_op, + wmOperator *op) { using namespace blender; Object *ob = CTX_data_active_object(C); @@ -1412,7 +2580,7 @@ static bool view3d_lasso_select(bContext *C, /* pass */ } else { - changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op); + changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op, op); if (changed_multi) { ED_outliner_select_sync_from_object_tag(C); } @@ -1426,7 +2594,7 @@ static bool view3d_lasso_select(bContext *C, switch (vc->obedit->type) { case OB_MESH: - changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op); + changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op, op); break; case OB_CURVES_LEGACY: case OB_SURF: @@ -1506,7 +2674,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph); eSelectOp sel_op = static_cast(RNA_enum_get(op->ptr, "mode")); - bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op); + bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op, op); MEM_freeN((void *)mcoords); @@ -2228,40 +3396,6 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc, return hits; } -/** - * Compare result of 'GPU_select': 'GPUSelectResult', - * Needed for stable sorting, so cycling through all items near the cursor behaves predictably. - */ -static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b_p) -{ - GPUSelectResult *a = (GPUSelectResult *)sel_a_p; - GPUSelectResult *b = (GPUSelectResult *)sel_b_p; - - if (a->depth < b->depth) { - return -1; - } - if (a->depth > b->depth) { - return 1; - } - - /* Depths match, sort by id. */ - uint sel_a = a->id; - uint sel_b = b->id; - -#ifdef __BIG_ENDIAN__ - BLI_endian_switch_uint32(&sel_a); - BLI_endian_switch_uint32(&sel_b); -#endif - - if (sel_a < sel_b) { - return -1; - } - if (sel_a > sel_b) { - return 1; - } - return 0; -} - /** * \param has_bones: When true, skip non-bone hits, also allow bases to be used * that are visible but not select-able, @@ -3496,23 +4630,12 @@ void VIEW3D_OT_select(wmOperatorType *ot) /** \name Box Select * \{ */ -struct BoxSelectUserData { - ViewContext *vc; - const rcti *rect; - const rctf *rect_fl; - rctf _rect_fl; - eSelectOp sel_op; - eBezTriple_Flag select_flag; - - /* runtime */ - bool is_done; - bool is_changed; -}; - static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, ViewContext *vc, const rcti *rect, - const eSelectOp sel_op) + const eSelectOp sel_op, + const int edge_style, + const int face_style) { r_data->vc = vc; @@ -3523,6 +4646,9 @@ static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, 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 = (eBezTriple_Flag)SELECT; + r_data->edge_style = edge_style; + r_data->face_style = face_style; + r_data->check_mesh_direction = false; /* runtime */ r_data->is_done = false; @@ -3560,7 +4686,8 @@ static void do_paintvert_box_select__doSelectVert(void *user_data, static bool do_paintvert_box_select(ViewContext *vc, wmGenericUserData *wm_userdata, const rcti *rect, - const eSelectOp sel_op) + const eSelectOp sel_op, + const bool square) { using namespace blender; const bool use_zbuf = !XRAY_ENABLED(vc->v3d); @@ -3579,15 +4706,31 @@ static bool do_paintvert_box_select(ViewContext *vc, /* pass */ } else if (use_zbuf) { - EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); - if (wm_userdata->data == nullptr) { - editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); + if (square) { + if (wm_userdata->data == nullptr) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); + } + EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); esel = static_cast(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( vc->depsgraph, vc->region, vc->v3d, rect, nullptr); + if (esel->select_bitmap != nullptr) { + changed |= edbm_backbuf_check_and_select_verts_obmode(mesh, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = nullptr; + } } - if (esel->select_bitmap != nullptr) { - changed |= edbm_backbuf_check_and_select_verts_obmode(mesh, esel, sel_op); + else { + EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); + if (wm_userdata->data == nullptr) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); + esel = static_cast(wm_userdata->data); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->region, vc->v3d, rect, nullptr); + } + if (esel->select_bitmap != nullptr) { + changed |= edbm_backbuf_check_and_select_verts_obmode(mesh, esel, sel_op); + } } } else { @@ -3598,7 +4741,7 @@ static bool do_paintvert_box_select(ViewContext *vc, BoxSelectUserData_ForMeshVert data; data.select_vert = select_vert.span; - view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op, 0, 0); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); @@ -3621,7 +4764,8 @@ static bool do_paintvert_box_select(ViewContext *vc, static bool do_paintface_box_select(ViewContext *vc, wmGenericUserData *wm_userdata, const rcti *rect, - eSelectOp sel_op) + eSelectOp sel_op, + const bool square) { Object *ob = vc->obact; Mesh *mesh; @@ -3640,15 +4784,31 @@ static bool do_paintface_box_select(ViewContext *vc, /* pass */ } else { - EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); - if (wm_userdata->data == nullptr) { - editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); + if (square) { + if (wm_userdata->data == nullptr) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); + } + EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); esel = static_cast(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( vc->depsgraph, vc->region, vc->v3d, rect, nullptr); + if (esel->select_bitmap != nullptr) { + changed |= edbm_backbuf_check_and_select_faces_obmode(mesh, esel, sel_op); + MEM_freeN(esel->select_bitmap); + esel->select_bitmap = nullptr; + } } - if (esel->select_bitmap != nullptr) { - changed |= edbm_backbuf_check_and_select_faces_obmode(mesh, esel, sel_op); + else { + EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); + if (wm_userdata->data == nullptr) { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); + esel = static_cast(wm_userdata->data); + esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( + vc->depsgraph, vc->region, vc->v3d, rect, nullptr); + } + if (esel->select_bitmap != nullptr) { + changed |= edbm_backbuf_check_and_select_faces_obmode(mesh, esel, sel_op); + } } } @@ -3704,7 +4864,7 @@ static bool do_nurbs_box_select(ViewContext *vc, const rcti *rect, const eSelect const bool deselect_all = (sel_op == SEL_OP_SET); BoxSelectUserData data; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data, vc, rect, sel_op, 0, 0); Curve *curve = (Curve *)vc->obedit->data; ListBase *nurbs = BKE_curve_editNurbs_get(curve); @@ -3743,7 +4903,7 @@ static bool do_lattice_box_select(ViewContext *vc, const rcti *rect, const eSele { BoxSelectUserData data; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data, vc, rect, sel_op, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); @@ -3764,7 +4924,17 @@ static void do_mesh_box_select__doSelectVert(void *user_data, BoxSelectUserData *data = static_cast(user_data); 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); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + bool mesh_facing = true; + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + eve, + nullptr, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_vert); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_vert_select_set(data->vc->em->bm, eve, sel_op_result); data->is_changed = true; @@ -3788,6 +4958,7 @@ static void do_mesh_box_select__doSelectEdge_pass0(void *user_data, user_data); BoxSelectUserData *data = data_for_edge->data; bool is_visible = true; + bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); @@ -3796,7 +4967,17 @@ static void do_mesh_box_select__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)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + eed, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_edge); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); data->is_done = true; @@ -3816,6 +4997,7 @@ static void do_mesh_box_select__doSelectEdge_pass1(void *user_data, user_data); BoxSelectUserData *data = data_for_edge->data; bool is_visible = true; + bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); @@ -3823,12 +5005,22 @@ static void do_mesh_box_select__doSelectEdge_pass1(void *user_data, const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + eed, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_edge); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); data->is_changed = true; } } + static void do_mesh_box_select__doSelectFace(void *user_data, BMFace *efa, const float screen_co[2], @@ -3837,7 +5029,18 @@ static void do_mesh_box_select__doSelectFace(void *user_data, BoxSelectUserData *data = static_cast(user_data); 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); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + bool mesh_facing = true; + + if (is_inside && data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport(data->vc, + nullptr, + nullptr, + efa, + data->vc->scene->toolsettings->viewport_facing_select_face); + } + + const int sel_op_result = ED_select_op_action_deselected( + data->sel_op, is_select, is_inside && mesh_facing); if (sel_op_result != -1) { BM_face_select_set(data->vc->em->bm, efa, sel_op_result); data->is_changed = true; @@ -3846,12 +5049,19 @@ static void do_mesh_box_select__doSelectFace(void *user_data, static bool do_mesh_box_select(ViewContext *vc, wmGenericUserData *wm_userdata, const rcti *rect, - const eSelectOp sel_op) + const eSelectOp sel_op, + wmOperator *op, + const bool square) { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data, + vc, + rect, + sel_op, + RNA_enum_get(op->ptr, "edge_type"), + RNA_enum_get(op->ptr, "face_type")); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -3865,12 +5075,28 @@ static bool do_mesh_box_select(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + const bool select_through = square ? ts->select_through && ts->select_through_edit && + ts->select_through_circle : + ts->select_through && ts->select_through_edit && + ts->select_through_box; + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; + + if (use_zbuf) { + /* for near enclose face */ + if (data.face_style == 4 && ts->selectmode & SCE_SELECT_FACE && + !(ts->selectmode & SCE_SELECT_VERTEX)) + { + editselect_buf_cache_init_with_generic_userdata( + wm_userdata, vc, ts->selectmode | SCE_SELECT_VERTEX); + } + else { + editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); + } + } EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); if (use_zbuf) { - if (wm_userdata->data == nullptr) { - editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); + if (esel->select_bitmap == nullptr) { esel = static_cast(wm_userdata->data); esel->select_bitmap = DRW_select_buffer_bitmap_from_rect( vc->depsgraph, vc->region, vc->v3d, rect, nullptr); @@ -3880,9 +5106,12 @@ static bool do_mesh_box_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( - esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_vert, true); + mesh_foreachScreenVert( vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -3898,12 +5127,19 @@ static bool do_mesh_box_select(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); - /* Fully inside. */ - mesh_foreachScreenEdge_clip_bb_segment( - vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); - if (data.is_done == false) { - /* Fall back to partially inside. - * Clip content to account for edges partially behind the view. */ + + data.check_mesh_direction = use_zbuf ? + edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_edge, false) : + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_edge, true); + /* Fully inside */ + if (data.edge_style != 2) { + mesh_foreachScreenEdge_clip_bb_segment( + vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, clip_flag); + } + /* Partially inside */ + if (data.edge_style == 2 || data.edge_style == 1 && data.is_done == false) { mesh_foreachScreenEdge_clip_bb_segment(vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, @@ -3913,12 +5149,30 @@ static bool do_mesh_box_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { - data.is_changed |= edbm_backbuf_check_and_select_faces( - esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + data.is_changed |= edbm_backbuf_check_and_select_faces(vc, + esel, + vc->depsgraph, + vc->obedit, + vc->em, + sel_op, + rect, + data.face_style, + nullptr, + nullptr); } else { - mesh_foreachScreenFace( - vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_face, true); + + /* center */ + if (data.face_style == 1 || data.face_style == 8) { + mesh_foreachScreenFace( + vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + /* touch & enclose */ + else { + mesh_filter(vc, &data, nullptr, nullptr, sel_op); + } } } @@ -4077,27 +5331,57 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_ static bool do_object_box_select(bContext *C, ViewContext *vc, const rcti *rect, - const eSelectOp sel_op) + const eSelectOp sel_op, + wmOperator *op, + bool square) { View3D *v3d = vc->v3d; - + ToolSettings *ts = vc->scene->toolsettings; GPUSelectBuffer buffer; const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); - const int hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter); - BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); - LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { - base->object->id.tag &= ~LIB_TAG_DOIT; + rctf rectf_data; + rctf *rectf = &rectf_data; + BLI_rctf_rcti_copy(rectf, rect); + int hits = 0; + bool changed = false; + float region_co[2]; + const int object_style = RNA_enum_get(op->ptr, "object_type"); + const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); + bool select_through; + bool select; + int select_flag; + + if (square) { + select_through = XRAY_FLAG_ENABLED(vc->v3d) || + ts->select_through && ts->select_through_object && ts->select_through_circle; + select = (sel_op != SEL_OP_SUB); + select_flag = select ? BASE_SELECTED : 0; + } + else { + select_through = XRAY_FLAG_ENABLED(vc->v3d) || + ts->select_through && ts->select_through_object && ts->select_through_box; } - blender::Vector bases; - - bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } + if (select_through) { + hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter); + } + else { + hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_PICK_NEAREST, select_filter); + } + + BKE_view_layer_synced_ensure(vc->scene, vc->view_layer); + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { + base->object->id.tag &= ~LIB_TAG_DOIT; + } + blender::Vector bases; ListBase *object_bases = BKE_view_layer_object_bases_get(vc->view_layer); + if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { goto finally; } @@ -4109,10 +5393,8 @@ static bool do_object_box_select(bContext *C, } } } - /* The draw order doesn't always match the order we populate the engine, see: #51695. */ qsort(buffer.storage.data(), hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp); - for (const GPUSelectResult *buf_iter = buffer.storage.data(), *buf_end = buf_iter + hits; buf_iter < buf_end; buf_iter++) @@ -4124,20 +5406,91 @@ static bool do_object_box_select(bContext *C, } } - for (Base *base = static_cast(object_bases->first); base && hits; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - const bool is_select = base->flag & BASE_SELECTED; - const bool is_inside = base->object->id.tag & LIB_TAG_DOIT; - 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); - changed = true; + if (wireless_touch) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) { + if (square) { + if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { + const bool is_select = base->flag & BASE_SELECTED; + const bool is_inside = + base->object->type == OB_MESH ? + object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true) : + base->object->id.tag & LIB_TAG_DOIT; + 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); + changed = true; + } + } + } + else { + if (BASE_SELECTABLE(v3d, base)) { + const bool is_select = base->flag & BASE_SELECTED; + const bool is_inside = + base->object->type == OB_MESH ? + object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, false) : + base->object->id.tag & LIB_TAG_DOIT; + 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); + changed = true; + } + } + } + } + } + else { + for (Base *base = static_cast(object_bases->first); base && hits; base = base->next) { + if (square) { + if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { + const bool is_select = base->flag & BASE_SELECTED; + bool is_inside = false; + if (base->object->type != OB_MESH || object_style < 2) { + is_inside = base->object->id.tag & LIB_TAG_DOIT; + } + else { + if (object_style == 2 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true); + } + else if (object_style == 4 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = (ED_view3d_project_base(vc->region, base, region_co) == + V3D_PROJ_RET_OK) && + BLI_rctf_isect_pt_v(rectf, region_co); + } + } + 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); + changed = true; + } + } + } + else { + if (BASE_SELECTABLE(v3d, base)) { + const bool is_select = base->flag & BASE_SELECTED; + bool is_inside = false; + if (base->object->type != OB_MESH || object_style < 2) { + is_inside = base->object->id.tag & LIB_TAG_DOIT; + } + else { + if (object_style == 2 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true); + } + else if (object_style == 4 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = (ED_view3d_project_base(vc->region, base, region_co) == + V3D_PROJ_RET_OK) && + BLI_rctf_isect_pt_v(rectf, region_co); + } + } + 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); + changed = true; + } + } } } } - finally: - if (changed) { DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); @@ -4290,7 +5643,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) switch (vc.obedit->type) { case OB_MESH: vc.em = BKE_editmesh_from_object(vc.obedit); - changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op); + changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op, op, false); if (changed) { DEG_id_tag_update(static_cast(vc.obedit->data), ID_RECALC_SELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); @@ -4357,10 +5710,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } else { /* No edit-mode, unified for bones and objects. */ if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op); + changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op, false); } else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op); + changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op, false); } else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { changed_multi = PE_box_select(C, &rect, sel_op); @@ -4375,7 +5728,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op) } } else { /* object mode with none active */ - changed_multi = do_object_box_select(C, &vc, &rect, sel_op); + changed_multi = do_object_box_select(C, &vc, &rect, sel_op, op, false); if (changed_multi) { ED_outliner_select_sync_from_object_tag(C); } @@ -4418,24 +5771,13 @@ void VIEW3D_OT_select_box(wmOperatorType *ot) /** \name Circle Select * \{ */ -struct CircleSelectUserData { - ViewContext *vc; - bool select; - int mval[2]; - float mval_fl[2]; - float radius; - float radius_squared; - eBezTriple_Flag select_flag; - - /* runtime */ - bool is_changed; -}; - static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, ViewContext *vc, const bool select, const int mval[2], - const float rad) + const float rad, + const int edge_style, + const int face_style) { r_data->vc = vc; r_data->select = select; @@ -4448,6 +5790,9 @@ static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, /* SELECT by default, but can be changed if needed (only few cases use and respect this). */ r_data->select_flag = (eBezTriple_Flag)SELECT; + r_data->edge_style = edge_style; + r_data->face_style = face_style; + r_data->check_mesh_direction = false; /* runtime */ r_data->is_changed = false; @@ -4461,8 +5806,20 @@ static void mesh_circle_doSelectVert(void *user_data, CircleSelectUserData *data = static_cast(user_data); if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - BM_vert_select_set(data->vc->em->bm, eve, data->select); + bool mesh_facing = true; data->is_changed = true; + if (data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport( + data->vc, + eve, + nullptr, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_vert); + } + if (mesh_facing) { + BM_vert_select_set(data->vc->em->bm, eve, data->select); + data->is_changed = true; + } } } static void mesh_circle_doSelectEdge(void *user_data, @@ -4472,22 +5829,52 @@ static void mesh_circle_doSelectEdge(void *user_data, int /*index*/) { CircleSelectUserData *data = static_cast(user_data); + bool enclose_edge = true; + bool mesh_facing = true; if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { - BM_edge_select_set(data->vc->em->bm, eed, data->select); - data->is_changed = true; + if (data->edge_style == 4) { + enclose_edge = edbm_circle_enclose_mesh(eed, nullptr, data); + } + + if (data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport( + data->vc, + nullptr, + eed, + nullptr, + data->vc->scene->toolsettings->viewport_facing_select_edge); + } + + if (enclose_edge && mesh_facing) { + BM_edge_select_set(data->vc->em->bm, eed, data->select); + data->is_changed = true; + } } } + static void mesh_circle_doSelectFace(void *user_data, BMFace *efa, const float screen_co[2], int /*index*/) { CircleSelectUserData *data = static_cast(user_data); + bool mesh_facing = true; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - BM_face_select_set(data->vc->em->bm, efa, data->select); - data->is_changed = true; + if (data->check_mesh_direction) { + mesh_facing = edbm_facing_viewport( + data->vc, + nullptr, + nullptr, + efa, + data->vc->scene->toolsettings->viewport_facing_select_face); + } + + if (mesh_facing) { + BM_face_select_set(data->vc->em->bm, efa, data->select); + data->is_changed = true; + } } } @@ -4495,7 +5882,8 @@ static bool mesh_circle_select(ViewContext *vc, wmGenericUserData *wm_userdata, eSelectOp sel_op, const int mval[2], - float rad) + float rad, + wmOperator *op) { ToolSettings *ts = vc->scene->toolsettings; CircleSelectUserData data; @@ -4515,9 +5903,17 @@ static bool mesh_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, + vc, + select, + mval, + rad, + RNA_enum_get(op->ptr, "edge_type"), + RNA_enum_get(op->ptr, "face_type")); - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d); + const bool select_through = ts->select_through && ts->select_through_edit && + ts->select_through_circle; + const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; if (use_zbuf) { if (wm_userdata->data == nullptr) { @@ -4537,10 +5933,13 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_verts( - esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + vc, esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_vert, true); + mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -4549,10 +5948,13 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_edges( - esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + &data, esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_edge, true); + mesh_foreachScreenEdge_clip_bb_segment( vc, mesh_circle_doSelectEdge, @@ -4564,12 +5966,30 @@ static bool mesh_circle_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_FACE) { if (use_zbuf) { if (esel->select_bitmap != nullptr) { - changed |= edbm_backbuf_check_and_select_faces( - esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + changed |= edbm_backbuf_check_and_select_faces(vc, + esel, + vc->depsgraph, + vc->obedit, + vc->em, + select ? SEL_OP_ADD : SEL_OP_SUB, + nullptr, + data.face_style, + nullptr, + &data); } } else { - mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + data.check_mesh_direction = edbm_facing_viewport_precheck( + ts, ts->viewport_facing_select_face, true); + + /* center */ + if (data.face_style == 1 || data.face_style == 8) { + mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + /* touch & enclose */ + else { + mesh_filter(vc, nullptr, nullptr, &data, sel_op); + } } } @@ -4683,7 +6103,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad, 0, 0); meshobject_foreachScreenVert( vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); changed |= data.circle_data.is_changed; @@ -4737,7 +6157,7 @@ static bool nurbscurve_circle_select(ViewContext *vc, const bool deselect_all = (sel_op == SEL_OP_SET); CircleSelectUserData data; - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); Curve *curve = (Curve *)vc->obedit->data; ListBase *nurbs = BKE_curve_editNurbs_get(curve); @@ -4778,7 +6198,7 @@ static bool lattice_circle_select(ViewContext *vc, CircleSelectUserData data; const bool select = (sel_op != SEL_OP_SUB); - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); @@ -4870,7 +6290,7 @@ static bool pose_circle_select(ViewContext *vc, CircleSelectUserData data; const bool select = (sel_op != SEL_OP_SUB); - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); @@ -5008,7 +6428,7 @@ static bool armature_circle_select(ViewContext *vc, const bool select = (sel_op != SEL_OP_SUB); - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); @@ -5061,7 +6481,7 @@ static bool mball_circle_select(ViewContext *vc, const bool select = (sel_op != SEL_OP_SUB); - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, 0, 0); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= BKE_mball_deselect_all(static_cast(vc->obedit->data)); @@ -5129,30 +6549,60 @@ static bool obedit_circle_select(bContext *C, wmGenericUserData *wm_userdata, const eSelectOp sel_op, const int mval[2], - float rad) + float rad, + wmOperator *op, + const bool square, + rcti *rect) { using namespace blender; bool changed = false; BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); switch (vc->obedit->type) { case OB_MESH: - changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad); + if (square) { + vc->em = BKE_editmesh_from_object(vc->obedit); + changed = do_mesh_box_select(vc, wm_userdata, rect, sel_op, op, true); + } + else { + changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad, op); + } break; case OB_CURVES_LEGACY: case OB_SURF: - changed = nurbscurve_circle_select(vc, sel_op, mval, rad); + if (square) { + changed = do_nurbs_box_select(vc, rect, sel_op); + } + else { + changed = nurbscurve_circle_select(vc, sel_op, mval, rad); + } break; case OB_LATTICE: - changed = lattice_circle_select(vc, sel_op, mval, rad); + if (square) { + changed = do_lattice_box_select(vc, rect, sel_op); + } + else { + changed = lattice_circle_select(vc, sel_op, mval, rad); + } break; case OB_ARMATURE: - changed = armature_circle_select(vc, sel_op, mval, rad); + if (square) { + changed = do_armature_box_select(vc, rect, sel_op); + } + else { + changed = armature_circle_select(vc, sel_op, mval, rad); + } + if (changed) { ED_outliner_select_sync_from_edit_bone_tag(C); } break; case OB_MBALL: - changed = mball_circle_select(vc, sel_op, mval, rad); + if (square) { + changed = do_meta_box_select(vc, rect, sel_op); + } + else { + changed = mball_circle_select(vc, sel_op, mval, rad); + } break; case OB_CURVES: { Curves &curves_id = *static_cast(vc->obedit->data); @@ -5161,8 +6611,15 @@ static bool obedit_circle_select(bContext *C, bke::crazyspace::get_evaluated_curves_deformation(*vc->depsgraph, *vc->obedit); const bke::AttrDomain selection_domain = bke::AttrDomain(curves_id.selection_domain); const IndexRange elements(curves.attributes().domain_size(selection_domain)); - changed = ed::curves::select_circle( - *vc, curves, deformation.positions, elements, selection_domain, mval, rad, sel_op); + + if (square) { + changed = ed::curves::select_box( + *vc, curves, deformation.positions, elements, selection_domain, *rect, sel_op); + } + else { + changed = ed::curves::select_circle( + *vc, curves, deformation.positions, elements, selection_domain, mval, rad, sel_op); + } if (changed) { /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a * generic attribute for now. */ @@ -5172,7 +6629,13 @@ static bool obedit_circle_select(bContext *C, break; } case OB_GREASE_PENCIL: - changed = grease_pencil_circle_select(vc, sel_op, mval, rad); + /* this is gpen 3.0 and won't happen in 4.1 release version */ + if (square) { + changed = do_grease_pencil_box_select(vc, rect, sel_op); + } + else { + changed = grease_pencil_circle_select(vc, sel_op, mval, rad); + } break; default: @@ -5187,42 +6650,162 @@ static bool obedit_circle_select(bContext *C, return changed; } -static bool object_circle_select(ViewContext *vc, - const eSelectOp sel_op, - const int mval[2], - float rad) +static bool object_circle_select( + ViewContext *vc, const eSelectOp sel_op, wmOperator *op, const int mval[2], float rad) { BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); Scene *scene = vc->scene; ViewLayer *view_layer = vc->view_layer; View3D *v3d = vc->v3d; - - const float radius_squared = rad * rad; - const float mval_fl[2] = {float(mval[0]), float(mval[1])}; - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); - } + ToolSettings *ts = scene->toolsettings; + float region_co[2]; + const int circle_data[3] = {mval[0], mval[1], int(rad)}; + float mval_fl[2] = {float(mval[0]), float(mval[1])}; + float radius_squared = rad * rad; + const int object_style = RNA_enum_get(op->ptr, "object_type"); + const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); const bool select = (sel_op != SEL_OP_SUB); const int select_flag = select ? BASE_SELECTED : 0; + bool changed = false; + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= object_deselect_all_visible(scene, view_layer, v3d); + } BKE_view_layer_synced_ensure(scene, view_layer); - LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { - if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { - float screen_co[2]; - if (ED_view3d_project_float_global(vc->region, - base->object->object_to_world[3], - screen_co, - V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) - { - if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) { - ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); - changed = true; + + if (wireless_touch) { + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { + if (base->object->type == OB_MESH) { + if (object_filter(vc, base, object_style, nullptr, 0, nullptr, circle_data, false)) { + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); + changed = true; + } + } + else { + if (ED_view3d_project_float_global(vc->region, + base->object->object_to_world[3], + region_co, + V3D_PROJ_TEST_CLIP_DEFAULT) == V3D_PROJ_RET_OK) + + { + if (len_squared_v2v2(mval_fl, region_co) <= radius_squared) { + ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); + changed = true; + } + } } } } } + else { + GPUSelectBuffer buffer; + const bool select_through = XRAY_FLAG_ENABLED(v3d) || + (ts->select_through && ts->select_through_object && + ts->select_through_circle); + BKE_object_update_select_id(CTX_data_main(vc->C)); + int hits = 0; + int point[4][2] = {}; + rcti rect; + blender::Vector bases; + for (int i = 0; i < 4; i++) { + float angle = 6.28f * (i + 1) / 4; + point[i][0] = circle_data[0] + circle_data[2] * cosf(angle); + point[i][1] = circle_data[1] + circle_data[2] * sinf(angle); + } + rect.xmin = rect.xmax = point[0][0]; + rect.ymin = rect.ymax = point[0][1]; + for (int i = 1; i < 4; i++) { + if (point[i][0] < rect.xmin) { + rect.xmin = point[i][0]; + } + else if (point[i][0] > rect.xmax) { + rect.xmax = point[i][0]; + } + if (point[i][1] < rect.ymin) { + rect.ymin = point[i][1]; + } + else if (point[i][1] > rect.ymax) { + rect.ymax = point[i][1]; + } + } + const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(scene, + vc->obact); + if (select_through) { + hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_ALL, select_filter); + } + else { + hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_PICK_NEAREST, select_filter); + } + + LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { + base->object->id.tag &= ~LIB_TAG_DOIT; + } + ListBase *object_bases = BKE_view_layer_object_bases_get(view_layer); + + if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { + goto finally; + } + + LISTBASE_FOREACH (Base *, base, object_bases) { + if (BASE_SELECTABLE(v3d, base)) { + if ((base->object->runtime->select_id & 0x0000FFFF) != 0) { + bases.append(base); + } + } + } + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(buffer.storage.data(), hits, sizeof(GPUSelectResult), gpu_select_buffer_depth_id_cmp); + for (const GPUSelectResult *buf_iter = buffer.storage.data(), *buf_end = buf_iter + hits; + buf_iter < buf_end; + buf_iter++) + { + bPoseChannel *pchan_dummy; + Base *base = ED_armature_base_and_pchan_from_select_buffer( + bases, buf_iter->id, &pchan_dummy); + if (base != nullptr) { + base->object->id.tag |= LIB_TAG_DOIT; + } + } + + for (Base *base = static_cast(object_bases->first); base && hits; base = base->next) { + if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { + const bool is_select = base->flag & BASE_SELECTED; + bool is_inside = false; + if (base->object->type == OB_MESH && (object_style == 1 || object_style == 2)) { + is_inside = base->object->id.tag & LIB_TAG_DOIT ? + object_filter( + vc, base, object_style, nullptr, 0, nullptr, circle_data, false) ? + true : + false : + false; + } + else { + is_inside = base->object->id.tag & LIB_TAG_DOIT && + (ED_view3d_project_float_global(vc->region, + base->object->object_to_world[3], + region_co, + V3D_PROJ_TEST_CLIP_DEFAULT) == + V3D_PROJ_RET_OK) && + (len_squared_v2v2(mval_fl, region_co) <= radius_squared); + } + 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); + changed = true; + } + } + } + + finally: + if (changed) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(vc->C, NC_SCENE | ND_OB_SELECT, scene); + } + } return changed; } @@ -5286,10 +6869,18 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) static_cast(RNA_enum_get(op->ptr, "mode")), WM_gesture_is_modal_first(gesture)); ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph); + ToolSettings *ts = vc.scene->toolsettings; + bool square = ts->square_select; + rcti rect; Object *obact = vc.obact; Object *obedit = vc.obedit; + if (square) { + BLI_rcti_init(&rect, mval[0] - radius, mval[0] + radius, mval[1] - radius, mval[1] + radius); + BKE_object_update_select_id(CTX_data_main(C)); + } + if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) { view3d_operator_needs_opengl(C); if (obedit == nullptr) { @@ -5305,16 +6896,31 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) obedit = vc.obedit; if (obedit) { - obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, float(radius)); + obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, float(radius), op, square, &rect); } else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); + if (square) { + do_paintface_box_select(&vc, wm_userdata, &rect, sel_op, true); + } + else { + paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); + } } else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); + if (square) { + do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op, true); + } + else { + paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, float(radius)); + } } else if (obact->mode & OB_MODE_POSE) { - pose_circle_select(&vc, sel_op, mval, float(radius)); + if (square) { + do_pose_box_select(C, &vc, &rect, sel_op); + } + else { + pose_circle_select(&vc, sel_op, mval, float(radius)); + } ED_outliner_select_sync_from_pose_bone_tag(C); } else { @@ -5324,8 +6930,15 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) FOREACH_OBJECT_IN_MODE_END; } else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) { - if (PE_circle_select(C, wm_userdata, sel_op, mval, float(radius))) { - return OPERATOR_FINISHED; + if (square) { + if (PE_box_select(C, &rect, sel_op)) { + return OPERATOR_FINISHED; + } + } + else { + if (PE_circle_select(C, wm_userdata, sel_op, mval, float(radius))) { + return OPERATOR_FINISHED; + } } return OPERATOR_CANCELLED; } @@ -5337,15 +6950,28 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) nullptr) { ED_view3d_viewcontext_init_object(&vc, obact_pose); - pose_circle_select(&vc, sel_op, mval, float(radius)); + if (square) { + do_pose_box_select(C, &vc, &rect, sel_op); + } + else { + pose_circle_select(&vc, sel_op, mval, float(radius)); + } ED_outliner_select_sync_from_pose_bone_tag(C); } else { - if (object_circle_select(&vc, sel_op, mval, float(radius))) { - DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); - - ED_outliner_select_sync_from_object_tag(C); + if (square) { + if (do_object_box_select(C, &vc, &rect, sel_op, op, true)) { + DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); + ED_outliner_select_sync_from_object_tag(C); + } + } + else { + if (object_circle_select(&vc, sel_op, op, mval, float(radius))) { + DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene); + ED_outliner_select_sync_from_object_tag(C); + } } } diff --git a/source/blender/editors/uvedit/uvedit_select.cc b/source/blender/editors/uvedit/uvedit_select.cc index 6bdf5f63741..51171585309 100644 --- a/source/blender/editors/uvedit/uvedit_select.cc +++ b/source/blender/editors/uvedit/uvedit_select.cc @@ -3724,6 +3724,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) int x, y, radius, width, height; float zoomx, zoomy; float offset[2], ellipse[2]; + rctf rectf; const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? (ts->selectmode == SCE_SELECT_FACE) : @@ -3733,6 +3734,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) (ts->uv_selectmode == UV_SELECT_EDGE)); const bool use_select_linked = !(ts->uv_flag & UV_SYNC_SELECTION) && (ts->uv_selectmode == UV_SELECT_ISLAND); + const bool square = ts->square_select; /* get operator properties */ x = RNA_int_get(op->ptr, "x"); @@ -3749,6 +3751,11 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); + if (square) { + BLI_rctf_init(&rectf, x - radius, x + radius, y - radius, y + radius); + UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); + } + bool changed_multi = false; Vector objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( @@ -3782,7 +3789,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) if (select != uvedit_face_select_test(scene, efa, offsets)) { float cent[2]; BM_face_uv_calc_center_median(efa, offsets.uv, cent); - if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { + if (square ? BLI_rctf_isect_pt_v(&rectf, cent) : + uv_circle_select_is_point_inside(cent, offset, ellipse)) + { BM_elem_flag_enable(efa, BM_ELEM_TAG); changed = true; } @@ -3805,7 +3814,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - if (uv_circle_select_is_edge_inside(luv, luv_prev, offset, ellipse)) { + if (square ? BLI_rctf_isect_pt_v(&rectf, luv) && BLI_rctf_isect_pt_v(&rectf, luv_prev) : + uv_circle_select_is_edge_inside(luv, luv_prev, offset, ellipse)) + { uvedit_edge_select_set_with_sticky(scene, em, l_prev, select, false, offsets); changed = true; } @@ -3825,7 +3836,9 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (select != uvedit_uv_select_test(scene, l, offsets)) { luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - if (uv_circle_select_is_point_inside(luv, offset, ellipse)) { + if (square ? BLI_rctf_isect_pt_v(&rectf, luv) : + uv_circle_select_is_point_inside(luv, offset, ellipse)) + { changed = true; uvedit_uv_select_set(scene, em->bm, l, select, false, offsets); BM_elem_flag_enable(l->v, BM_ELEM_TAG); @@ -3919,7 +3932,7 @@ static bool do_lasso_select_mesh_uv_is_edge_inside(const ARegion *region, ®ion->v2d, co_test_a, co_test_b, co_screen_a, co_screen_b) && BLI_rcti_isect_segment(clip_rect, co_screen_a, co_screen_b) && BLI_lasso_is_edge_inside( - mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED)) + mcoords, mcoords_len, UNPACK2(co_screen_a), UNPACK2(co_screen_b), V2D_IS_CLIPPED, false)) { return true; } diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 29661489c52..1bd648f1d5b 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -408,6 +408,25 @@ /* Placement */ \ .snap_mode_tools = SCE_SNAP_TO_GEOM,\ .plane_axis = 2,\ +\ + /* X-Ray */ \ + .xray_button = true, \ + .auto_xray_object = true, \ + .auto_xray_edit = true, \ + .auto_xray_box = true, \ + .auto_xray_lasso = true, \ + .auto_xray_circle = true, \ + .select_through = true, \ + .select_through_object = true, \ + .select_through_box = true, \ + .select_through_lasso = true, \ + .select_through_circle = true, \ + \ + /* Viewport-Facing Select */ \ + .viewport_facing_select_mode = 1, \ + .viewport_facing_select_vert = 1, \ + .viewport_facing_select_edge = 1, \ + .viewport_facing_select_face = 1, \ } #define _DNA_DEFAULT_Sculpt \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index dc9e9d868f8..abff1376149 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1599,7 +1599,40 @@ typedef struct ToolSettings { char gpencil_selectmode_edit; /** Stroke selection mode for Sculpt. */ char gpencil_selectmode_sculpt; - char _pad0[6]; + + /* Mesh Normal Direction Select */ + char viewport_facing_select; + char viewport_facing_select_mode; + float viewport_facing_select_threshold; + char viewport_facing_select_vert; + char viewport_facing_select_edge; + char viewport_facing_select_face; + + /* X-Ray Options */ + char xray_button; + char auto_xray; + char auto_xray_button; + char auto_xray_reset; + char auto_xray_object; + char auto_xray_edit; + char auto_xray_box; + char auto_xray_lasso; + char auto_xray_circle; + char select_through; + char select_through_button; + char select_through_object; + char select_through_edit; + char select_through_box; + char select_through_lasso; + char select_through_circle; + char wireless_touch_object; + + /* Combine shading and xray header buttons */ + char shrink_shading_header; + + /* Square Select option for Circle */ + char square_select; + char _pad0[2]; /** Grease Pencil Sculpt. */ struct GP_Sculpt_Settings gp_sculpt; @@ -2451,6 +2484,78 @@ typedef enum eSnapTransformMode { SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2), } eSnapTransformMode; +/** #Viewport-facing select mode */ +enum { + VIEWPORT_FACING_SELECT_BOTH = (1 << 0), + VIEWPORT_FACING_SELECT_NEAR = (1 << 1), + VIEWPORT_FACING_SELECT_XRAY = (1 << 2), +}; + +/** #Viewport-facing select vert */ +enum { + VIEWPORT_FACING_SELECT_FRONT_VERTS = (1 << 0), + VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE = (1 << 1), + VIEWPORT_FACING_SELECT_REAR_VERTS = (1 << 2), + VIEWPORT_FACING_SELECT_REAR_VERTS_FACE = (1 << 3), + VIEWPORT_FACING_SELECT_ALL_VERTS = (1 << 4), +}; + +/** #Viewport-facing select edge */ +enum { + VIEWPORT_FACING_SELECT_FRONT_EDGES = (1 << 0), + VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE = (1 << 1), + VIEWPORT_FACING_SELECT_REAR_EDGES = (1 << 2), + VIEWPORT_FACING_SELECT_REAR_EDGES_FACE = (1 << 3), + VIEWPORT_FACING_SELECT_ALL_EDGES = (1 << 4), +}; + +/** #Viewport-facing select face */ +enum { + VIEWPORT_FACING_SELECT_FRONT_FACES = (1 << 0), + VIEWPORT_FACING_SELECT_FRONT_FACES_VERT = (1 << 1), + VIEWPORT_FACING_SELECT_REAR_FACES = (1 << 2), + VIEWPORT_FACING_SELECT_REAR_FACES_VERT = (1 << 3), + VIEWPORT_FACING_SELECT_ALL_FACES = (1 << 4), +}; + +/** #Object select style */ +enum { + OBJECT_TOUCH = (1 << 0), + OBJECT_ENCLOSE = (1 << 1), + OBJECT_ORIGIN = (1 << 2), +}; + +/** #Face select style */ +enum { + FACE_DEFAULT = (1 << 0), + FACE_TOUCH = (1 << 1), + FACE_ENCLOSE = (1 << 2), + FACE_CENTER = (1 << 3), +}; + +/** #Edge select style */ +enum { + EDGE_DEFAULT = (1 << 0), + EDGE_TOUCH = (1 << 1), + EDGE_ENCLOSE = (1 << 2), +}; + +/** #Auto X-Ray mode */ +enum { + AUTO_XRAY_DISABLE = (1 << 0), + AUTO_XRAY_OBJECT = (1 << 1), + AUTO_XRAY_EDIT = (1 << 2), + AUTO_XRAY_BOTH = (1 << 3), +}; + +/** #Select through mode */ +enum { + SELECT_THROUGH_DISABLE = (1 << 0), + SELECT_THROUGH_OBJECT = (1 << 1), + SELECT_THROUGH_EDIT = (1 << 2), + SELECT_THROUGH_BOTH = (1 << 3), +}; + /** #ToolSettings::selectmode */ enum { SCE_SELECT_VERTEX = 1 << 0, /* for mesh */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 96977c5cd11..f51b87942ed 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -886,7 +886,9 @@ typedef struct UserDef { char gizmo_size; /** Navigate gizmo size. */ char gizmo_size_navigate_v3d; - char _pad3[5]; + /** Header highlight */ + char header_highlight; + char _pad3[4]; short edit_studio_light; short lookdev_sphere_size; short vbotimeout, vbocollectrate; @@ -929,7 +931,10 @@ typedef struct UserDef { /** Number of samples for FPS display calculations. */ short playback_fps_samples; - char _pad7[2]; + /** Keymap click-drag direction style. */ + char click_drag_direction; + + char _pad7[1]; /** Private, defaults to 20 for 72 DPI setting. */ short widget_unit; @@ -992,6 +997,22 @@ typedef struct UserDef { char drag_threshold; char move_threshold; + /** Adjustable selection radius. */ + float selection_radius; + char adjustable_click_select; + char select_unbiased; + + /** Mouse cursor styles. **/ + char system_cursor; + char edit_cursor; + char paint_cursor; + char dot_cursor; + char knife_cursor; + char pencil_cursor; + char eraser_cursor; + char eyedropper_cursor; + char _pad9[2]; + char font_path_ui[1024]; char font_path_ui_mono[1024]; @@ -1096,8 +1117,8 @@ typedef enum eUserPref_Flag { USER_AUTOSAVE = (1 << 0), USER_FLAG_NUMINPUT_ADVANCED = (1 << 1), USER_FLAG_RECENT_SEARCHES_DISABLE = (1 << 2), - USER_FLAG_UNUSED_3 = (1 << 3), /* cleared */ - USER_FLAG_UNUSED_4 = (1 << 4), /* cleared */ + USER_ADJUSTABLE_CLICK_SELECT = (1 << 3), + USER_SELECT_UNBIASED = (1 << 4), USER_TRACKBALL = (1 << 5), USER_FLAG_UNUSED_6 = (1 << 6), /* cleared */ USER_FLAG_UNUSED_7 = (1 << 7), /* cleared */ @@ -1247,6 +1268,131 @@ typedef enum eUserpref_TableAPI { USER_TABLET_WINTAB = 2, } eUserpref_TabletAPI; +/** #UserDef.click_drag_direction_types */ +typedef enum eUserpref_Click_Drag_Direction { + USER_CLICK_DRAG_DIRECTION_EIGHT_WAY = 0, + USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT = 1, + USER_CLICK_DRAG_DIRECTION_UP_DOWN = 2, +} eUserpref_Click_Drag_Direction; + +/** #UserDef.system_cursor_types */ +typedef enum eUserpref_System_Cursor_Types { + USER_SYSTEM_CURSOR_SYSTEM = 0, + USER_SYSTEM_CURSOR_CROSS = 1, + USER_SYSTEM_CURSOR_POINTER = 2, + USER_SYSTEM_CURSOR_CROSS_OPEN = 3, + USER_SYSTEM_CURSOR_CROSS_DOT = 4, + USER_SYSTEM_CURSOR_CROSS_MIN = 5, + USER_SYSTEM_CURSOR_BOX = 6, + USER_SYSTEM_CURSOR_BOX_DOT = 7, + USER_SYSTEM_CURSOR_BOX_POINTER = 8, + USER_SYSTEM_CURSOR_DOT = 9, +} eUserpref_System_Cursor_Types; + +/** #UserDef.edit_cursor_types */ +typedef enum eUserpref_Edit_Cursor_Types { + USER_EDIT_CURSOR_CROSS = 0, + USER_EDIT_CURSOR_SYSTEM = 1, + USER_EDIT_CURSOR_POINTER = 2, + USER_EDIT_CURSOR_CROSS_OPEN = 3, + USER_EDIT_CURSOR_CROSS_DOT = 4, + USER_EDIT_CURSOR_CROSS_MIN = 5, + USER_EDIT_CURSOR_BOX = 6, + USER_EDIT_CURSOR_BOX_DOT = 7, + USER_EDIT_CURSOR_BOX_POINTER = 8, + USER_EDIT_CURSOR_DOT = 9, +} eUserpref_Edit_Cursor_Types; + +/** #UserDef.paint_cursor_types */ +typedef enum eUserpref_Paint_Cursor_Types { + USER_PAINT_CURSOR_CROSS_DOT = 0, + USER_PAINT_CURSOR_CROSS = 1, + USER_PAINT_CURSOR_SYSTEM = 2, + USER_PAINT_CURSOR_POINTER = 3, + USER_PAINT_CURSOR_CROSS_OPEN = 4, + USER_PAINT_CURSOR_CROSS_MIN = 5, + USER_PAINT_CURSOR_BOX = 6, + USER_PAINT_CURSOR_BOX_DOT = 7, + USER_PAINT_CURSOR_BOX_POINTER = 8, + USER_PAINT_CURSOR_DOT = 9, + USER_PAINT_CURSOR_BLANK = 10, +} eUserpref_Paint_Cursor_Types; + +/** #UserDef.dot_cursor_types */ +typedef enum eUserpref_Dot_Cursor_Types { + USER_DOT_CURSOR_DOT = 0, + USER_DOT_CURSOR_CROSS = 1, + USER_DOT_CURSOR_SYSTEM = 2, + USER_DOT_CURSOR_POINTER = 3, + USER_DOT_CURSOR_CROSS_OPEN = 4, + USER_DOT_CURSOR_CROSS_DOT = 5, + USER_DOT_CURSOR_CROSS_MIN = 6, + USER_DOT_CURSOR_BOX = 7, + USER_DOT_CURSOR_BOX_DOT = 8, + USER_DOT_CURSOR_BOX_POINTER = 9, + USER_DOT_CURSOR_BLANK = 10, +} eUserpref_Dot_Cursor_Types; + +/** #UserDef.knife_cursor_types */ +typedef enum eUserpref_Knife_Cursor_Types { + USER_KNIFE_CURSOR_KNIFE = 0, + USER_KNIFE_CURSOR_CROSS = 1, + USER_KNIFE_CURSOR_SYSTEM = 2, + USER_KNIFE_CURSOR_POINTER = 3, + USER_KNIFE_CURSOR_CROSS_OPEN = 4, + USER_KNIFE_CURSOR_CROSS_DOT = 5, + USER_KNIFE_CURSOR_CROSS_MIN = 6, + USER_KNIFE_CURSOR_BOX = 7, + USER_KNIFE_CURSOR_BOX_DOT = 8, + USER_KNIFE_CURSOR_BOX_POINTER = 9, + USER_KNIFE_CURSOR_DOT = 10, +} eUserpref_Knife_Cursor_Types; + +/** #UserDef.pencil_cursor_types */ +typedef enum eUserpref_Pencil_Cursor_Types { + USER_PENCIL_CURSOR_PENCIL = 0, + USER_PENCIL_CURSOR_CROSS = 1, + USER_PENCIL_CURSOR_SYSTEM = 2, + USER_PENCIL_CURSOR_POINTER = 3, + USER_PENCIL_CURSOR_CROSS_OPEN = 4, + USER_PENCIL_CURSOR_CROSS_DOT = 5, + USER_PENCIL_CURSOR_CROSS_MIN = 6, + USER_PENCIL_CURSOR_BOX = 7, + USER_PENCIL_CURSOR_BOX_DOT = 8, + USER_PENCIL_CURSOR_BOX_POINTER = 9, + USER_PENCIL_CURSOR_DOT = 10, +} eUserpref_Pencil_Cursor_Types; + +/** #UserDef.eraser_cursor_types */ +typedef enum eUserpref_Eraser_Cursor_Types { + USER_ERASER_CURSOR_ERASER = 0, + USER_ERASER_CURSOR_CROSS = 1, + USER_ERASER_CURSOR_SYSTEM = 2, + USER_ERASER_CURSOR_POINTER = 3, + USER_ERASER_CURSOR_CROSS_OPEN = 4, + USER_ERASER_CURSOR_CROSS_DOT = 5, + USER_ERASER_CURSOR_CROSS_MIN = 6, + USER_ERASER_CURSOR_BOX = 7, + USER_ERASER_CURSOR_BOX_DOT = 8, + USER_ERASER_CURSOR_BOX_POINTER = 9, + USER_ERASER_CURSOR_DOT = 10, +} eUserpref_Eraser_Cursor_Types; + +/** #UserDef.eyedropper_cursor_types */ +typedef enum eUserpref_Eyedropper_Cursor_Types { + USER_EYEDROPPER_CURSOR_EYEDROPPER = 0, + USER_EYEDROPPER_CURSOR_CROSS = 1, + USER_EYEDROPPER_CURSOR_SYSTEM = 2, + USER_EYEDROPPER_CURSOR_POINTER = 3, + USER_EYEDROPPER_CURSOR_CROSS_OPEN = 4, + USER_EYEDROPPER_CURSOR_CROSS_DOT = 5, + USER_EYEDROPPER_CURSOR_CROSS_MIN = 6, + USER_EYEDROPPER_CURSOR_BOX = 7, + USER_EYEDROPPER_CURSOR_BOX_DOT = 8, + USER_EYEDROPPER_CURSOR_BOX_POINTER = 9, + USER_EYEDROPPER_CURSOR_DOT = 10, +} eUserpref_Eyedropper_Cursor_Types; + /** #UserDef.app_flag */ typedef enum eUserpref_APP_Flag { USER_APP_LOCK_CORNER_SPLIT = (1 << 0), diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 4dd7e16cb11..41fff0473c4 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -610,6 +610,7 @@ enum { V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21), V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22), + V3D_OVERLAY_EDIT_FACE_DOT_XRAY = (1 << 23), }; /** #View3DOverlay.paint_flag */ diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index bbe87c44ad1..3efa3a02535 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3186,10 +3186,149 @@ static void rna_def_tool_settings(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem viewport_facing_select_mode_items[] = { + {VIEWPORT_FACING_SELECT_BOTH, + "BOTH", + 0, + "Near and X-Ray", + "Use viewport-facing selection in near select and X-Ray"}, + {VIEWPORT_FACING_SELECT_NEAR, + "NEAR", + 0, + "Near", + "Use viewport-facing selection in near select"}, + {VIEWPORT_FACING_SELECT_XRAY, "XRAY", 0, "X-Ray", "Use viewport-facing selection in X-Ray"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem viewport_facing_select_vert_items[] = { + {VIEWPORT_FACING_SELECT_FRONT_VERTS, + "FRONT_VERTS", + 0, + "Front Verts", + "Select vertices with viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE, + "FRONT_VERTS_FACE", + 0, + "Verts of Front Face", + "Select vertices if they are part of a face that has a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_REAR_VERTS, + "REAR_VERTS", + 0, + "Rear Verts", + "Select vertices without viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_REAR_VERTS_FACE, + "REAR_VERTS_FACE", + 0, + "Verts of Rear Face", + "Select vertices if they are part of a face that does not have a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_ALL_VERTS, + "ALL_VERTS", + 0, + "All Verts", + "Select vertices regarless of their normal direction"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem viewport_facing_select_edge_items[] = { + {VIEWPORT_FACING_SELECT_FRONT_EDGES, + "FRONT_EDGES", + 0, + "Front Edges", + "Select edges with viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE, + "FRONT_EDGES_FACE", + 0, + "Edges of Front Face", + "Select edges if they are part of a face that has a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_REAR_EDGES, + "REAR_EDGES", + 0, + "Rear Edges", + "Select edges without viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_REAR_EDGES_FACE, + "REAR_EDGES_FACE", + 0, + "Edges of Rear Face", + "Select edges if they are part of a face that does not have a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_ALL_EDGES, + "ALL_EDGES", + 0, + "All Edges", + "Select edges regarless of their normal direction"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem viewport_facing_select_face_items[] = { + {VIEWPORT_FACING_SELECT_FRONT_FACES, + "FRONT_FACES", + 0, + "Front Faces", + "Select faces with viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_FRONT_FACES_VERT, + "FRONT_FACES_VERT", + 0, + "Faces of Front Vert", + "Select faces if they have a vertex with a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_REAR_FACES, + "REAR_FACES", + 0, + "Rear Faces", + "Select faces without viewport-facing normals"}, + {VIEWPORT_FACING_SELECT_REAR_FACES_VERT, + "REAR_FACES_VERT", + 0, + "Faces of Rear Vert", + "Select faces if they have a vertex without a viewport-facing normal"}, + {VIEWPORT_FACING_SELECT_ALL_FACES, + "ALL_FACES", + 0, + "All Faces", + "Select faces regarless of their normal direction"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + srna = RNA_def_struct(brna, "ToolSettings", nullptr); RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); + /* Viewport-Facing Select */ + prop = RNA_def_property(srna, "viewport_facing_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "viewport_facing_select", 0); + RNA_def_property_ui_text( + prop, + "Viewport Facing Select", + "Filter box, lasso, and circle selection of mesh elements based on the direction of their " + "normals compared to the viewport"); + + prop = RNA_def_property(srna, "viewport_facing_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_mode"); + RNA_def_property_enum_items(prop, viewport_facing_select_mode_items); + RNA_def_property_ui_text(prop, "Mode", "Which selection modes to use viewport-facing selection"); + + prop = RNA_def_property(srna, "viewport_facing_select_vert", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_vert"); + RNA_def_property_enum_items(prop, viewport_facing_select_vert_items); + RNA_def_property_ui_text(prop, "Vert", "Direction and mode for vertices"); + + prop = RNA_def_property(srna, "viewport_facing_select_edge", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_edge"); + RNA_def_property_enum_items(prop, viewport_facing_select_edge_items); + RNA_def_property_ui_text(prop, "Edge", "Direction and mode for edges"); + + prop = RNA_def_property(srna, "viewport_facing_select_face", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_face"); + RNA_def_property_enum_items(prop, viewport_facing_select_face_items); + RNA_def_property_ui_text(prop, "Face", "Direction and mode for faces"); + + prop = RNA_def_property(srna, "viewport_facing_select_threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, -0.999999, 0.999999); + RNA_def_property_ui_range(prop, -0.999999, 0.999999, 1.0, 6); + RNA_def_property_ui_text( + prop, + "Threshold", + "How close the angles of the viewport and mesh element need to be for selection to occur"); + prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Sculpt"); RNA_def_property_ui_text(prop, "Sculpt", ""); @@ -4041,6 +4180,119 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply"); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3); + /* Square Select */ + prop = RNA_def_property(srna, "square_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "square_select", 0); + RNA_def_property_ui_text( + prop, + "Square Select", + "Change selection shape to a square with side length equal to the circle diameter"); + + /* Wireless Touch Object */ + prop = RNA_def_property(srna, "wireless_touch_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "wireless_touch_object", 0); + RNA_def_property_ui_text(prop, + "Wireless Touch Object", + "If using Touch select with X-Ray and Wireframe shading, select " + "objects if inside them but not intersecting any wires"); + + /* Shrink Shading Header */ + prop = RNA_def_property(srna, "shrink_shading_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "shrink_shading_header", 0); + RNA_def_property_ui_text( + prop, + "Shrink Header", + "Combine the four Shading Header buttons into one button that also toggles X-Ray"); + + /* X-Ray header button */ + prop = RNA_def_property(srna, "xray_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "xray_button", 0); + RNA_def_property_ui_text(prop, "X-Ray", "Show button for X-Ray in viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + /* Auto X-Ray */ + prop = RNA_def_property(srna, "auto_xray", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray", 0); + RNA_def_property_ui_text(prop, "Enable", "Transparent scene display during drag select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_button", 0); + RNA_def_property_ui_text( + prop, "Auto X-Ray", "Show button for automatic X-Ray in viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_reset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_reset", 0); + RNA_def_property_ui_text(prop, "Auto X-Ray Reset", "Helper that turns xray off for autoxray"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_object", 0); + RNA_def_property_ui_text(prop, "Object", "Automatic X-Ray in object mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_edit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_edit", 0); + RNA_def_property_ui_text(prop, "Edit", "Automatic X-Ray in edit mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_box", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_box", 0); + RNA_def_property_ui_text(prop, "Box", "Transparent scene display during box select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_lasso", 0); + RNA_def_property_ui_text(prop, "Lasso", "Transparent scene display during lasso select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_circle", 0); + RNA_def_property_ui_text(prop, "Circle", "Transparent scene display during circle select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + /* Select Through */ + prop = RNA_def_property(srna, "select_through", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through", 0); + RNA_def_property_ui_text( + prop, "Enable", "Select occluded objects and mesh elements with drag select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_button", 0); + RNA_def_property_ui_text( + prop, "Select Through", "Show button for select through in viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_object", 0); + RNA_def_property_ui_text(prop, "Object", "Select through in object mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_edit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_edit", 0); + RNA_def_property_ui_text(prop, "Edit", "Select through in edit mode"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_box", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_box", 0); + RNA_def_property_ui_text( + prop, "Box", "Select occluded objects and mesh elements with box select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_lasso", 0); + RNA_def_property_ui_text( + prop, "Lasso", "Select occluded objects and mesh elements with lasso select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_circle", 0); + RNA_def_property_ui_text( + prop, "Circle", "Select occluded objects and mesh elements with circle select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + /* Unified Paint Settings */ prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_space.cc b/source/blender/makesrna/intern/rna_space.cc index c9f7d2d1725..8d4b475030b 100644 --- a/source/blender/makesrna/intern/rna_space.cc +++ b/source/blender/makesrna/intern/rna_space.cc @@ -4661,6 +4661,16 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) "Display face center when face selection is enabled in solid shading modes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, nullptr); + prop = RNA_def_property(srna, "show_face_center_xray", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, nullptr, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACE_DOT_XRAY); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_ui_text( + prop, + "Display Face Center X-Ray", + "Display face center when face selection is enabled in X-Ray shading modes"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, nullptr); + prop = RNA_def_property(srna, "show_edge_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "overlay.edit_flag", V3D_OVERLAY_EDIT_CREASES); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_userdef.cc b/source/blender/makesrna/intern/rna_userdef.cc index fb55898f09f..e05d1a0c09a 100644 --- a/source/blender/makesrna/intern/rna_userdef.cc +++ b/source/blender/makesrna/intern/rna_userdef.cc @@ -5366,6 +5366,124 @@ static void rna_def_userdef_edit(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem system_cursor_items[] = { + {USER_SYSTEM_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_SYSTEM_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_SYSTEM_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_SYSTEM_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_SYSTEM_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_SYSTEM_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_SYSTEM_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_SYSTEM_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_SYSTEM_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_SYSTEM_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edit_cursor_items[] = { + {USER_EDIT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_EDIT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_EDIT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_EDIT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_EDIT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_EDIT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_EDIT_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_EDIT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_EDIT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_EDIT_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem paint_cursor_items[] = { + {USER_PAINT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_PAINT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_PAINT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_PAINT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_PAINT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_PAINT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_PAINT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_PAINT_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_PAINT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_PAINT_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {USER_PAINT_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem dot_cursor_items[] = { + {USER_DOT_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {USER_DOT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_DOT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_DOT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_DOT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_DOT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_DOT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_DOT_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_DOT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_DOT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_DOT_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem knife_cursor_items[] = { + {USER_KNIFE_CURSOR_KNIFE, "KNIFE", 0, "Knife", ""}, + {USER_KNIFE_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_KNIFE_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_KNIFE_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_KNIFE_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_KNIFE_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_KNIFE_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_KNIFE_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_KNIFE_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_KNIFE_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_KNIFE_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem eyedropper_cursor_items[] = { + {USER_EYEDROPPER_CURSOR_EYEDROPPER, "EYEDROPPER", 0, "Eyedropper", ""}, + {USER_EYEDROPPER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_EYEDROPPER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_EYEDROPPER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_EYEDROPPER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_EYEDROPPER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_EYEDROPPER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_EYEDROPPER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_EYEDROPPER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_EYEDROPPER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_EYEDROPPER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem eraser_cursor_items[] = { + {USER_ERASER_CURSOR_ERASER, "ERASER", 0, "Eraser", ""}, + {USER_ERASER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_ERASER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_ERASER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_ERASER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_ERASER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_ERASER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_ERASER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_ERASER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_ERASER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_ERASER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem pencil_cursor_items[] = { + {USER_PENCIL_CURSOR_PENCIL, "PENCIL", 0, "Pencil", ""}, + {USER_PENCIL_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_PENCIL_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_PENCIL_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_PENCIL_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_PENCIL_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_PENCIL_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_PENCIL_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_PENCIL_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_PENCIL_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_PENCIL_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + srna = RNA_def_struct(brna, "PreferencesEdit", nullptr); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "Preferences"); @@ -5740,6 +5858,60 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_DEPTH_CURSOR); RNA_def_property_ui_text( prop, "Cursor Surface Project", "Use the surface depth for cursor placement"); + + prop = RNA_def_property(srna, "adjustable_click_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_ADJUSTABLE_CLICK_SELECT); + RNA_def_property_ui_text(prop, "Enable", "Use additional options for single-click select"); + + prop = RNA_def_property(srna, "select_unbiased", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_SELECT_UNBIASED); + RNA_def_property_ui_text( + prop, "Select Unbiased", "Click-select will not favor unselected mesh elements"); + + prop = RNA_def_property(srna, "selection_radius", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.1f, 150.0f); + RNA_def_property_ui_range(prop, 0.1f, 150.0f, 0.01f, 2); + RNA_def_property_ui_text(prop, "Radius", "Size of single-click selection radius"); + + prop = RNA_def_property(srna, "system_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, system_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "system_cursor"); + RNA_def_property_ui_text(prop, "System Cursor", "System mode cursor style"); + + prop = RNA_def_property(srna, "edit_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edit_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "edit_cursor"); + RNA_def_property_ui_text(prop, "Edit Cursor", "Edit mode cursor style"); + + prop = RNA_def_property(srna, "paint_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, paint_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "paint_cursor"); + RNA_def_property_ui_text(prop, "Paint Cursor", "Paint mode cursor style"); + + prop = RNA_def_property(srna, "dot_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, dot_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "dot_cursor"); + RNA_def_property_ui_text(prop, "2D Cursor", "2D mode cursor style"); + + prop = RNA_def_property(srna, "knife_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, knife_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "knife_cursor"); + RNA_def_property_ui_text(prop, "Knife Cursor", "Knife cursor style"); + + prop = RNA_def_property(srna, "eyedropper_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, eyedropper_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "eyedropper_cursor"); + RNA_def_property_ui_text(prop, "Eyedropper Cursor", "Eyedropper cursor style"); + + prop = RNA_def_property(srna, "eraser_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, eraser_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "eraser_cursor"); + RNA_def_property_ui_text(prop, "Eraser Cursor", "Eraser cursor style"); + + prop = RNA_def_property(srna, "pencil_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, pencil_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "pencil_cursor"); + RNA_def_property_ui_text(prop, "Pencil Cursor", "Pencil cursor style"); } static void rna_def_userdef_system(BlenderRNA *brna) @@ -6210,6 +6382,17 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem click_drag_direction_types[] = { + {USER_CLICK_DRAG_DIRECTION_EIGHT_WAY, + "EIGHT_WAY", + 0, + "Eight", + "Eight directions (N, NE, E, SE, S, SW, W, NW)"}, + {USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT, "LEFT_RIGHT", 0, "Left Right", "Left and right"}, + {USER_CLICK_DRAG_DIRECTION_UP_DOWN, "UP_DOWN", 0, "Up Down", "Up and down"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + static const EnumPropertyItem view_zoom_styles[] = { {USER_ZOOM_CONTINUE, "CONTINUE", @@ -6316,6 +6499,11 @@ static void rna_def_userdef_input(BlenderRNA *brna) "Release Confirms", "Moving things with a mouse drag confirms when releasing the button"); + prop = RNA_def_property(srna, "click_drag_direction", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, click_drag_direction_types); + RNA_def_property_ui_text( + prop, "Keymap Drag Directions", "Style of click-drag direction the keymap will use"); + prop = RNA_def_property(srna, "use_numeric_input_advanced", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_FLAG_NUMINPUT_ADVANCED); RNA_def_property_ui_text(prop, @@ -6380,6 +6568,12 @@ static void rna_def_userdef_input(BlenderRNA *brna) "Number of pixels to before the cursor is considered to have moved " "(used for cycling selected items on successive clicks)"); + prop = RNA_def_property(srna, "header_highlight", PROP_INT, PROP_FACTOR); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_range(prop, 0, 10, 1, -1); + RNA_def_property_ui_text( + prop, "Header Highlight", "How much brighter the header of the active window is"); + /* tablet pressure curve */ prop = RNA_def_property(srna, "pressure_threshold_max", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); diff --git a/source/blender/makesrna/intern/rna_wm_api.cc b/source/blender/makesrna/intern/rna_wm_api.cc index 8b25313aad5..e230fa8f8a8 100644 --- a/source/blender/makesrna/intern/rna_wm_api.cc +++ b/source/blender/makesrna/intern/rna_wm_api.cc @@ -421,6 +421,41 @@ static void rna_KeyMap_item_remove(wmKeyMap *km, ReportList *reports, PointerRNA RNA_POINTER_INVALIDATE(kmi_ptr); } +static void rna_keymap_set_direction_any(wmKeyMap *km, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = static_cast(kmi_ptr->data); + kmi->direction = -1; + WM_keyconfig_update_tag(km, kmi); +} + +static void rna_keymap_set_direction_left(wmKeyMap *km, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = static_cast(kmi_ptr->data); + kmi->direction = 7; + WM_keyconfig_update_tag(km, kmi); +} + +static void rna_keymap_set_direction_right(wmKeyMap *km, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = static_cast(kmi_ptr->data); + kmi->direction = 3; + WM_keyconfig_update_tag(km, kmi); +} + +static void rna_keymap_set_direction_up(wmKeyMap *km, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = static_cast(kmi_ptr->data); + kmi->direction = 1; + WM_keyconfig_update_tag(km, kmi); +} + +static void rna_keymap_set_direction_down(wmKeyMap *km, PointerRNA *kmi_ptr) +{ + wmKeyMapItem *kmi = static_cast(kmi_ptr->data); + kmi->direction = 5; + WM_keyconfig_update_tag(km, kmi); +} + static PointerRNA rna_KeyMap_item_find_from_operator(ID *id, wmKeyMap *km, const char *idname, @@ -1278,6 +1313,31 @@ void RNA_api_keymapitems(StructRNA *srna) RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + func = RNA_def_function(srna, "set_direction_any", "rna_keymap_set_direction_any"); + parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + + func = RNA_def_function(srna, "set_direction_left", "rna_keymap_set_direction_left"); + parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + + func = RNA_def_function(srna, "set_direction_right", "rna_keymap_set_direction_right"); + parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + + func = RNA_def_function(srna, "set_direction_up", "rna_keymap_set_direction_up"); + parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + + func = RNA_def_function(srna, "set_direction_down", "rna_keymap_set_direction_down"); + parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, ParameterFlag(0)); + func = RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); parm = RNA_def_property(func, "id", PROP_INT, PROP_NONE); RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED); diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index b7953353f1b..661ec9e6ac2 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -791,6 +791,7 @@ int WM_operator_call_notest(bContext *C, wmOperator *op); * Execute this operator again, put here so it can share above code */ int WM_operator_repeat(bContext *C, wmOperator *op); +int WM_operator_invoke_last(bContext *C, wmOperator *op); int WM_operator_repeat_last(bContext *C, wmOperator *op); /** * \return true if #WM_operator_repeat can run. diff --git a/source/blender/windowmanager/WM_types.hh b/source/blender/windowmanager/WM_types.hh index 3bd132a83ec..1ba54223df5 100644 --- a/source/blender/windowmanager/WM_types.hh +++ b/source/blender/windowmanager/WM_types.hh @@ -559,6 +559,7 @@ struct wmNotifier { #define WM_GESTURE_LASSO 4 #define WM_GESTURE_CIRCLE 5 #define WM_GESTURE_STRAIGHTLINE 6 +#define WM_GESTURE_SQUARE 7 /** * wmGesture is registered to #wmWindow.gesture, handled by operator callbacks. diff --git a/source/blender/windowmanager/intern/wm_cursors.cc b/source/blender/windowmanager/intern/wm_cursors.cc index 48529de8fef..cbab9c1a06d 100644 --- a/source/blender/windowmanager/intern/wm_cursors.cc +++ b/source/blender/windowmanager/intern/wm_cursors.cc @@ -44,14 +44,80 @@ static BCursor *BlenderCursor[WM_CURSOR_NUM] = {nullptr}; /* Blender cursor to GHOST standard cursor conversion. */ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) { + const int system_style = U.system_cursor; + const int edit_style = U.edit_cursor; + const int paint_style = U.paint_cursor; + const int dot_style = U.dot_cursor; + const int knife_style = U.knife_cursor; + const int pencil_style = U.pencil_cursor; + const int eraser_style = U.eraser_cursor; + const int eyedropper_style = U.eyedropper_cursor; switch (curs) { case WM_CURSOR_DEFAULT: - return GHOST_kStandardCursorDefault; + if (system_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (system_style == 2) { + return GHOST_kStandardCursorPointer; + } + else if (system_style == 3) { + return GHOST_kStandardCursorCrosshairD; + } + else if (system_style == 4) { + return GHOST_kStandardCursorCrosshairA; + } + else if (system_style == 5) { + return GHOST_kStandardCursorCrosshairC; + } + else if (system_style == 6) { + return GHOST_kStandardCursorBox; + } + else if (system_style == 7) { + return GHOST_kStandardCursorBoxDot; + } + else if (system_style == 8) { + return GHOST_kStandardCursorBoxPointer; + } + else if (system_style == 9) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorDefault; + } case WM_CURSOR_WAIT: return GHOST_kStandardCursorWait; case WM_CURSOR_EDIT: case WM_CURSOR_CROSS: - return GHOST_kStandardCursorCrosshair; + if (edit_style == 1) { + return GHOST_kStandardCursorDefault; + } + else if (edit_style == 2) { + return GHOST_kStandardCursorPointer; + } + else if (edit_style == 3) { + return GHOST_kStandardCursorCrosshairD; + } + else if (edit_style == 4) { + return GHOST_kStandardCursorCrosshairA; + } + else if (edit_style == 5) { + return GHOST_kStandardCursorCrosshairC; + } + else if (edit_style == 6) { + return GHOST_kStandardCursorBox; + } + else if (edit_style == 7) { + return GHOST_kStandardCursorBoxDot; + } + else if (edit_style == 8) { + return GHOST_kStandardCursorBoxPointer; + } + else if (edit_style == 9) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorCrosshair; + } case WM_CURSOR_X_MOVE: return GHOST_kStandardCursorLeftRight; case WM_CURSOR_Y_MOVE: @@ -67,7 +133,39 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_STOP: return GHOST_kStandardCursorStop; case WM_CURSOR_KNIFE: - return GHOST_kStandardCursorKnife; + if (knife_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (knife_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (knife_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (knife_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (knife_style == 5) { + return GHOST_kStandardCursorCrosshairA; + } + else if (knife_style == 6) { + return GHOST_kStandardCursorCrosshairC; + } + else if (knife_style == 7) { + return GHOST_kStandardCursorBox; + } + else if (knife_style == 8) { + return GHOST_kStandardCursorBoxDot; + } + else if (knife_style == 9) { + return GHOST_kStandardCursorBoxPointer; + } + else if (knife_style == 10) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorKnife; + } case WM_CURSOR_NSEW_SCROLL: return GHOST_kStandardCursorNSEWScroll; case WM_CURSOR_NS_SCROLL: @@ -75,19 +173,147 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_EW_SCROLL: return GHOST_kStandardCursorEWScroll; case WM_CURSOR_EYEDROPPER: - return GHOST_kStandardCursorEyedropper; + if (eyedropper_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (eyedropper_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (eyedropper_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (eyedropper_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (eyedropper_style == 5) { + return GHOST_kStandardCursorCrosshairA; + } + else if (eyedropper_style == 6) { + return GHOST_kStandardCursorCrosshairC; + } + else if (eyedropper_style == 7) { + return GHOST_kStandardCursorBox; + } + else if (eyedropper_style == 8) { + return GHOST_kStandardCursorBoxDot; + } + else if (eyedropper_style == 9) { + return GHOST_kStandardCursorBoxPointer; + } + else if (eyedropper_style == 10) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorEyedropper; + } case WM_CURSOR_N_ARROW: return GHOST_kStandardCursorUpArrow; case WM_CURSOR_S_ARROW: return GHOST_kStandardCursorDownArrow; case WM_CURSOR_PAINT: - return GHOST_kStandardCursorCrosshairA; + if (paint_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (paint_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (paint_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (paint_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (paint_style == 5) { + return GHOST_kStandardCursorCrosshairC; + } + else if (paint_style == 6) { + return GHOST_kStandardCursorBox; + } + else if (paint_style == 7) { + return GHOST_kStandardCursorBoxDot; + } + else if (paint_style == 8) { + return GHOST_kStandardCursorBoxPointer; + } + else if (paint_style == 9) { + return GHOST_kStandardCursorCrosshairB; + } + else if (paint_style == 10) { + return GHOST_kStandardCursorBlank; + } + else { + return GHOST_kStandardCursorCrosshairA; + } case WM_CURSOR_DOT: - return GHOST_kStandardCursorCrosshairB; + if (dot_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (dot_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (dot_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (dot_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (dot_style == 5) { + return GHOST_kStandardCursorCrosshairA; + } + else if (dot_style == 6) { + return GHOST_kStandardCursorCrosshairC; + } + else if (dot_style == 7) { + return GHOST_kStandardCursorBox; + } + else if (dot_style == 8) { + return GHOST_kStandardCursorBoxDot; + } + else if (dot_style == 9) { + return GHOST_kStandardCursorBoxPointer; + } + else if (dot_style == 10) { + return GHOST_kStandardCursorBlank; + } + else { + return GHOST_kStandardCursorCrosshairB; + } case WM_CURSOR_CROSSC: return GHOST_kStandardCursorCrosshairC; case WM_CURSOR_ERASER: - return GHOST_kStandardCursorEraser; + if (eraser_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (eraser_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (eraser_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (eraser_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (eraser_style == 5) { + return GHOST_kStandardCursorCrosshairA; + } + else if (eraser_style == 6) { + return GHOST_kStandardCursorCrosshairC; + } + else if (eraser_style == 7) { + return GHOST_kStandardCursorBox; + } + else if (eraser_style == 8) { + return GHOST_kStandardCursorBoxDot; + } + else if (eraser_style == 9) { + return GHOST_kStandardCursorBoxPointer; + } + else if (eraser_style == 10) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorEraser; + } case WM_CURSOR_ZOOM_IN: return GHOST_kStandardCursorZoomIn; case WM_CURSOR_ZOOM_OUT: @@ -95,7 +321,39 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_TEXT_EDIT: return GHOST_kStandardCursorText; case WM_CURSOR_PAINT_BRUSH: - return GHOST_kStandardCursorPencil; + if (pencil_style == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (pencil_style == 2) { + return GHOST_kStandardCursorDefault; + } + else if (pencil_style == 3) { + return GHOST_kStandardCursorPointer; + } + else if (pencil_style == 4) { + return GHOST_kStandardCursorCrosshairD; + } + else if (pencil_style == 5) { + return GHOST_kStandardCursorCrosshairA; + } + else if (pencil_style == 6) { + return GHOST_kStandardCursorCrosshairC; + } + else if (pencil_style == 7) { + return GHOST_kStandardCursorBox; + } + else if (pencil_style == 8) { + return GHOST_kStandardCursorBoxDot; + } + else if (pencil_style == 9) { + return GHOST_kStandardCursorBoxPointer; + } + else if (pencil_style == 10) { + return GHOST_kStandardCursorCrosshairB; + } + else { + return GHOST_kStandardCursorPencil; + } case WM_CURSOR_E_ARROW: return GHOST_kStandardCursorRightArrow; case WM_CURSOR_W_ARROW: diff --git a/source/blender/windowmanager/intern/wm_event_query.cc b/source/blender/windowmanager/intern/wm_event_query.cc index b5b3cb6ceee..3ccc2b11c96 100644 --- a/source/blender/windowmanager/intern/wm_event_query.cc +++ b/source/blender/windowmanager/intern/wm_event_query.cc @@ -274,29 +274,42 @@ int WM_event_drag_direction(const wmEvent *event) event->xy[1] - event->prev_press_xy[1], }; - int theta = round_fl_to_int(4.0f * atan2f(float(delta[1]), float(delta[0])) / float(M_PI)); - int val = KM_DIRECTION_W; + const bool left_right = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT; + const bool up_down = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_UP_DOWN; + int val = up_down ? KM_DIRECTION_S : KM_DIRECTION_W; - if (theta == 0) { - val = KM_DIRECTION_E; + if (left_right || up_down) { + float thetaf = 4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI; + if (left_right && thetaf > -2.0f && thetaf < 2.0f) { + val = KM_DIRECTION_E; + } + else if (up_down && thetaf > 0.0f) { + val = KM_DIRECTION_N; + } } - else if (theta == 1) { - val = KM_DIRECTION_NE; - } - else if (theta == 2) { - val = KM_DIRECTION_N; - } - else if (theta == 3) { - val = KM_DIRECTION_NW; - } - else if (theta == -1) { - val = KM_DIRECTION_SE; - } - else if (theta == -2) { - val = KM_DIRECTION_S; - } - else if (theta == -3) { - val = KM_DIRECTION_SW; + else { + int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI); + if (theta == 0) { + val = KM_DIRECTION_E; + } + else if (theta == 1) { + val = KM_DIRECTION_NE; + } + else if (theta == 2) { + val = KM_DIRECTION_N; + } + else if (theta == 3) { + val = KM_DIRECTION_NW; + } + else if (theta == -1) { + val = KM_DIRECTION_SE; + } + else if (theta == -2) { + val = KM_DIRECTION_S; + } + else if (theta == -3) { + val = KM_DIRECTION_SW; + } } #if 0 diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 89b7769fc0f..bff6edb91a4 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -1323,6 +1323,11 @@ int WM_operator_repeat(bContext *C, wmOperator *op) op->flag &= ~op_flag; return ret; } +int WM_operator_invoke_last(bContext *C, wmOperator *op) +{ + const int ret = WM_operator_name_call_ptr(C, op->type, WM_OP_INVOKE_DEFAULT, nullptr, nullptr); + return ret; +} int WM_operator_repeat_last(bContext *C, wmOperator *op) { const int op_flag = OP_IS_REPEAT_LAST; diff --git a/source/blender/windowmanager/intern/wm_gesture.cc b/source/blender/windowmanager/intern/wm_gesture.cc index e1c3005b2f2..ae8e339ab6a 100644 --- a/source/blender/windowmanager/intern/wm_gesture.cc +++ b/source/blender/windowmanager/intern/wm_gesture.cc @@ -56,6 +56,7 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent WM_GESTURE_RECT, WM_GESTURE_CROSS_RECT, WM_GESTURE_CIRCLE, + WM_GESTURE_SQUARE, WM_GESTURE_STRAIGHTLINE)) { rcti *rect = static_cast(MEM_callocN(sizeof(rcti), "gesture rect new")); @@ -63,7 +64,7 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent gesture->customdata = rect; rect->xmin = xy[0] - gesture->winrct.xmin; rect->ymin = xy[1] - gesture->winrct.ymin; - if (type == WM_GESTURE_CIRCLE) { + if (type == WM_GESTURE_CIRCLE || type == WM_GESTURE_SQUARE) { /* caller is responsible for initializing 'xmax' to radius. */ } else { @@ -275,6 +276,51 @@ static void wm_gesture_draw_circle(wmGesture *gt) immUnbindProgram(); } +static void wm_gesture_draw_square(wmGesture *gt) +{ + rcti *rect = (rcti *)gt->customdata; + + uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + + GPU_blend(GPU_BLEND_ALPHA); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4f(1.0f, 1.0f, 1.0f, 0.05f); + + immRecti(shdr_pos, + rect->xmin - rect->xmax, + rect->ymin - rect->xmax, + rect->xmin + rect->xmax, + rect->ymin + rect->xmax); + + immUnbindProgram(); + + GPU_blend(GPU_BLEND_NONE); + + shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + 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 */ + immUniform4f("color", 0.4f, 0.4f, 0.4f, 1.0f); + immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f); + immUniform1f("dash_width", 8.0f); + immUniform1f("udash_factor", 0.5f); + + imm_draw_box_wire_2d(shdr_pos, + float(rect->xmin - rect->xmax), + float(rect->ymin - rect->xmax), + float(rect->xmin + rect->xmax), + float(rect->ymin + rect->xmax)); + + immUnbindProgram(); +} + struct LassoFillData { uchar *px; int width; @@ -447,6 +493,9 @@ void wm_gesture_draw(wmWindow *win) else if (gt->type == WM_GESTURE_CIRCLE) { wm_gesture_draw_circle(gt); } + else if (gt->type == WM_GESTURE_SQUARE) { + wm_gesture_draw_square(gt); + } else if (gt->type == WM_GESTURE_CROSS_RECT) { if (gt->is_active) { wm_gesture_draw_rect(gt); diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.cc b/source/blender/windowmanager/intern/wm_gesture_ops.cc index 012e2c8441a..4a65579a6c3 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.cc +++ b/source/blender/windowmanager/intern/wm_gesture_ops.cc @@ -31,6 +31,7 @@ #include "ED_screen.hh" #include "ED_select_utils.hh" +#include "ED_view3d.hh" #include "UI_interface.hh" @@ -87,6 +88,18 @@ static void gesture_modal_state_to_operator(wmOperator *op, int modal_state) } } +static void gesture_toggle_xray(bContext *C) +{ + wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_toggle_xray", true); + ToolSettings *ts = CTX_data_tool_settings(C); + BLI_assert(ot); + PointerRNA ptr; + WM_operator_properties_create_ptr(&ptr, ot); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); + WM_operator_properties_free(&ptr); + ts->auto_xray_reset ^= true; +} + static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op) { PropertyRNA *prop; @@ -165,10 +178,27 @@ static bool gesture_box_apply(bContext *C, wmOperator *op) int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + View3D *v3d = CTX_wm_view3d(C); + Object *obedit = CTX_data_edit_object(C); + ToolSettings *ts = CTX_data_tool_settings(C); const ARegion *region = CTX_wm_region(C); const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) && RNA_boolean_get(op->ptr, "wait_for_input"); + const bool auto_xray = ts->auto_xray && ts->auto_xray_box ? + obedit ? ts->auto_xray_edit : ts->auto_xray_object : + false; + + if (ts->auto_xray_reset) { + ts->auto_xray_reset ^= true; + } + + if (v3d && auto_xray) { + if (!XRAY_FLAG_ENABLED(v3d)) { + gesture_toggle_xray(C); + } + } + if (wait_for_input) { op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT); } @@ -192,8 +222,11 @@ int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + View3D *v3d = CTX_wm_view3d(C); wmGesture *gesture = static_cast(op->customdata); rcti *rect = static_cast(gesture->customdata); + Object *obedit = CTX_data_edit_object(C); + ToolSettings *ts = CTX_data_tool_settings(C); if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -216,13 +249,22 @@ int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) gesture->modal_state = event->val; } if (gesture_box_apply(C, op)) { + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } gesture_modal_end(C, op); return OPERATOR_FINISHED; } + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } gesture_modal_end(C, op); return OPERATOR_CANCELLED; } case GESTURE_MODAL_CANCEL: { + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } gesture_modal_end(C, op); return OPERATOR_CANCELLED; } @@ -288,10 +330,33 @@ static void gesture_circle_apply(bContext *C, wmOperator *op); int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + View3D *v3d = CTX_wm_view3d(C); const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) && RNA_boolean_get(op->ptr, "wait_for_input"); - op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_CIRCLE); + Object *obedit = CTX_data_edit_object(C); + ToolSettings *ts = static_cast(win->scene->toolsettings); + const bool auto_xray = ts->auto_xray && ts->auto_xray_circle ? + obedit ? ts->auto_xray_edit : ts->auto_xray_object : + false; + + if (ts->auto_xray_reset) { + ts->auto_xray_reset ^= true; + } + + if (v3d && auto_xray) { + if (!XRAY_FLAG_ENABLED(v3d)) { + gesture_toggle_xray(C); + } + } + + if (ts->square_select) { + op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_SQUARE); + } + else { + op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_CIRCLE); + } + wmGesture *gesture = static_cast(op->customdata); rcti *rect = static_cast(gesture->customdata); @@ -347,8 +412,11 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + View3D *v3d = CTX_wm_view3d(C); wmGesture *gesture = static_cast(op->customdata); rcti *rect = static_cast(gesture->customdata); + Object *obedit = CTX_data_edit_object(C); + ToolSettings *ts = static_cast(win->scene->toolsettings); if (event->type == MOUSEMOVE) { @@ -417,6 +485,9 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (is_finished) { + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } gesture_modal_end(C, op); return OPERATOR_FINISHED; /* use finish or we don't get an undo */ } @@ -479,7 +550,24 @@ void WM_OT_circle_gesture(wmOperatorType *ot) int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + View3D *v3d = CTX_wm_view3d(C); PropertyRNA *prop; + Object *obedit = CTX_data_edit_object(C); + ToolSettings *ts = static_cast(win->scene->toolsettings); + + const bool auto_xray = ts->auto_xray && ts->auto_xray_lasso ? + obedit ? ts->auto_xray_edit : ts->auto_xray_object : + false; + + if (ts->auto_xray_reset) { + ts->auto_xray_reset ^= true; + } + + if (v3d && auto_xray) { + if (!XRAY_FLAG_ENABLED(v3d)) { + gesture_toggle_xray(C); + } + } op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_LASSO); @@ -519,6 +607,10 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op) int retval = OPERATOR_FINISHED; wmGesture *gesture = static_cast(op->customdata); PointerRNA itemptr; + View3D *v3d = CTX_wm_view3d(C); + Object *obedit = CTX_data_edit_object(C); + wmWindow *win = CTX_wm_window(C); + ToolSettings *ts = static_cast(win->scene->toolsettings); float loc[2]; int i; const short *lasso = static_cast(gesture->customdata); @@ -540,12 +632,20 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op) OPERATOR_RETVAL_CHECK(retval); } + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } + return retval; } int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = static_cast(op->customdata); + View3D *v3d = CTX_wm_view3d(C); + Object *obedit = CTX_data_edit_object(C); + wmWindow *win = CTX_wm_window(C); + ToolSettings *ts = static_cast(win->scene->toolsettings); if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -599,6 +699,9 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) break; } case EVT_ESCKEY: { + if (ts->auto_xray_reset) { + gesture_toggle_xray(C); + } gesture_modal_end(C, op); return OPERATOR_CANCELLED; } diff --git a/source/blender/windowmanager/intern/wm_operator_props.cc b/source/blender/windowmanager/intern/wm_operator_props.cc index fad16982f65..c122282f1f8 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.cc +++ b/source/blender/windowmanager/intern/wm_operator_props.cc @@ -416,8 +416,59 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo { PropertyRNA *prop; + static const EnumPropertyItem object_select_items[] = { + {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, + {OBJECT_ENCLOSE, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the box"}, + {OBJECT_ORIGIN, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_items[] = { + {FACE_DEFAULT, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the box in near select. Select faces if their center is " + "touched by the box in X-Ray select"}, + {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, + {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the box"}, + {FACE_CENTER, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_items[] = { + {EDGE_DEFAULT, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the box. If no edges are fully inside the box, select " + "edges that are touched by the box"}, + {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"}, + {EDGE_ENCLOSE, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + WM_operator_properties_border(ot); + prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + if (deselect) { prop = RNA_def_boolean( ot->srna, "deselect", false, "Deselect", "Deselect rather than select items"); @@ -524,6 +575,58 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot) void WM_operator_properties_gesture_lasso(wmOperatorType *ot) { PropertyRNA *prop; + static const EnumPropertyItem object_select_items[] = { + {OBJECT_ORIGIN, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the lasso"}, + {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the lasso"}, + {OBJECT_ENCLOSE, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_items[] = { + {FACE_DEFAULT, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the lasso in near select. Select faces if their center " + "is touched by the lasso in X-Ray select"}, + {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, + {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the lasso"}, + {FACE_CENTER, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_items[] = { + {EDGE_DEFAULT, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the lasso. If no edges are fully inside the lasso, " + "select edges that are touched by the lasso"}, + {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"}, + {EDGE_ENCLOSE, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + WM_operator_properties_border(ot); + + prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } @@ -562,6 +665,52 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) PropertyRNA *prop; const int radius_default = 25; + static const EnumPropertyItem object_select_items[] = { + {OBJECT_ORIGIN, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the circle"}, + {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the circle"}, + {OBJECT_ENCLOSE, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_items[] = { + {FACE_DEFAULT, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the circle in near select. Select faces if their center " + "is touched by the circle in X-Ray select"}, + {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"}, + {FACE_ENCLOSE, + "FACE_ENCLOSE", + 0, + "Enclose", + "Select faces that are fully inside the circle"}, + {FACE_CENTER, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_items[] = { + {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the circle"}, + {EDGE_ENCLOSE, + "EDGE_ENCLOSE", + 0, + "Enclose", + "Select edges that are fully inside the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); @@ -570,6 +719,13 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_mouse_select(wmOperatorType *ot) -- 2.30.2 From 82a416cee5b8dd92d3ddb26a8ac6b2d91f144628 Mon Sep 17 00:00:00 2001 From: bla BLA Date: Wed, 3 Apr 2024 19:51:02 -0700 Subject: [PATCH 2/6] fix VFS in ortho, streamline it, make it faster, other fixes --- scripts/startup/bl_ui/space_view3d_toolbar.py | 23 +- .../blenloader/intern/versioning_defaults.cc | 9 +- .../view3d_navigate_smoothview.cc | 1 - .../editors/space_view3d/view3d_select.cc | 1041 +++++++++++------ source/blender/makesdna/DNA_scene_defaults.h | 9 +- source/blender/makesdna/DNA_scene_types.h | 54 +- source/blender/makesrna/intern/rna_scene.cc | 148 +-- 7 files changed, 696 insertions(+), 589 deletions(-) diff --git a/scripts/startup/bl_ui/space_view3d_toolbar.py b/scripts/startup/bl_ui/space_view3d_toolbar.py index 066c3d98704..e5add9c52c4 100644 --- a/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -231,21 +231,15 @@ class VIEW3D_PT_tools_meshedit_options_uvs(View3DPanel, Panel): layout.prop(tool_settings, "use_edge_path_live_unwrap") -class VIEW3D_PT_tools_meshedit_options_viewport_facing_select(View3DPanel, Panel): +class VIEW3D_PT_tools_meshedit_options_select(View3DPanel, Panel): bl_category = "Tool" bl_context = ".mesh_edit" # dot on purpose (access from topbar) - bl_label = "Viewport Facing Select" + bl_label = "Drag Select" bl_parent_id = "VIEW3D_PT_tools_meshedit_options" - bl_options = {'DEFAULT_CLOSED'} @classmethod def poll(cls, context): - return context.active_object - - def draw_header(self, context): - tool_settings = context.tool_settings - - self.layout.prop(tool_settings, "viewport_facing_select", text="", toggle=False) + return context.active_object def draw(self, context): layout = self.layout @@ -256,12 +250,9 @@ class VIEW3D_PT_tools_meshedit_options_viewport_facing_select(View3DPanel, Panel layout.use_property_decorate = False col = layout.column() - col.active = tool_settings.viewport_facing_select - col.prop(tool_settings, "viewport_facing_select_mode") - col.prop(tool_settings, "viewport_facing_select_threshold", text="Threshold") - col.prop(tool_settings, "viewport_facing_select_vert") - col.prop(tool_settings, "viewport_facing_select_edge") - col.prop(tool_settings, "viewport_facing_select_face") + self.layout.prop(tool_settings, "backface_select") + if tool_settings.backface_select: + self.layout.prop(tool_settings, "backface_select_mode") # ********** default tools for editmode_armature **************** @@ -2531,7 +2522,7 @@ classes = ( VIEW3D_PT_tools_meshedit_options, VIEW3D_PT_tools_meshedit_options_transform, VIEW3D_PT_tools_meshedit_options_uvs, - VIEW3D_PT_tools_meshedit_options_viewport_facing_select, + VIEW3D_PT_tools_meshedit_options_select, VIEW3D_PT_tools_armatureedit_options, VIEW3D_PT_tools_posemode_options, diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index 0fc2a6be3b8..639c6499ba6 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -395,7 +395,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) ts->unified_paint_settings.input_samples = 1; } - /* X-Ray. */ + /* Drag Select. */ ts->xray_button = true; ts->auto_xray_object = true; ts->auto_xray_edit = true; @@ -407,12 +407,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) ts->select_through_box = true; ts->select_through_lasso = true; ts->select_through_circle = true; - - /* Viewport-Facing Select */ - ts->viewport_facing_select_mode = 1; - ts->viewport_facing_select_vert = 1; - ts->viewport_facing_select_edge = 1; - ts->viewport_facing_select_face = 1; + ts->backface_select_mode = 1; } void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) diff --git a/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc b/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc index 94ecacb1709..aa18a4302c7 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc +++ b/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc @@ -281,7 +281,6 @@ void ED_view3d_smooth_view_ex( /* Skip smooth viewing for external render engine draw. */ if (smooth_viewtx && !(v3d->shading.type == OB_RENDER && rv3d->view_render)) { - /* original values */ if (sview->camera_old) { Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old); diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 66064b5c151..715b892687d 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -606,6 +606,8 @@ struct BoxSelectUserData { int edge_style; int face_style; bool check_mesh_direction; + blender::BitVector<> visited_face; + blender::BitVector<> front_face; /* runtime */ bool is_done; @@ -624,6 +626,8 @@ struct LassoSelectUserData { int edge_style; int face_style; bool check_mesh_direction; + blender::BitVector<> visited_face; + blender::BitVector<> front_face; /* runtime */ int pass; @@ -642,6 +646,8 @@ struct CircleSelectUserData { int edge_style; int face_style; bool check_mesh_direction; + blender::BitVector<> visited_face; + blender::BitVector<> front_face; /* runtime */ bool is_changed; @@ -649,14 +655,14 @@ struct CircleSelectUserData { void edbm_vert_orientation(const BMVert *eve, float normal[3], float plane[3], float meshmat[3][3]) { - float vec[3] = {}; + float vec[3] = {0.0, 0.0, 0.0}; float tangent[3] = {0.0f, 0.0f, 1.0f}; copy_v3_v3(normal, eve->no); if (eve->e) { - float v1co[3] = {eve->e->v1->co[0], eve->e->v1->co[1], eve->e->v1->co[2]}; - float v2co[3] = {eve->e->v2->co[0], eve->e->v2->co[1], eve->e->v2->co[2]}; - sub_v3_v3v3(plane, v2co, v1co); + float vert1v3[3] = {eve->e->v1->co[0], eve->e->v1->co[1], eve->e->v1->co[2]}; + float vert2v3[3] = {eve->e->v2->co[0], eve->e->v2->co[1], eve->e->v2->co[2]}; + sub_v3_v3v3(plane, vert2v3, vert1v3); } else { if (eve->no[0] < 0.5f) { @@ -682,166 +688,165 @@ void edbm_vert_orientation(const BMVert *eve, float normal[3], float plane[3], f cross_v3_v3v3(meshmat[1], meshmat[2], meshmat[0]); } -void edbm_edge_orientation(const BMEdge *eed, float normal[3], float plane[3]) +void edbm_edge_orientation(const BMEdge *eed, float normal[3], float plane[3], float meshmat[3][3]) { - float eed_plane[3] = {}; - float vec[3] = {}; + float eed_plane[3], vec[3]; add_v3_v3v3(normal, eed->v1->no, eed->v2->no); sub_v3_v3v3(eed_plane, eed->v2->co, eed->v1->co); cross_v3_v3v3(vec, normal, eed_plane); cross_v3_v3v3(normal, eed_plane, vec); normalize_v3(normal); - if (BM_edge_is_boundary(eed)) { - sub_v3_v3v3(plane, eed->l->v->co, eed->l->next->v->co); - } - else { - if (eed->v2->co[1] > eed->v1->co[1]) { - sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); + if (plane != nullptr && meshmat != nullptr) { + if (BM_edge_is_boundary(eed)) { + sub_v3_v3v3(plane, eed->l->v->co, eed->l->next->v->co); } else { - sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); + if (eed->v2->co[1] > eed->v1->co[1]) { + sub_v3_v3v3(plane, eed->v2->co, eed->v1->co); + } + else { + sub_v3_v3v3(plane, eed->v1->co, eed->v2->co); + } } + normalize_v3(plane); } - normalize_v3(plane); } -bool edbm_normal_facing_viewport(ViewContext *vc, - struct BMVert *eve, - struct BMEdge *eed, - struct BMFace *efa, - bool use_direction) +bool edbm_mesh_facing_viewport(ViewContext *vc, + struct BMFace *efa, + struct BMEdge *eed, + struct BMVert *eve) { ToolSettings *ts = vc->scene->toolsettings; - float normal[3], plane[3], meshcol3[3], viewcol3[3], meshmat[3][3]; - int direction = eve != nullptr ? ts->viewport_facing_select_vert : - eed != nullptr ? ts->viewport_facing_select_edge : - ts->viewport_facing_select_face; - bool backface = use_direction && (direction == 4 || direction == 8); - - if (eve != nullptr) { - edbm_vert_orientation(eve, normal, plane, meshmat); - } - else { - if (eed != nullptr) { - edbm_edge_orientation(eed, normal, plane); - } - else if (efa != nullptr) { - copy_v3_v3(normal, efa->no); - BM_face_calc_tangent_auto(efa, plane); - } - normalize_v3_v3(meshmat[2], normal); - negate_v3_v3(meshmat[1], plane); - - if (is_zero_v3(meshmat[1])) { - meshmat[1][2] = 1.0f; - } - cross_v3_v3v3(meshmat[0], meshmat[2], meshmat[1]); - cross_v3_v3v3(meshmat[1], meshmat[2], meshmat[0]); - normalize_v3(meshmat[1]); - } - normalize_m3(meshmat); - invert_m3(meshmat); - meshcol3[0] = meshmat[0][2]; - meshcol3[1] = meshmat[1][2]; - meshcol3[2] = meshmat[2][2]; - viewcol3[0] = vc->rv3d->viewmat[0][2]; - viewcol3[1] = vc->rv3d->viewmat[1][2]; - viewcol3[2] = vc->rv3d->viewmat[2][2]; - + const bool face = efa != nullptr; + const bool edge = eed != nullptr; + const bool vert = eve != nullptr; + const bool persp = vc->rv3d->is_persp; + float view[3], mesh_co[3], mesh_no[3]; bool mesh_facing = false; - if (backface) { - mesh_facing = dot_v3v3(meshcol3, viewcol3) < -ts->viewport_facing_select_threshold; + + for (int i = 0; i < 3; i++) { + if (persp) { + view[i] = vc->rv3d->viewinv[3][i]; + } + else { + view[i] = vc->rv3d->viewmat[i][2]; + } + } + + if (persp) { + if (face) { + BMIter iter; + BMVert *eve; + int vcount = 0; + mesh_no[0] = efa->no[0]; + mesh_no[1] = efa->no[1]; + mesh_no[2] = efa->no[2]; + + if (efa->len == 3) { + float tri[3][3]; + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + tri[vcount][0] = eve->co[0]; + tri[vcount][1] = eve->co[1]; + tri[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3v3v3(mesh_co, tri[0], tri[1], tri[2]); + } + else if (efa->len == 4) { + float quad[4][3]; + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + quad[vcount][0] = eve->co[0]; + quad[vcount][1] = eve->co[1]; + quad[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3v3v3v3(mesh_co, quad[0], quad[1], quad[2], quad[3]); + } + else { + float(*ngon)[3] = static_cast( + MEM_mallocN(sizeof(float) * 3 * efa->len, __func__)); + BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { + ngon[vcount][0] = eve->co[0]; + ngon[vcount][1] = eve->co[1]; + ngon[vcount][2] = eve->co[2]; + vcount++; + } + mid_v3_v3_array(mesh_co, ngon, efa->len); + MEM_freeN(ngon); + } + } + else if (edge) { + edbm_edge_orientation(eed, mesh_no, nullptr, nullptr); + mid_v3_v3v3(mesh_co, eed->v1->co, eed->v2->co); + } + else if (vert) { + for (int i = 0; i < 3; i++) { + mesh_no[i] = eve->no[i]; + mesh_co[i] = eve->co[i]; + } + } + + mesh_co[0] -= view[0]; + mesh_co[1] -= view[1]; + mesh_co[2] -= view[2]; + normalize_v3(mesh_co); } else { - mesh_facing = dot_v3v3(meshcol3, viewcol3) > ts->viewport_facing_select_threshold; + float plane[3], meshmat[3][3]; + + if (vert) { + edbm_vert_orientation(eve, mesh_no, plane, meshmat); + } + else { + if (edge) { + edbm_edge_orientation(eed, mesh_no, plane, meshmat); + } + else if (face) { + copy_v3_v3(mesh_no, efa->no); + BM_face_calc_tangent_auto(efa, plane); + } + normalize_v3_v3(meshmat[2], mesh_no); + negate_v3_v3(meshmat[1], plane); + + if (is_zero_v3(meshmat[1])) { + meshmat[1][2] = 1.0f; + } + + cross_v3_v3v3(meshmat[0], meshmat[2], meshmat[1]); + cross_v3_v3v3(meshmat[1], meshmat[2], meshmat[0]); + normalize_v3(meshmat[1]); + } + + normalize_m3(meshmat); + invert_m3(meshmat); + mesh_no[0] = meshmat[0][2]; + mesh_no[1] = meshmat[1][2]; + mesh_no[2] = meshmat[2][2]; } + + if (persp) { + mesh_facing = dot_v3v3(mesh_no, mesh_co) < 0.0f; + } + else { + mesh_facing = dot_v3v3(mesh_no, view) > 0.0f; + } + return mesh_facing; } -bool edbm_facing_viewport_precheck(ToolSettings *ts, int style, bool xray) +bool edbm_check_mesh_facing(ToolSettings *ts, bool zbuf) { - if (!ts->viewport_facing_select) { - return false; - } - const bool mode_match = xray ? ts->viewport_facing_select_mode == 1 || - ts->viewport_facing_select_mode == 4 : - ts->viewport_facing_select_mode < 4; - const bool check_mesh_facing = mode_match && style > 0 && style < 16; - return check_mesh_facing; + const bool mode_match = zbuf ? ts->backface_select && (ts->backface_select_mode == 2 || + ts->backface_select_mode == 8) : + ts->backface_select && (ts->backface_select_mode == 4 || + ts->backface_select_mode == 8); + + return mode_match; } -bool edbm_facing_viewport(ViewContext *vc, BMVert *eve, BMEdge *eed, BMFace *efa, int style) -{ - BMIter iter; - bool mesh_facing = false; - if (eve != nullptr) { - /* viewport-facing or rear-facing vert */ - mesh_facing = edbm_normal_facing_viewport(vc, eve, nullptr, nullptr, true); - if (!mesh_facing && eve->e && eve->e->l && (style == 2 || style == 8)) { - BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { - const bool eve_efa_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, false); - /* vert of a viewport-facing face */ - if (style == 2) { - if (eve_efa_facing) { - mesh_facing = true; - break; - } - } - /* vert of a rear-facing face */ - else if (!eve_efa_facing) { - mesh_facing = true; - break; - } - } - } - } - else if (eed != nullptr) { - /* viewport-facing or rear-facing edge */ - mesh_facing = edbm_normal_facing_viewport(vc, nullptr, eed, nullptr, true); - if (!mesh_facing && eed->l && (style == 2 || style == 8)) { - BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { - const bool eed_efa_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, false); - /* edge of a viewport-facing face */ - if (style == 2) { - if (eed_efa_facing) { - mesh_facing = true; - break; - } - } - /* edge of a rear-facing face */ - else if (!eed_efa_facing) { - mesh_facing = true; - break; - } - } - } - } - else if (efa != nullptr) { - /* viewport-facing or rear-facing face */ - mesh_facing = edbm_normal_facing_viewport(vc, nullptr, nullptr, efa, true); - if (!mesh_facing && (style == 2 || style == 8)) { - BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { - const bool efa_eve_facing = edbm_normal_facing_viewport(vc, eve, nullptr, nullptr, false); - /* face has a viewport-facing vert */ - if (style == 2) { - if (efa_eve_facing) { - mesh_facing = true; - break; - } - } - /* face has a rear-facing vert */ - else if (!efa_eve_facing) { - mesh_facing = true; - break; - } - } - } - } - return mesh_facing; -} - -static void mesh_filter( +static void face_filter( ViewContext *vc, void *box_data, void *lasso_data, void *circle_data, eSelectOp sel_op) { BMVert *eve; @@ -855,15 +860,15 @@ static void mesh_filter( const bool enclose = box ? data->face_style == 4 : lasso ? ldata->face_style == 4 : cdata->face_style == 4; - const bool check_direction = box ? data->check_mesh_direction : - lasso ? ldata->check_mesh_direction : - cdata->check_mesh_direction; - int totvert = bm->totvert; + const bool check_mesh_facing = box ? data->check_mesh_direction : + lasso ? ldata->check_mesh_direction : + cdata->check_mesh_direction; + const int totvert = bm->totvert; float v1co[2], v2co[2]; - float(*vco)[2] = static_cast(MEM_mallocN(sizeof(int) * 2 * totvert, __func__)); + float(*vco)[2] = static_cast(MEM_mallocN(sizeof(float) * 2 * totvert, __func__)); /* store 2d vert co */ - for (int i = 0; i < bm->totvert; i++) { + for (int i = 0; i < totvert; i++) { eve = BM_vert_at_index(vc->em->bm, i); if (ED_view3d_project_float_object( vc->region, eve->co, v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB) == @@ -882,7 +887,6 @@ static void mesh_filter( for (int i = 0; i < bm->totface; i++) { BMFace *efa = BM_face_at_index(vc->em->bm, i); bool inside = false; - bool mesh_facing = true; if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { BMLoop *l_first, *l_iter; @@ -891,38 +895,17 @@ static void mesh_filter( BLI_rctf_init_minmax(face); bool skip = false; - /* out of range check */ - if (bm->totvert > totvert) { - MEM_freeN(vco); - totvert = bm->totvert; - vco = static_cast(MEM_mallocN(sizeof(float) * 2 * totvert, __func__)); - - for (int i = 0; i < bm->totvert; i++) { - eve = BM_vert_at_index(vc->em->bm, i); - if (ED_view3d_project_float_object( - vc->region, eve->co, v1co, V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_BB) == - V3D_PROJ_RET_OK) - { - vco[i][0] = v1co[0]; - vco[i][1] = v1co[1]; - } - else { - vco[i][0] = 0.0f; - vco[i][1] = 0.0f; - } - } - } - /* skip invalid */ l_iter = l_first = BM_FACE_FIRST_LOOP(efa); do { - if (vco[BM_elem_index_get(l_iter->v)][0] == 0.0f && - vco[BM_elem_index_get(l_iter->v)][1] == 0.0f) - { + const int index = BM_elem_index_get(l_iter->v); + + if (index > totvert || index < 0 || (vco[index][0] == 0.0f && vco[index][1] == 0.0f)) { skip = true; break; } - BLI_rctf_do_minmax_v(face, vco[BM_elem_index_get(l_iter->v)]); + + BLI_rctf_do_minmax_v(face, vco[index]); } while ((l_iter = l_iter->next) != l_first); /* skip non-intersect, not enough on its own, selects too many things */ @@ -931,7 +914,7 @@ static void mesh_filter( lasso && !BLI_rctf_isect(face, ldata->rect_fl, nullptr) || circle && !BLI_rctf_isect_circle(face, cdata->mval_fl, cdata->radius)) { - skip ^= true; + skip = true; } } @@ -939,8 +922,9 @@ static void mesh_filter( l_iter = l_first = BM_FACE_FIRST_LOOP(efa); if (circle && enclose) { do { - v1co[0] = vco[BM_elem_index_get(l_iter->v)][0]; - v1co[1] = vco[BM_elem_index_get(l_iter->v)][1]; + const int index = BM_elem_index_get(l_iter->v); + v1co[0] = vco[index][0]; + v1co[1] = vco[index][1]; inside = len_squared_v2v2(cdata->mval_fl, v1co) <= cdata->radius_squared; if (!inside) { @@ -950,10 +934,12 @@ static void mesh_filter( } else { do { - v1co[0] = vco[BM_elem_index_get(l_iter->e->v1)][0]; - v1co[1] = vco[BM_elem_index_get(l_iter->e->v1)][1]; - v2co[0] = vco[BM_elem_index_get(l_iter->e->v2)][0]; - v2co[1] = vco[BM_elem_index_get(l_iter->e->v2)][1]; + const int index1 = BM_elem_index_get(l_iter->e->v1); + const int index2 = BM_elem_index_get(l_iter->e->v2); + v1co[0] = vco[index1][0]; + v1co[1] = vco[index1][1]; + v2co[0] = vco[index2][0]; + v2co[1] = vco[index2][1]; if (box) { inside = enclose ? edge_fully_inside_rect(data->rect_fl, v1co, v2co) : @@ -1004,8 +990,9 @@ static void mesh_filter( if (efa->len == 3) { float tri[3][2]; do { - tri[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; - tri[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + const int index = BM_elem_index_get(l_iter->v); + tri[vcount][0] = vco[index][0]; + tri[vcount][1] = vco[index][1]; vcount++; } while ((l_iter = l_iter->next) != l_first); @@ -1014,8 +1001,9 @@ static void mesh_filter( else if (efa->len == 4) { float quad[4][2]; do { - quad[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; - quad[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + const int index = BM_elem_index_get(l_iter->v); + quad[vcount][0] = vco[index][0]; + quad[vcount][1] = vco[index][1]; vcount++; } while ((l_iter = l_iter->next) != l_first); @@ -1025,8 +1013,9 @@ static void mesh_filter( float(*ngon)[2] = static_cast( MEM_mallocN(sizeof(float) * 2 * efa->len, __func__)); do { - ngon[vcount][0] = vco[BM_elem_index_get(l_iter->v)][0]; - ngon[vcount][1] = vco[BM_elem_index_get(l_iter->v)][1]; + const int index = BM_elem_index_get(l_iter->v); + ngon[vcount][0] = vco[index][0]; + ngon[vcount][1] = vco[index][1]; vcount++; } while ((l_iter = l_iter->next) != l_first); @@ -1035,16 +1024,14 @@ static void mesh_filter( } } - if (inside && check_direction) { - mesh_facing = edbm_facing_viewport( - vc, nullptr, nullptr, efa, vc->scene->toolsettings->viewport_facing_select_face); + if (inside && check_mesh_facing) { + inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); } } } const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const int sel_op_result = ED_select_op_action_deselected( - sel_op, is_select, inside && mesh_facing); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, inside); if (sel_op_result != -1) { BM_face_select_set(vc->em->bm, efa, sel_op_result); @@ -1164,12 +1151,21 @@ static bool edbm_backbuf_check_and_select_verts(ViewContext *vc, BMEditMesh *em, const eSelectOp sel_op) { - ToolSettings *ts = vc->scene->toolsettings; BMVert *eve; BMIter iter; + ToolSettings *ts = vc->scene->toolsettings; + const int totface = em->bm->totface; + const bool check_mesh_facing = ts->backface_select && ts->backface_select_mode == 8; + blender::BitVector<> visited_face; + blender::BitVector<> front_face; bool changed = false; - const int style = ts->viewport_facing_select_vert; - const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); + + if (check_mesh_facing) { + blender::BitVector<> vtmp(totface); + blender::BitVector<> ftmp(totface); + visited_face = vtmp; + front_face = ftmp; + } const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_VERTEX); @@ -1178,16 +1174,48 @@ static bool edbm_backbuf_check_and_select_verts(ViewContext *vc, } index -= 1; + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - bool mesh_facing = true; + bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); + if (is_inside && check_mesh_facing) { - mesh_facing = edbm_facing_viewport(vc, eve, nullptr, nullptr, style); + is_inside = false; + + if (eve->e && eve->e->l) { + BMIter fiter; + BMFace *efa; + BM_ITER_ELEM (efa, &fiter, eve, BM_FACES_OF_VERT) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (visited_face[index]) { + if (front_face[index]) { + is_inside = true; + break; + } + } + else { + visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + front_face[index].set(true); + break; + } + } + } + } + } + } + /* use vert normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, nullptr, eve); + } } - const int sel_op_result = ED_select_op_action_deselected( - sel_op, is_select, is_inside && mesh_facing); + + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(em->bm, eve, sel_op_result); changed = true; @@ -1206,12 +1234,12 @@ static bool edbm_backbuf_check_and_select_edges(void *userData, const eSelectOp sel_op) { CircleSelectUserData *data = static_cast(userData); - ToolSettings *ts = data->vc->scene->toolsettings; + ViewContext *vc = data->vc; + ToolSettings *ts = vc->scene->toolsettings; BMEdge *eed; BMIter iter; bool changed = false; - const int style = ts->viewport_facing_select_edge; - const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); + const bool check_mesh_facing = edbm_check_mesh_facing(ts, true); const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); @@ -1223,20 +1251,51 @@ static bool edbm_backbuf_check_and_select_edges(void *userData, BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - bool enclose_edge = true; - bool mesh_facing = true; + bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - if (data->edge_style == 4 && is_inside) { - enclose_edge = edbm_circle_enclose_mesh(eed, nullptr, data); + /* enclose */ + if (is_inside && data->edge_style == 4) { + is_inside = edbm_circle_enclose_mesh(eed, nullptr, data); } - if (check_mesh_facing && is_inside) { - mesh_facing = edbm_facing_viewport(data->vc, nullptr, eed, nullptr, style); + if (is_inside && check_mesh_facing) { + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - const int sel_op_result = ED_select_op_action_deselected( - sel_op, is_select, is_inside && enclose_edge && mesh_facing); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(em->bm, eed, sel_op_result); changed = true; @@ -1264,8 +1323,7 @@ static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, BMVert *eve; rctf rectf; bool changed = false; - const int style = ts->viewport_facing_select_face; - const bool check_mesh_facing = edbm_facing_viewport_precheck(ts, style, false); + const bool check_mesh_facing = edbm_check_mesh_facing(ts, true); const BLI_bitmap *select_bitmap = esel->select_bitmap; LassoSelectUserData *ldata = static_cast(lasso_data); CircleSelectUserData *cdata = static_cast(circle_data); @@ -1276,45 +1334,44 @@ static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, BLI_rctf_rcti_copy(&rectf, rect); } - if (index == 0 || vindex == 0) { + if (index == 0) { return false; } index -= 1; vindex -= 1; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); - bool enclose_face = true; - bool center_face = true; - bool mesh_facing = true; + bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index); if (face_style > 2 && is_inside) { + /* enclose */ if (face_style == 4) { if (cdata != nullptr) { - enclose_face = edbm_circle_enclose_mesh(nullptr, efa, cdata); + is_inside = edbm_circle_enclose_mesh(nullptr, efa, cdata); } else { BM_ITER_ELEM (eve, &viter, efa, BM_VERTS_OF_FACE) { - enclose_face = BLI_BITMAP_TEST_BOOL(select_bitmap, vindex + BM_elem_index_get(eve)); - if (!enclose_face) { + is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, vindex + BM_elem_index_get(eve)); + if (!is_inside) { break; } } } } + /* center */ else { - center_face = edbm_center_face(vc, efa, &rectf, ldata, cdata); + is_inside = edbm_center_face(vc, efa, &rectf, ldata, cdata); } } - if (check_mesh_facing && is_inside) { - mesh_facing = edbm_facing_viewport(vc, nullptr, nullptr, efa, style); + if (is_inside && check_mesh_facing) { + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); } - const int sel_op_result = ED_select_op_action_deselected( - sel_op, is_select, is_inside && enclose_face && center_face && mesh_facing); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(em->bm, efa, sel_op_result); changed = true; @@ -1797,23 +1854,50 @@ static void do_lasso_select_mesh__doSelectVert(void *user_data, int /*index*/) { LassoSelectUserData *data = static_cast(user_data); + ViewContext *vc = data->vc; 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->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); - bool mesh_facing = true; + 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)); if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - eve, - nullptr, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_vert); + is_inside = false; + + if (eve->e && eve->e->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use vert normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, nullptr, eve); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); data->is_changed = true; @@ -1833,31 +1917,59 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, LassoSelectUserData_ForMeshEdge *data_for_edge = static_cast( user_data); LassoSelectUserData *data = data_for_edge->data; + ViewContext *vc = data->vc; bool is_visible = true; - bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); } 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->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)); + bool is_inside = (is_visible && + edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && + 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)); if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - eed, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_edge); + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); data->is_done = true; @@ -1873,29 +1985,58 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, LassoSelectUserData_ForMeshEdge *data_for_edge = static_cast( user_data); LassoSelectUserData *data = data_for_edge->data; + ViewContext *vc = data->vc; bool is_visible = true; - bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); } const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - 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, - false)); + 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, + false)); + if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - eed, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_edge); + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); data->is_changed = true; @@ -1908,23 +2049,17 @@ static void do_lasso_select_mesh__doSelectFace(void *user_data, int /*index*/) { LassoSelectUserData *data = static_cast(user_data); + ViewContext *vc = data->vc; 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->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); - bool mesh_facing = true; + 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)); if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - nullptr, - efa, - data->vc->scene->toolsettings->viewport_facing_select_face); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); data->is_changed = true; @@ -1991,15 +2126,24 @@ static bool do_lasso_select_mesh(ViewContext *vc, } } + if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { + data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + + if (data.check_mesh_direction) { + const int totface = vc->em->bm->totface; + blender::BitVector<> visited_face(totface); + blender::BitVector<> front_face(totface); + data.visited_face = visited_face; + data.front_face = front_face; + } + } + if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_vert, true); - mesh_foreachScreenVert( vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -2016,12 +2160,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); - data.check_mesh_direction = use_zbuf ? - edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_edge, false) : - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_edge, true); - /* Fully inside */ if (data.edge_style != 2) { mesh_foreachScreenEdge_clip_bb_segment( @@ -2050,9 +2188,6 @@ static bool do_lasso_select_mesh(ViewContext *vc, nullptr); } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_face, true); - /* center */ if (data.face_style == 1 || data.face_style == 8) { mesh_foreachScreenFace( @@ -2060,7 +2195,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, } /* touch & enclose */ else { - mesh_filter(vc, nullptr, &data, nullptr, sel_op); + face_filter(vc, nullptr, &data, nullptr, sel_op); } } } @@ -4922,19 +5057,48 @@ static void do_mesh_box_select__doSelectVert(void *user_data, int /*index*/) { BoxSelectUserData *data = static_cast(user_data); + ViewContext *vc = data->vc; 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); - bool mesh_facing = true; + bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); + if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - eve, - nullptr, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_vert); + is_inside = false; + + if (eve->e && eve->e->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use vert normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, nullptr, eve); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); data->is_changed = true; @@ -4957,29 +5121,56 @@ static void do_mesh_box_select__doSelectEdge_pass0(void *user_data, BoxSelectUserData_ForMeshEdge *data_for_edge = static_cast( user_data); BoxSelectUserData *data = data_for_edge->data; + ViewContext *vc = data->vc; bool is_visible = true; - bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); } 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)); + bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - eed, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_edge); + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); + BM_edge_select_set(vc->em->bm, eed, sel_op_result); data->is_done = true; data->is_changed = true; } @@ -4996,27 +5187,56 @@ static void do_mesh_box_select__doSelectEdge_pass1(void *user_data, BoxSelectUserData_ForMeshEdge *data_for_edge = static_cast( user_data); BoxSelectUserData *data = data_for_edge->data; + ViewContext *vc = data->vc; bool is_visible = true; - bool mesh_facing = true; if (data_for_edge->backbuf_offset) { uint bitmap_inedx = data_for_edge->backbuf_offset + index - 1; is_visible = BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap, bitmap_inedx); } const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); + bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b)); + if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - eed, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_edge); + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); + BM_edge_select_set(vc->em->bm, eed, sel_op_result); data->is_changed = true; } } @@ -5027,22 +5247,17 @@ static void do_mesh_box_select__doSelectFace(void *user_data, int /*index*/) { BoxSelectUserData *data = static_cast(user_data); + ViewContext *vc = data->vc; 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); - bool mesh_facing = true; + bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); if (is_inside && data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport(data->vc, - nullptr, - nullptr, - efa, - data->vc->scene->toolsettings->viewport_facing_select_face); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); } - const int sel_op_result = ED_select_op_action_deselected( - data->sel_op, is_select, is_inside && mesh_facing); + 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); + BM_face_select_set(vc->em->bm, efa, sel_op_result); data->is_changed = true; } } @@ -5103,15 +5318,24 @@ static bool do_mesh_box_select(ViewContext *vc, } } + if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { + data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + + if (data.check_mesh_direction) { + const int totface = vc->em->bm->totface; + blender::BitVector<> visited_face(totface); + blender::BitVector<> front_face(totface); + data.visited_face = visited_face; + data.front_face = front_face; + } + } + if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_vert, true); - mesh_foreachScreenVert( vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } @@ -5128,11 +5352,6 @@ static bool do_mesh_box_select(ViewContext *vc, const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_NEAR | (use_zbuf ? (eV3DProjTest)0 : V3D_PROJ_TEST_CLIP_BB); - data.check_mesh_direction = use_zbuf ? - edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_edge, false) : - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_edge, true); /* Fully inside */ if (data.edge_style != 2) { mesh_foreachScreenEdge_clip_bb_segment( @@ -5161,9 +5380,6 @@ static bool do_mesh_box_select(ViewContext *vc, nullptr); } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_face, true); - /* center */ if (data.face_style == 1 || data.face_style == 8) { mesh_foreachScreenFace( @@ -5171,7 +5387,7 @@ static bool do_mesh_box_select(ViewContext *vc, } /* touch & enclose */ else { - mesh_filter(vc, &data, nullptr, nullptr, sel_op); + face_filter(vc, &data, nullptr, nullptr, sel_op); } } } @@ -5804,20 +6020,50 @@ static void mesh_circle_doSelectVert(void *user_data, int /*index*/) { CircleSelectUserData *data = static_cast(user_data); + ViewContext *vc = data->vc; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - bool mesh_facing = true; - data->is_changed = true; + bool is_inside = true; + if (data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport( - data->vc, - eve, - nullptr, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_vert); + is_inside = false; + + if (eve->e && eve->e->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use vert normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, nullptr, eve); + } } - if (mesh_facing) { - BM_vert_select_set(data->vc->em->bm, eve, data->select); + + if (is_inside) { + BM_vert_select_set(vc->em->bm, eve, data->select); data->is_changed = true; } } @@ -5829,25 +6075,54 @@ static void mesh_circle_doSelectEdge(void *user_data, int /*index*/) { CircleSelectUserData *data = static_cast(user_data); - bool enclose_edge = true; - bool mesh_facing = true; + ViewContext *vc = data->vc; if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + bool is_inside = true; + if (data->edge_style == 4) { - enclose_edge = edbm_circle_enclose_mesh(eed, nullptr, data); + is_inside = edbm_circle_enclose_mesh(eed, nullptr, data); } - if (data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport( - data->vc, - nullptr, - eed, - nullptr, - data->vc->scene->toolsettings->viewport_facing_select_edge); + if (is_inside && data->check_mesh_direction) { + is_inside = false; + + if (eed->l) { + const int totface = vc->em->bm->totface; + BMIter iter; + BMFace *efa; + + BM_ITER_ELEM (efa, &iter, eed, BM_FACES_OF_EDGE) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const int index = BM_elem_index_get(efa); + if (!(index < 0 || index > totface)) { + if (data->visited_face[index]) { + if (data->front_face[index]) { + is_inside = true; + break; + } + } + else { + data->visited_face[index].set(true); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); + + if (is_inside) { + data->front_face[index].set(true); + break; + } + } + } + } + } + } + /* use edge normals */ + else { + is_inside = edbm_mesh_facing_viewport(vc, nullptr, eed, nullptr); + } } - if (enclose_edge && mesh_facing) { - BM_edge_select_set(data->vc->em->bm, eed, data->select); + if (is_inside) { + BM_edge_select_set(vc->em->bm, eed, data->select); data->is_changed = true; } } @@ -5859,20 +6134,17 @@ static void mesh_circle_doSelectFace(void *user_data, int /*index*/) { CircleSelectUserData *data = static_cast(user_data); - bool mesh_facing = true; + ViewContext *vc = data->vc; if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + bool is_inside = true; + if (data->check_mesh_direction) { - mesh_facing = edbm_facing_viewport( - data->vc, - nullptr, - nullptr, - efa, - data->vc->scene->toolsettings->viewport_facing_select_face); + is_inside = edbm_mesh_facing_viewport(vc, efa, nullptr, nullptr); } - if (mesh_facing) { - BM_face_select_set(data->vc->em->bm, efa, data->select); + if (is_inside) { + BM_face_select_set(vc->em->bm, efa, data->select); data->is_changed = true; } } @@ -5929,6 +6201,18 @@ static bool mesh_circle_select(ViewContext *vc, } } + if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { + data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + + if (data.check_mesh_direction) { + const int totface = vc->em->bm->totface; + blender::BitVector<> visited_face(totface); + blender::BitVector<> front_face(totface); + data.visited_face = visited_face; + data.front_face = front_face; + } + } + if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { if (esel->select_bitmap != nullptr) { @@ -5937,9 +6221,6 @@ static bool mesh_circle_select(ViewContext *vc, } } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_vert, true); - mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } } @@ -5952,9 +6233,6 @@ static bool mesh_circle_select(ViewContext *vc, } } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_edge, true); - mesh_foreachScreenEdge_clip_bb_segment( vc, mesh_circle_doSelectEdge, @@ -5979,16 +6257,13 @@ static bool mesh_circle_select(ViewContext *vc, } } else { - data.check_mesh_direction = edbm_facing_viewport_precheck( - ts, ts->viewport_facing_select_face, true); - /* center */ if (data.face_style == 1 || data.face_style == 8) { mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } /* touch & enclose */ else { - mesh_filter(vc, nullptr, nullptr, &data, sel_op); + face_filter(vc, nullptr, nullptr, &data, sel_op); } } } diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 1bd648f1d5b..89c2ed937ae 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -409,7 +409,7 @@ .snap_mode_tools = SCE_SNAP_TO_GEOM,\ .plane_axis = 2,\ \ - /* X-Ray */ \ + /* Drag Select */ \ .xray_button = true, \ .auto_xray_object = true, \ .auto_xray_edit = true, \ @@ -421,12 +421,7 @@ .select_through_box = true, \ .select_through_lasso = true, \ .select_through_circle = true, \ - \ - /* Viewport-Facing Select */ \ - .viewport_facing_select_mode = 1, \ - .viewport_facing_select_vert = 1, \ - .viewport_facing_select_edge = 1, \ - .viewport_facing_select_face = 1, \ + .backface_select_mode = 1, \ } #define _DNA_DEFAULT_Sculpt \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index abff1376149..d01509eaf36 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1600,15 +1600,9 @@ typedef struct ToolSettings { /** Stroke selection mode for Sculpt. */ char gpencil_selectmode_sculpt; - /* Mesh Normal Direction Select */ - char viewport_facing_select; - char viewport_facing_select_mode; - float viewport_facing_select_threshold; - char viewport_facing_select_vert; - char viewport_facing_select_edge; - char viewport_facing_select_face; - - /* X-Ray Options */ + /* LCB Options */ + char backface_select; + char backface_select_mode; char xray_button; char auto_xray; char auto_xray_button; @@ -1626,13 +1620,9 @@ typedef struct ToolSettings { char select_through_lasso; char select_through_circle; char wireless_touch_object; - - /* Combine shading and xray header buttons */ char shrink_shading_header; - - /* Square Select option for Circle */ char square_select; - char _pad0[2]; + char _pad0[1]; /** Grease Pencil Sculpt. */ struct GP_Sculpt_Settings gp_sculpt; @@ -2484,38 +2474,12 @@ typedef enum eSnapTransformMode { SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2), } eSnapTransformMode; -/** #Viewport-facing select mode */ +/** #Ignore backface select mode */ enum { - VIEWPORT_FACING_SELECT_BOTH = (1 << 0), - VIEWPORT_FACING_SELECT_NEAR = (1 << 1), - VIEWPORT_FACING_SELECT_XRAY = (1 << 2), -}; - -/** #Viewport-facing select vert */ -enum { - VIEWPORT_FACING_SELECT_FRONT_VERTS = (1 << 0), - VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE = (1 << 1), - VIEWPORT_FACING_SELECT_REAR_VERTS = (1 << 2), - VIEWPORT_FACING_SELECT_REAR_VERTS_FACE = (1 << 3), - VIEWPORT_FACING_SELECT_ALL_VERTS = (1 << 4), -}; - -/** #Viewport-facing select edge */ -enum { - VIEWPORT_FACING_SELECT_FRONT_EDGES = (1 << 0), - VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE = (1 << 1), - VIEWPORT_FACING_SELECT_REAR_EDGES = (1 << 2), - VIEWPORT_FACING_SELECT_REAR_EDGES_FACE = (1 << 3), - VIEWPORT_FACING_SELECT_ALL_EDGES = (1 << 4), -}; - -/** #Viewport-facing select face */ -enum { - VIEWPORT_FACING_SELECT_FRONT_FACES = (1 << 0), - VIEWPORT_FACING_SELECT_FRONT_FACES_VERT = (1 << 1), - VIEWPORT_FACING_SELECT_REAR_FACES = (1 << 2), - VIEWPORT_FACING_SELECT_REAR_FACES_VERT = (1 << 3), - VIEWPORT_FACING_SELECT_ALL_FACES = (1 << 4), + BACKFACE_DEFAULT = (1 << 0), + BACKFACE_NEAR = (1 << 1), + BACKFACE_XRAY = (1 << 2), + BACKFACE_NONE = (1 << 3), }; /** #Object select style */ diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index 3efa3a02535..33abb14a38c 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3186,105 +3186,19 @@ static void rna_def_tool_settings(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; - static const EnumPropertyItem viewport_facing_select_mode_items[] = { - {VIEWPORT_FACING_SELECT_BOTH, - "BOTH", - 0, - "Near and X-Ray", - "Use viewport-facing selection in near select and X-Ray"}, - {VIEWPORT_FACING_SELECT_NEAR, + static const EnumPropertyItem backface_select_items[] = { + {BACKFACE_NEAR, "NEAR", 0, - "Near", - "Use viewport-facing selection in near select"}, - {VIEWPORT_FACING_SELECT_XRAY, "XRAY", 0, "X-Ray", "Use viewport-facing selection in X-Ray"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem viewport_facing_select_vert_items[] = { - {VIEWPORT_FACING_SELECT_FRONT_VERTS, - "FRONT_VERTS", + "Fix Near", + "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " + "filtering"}, + {BACKFACE_XRAY, + "XRAY", 0, - "Front Verts", - "Select vertices with viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_FRONT_VERTS_FACE, - "FRONT_VERTS_FACE", - 0, - "Verts of Front Face", - "Select vertices if they are part of a face that has a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_REAR_VERTS, - "REAR_VERTS", - 0, - "Rear Verts", - "Select vertices without viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_REAR_VERTS_FACE, - "REAR_VERTS_FACE", - 0, - "Verts of Rear Face", - "Select vertices if they are part of a face that does not have a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_ALL_VERTS, - "ALL_VERTS", - 0, - "All Verts", - "Select vertices regarless of their normal direction"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem viewport_facing_select_edge_items[] = { - {VIEWPORT_FACING_SELECT_FRONT_EDGES, - "FRONT_EDGES", - 0, - "Front Edges", - "Select edges with viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_FRONT_EDGES_FACE, - "FRONT_EDGES_FACE", - 0, - "Edges of Front Face", - "Select edges if they are part of a face that has a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_REAR_EDGES, - "REAR_EDGES", - 0, - "Rear Edges", - "Select edges without viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_REAR_EDGES_FACE, - "REAR_EDGES_FACE", - 0, - "Edges of Rear Face", - "Select edges if they are part of a face that does not have a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_ALL_EDGES, - "ALL_EDGES", - 0, - "All Edges", - "Select edges regarless of their normal direction"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem viewport_facing_select_face_items[] = { - {VIEWPORT_FACING_SELECT_FRONT_FACES, - "FRONT_FACES", - 0, - "Front Faces", - "Select faces with viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_FRONT_FACES_VERT, - "FRONT_FACES_VERT", - 0, - "Faces of Front Vert", - "Select faces if they have a vertex with a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_REAR_FACES, - "REAR_FACES", - 0, - "Rear Faces", - "Select faces without viewport-facing normals"}, - {VIEWPORT_FACING_SELECT_REAR_FACES_VERT, - "REAR_FACES_VERT", - 0, - "Faces of Rear Vert", - "Select faces if they have a vertex without a viewport-facing normal"}, - {VIEWPORT_FACING_SELECT_ALL_FACES, - "ALL_FACES", - 0, - "All Faces", - "Select faces regarless of their normal direction"}, + "Front X-Ray", + "Ignore backfacing mesh in X-Ray and Select Through"}, + {BACKFACE_NONE, "NONE", 0, "Zero Backface", "Don't select backfacing mesh"}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -3292,42 +3206,16 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); - /* Viewport-Facing Select */ - prop = RNA_def_property(srna, "viewport_facing_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "viewport_facing_select", 0); + /* Ignore Backface Select */ + prop = RNA_def_property(srna, "backface_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "backface_select", 0); RNA_def_property_ui_text( - prop, - "Viewport Facing Select", - "Filter box, lasso, and circle selection of mesh elements based on the direction of their " - "normals compared to the viewport"); + prop, "Backface Filter", "Select mesh based on the direction of their normals"); - prop = RNA_def_property(srna, "viewport_facing_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_mode"); - RNA_def_property_enum_items(prop, viewport_facing_select_mode_items); - RNA_def_property_ui_text(prop, "Mode", "Which selection modes to use viewport-facing selection"); - - prop = RNA_def_property(srna, "viewport_facing_select_vert", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_vert"); - RNA_def_property_enum_items(prop, viewport_facing_select_vert_items); - RNA_def_property_ui_text(prop, "Vert", "Direction and mode for vertices"); - - prop = RNA_def_property(srna, "viewport_facing_select_edge", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_edge"); - RNA_def_property_enum_items(prop, viewport_facing_select_edge_items); - RNA_def_property_ui_text(prop, "Edge", "Direction and mode for edges"); - - prop = RNA_def_property(srna, "viewport_facing_select_face", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "viewport_facing_select_face"); - RNA_def_property_enum_items(prop, viewport_facing_select_face_items); - RNA_def_property_ui_text(prop, "Face", "Direction and mode for faces"); - - prop = RNA_def_property(srna, "viewport_facing_select_threshold", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, -0.999999, 0.999999); - RNA_def_property_ui_range(prop, -0.999999, 0.999999, 1.0, 6); - RNA_def_property_ui_text( - prop, - "Threshold", - "How close the angles of the viewport and mesh element need to be for selection to occur"); + prop = RNA_def_property(srna, "backface_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "backface_select_mode"); + RNA_def_property_enum_items(prop, backface_select_items); + RNA_def_property_ui_text(prop, "Mode", "Backface Filter Method"); prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Sculpt"); -- 2.30.2 From 250a8557b3dea5a5be77fbb1a0bf7f185b442fb3 Mon Sep 17 00:00:00 2001 From: bla BLA Date: Wed, 3 Apr 2024 19:54:50 -0700 Subject: [PATCH 3/6] add empty line back to view3d_navigate_smoothview.cc --- .../blender/editors/space_view3d/view3d_navigate_smoothview.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc b/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc index aa18a4302c7..94ecacb1709 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc +++ b/source/blender/editors/space_view3d/view3d_navigate_smoothview.cc @@ -281,6 +281,7 @@ void ED_view3d_smooth_view_ex( /* Skip smooth viewing for external render engine draw. */ if (smooth_viewtx && !(v3d->shading.type == OB_RENDER && rv3d->view_render)) { + /* original values */ if (sview->camera_old) { Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old); -- 2.30.2 From a7807e4cb65df706b20ae85fb7aadde413d27df9 Mon Sep 17 00:00:00 2001 From: bla BLA Date: Sun, 7 Apr 2024 21:50:15 -0700 Subject: [PATCH 4/6] add header vs keymap control for xray and drag select, remove warnlog --- .../blender_icons16/icon16_edge_default.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_edge_enclose.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_edge_touch.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_face_default.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_face_enclose.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_face_touch.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_object_enclose.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_object_touch.dat | Bin 0 -> 1048 bytes .../blender_icons32/icon32_edge_default.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_edge_enclose.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_edge_touch.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_face_default.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_face_enclose.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_face_touch.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_object_enclose.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_object_touch.dat | Bin 0 -> 4120 bytes scripts/startup/bl_ui/space_view3d.py | 302 +++++++++++------- scripts/startup/bl_ui/space_view3d_toolbar.py | 25 -- .../blenloader/intern/versioning_defaults.cc | 15 +- source/blender/editors/include/UI_icons.hh | 16 +- .../editors/space_view3d/view3d_edit.cc | 182 +++++++++++ .../editors/space_view3d/view3d_intern.h | 3 + .../editors/space_view3d/view3d_ops.cc | 3 + .../editors/space_view3d/view3d_select.cc | 234 +++++++++----- source/blender/makesdna/DNA_scene_defaults.h | 15 +- source/blender/makesdna/DNA_scene_types.h | 29 +- source/blender/makesrna/intern/rna_scene.cc | 202 +++++++++++- source/blender/python/intern/bpy_rna.cc | 4 +- .../windowmanager/intern/wm_gesture_ops.cc | 77 +++-- .../windowmanager/intern/wm_operator_props.cc | 129 +++++++- 30 files changed, 935 insertions(+), 301 deletions(-) create mode 100644 release/datafiles/blender_icons16/icon16_edge_default.dat create mode 100644 release/datafiles/blender_icons16/icon16_edge_enclose.dat create mode 100644 release/datafiles/blender_icons16/icon16_edge_touch.dat create mode 100644 release/datafiles/blender_icons16/icon16_face_default.dat create mode 100644 release/datafiles/blender_icons16/icon16_face_enclose.dat create mode 100644 release/datafiles/blender_icons16/icon16_face_touch.dat create mode 100644 release/datafiles/blender_icons16/icon16_object_enclose.dat create mode 100644 release/datafiles/blender_icons16/icon16_object_touch.dat create mode 100644 release/datafiles/blender_icons32/icon32_edge_default.dat create mode 100644 release/datafiles/blender_icons32/icon32_edge_enclose.dat create mode 100644 release/datafiles/blender_icons32/icon32_edge_touch.dat create mode 100644 release/datafiles/blender_icons32/icon32_face_default.dat create mode 100644 release/datafiles/blender_icons32/icon32_face_enclose.dat create mode 100644 release/datafiles/blender_icons32/icon32_face_touch.dat create mode 100644 release/datafiles/blender_icons32/icon32_object_enclose.dat create mode 100644 release/datafiles/blender_icons32/icon32_object_touch.dat diff --git a/release/datafiles/blender_icons16/icon16_edge_default.dat b/release/datafiles/blender_icons16/icon16_edge_default.dat new file mode 100644 index 0000000000000000000000000000000000000000..b0ed5dc1fff801e09db35a032c7afab066c3edab GIT binary patch literal 1048 zcmdtg!3qIU6oBD7lTuP<zp~~o_nWh9Ho?lw53!QHCri9c;46fzHgz92}a1hyO+M~FCixTh%$4< z0&85*FwfxGgY&-xtnEp&SAel}bRtEp2IE+yi+_>-8{R_#&yl6LkN6k5@)>&Y9uKXzcN-_3{}$x_^|9?qA`D|Btu7 SH&f4)K@Ma8t;TC|EAauuHXtnk literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons16/icon16_edge_touch.dat b/release/datafiles/blender_icons16/icon16_edge_touch.dat new file mode 100644 index 0000000000000000000000000000000000000000..d039492536123517c56554fe74b8a7df2f1945db GIT binary patch literal 1048 zcmWe&U|jAO_fcOK6`cd=%^|Rp8 z50t9~Vi<^psRIh&)B{rkqJirAVVZ$-0kRxa9}}!i*6Cl literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons16/icon16_face_default.dat b/release/datafiles/blender_icons16/icon16_face_default.dat new file mode 100644 index 0000000000000000000000000000000000000000..01012922c77a0f6a967b726d8f6dcbd972e975c5 GIT binary patch literal 1048 zcmcK1F-QVY9LMpeSztIEI0bE~2sX6ZqD?}yi3aJUU<3^{yPUNZ1P%#q(XL}44dLGG z5CpAJ3CU_#>tvKvvS5Q zR**x=^yXK3KUr!EY4^-5wfy&y`HZ=zw}HOrUcPSt^X^sZQ`7fb>DSSa9_tngZk?dM kN6ath-D5`1I5vCKNi3B0WSlepll7c&LjDd>v$xE3260(LkpKVy literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons16/icon16_face_enclose.dat b/release/datafiles/blender_icons16/icon16_face_enclose.dat new file mode 100644 index 0000000000000000000000000000000000000000..2158a9ad07b8c1a14a2ca485092d5b93f0a1bfa4 GIT binary patch literal 1048 zcmbu5OAf*?3`AW{(0gzo5DUZxA&_9tF8AgWo+DzpR@BlGX&NVNMNj9A<%^9&U#(<5!u{9a`KlT$Id&`*5_sBG+*34NwbJsq1N&NvlTW%Ks literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons16/icon16_face_touch.dat b/release/datafiles/blender_icons16/icon16_face_touch.dat new file mode 100644 index 0000000000000000000000000000000000000000..af000aea0a9a8c83dc8e7548df65e48563f612ff GIT binary patch literal 1048 zcmWe&U|p^A{YX&)bh&7v3b;P&@ zs74)#gJ5PO>w&U?6eJ9>@YR4~PeJlPoQ^IJGZPyPR14D!WP$M4%rz{k$~v;XeS9yVu;$w3)v8DsicVkx;YQ}1YPSi!Tb&DevE#xKNMXlZ_NU#g9$ zze%jQ_iNswKGfLzC08x6-+9z`>V>tvpZFbi@DEL$7w#X|zxX4NK0hE21rTimpKx=2 zG!Pu`tboT3Brnn-D@ku&@f)`2rSc1m7Z++a-_`sbdvER#F8_LY^QG zVrMP3S Id~z>% literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons32/icon32_edge_default.dat b/release/datafiles/blender_icons32/icon32_edge_default.dat new file mode 100644 index 0000000000000000000000000000000000000000..0cbc0105e7da9eed7679356b9a52e9a9b64765d1 GIT binary patch literal 4120 zcmeH~F-TTX6vtnd)uaTb7=dDwB}fGgl0tKVo0GVOfo*|H1m7YqE>Q&G)*R(f5RQou zZ3z<8+~lHY4r;!Be>s=VcfC&^@@nZ__-mm?y;+v^!az%wjlsJ!Y+AFd z(P-3E+=D#N&%+&I$5UII2;WVj zeguEb?wPSOZvbHo!?|}{oz0%Kq z)#t}P=gH-D2yVa&cxfzP{nGrsg7=^~)zaMF^L0}Gfim&owH!|+Bu9lbql3OikzZ6K z)}!l#n+43fI_iCUoL{tec};GS-p5JMOzQ7}=1y}dzr|~g^U){Qad|o?@v$Xq9*4{1 z#G2&g1Y=!lkL(iMhtAY_nHagrRVKFzP4aSrRn#t1qrN}gfik_TLX*Dzzxw`{6Fpd} QqPKO8`v1Lp2L8;zZ|f$-`~Uy| literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons32/icon32_edge_enclose.dat b/release/datafiles/blender_icons32/icon32_edge_enclose.dat new file mode 100644 index 0000000000000000000000000000000000000000..420e3d9806f7bc67db14ca7ef1540c811af61f7d GIT binary patch literal 4120 zcmeH@>j}d!5Q9x=_sCS8Cqs3DKITg87J>b7hC435(guPeS&t-3DP^hm_4K`O=SnW6 ztn2!}>p$3V@xS1BJL);VYj3Xq$ljSwUzYE&Q#+pO>F}O?H*db%93H*-tZx|YNVeCT z?JO(FMx7xZ!-zl5{{z``cKHt}w&Y|R~U(b7c{?BvX?|r}T6r(6ALT5gT z+MuhRP9cg)rP6<@um|OGxdC>-4R`_1;VNu}5w+ZB^jE-ZsANx>XdO%q#J9k*P=m1r z@EOd$)98i=@WTf2?_p*bpR`ZxGpBU|KU{J69Ncr`a>rquY0{nqXTa==&877S>@gAi zU6=s#ys=ZXRnKxb3+G`S)WKyiYfhWn)+4YPJ~^RR_`R+zw-Ba-|17lsi(wU*tv0^_Y4b&|G; zn+CgKDCm5rwMzsvCC%rrBTi@f5$L?@UNyol=&Zm=#_bO1{HyLdUo&Z&xT(+shhZ$- zhAtQur@{CrI1RFQur_X8k}+ca+zGpw z((h9P{n?;*vEE5TY<*f!Y{lHB#TtEUufs*C+P4+0-{uZ#xaMjYY2#V_K)IP)58BsR zzCL~J!=P(GL+=vZu>+6`ax7&`?-xDqmrx(f>ptFu3sCUqlD3J{JLLoPyDyCCx9i=y z1-`(qZ@+2N&%q&h3=KA())U(Xz4Cr6{Q?{V-L3XuPPz45o_S literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons32/icon32_face_enclose.dat b/release/datafiles/blender_icons32/icon32_face_enclose.dat new file mode 100644 index 0000000000000000000000000000000000000000..5e49bd8e9bbbaf9280f9bd533f0124fa2ca74054 GIT binary patch literal 4120 zcmd^>QBK1!42Gi#?y(afo_Lv%c;pEoF}TDo(L-?*P696=(8`yoMlQ3n%&qdUMY59G zvA;iVBXyZlT4HaDlwPpc3mz_0>bmait?&Bcv+xWy_Lg45!iH1W=rKHm_wWFAYGQ#8WQ=T>UG|T}z$PyX zv&{P*KW@y3D1)}pCLuacagY+_c|Ld*MUg_~c*T4k@NeZv_0U-)j#M8CKlFW$e*d+n zg#7;DHIv@I#F6TfPg@-x33P<+&`P+*wEv*B8jXDr74EB-oBJe+6X?K;n4i#^GvL_N z@4OCgm5ow0z8P?)_2-JxEny7{^ant3l_6mK*{F(J30rK?;Jvp&*5ZaB6KcsOfI)ZM8)Z)Yu0Em4iV> zgfwVDU(nzpI0-@@a{K)c=h64mbFq6s=)%wQywBJFdC$4;Jq{H`F$5=Ird1SA`!Nm{ zMZ4YJ7j!zEK9_JVHzvD*IBj=6iT*o5tOny-wBJhfFa3)BW1RB*{Go2I*QIz`Ke?|4 z^n0Si7W&~bOhfd2?DgE%53Lqlf=^)Ii7(h!p|LsWt^LlzXZQv8;T^n&NAMd~K=-6& z^LBfsrab>)zIuV}R~iptM0s4Fz=O&j#l8ocEqgzR<#Y)7=Yr)$aQ8dx&PQxp-~9N- z!0yK~_IZm{bK>%Ka(>dj!aR7o)(?NA@5D668(1=5PABK5_B-5k>s^~zR=?_bi<}QZ z4X)(=qjO1G6Z(;kJD+Peq3`yuv-h(;vrWP`_z0&{d%+()|5ToQqsA8q*Lh=^1qiXxAn2lg3gn)q(5a^*c0#yY^Evf1CY|k?d#O& zKO=n!)cZM1m~MC_b_V7_xo_bGbbJ0t_2*)#{j1kwI2r2Y*5vAbXjavBtFK(|{~p%* zt(SihEz3a|d`8*vr9@^wudLIy8>M9oU35SceU`4ae&0b8%{u=W>_)qtx7h zIXIHb3;j7A{N*Ri@AW#TV}7p5`(S>%hI5(UuDirZ@z1$(OQ-WEQSU?>sV~nzBIPxq M-)KD4`(M_70pw25v;Y7A literal 0 HcmV?d00001 diff --git a/release/datafiles/blender_icons32/icon32_object_touch.dat b/release/datafiles/blender_icons32/icon32_object_touch.dat new file mode 100644 index 0000000000000000000000000000000000000000..02be7426e6d45966e485a5bb836c629b6f0c807d GIT binary patch literal 4120 zcmeH|yDtP$6o-dJ;SmI#LR3N&3Y`)SiGm2lCL#*aX;hM3@dwb-DZCPu=(Hjlf&`^^ z$fBUI@m$|e+|BIlj4WnFu*sLX=bSm`cOQGtR9Kc(0neG1)d@>k7}=H;4u}6du~@7W z9^ovV`{AX7zYO%dNVC4H4!W*>zvtqm8$r%I!@hx+q=(kCcozX zvz8hNLV@$l@wwh}o1bBFAH-+&M?KQDPvWnJDY%Cxh(HJm!Jdzq*ypg#ycE+fp$}qv z#))aYbMOG`FbQ`Mf-BHGM#26|sIPq@sQYh7>I1geYoEZjuXhW(12UisqHi?|7!ScE zXdWX_0!j6qXXRy+tNok>v)(qw8RmV)aebSw2!9C7e)OBzN1xPa0-f*cdY$?Bll09y z#59j-I5EDDKFMtc>F2rS;`h|o`@{#})Gap^AG!bfKXCs!mrQ7fO;C?gFRF5$DL!A% zpLzl4hHcQDoPj=2Pmryg`>_c1;FtbBwW2Tq zm1cd;Co#>V1y(`xIE1g2_W8iEL1!#I@NbFmvh=dOLselect_through_box = true; ts->select_through_lasso = true; ts->select_through_circle = true; - ts->backface_select_mode = 1; + ts->object_cycle_touch = true; + ts->object_cycle_enclose = true; + ts->object_cycle_origin = true; + ts->face_cycle_default = true; + ts->face_cycle_touch = true; + ts->face_cycle_enclose = true; + ts->face_cycle_center = true; + ts->edge_cycle_default = true; + ts->edge_cycle_touch = true; + ts->edge_cycle_enclose = true; + ts->object_select_mode = 1; + ts->face_select_mode = 1; + ts->edge_select_mode = 1; + ts->backface_select_mode = 2; } void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) diff --git a/source/blender/editors/include/UI_icons.hh b/source/blender/editors/include/UI_icons.hh index 462dc25cf59..89552fe111d 100644 --- a/source/blender/editors/include/UI_icons.hh +++ b/source/blender/editors/include/UI_icons.hh @@ -430,8 +430,8 @@ DEF_ICON(IMAGE_REFERENCE) /* EMPTY */ DEF_ICON_BLANK(445) -DEF_ICON_BLANK(446) -DEF_ICON_BLANK(447) +DEF_ICON(OBJECT_ENCLOSE) +DEF_ICON(FACE_TOUCH) DEF_ICON(NODE_INSERT_ON) DEF_ICON(NODE_INSERT_OFF) DEF_ICON(NODE_TOP) @@ -442,12 +442,12 @@ DEF_ICON(ANCHOR_BOTTOM) DEF_ICON(ANCHOR_LEFT) DEF_ICON(ANCHOR_RIGHT) DEF_ICON(ANCHOR_CENTER) -DEF_ICON_BLANK(703) -DEF_ICON_BLANK(704) -DEF_ICON_BLANK(705) -DEF_ICON_BLANK(706) -DEF_ICON_BLANK(707) -DEF_ICON_BLANK(708) +DEF_ICON(EDGE_DEFAULT) +DEF_ICON(EDGE_ENCLOSE) +DEF_ICON(EDGE_TOUCH) +DEF_ICON(FACE_DEFAULT) +DEF_ICON(FACE_ENCLOSE) +DEF_ICON(OBJECT_TOUCH) DEF_ICON(AUTO_XRAY) DEF_ICON(SELECT_THROUGH) DEF_ICON(SELECT_SET) diff --git a/source/blender/editors/space_view3d/view3d_edit.cc b/source/blender/editors/space_view3d/view3d_edit.cc index 6dacf24879e..ab4155918cd 100644 --- a/source/blender/editors/space_view3d/view3d_edit.cc +++ b/source/blender/editors/space_view3d/view3d_edit.cc @@ -1488,3 +1488,185 @@ void VIEW3D_OT_toggle_facedots(wmOperatorType *ot) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cycle Object Mode + * \{ */ + +static int cycle_object_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + if (ts->object_select_mode == 2) { + if (ts->object_cycle_origin) { + ts->object_select_mode = 4; + } + else if (ts->object_cycle_touch) { + ts->object_select_mode = 1; + } + } + else if (ts->object_select_mode == 4) { + if (ts->object_cycle_touch) { + ts->object_select_mode = 1; + } + else if (ts->object_cycle_enclose) { + ts->object_select_mode = 2; + } + } + else { + if (ts->object_cycle_enclose) { + ts->object_select_mode = 2; + } + else if (ts->object_cycle_origin) { + ts->object_select_mode = 4; + } + else { + ts->object_select_mode = 1; + } + } + + ED_area_tag_redraw(area); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_cycle_object(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Object"; + ot->idname = "VIEW3D_OT_cycle_object"; + ot->description = "Change to the next object selection mode with box, lasso, and circle select"; + /* api callbacks */ + ot->exec = cycle_object_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cycle Face Mode + * \{ */ + +static int cycle_face_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + if (ts->face_select_mode == 2) { + if (ts->face_cycle_enclose) { + ts->face_select_mode = 4; + } + else if (ts->face_cycle_center) { + ts->face_select_mode = 8; + } + else if (ts->face_cycle_default) { + ts->face_select_mode = 1; + } + } + else if (ts->face_select_mode == 4) { + if (ts->face_cycle_center) { + ts->face_select_mode = 8; + } + else if (ts->face_cycle_default) { + ts->face_select_mode = 1; + } + else if (ts->face_cycle_touch) { + ts->face_select_mode = 2; + } + } + else if (ts->face_select_mode == 8) { + if (ts->face_cycle_default) { + ts->face_select_mode = 1; + } + else if (ts->face_cycle_touch) { + ts->face_select_mode = 2; + } + else if (ts->face_cycle_enclose) { + ts->face_select_mode = 4; + } + } + else { + if (ts->face_cycle_touch) { + ts->face_select_mode = 2; + } + else if (ts->face_cycle_enclose) { + ts->face_select_mode = 4; + } + else if (ts->face_cycle_center) { + ts->face_select_mode = 8; + } + else { + ts->face_select_mode = 1; + } + } + + ED_area_tag_redraw(area); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_cycle_face(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Face"; + ot->idname = "VIEW3D_OT_cycle_face"; + ot->description = "Change to the next face selection mode with box, lasso, and circle select"; + /* api callbacks */ + ot->exec = cycle_face_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cycle Edge Mode + * \{ */ + +static int cycle_edge_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + if (ts->edge_select_mode == 2) { + if (ts->edge_cycle_enclose) { + ts->edge_select_mode = 4; + } + else if (ts->edge_cycle_default) { + ts->edge_select_mode = 1; + } + } + else if (ts->edge_select_mode == 4) { + if (ts->edge_cycle_default) { + ts->edge_select_mode = 1; + } + else if (ts->edge_cycle_touch) { + ts->edge_select_mode = 2; + } + } + else { + if (ts->edge_cycle_touch) { + ts->edge_select_mode = 2; + } + else if (ts->edge_cycle_enclose) { + ts->edge_select_mode = 4; + } + else { + ts->edge_select_mode = 1; + } + } + + ED_area_tag_redraw(area); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_cycle_edge(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Edge"; + ot->idname = "VIEW3D_OT_cycle_edge"; + ot->description = "Change to the next edge selection mode with box, lasso, and circle select"; + /* api callbacks */ + ot->exec = cycle_edge_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 1c3a2b1b725..2440ee78929 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -64,6 +64,9 @@ void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot); void VIEW3D_OT_toggle_auto_xray(struct wmOperatorType *ot); void VIEW3D_OT_toggle_select_through(struct wmOperatorType *ot); void VIEW3D_OT_toggle_facedots(struct wmOperatorType *ot); +void VIEW3D_OT_cycle_object(struct wmOperatorType *ot); +void VIEW3D_OT_cycle_face(struct wmOperatorType *ot); +void VIEW3D_OT_cycle_edge(struct wmOperatorType *ot); /* `view3d_draw.cc` */ diff --git a/source/blender/editors/space_view3d/view3d_ops.cc b/source/blender/editors/space_view3d/view3d_ops.cc index c6017358431..a0fdc748789 100644 --- a/source/blender/editors/space_view3d/view3d_ops.cc +++ b/source/blender/editors/space_view3d/view3d_ops.cc @@ -226,6 +226,9 @@ void view3d_operatortypes() WM_operatortype_append(VIEW3D_OT_toggle_auto_xray); WM_operatortype_append(VIEW3D_OT_toggle_select_through); WM_operatortype_append(VIEW3D_OT_toggle_facedots); + WM_operatortype_append(VIEW3D_OT_cycle_object); + WM_operatortype_append(VIEW3D_OT_cycle_face); + WM_operatortype_append(VIEW3D_OT_cycle_edge); WM_operatortype_append(VIEW3D_OT_ruler_add); WM_operatortype_append(VIEW3D_OT_ruler_remove); diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 715b892687d..00a3d8cde2c 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -836,17 +836,109 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, return mesh_facing; } -bool edbm_check_mesh_facing(ToolSettings *ts, bool zbuf) +bool edbm_check_mesh_facing(ToolSettings *ts, wmOperator *op, const bool zbuf) { - const bool mode_match = zbuf ? ts->backface_select && (ts->backface_select_mode == 2 || - ts->backface_select_mode == 8) : - ts->backface_select && (ts->backface_select_mode == 4 || - ts->backface_select_mode == 8); + bool check_facing = false; - return mode_match; + if (ts->select_header) { + check_facing = zbuf ? ts->backface_select && + (ts->backface_select_mode == 2 || ts->backface_select_mode == 8) : + ts->backface_select && + (ts->backface_select_mode == 4 || ts->backface_select_mode == 8); + } + else { + const int mode = RNA_enum_get(op->ptr, "backface_filter"); + check_facing = zbuf ? mode == 2 || mode == 8 : mode == 4 || mode == 8; + } + + return check_facing; } -static void face_filter( +int object_style(ToolSettings *ts, wmOperator *op) +{ + int type = 0; + + if (ts->select_header) { + type = ts->object_select_mode; + } + else { + type = RNA_enum_get(op->ptr, "object_type"); + } + + if (type == 0) { + type = 1; + } + + return type; +} + +int face_style(ToolSettings *ts, wmOperator *op) +{ + int type = 0; + + if (ts->select_header) { + type = ts->face_select_mode; + } + else { + type = RNA_enum_get(op->ptr, "face_type"); + } + + if (type == 0) { + type = 1; + } + + return type; +} + +int edge_style(ToolSettings *ts, wmOperator *op) +{ + int type = 0; + + if (ts->select_header) { + type = ts->edge_select_mode; + } + else { + type = RNA_enum_get(op->ptr, "edge_type"); + } + + if (type == 0) { + type = 1; + } + + return type; +} + +bool drag_select_through(View3D *v3d, + ToolSettings *ts, + wmOperator *op, + const bool mesh, + const bool lasso, + const bool circle) +{ + if (XRAY_FLAG_ENABLED(v3d)) { + return true; + } + + bool select_through = false; + + if (ts->xray_header) { + if (ts->select_through && mesh && ts->select_through_edit || + ts->select_through && !mesh && ts->select_through_object) + { + select_through = lasso ? ts->select_through_lasso : + circle ? ts->select_through_circle : + ts->select_through_box; + } + } + else { + const int mode = RNA_enum_get(op->ptr, "select_through"); + select_through = mesh ? mode == 4 || mode == 8 : mode == 2 || mode == 8; + } + + return select_through; +} + +void face_filter( ViewContext *vc, void *box_data, void *lasso_data, void *circle_data, eSelectOp sel_op) { BMVert *eve; @@ -1231,6 +1323,7 @@ static bool edbm_backbuf_check_and_select_edges(void *userData, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, + wmOperator *op, const eSelectOp sel_op) { CircleSelectUserData *data = static_cast(userData); @@ -1239,7 +1332,7 @@ static bool edbm_backbuf_check_and_select_edges(void *userData, BMEdge *eed; BMIter iter; bool changed = false; - const bool check_mesh_facing = edbm_check_mesh_facing(ts, true); + const bool check_mesh_facing = edbm_check_mesh_facing(ts, op, true); const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); @@ -1311,6 +1404,7 @@ static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, + wmOperator *op, const eSelectOp sel_op, const rcti *rect, const int face_style, @@ -1323,7 +1417,7 @@ static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, BMVert *eve; rctf rectf; bool changed = false; - const bool check_mesh_facing = edbm_check_mesh_facing(ts, true); + const bool check_mesh_facing = edbm_check_mesh_facing(ts, op, true); const BLI_bitmap *select_bitmap = esel->select_bitmap; LassoSelectUserData *ldata = static_cast(lasso_data); CircleSelectUserData *cdata = static_cast(circle_data); @@ -1601,8 +1695,8 @@ static bool do_lasso_select_objects(ViewContext *vc, ToolSettings *ts = vc->scene->toolsettings; bool changed = false; float region_co[2]; - const int object_style = RNA_enum_get(op->ptr, "object_type"); - const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + const int object_type = object_style(ts, op); + const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -1617,7 +1711,7 @@ static bool do_lasso_select_objects(ViewContext *vc, bool is_inside = false; if (base->object->type == OB_MESH) { is_inside = object_filter( - vc, base, object_style, mcoords, mcoords_len, nullptr, nullptr, false); + vc, base, object_type, mcoords, mcoords_len, nullptr, nullptr, false); } else { is_inside = (ED_view3d_project_base(vc->region, base, region_co) == -V3D_PROJ_RET_OK) && @@ -1647,13 +1741,10 @@ static bool do_lasso_select_objects(ViewContext *vc, rcti rect; blender::Vector bases; BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - const bool select_through = XRAY_FLAG_ENABLED(v3d) || - (ts->select_through && ts->select_through_object && - ts->select_through_lasso); const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); - if (select_through) { + if (drag_select_through(v3d, ts, op, false, true, false)) { hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_PICK_ALL, select_filter); } else { @@ -1697,10 +1788,10 @@ static bool do_lasso_select_objects(ViewContext *vc, if (BASE_SELECTABLE(v3d, base)) { const bool is_select = base->flag & BASE_SELECTED; bool is_inside = false; - if (base->object->type == OB_MESH && (object_style == 1 || object_style == 2)) { + if (base->object->type == OB_MESH && (object_type == 1 || object_type == 2)) { is_inside = base->object->id.tag & LIB_TAG_DOIT && object_filter( - vc, base, object_style, mcoords, mcoords_len, nullptr, nullptr, false); + vc, base, object_type, mcoords, mcoords_len, nullptr, nullptr, false); } else { is_inside = base->object->id.tag & LIB_TAG_DOIT && @@ -2076,20 +2167,15 @@ static bool do_lasso_select_mesh(ViewContext *vc, LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; rcti rect; + const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, - vc, - &rect, - mcoords, - mcoords_len, - sel_op, - RNA_enum_get(op->ptr, "edge_type"), - RNA_enum_get(op->ptr, "face_type")); + view3d_userdata_lassoselect_init( + &data, vc, &rect, mcoords, mcoords_len, sel_op, mesh_type[0], mesh_type[1]); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -2103,9 +2189,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool select_through = ts->select_through && ts->select_through_edit && - ts->select_through_lasso; - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; + const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, true, false); EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); if (use_zbuf) { @@ -2127,7 +2211,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -2181,6 +2265,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, vc->depsgraph, vc->obedit, vc->em, + op, sel_op, &rect, data.face_style, @@ -5270,13 +5355,9 @@ static bool do_mesh_box_select(ViewContext *vc, { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; + const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; - view3d_userdata_boxselect_init(&data, - vc, - rect, - sel_op, - RNA_enum_get(op->ptr, "edge_type"), - RNA_enum_get(op->ptr, "face_type")); + view3d_userdata_boxselect_init(&data, vc, rect, sel_op, mesh_type[0], mesh_type[1]); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -5290,11 +5371,7 @@ static bool do_mesh_box_select(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool select_through = square ? ts->select_through && ts->select_through_edit && - ts->select_through_circle : - ts->select_through && ts->select_through_edit && - ts->select_through_box; - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; + const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, false, square); if (use_zbuf) { /* for near enclose face */ @@ -5319,7 +5396,7 @@ static bool do_mesh_box_select(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -5373,6 +5450,7 @@ static bool do_mesh_box_select(ViewContext *vc, vc->depsgraph, vc->obedit, vc->em, + op, sel_op, rect, data.face_style, @@ -5562,29 +5640,22 @@ static bool do_object_box_select(bContext *C, int hits = 0; bool changed = false; float region_co[2]; - const int object_style = RNA_enum_get(op->ptr, "object_type"); - const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + const int object_type = object_style(ts, op); + const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); - bool select_through; bool select; int select_flag; if (square) { - select_through = XRAY_FLAG_ENABLED(vc->v3d) || - ts->select_through && ts->select_through_object && ts->select_through_circle; select = (sel_op != SEL_OP_SUB); select_flag = select ? BASE_SELECTED : 0; } - else { - select_through = XRAY_FLAG_ENABLED(vc->v3d) || - ts->select_through && ts->select_through_object && ts->select_through_box; - } if (SEL_OP_USE_PRE_DESELECT(sel_op)) { changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } - if (select_through) { + if (drag_select_through(v3d, ts, op, false, false, square)) { hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter); } else { @@ -5627,10 +5698,10 @@ static bool do_object_box_select(bContext *C, if (square) { if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { const bool is_select = base->flag & BASE_SELECTED; - const bool is_inside = - base->object->type == OB_MESH ? - object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true) : - base->object->id.tag & LIB_TAG_DOIT; + const bool is_inside = base->object->type == OB_MESH ? + object_filter( + vc, base, object_type, nullptr, 0, rectf, nullptr, true) : + base->object->id.tag & LIB_TAG_DOIT; 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); @@ -5643,7 +5714,7 @@ static bool do_object_box_select(bContext *C, const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = base->object->type == OB_MESH ? - object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, false) : + object_filter(vc, base, object_type, nullptr, 0, rectf, nullptr, false) : base->object->id.tag & LIB_TAG_DOIT; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -5660,14 +5731,14 @@ static bool do_object_box_select(bContext *C, if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { const bool is_select = base->flag & BASE_SELECTED; bool is_inside = false; - if (base->object->type != OB_MESH || object_style < 2) { + if (base->object->type != OB_MESH || object_type < 2) { is_inside = base->object->id.tag & LIB_TAG_DOIT; } else { - if (object_style == 2 && base->object->id.tag & LIB_TAG_DOIT) { - is_inside = object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true); + if (object_type == 2 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = object_filter(vc, base, object_type, nullptr, 0, rectf, nullptr, true); } - else if (object_style == 4 && base->object->id.tag & LIB_TAG_DOIT) { + else if (object_type == 4 && base->object->id.tag & LIB_TAG_DOIT) { is_inside = (ED_view3d_project_base(vc->region, base, region_co) == V3D_PROJ_RET_OK) && BLI_rctf_isect_pt_v(rectf, region_co); @@ -5684,14 +5755,14 @@ static bool do_object_box_select(bContext *C, if (BASE_SELECTABLE(v3d, base)) { const bool is_select = base->flag & BASE_SELECTED; bool is_inside = false; - if (base->object->type != OB_MESH || object_style < 2) { + if (base->object->type != OB_MESH || object_type < 2) { is_inside = base->object->id.tag & LIB_TAG_DOIT; } else { - if (object_style == 2 && base->object->id.tag & LIB_TAG_DOIT) { - is_inside = object_filter(vc, base, object_style, nullptr, 0, rectf, nullptr, true); + if (object_type == 2 && base->object->id.tag & LIB_TAG_DOIT) { + is_inside = object_filter(vc, base, object_type, nullptr, 0, rectf, nullptr, true); } - else if (object_style == 4 && base->object->id.tag & LIB_TAG_DOIT) { + else if (object_type == 4 && base->object->id.tag & LIB_TAG_DOIT) { is_inside = (ED_view3d_project_base(vc->region, base, region_co) == V3D_PROJ_RET_OK) && BLI_rctf_isect_pt_v(rectf, region_co); @@ -6160,6 +6231,7 @@ static bool mesh_circle_select(ViewContext *vc, ToolSettings *ts = vc->scene->toolsettings; CircleSelectUserData data; vc->em = BKE_editmesh_from_object(vc->obedit); + const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -6175,17 +6247,9 @@ static bool mesh_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data, - vc, - select, - mval, - rad, - RNA_enum_get(op->ptr, "edge_type"), - RNA_enum_get(op->ptr, "face_type")); + view3d_userdata_circleselect_init(&data, vc, select, mval, rad, mesh_type[0], mesh_type[1]); - const bool select_through = ts->select_through && ts->select_through_edit && - ts->select_through_circle; - const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d) && !select_through; + const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, false, true); if (use_zbuf) { if (wm_userdata->data == nullptr) { @@ -6202,7 +6266,7 @@ static bool mesh_circle_select(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -6229,7 +6293,7 @@ static bool mesh_circle_select(ViewContext *vc, if (use_zbuf) { if (esel->select_bitmap != nullptr) { changed |= edbm_backbuf_check_and_select_edges( - &data, esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + &data, esel, vc->depsgraph, vc->obedit, vc->em, op, select ? SEL_OP_ADD : SEL_OP_SUB); } } else { @@ -6249,6 +6313,7 @@ static bool mesh_circle_select(ViewContext *vc, vc->depsgraph, vc->obedit, vc->em, + op, select ? SEL_OP_ADD : SEL_OP_SUB, nullptr, data.face_style, @@ -6937,8 +7002,8 @@ static bool object_circle_select( const int circle_data[3] = {mval[0], mval[1], int(rad)}; float mval_fl[2] = {float(mval[0]), float(mval[1])}; float radius_squared = rad * rad; - const int object_style = RNA_enum_get(op->ptr, "object_type"); - const bool wireless_touch = ts->wireless_touch_object && object_style == 1 && + const int object_type = object_style(ts, op); + const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); const bool select = (sel_op != SEL_OP_SUB); const int select_flag = select ? BASE_SELECTED : 0; @@ -6953,7 +7018,7 @@ static bool object_circle_select( LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) { if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { if (base->object->type == OB_MESH) { - if (object_filter(vc, base, object_style, nullptr, 0, nullptr, circle_data, false)) { + if (object_filter(vc, base, object_type, nullptr, 0, nullptr, circle_data, false)) { ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT); changed = true; } @@ -6976,9 +7041,6 @@ static bool object_circle_select( } else { GPUSelectBuffer buffer; - const bool select_through = XRAY_FLAG_ENABLED(v3d) || - (ts->select_through && ts->select_through_object && - ts->select_through_circle); BKE_object_update_select_id(CTX_data_main(vc->C)); int hits = 0; int point[4][2] = {}; @@ -7008,7 +7070,7 @@ static bool object_circle_select( const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(scene, vc->obact); - if (select_through) { + if (drag_select_through(v3d, ts, op, false, false, true)) { hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_ALL, select_filter); } else { @@ -7049,10 +7111,10 @@ static bool object_circle_select( if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { const bool is_select = base->flag & BASE_SELECTED; bool is_inside = false; - if (base->object->type == OB_MESH && (object_style == 1 || object_style == 2)) { + if (base->object->type == OB_MESH && (object_type == 1 || object_type == 2)) { is_inside = base->object->id.tag & LIB_TAG_DOIT ? object_filter( - vc, base, object_style, nullptr, 0, nullptr, circle_data, false) ? + vc, base, object_type, nullptr, 0, nullptr, circle_data, false) ? true : false : false; diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 89c2ed937ae..9ca8dd51ffb 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -421,7 +421,20 @@ .select_through_box = true, \ .select_through_lasso = true, \ .select_through_circle = true, \ - .backface_select_mode = 1, \ + .object_cycle_touch = true, \ + .object_cycle_enclose = true, \ + .object_cycle_origin = true, \ + .face_cycle_default = true, \ + .face_cycle_touch = true, \ + .face_cycle_enclose = true, \ + .face_cycle_center = true, \ + .edge_cycle_default = true, \ + .edge_cycle_touch = true, \ + .edge_cycle_enclose = true, \ + .object_select_mode = 1, \ + .face_select_mode = 1, \ + .edge_select_mode = 1, \ + .backface_select_mode = 2, \ } #define _DNA_DEFAULT_Sculpt \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index d01509eaf36..3ba9e7d6a55 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1600,10 +1600,9 @@ typedef struct ToolSettings { /** Stroke selection mode for Sculpt. */ char gpencil_selectmode_sculpt; - /* LCB Options */ - char backface_select; - char backface_select_mode; + /** LCB Options */ char xray_button; + char xray_header; char auto_xray; char auto_xray_button; char auto_xray_reset; @@ -1620,9 +1619,29 @@ typedef struct ToolSettings { char select_through_lasso; char select_through_circle; char wireless_touch_object; - char shrink_shading_header; char square_select; - char _pad0[1]; + char shrink_shading_header; + char select_header; + char object_select_mode; + char face_select_mode; + char edge_select_mode; + char backface_select; + char backface_select_mode; + char face_button; + char edge_button; + char backface_button; + char object_cycle_touch; + char object_cycle_enclose; + char object_cycle_origin; + char face_cycle_default; + char face_cycle_touch; + char face_cycle_enclose; + char face_cycle_center; + char edge_cycle_default; + char edge_cycle_touch; + char edge_cycle_enclose; + char blank_text; + char _pad0[6]; /** Grease Pencil Sculpt. */ struct GP_Sculpt_Settings gp_sculpt; diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index 33abb14a38c..2fb83eb2b9d 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3186,19 +3186,82 @@ static void rna_def_tool_settings(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem object_select_items[] = { + {OBJECT_TOUCH, + "TOUCH", + ICON_OBJECT_TOUCH, + "Touch", + "Select objects that are touched by the selection area"}, + {OBJECT_ENCLOSE, + "ENCLOSE", + ICON_OBJECT_ENCLOSE, + "Enclose", + "Select objects that are fully inside the selection area"}, + {OBJECT_ORIGIN, + "ORIGIN", + ICON_LIGHTPROBE_SPHERE, + "Origin", + "Select objects if their origin is touched by the selection area"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_items[] = { + {FACE_DEFAULT, + "DEFAULT", + ICON_FACE_DEFAULT, + "Default", + "Select faces that are touched by the selection area in Near Select. Select faces if their " + "center is touched by the selection area in X-Ray and Select Through"}, + {FACE_TOUCH, + "TOUCH", + ICON_FACE_TOUCH, + "Touch", + "Select faces that are touched by the selection area"}, + {FACE_ENCLOSE, + "ENCLOSE", + ICON_FACE_ENCLOSE, + "Enclose", + "Select faces that are fully inside the selection area"}, + {FACE_CENTER, + "CENTER", + ICON_LIGHTPROBE_PLANE, + "Center", + "Select faces if their center is touched by the selection area"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_items[] = { + {EDGE_DEFAULT, + "DEFAULT", + ICON_EDGE_DEFAULT, + "Default", + "Select edges that are fully inside the selection area. If no edges are fully inside, " + "select edges that are touched by the selection area"}, + {EDGE_TOUCH, + "TOUCH", + ICON_EDGE_TOUCH, + "Touch", + "Select edges that are touched by the selection area"}, + {EDGE_ENCLOSE, + "ENCLOSE", + ICON_EDGE_ENCLOSE, + "Enclose", + "Select edges that are fully inside the selection area"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + static const EnumPropertyItem backface_select_items[] = { {BACKFACE_NEAR, "NEAR", 0, "Fix Near", - "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " - "filtering"}, + "Ignore backfacing mesh when not using X-Ray or Select Through, verts won't be filtered"}, {BACKFACE_XRAY, "XRAY", 0, "Front X-Ray", "Ignore backfacing mesh in X-Ray and Select Through"}, - {BACKFACE_NONE, "NONE", 0, "Zero Backface", "Don't select backfacing mesh"}, + {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -3206,17 +3269,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); - /* Ignore Backface Select */ - prop = RNA_def_property(srna, "backface_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "backface_select", 0); - RNA_def_property_ui_text( - prop, "Backface Filter", "Select mesh based on the direction of their normals"); - - prop = RNA_def_property(srna, "backface_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "backface_select_mode"); - RNA_def_property_enum_items(prop, backface_select_items); - RNA_def_property_ui_text(prop, "Mode", "Backface Filter Method"); - prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Sculpt"); RNA_def_property_ui_text(prop, "Sculpt", ""); @@ -4091,14 +4143,131 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop, "Shrink Header", "Combine the four Shading Header buttons into one button that also toggles X-Ray"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + /* Blank Text, for ui formatting */ + prop = RNA_def_property(srna, "blank_text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "blank_text", 0); + RNA_def_property_ui_text(prop, "", ""); + + /* Drag Select Options */ + prop = RNA_def_property(srna, "select_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_header", 0); + RNA_def_property_ui_text( + prop, + "Selection Control", + "Use either the header or keymap to control additional selection options"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "object_select_mode"); + RNA_def_property_enum_items(prop, object_select_items); + RNA_def_property_ui_text(prop, "Object", "Object Select Style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "face_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "face_select_mode"); + RNA_def_property_enum_items(prop, face_select_items); + RNA_def_property_ui_text(prop, "Face", "Face Select Style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "edge_select_mode"); + RNA_def_property_enum_items(prop, edge_select_items); + RNA_def_property_ui_text(prop, "Edge", "Edge Select Style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "backface_select", 0); + RNA_def_property_ui_text( + prop, "Backface Filter", "Select mesh based on the direction of their normals"); + + prop = RNA_def_property(srna, "backface_select_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, nullptr, "backface_select_mode"); + RNA_def_property_enum_items(prop, backface_select_items); + RNA_def_property_ui_text(prop, "Mode", "Backface Filter Style"); + + prop = RNA_def_property(srna, "face_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_button", 0); + RNA_def_property_ui_text( + prop, "Face", "Show header button that cycles through face selection modes"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_button", 0); + RNA_def_property_ui_text( + prop, "Edge", "Show header button that cycles through edge selection modes"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_button", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "backface_button", 0); + RNA_def_property_ui_text( + prop, "Backface", "Show header button that toggles the backface filter"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "Object header button will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "Object header button will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_origin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_origin", 0); + RNA_def_property_ui_text( + prop, "Origin", "Object header button will include origin mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_default", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_default", 0); + RNA_def_property_ui_text( + prop, "Default", "Face header button will include default mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "Face header button will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "Face header button will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_center", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_center", 0); + RNA_def_property_ui_text( + prop, "Center", "Face header button will include center mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_default", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_default", 0); + RNA_def_property_ui_text( + prop, "Default", "Edge header button will include default mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "Edge header button will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "Edge header button will include enclose mode in its cycle"); + + /* X-Ray Options */ + prop = RNA_def_property(srna, "xray_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "xray_header", 0); + RNA_def_property_ui_text(prop, + "X-Ray Control", + "Use either the header or keymap to control additional X-Ray options"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - /* X-Ray header button */ prop = RNA_def_property(srna, "xray_button", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "xray_button", 0); RNA_def_property_ui_text(prop, "X-Ray", "Show button for X-Ray in viewport header"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - /* Auto X-Ray */ prop = RNA_def_property(srna, "auto_xray", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray", 0); RNA_def_property_ui_text(prop, "Enable", "Transparent scene display during drag select"); @@ -4140,7 +4309,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Circle", "Transparent scene display during circle select"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - /* Select Through */ prop = RNA_def_property(srna, "select_through", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "select_through", 0); RNA_def_property_ui_text( diff --git a/source/blender/python/intern/bpy_rna.cc b/source/blender/python/intern/bpy_rna.cc index b6c658a52b5..93d55c89697 100644 --- a/source/blender/python/intern/bpy_rna.cc +++ b/source/blender/python/intern/bpy_rna.cc @@ -1356,14 +1356,14 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) if (enum_item != rna_enum_dummy_NULL_items) { const char *ptr_name = RNA_struct_name_get_alloc(ptr, nullptr, 0, nullptr); - /* Prefer not to fail silently in case of API errors, maybe disable it later. */ + /* Prefer not to fail silently in case of API errors, maybe disable it later. CLOG_WARN(BPY_LOG_RNA, "current value '%d' " "matches no enum in '%s', '%s', '%s'", val, RNA_struct_identifier(ptr->type), ptr_name, - RNA_property_identifier(prop)); + RNA_property_identifier(prop));*/ #if 0 /* Gives Python decoding errors while generating docs :( */ char error_str[256]; diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.cc b/source/blender/windowmanager/intern/wm_gesture_ops.cc index 4a65579a6c3..a57ea112a11 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.cc +++ b/source/blender/windowmanager/intern/wm_gesture_ops.cc @@ -100,6 +100,41 @@ static void gesture_toggle_xray(bContext *C) ts->auto_xray_reset ^= true; } +static void gesture_auto_xray(bContext *C, + View3D *v3d, + ToolSettings *ts, + wmOperator *op, + const bool mesh, + const bool lasso, + const bool circle) +{ + if (!v3d || XRAY_FLAG_ENABLED(v3d)) { + return; + } + + bool auto_xray = false; + + if (ts->xray_header) { + if (ts->auto_xray && mesh && ts->auto_xray_edit || + ts->auto_xray && !mesh && ts->auto_xray_object) + { + auto_xray = lasso ? ts->auto_xray_lasso : circle ? ts->auto_xray_circle : ts->auto_xray_box; + } + } + else { + const int mode = RNA_enum_get(op->ptr, "auto_xray"); + auto_xray = mesh ? mode == 4 || mode == 8 : mode == 2 || mode == 8; + } + + if (ts->auto_xray_reset) { + ts->auto_xray_reset ^= true; + } + + if (auto_xray) { + gesture_toggle_xray(C); + } +} + static int UNUSED_FUNCTION(gesture_modal_state_from_operator)(wmOperator *op) { PropertyRNA *prop; @@ -185,19 +220,7 @@ int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) && RNA_boolean_get(op->ptr, "wait_for_input"); - const bool auto_xray = ts->auto_xray && ts->auto_xray_box ? - obedit ? ts->auto_xray_edit : ts->auto_xray_object : - false; - - if (ts->auto_xray_reset) { - ts->auto_xray_reset ^= true; - } - - if (v3d && auto_xray) { - if (!XRAY_FLAG_ENABLED(v3d)) { - gesture_toggle_xray(C); - } - } + gesture_auto_xray(C, v3d, ts, op, obedit, false, false); if (wait_for_input) { op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT); @@ -336,19 +359,7 @@ int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) Object *obedit = CTX_data_edit_object(C); ToolSettings *ts = static_cast(win->scene->toolsettings); - const bool auto_xray = ts->auto_xray && ts->auto_xray_circle ? - obedit ? ts->auto_xray_edit : ts->auto_xray_object : - false; - - if (ts->auto_xray_reset) { - ts->auto_xray_reset ^= true; - } - - if (v3d && auto_xray) { - if (!XRAY_FLAG_ENABLED(v3d)) { - gesture_toggle_xray(C); - } - } + gesture_auto_xray(C, v3d, ts, op, obedit, false, true); if (ts->square_select) { op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_SQUARE); @@ -555,19 +566,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) Object *obedit = CTX_data_edit_object(C); ToolSettings *ts = static_cast(win->scene->toolsettings); - const bool auto_xray = ts->auto_xray && ts->auto_xray_lasso ? - obedit ? ts->auto_xray_edit : ts->auto_xray_object : - false; - - if (ts->auto_xray_reset) { - ts->auto_xray_reset ^= true; - } - - if (v3d && auto_xray) { - if (!XRAY_FLAG_ENABLED(v3d)) { - gesture_toggle_xray(C); - } - } + gesture_auto_xray(C, v3d, ts, op, obedit, true, false); op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_LASSO); diff --git a/source/blender/windowmanager/intern/wm_operator_props.cc b/source/blender/windowmanager/intern/wm_operator_props.cc index c122282f1f8..40a4baa3441 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.cc +++ b/source/blender/windowmanager/intern/wm_operator_props.cc @@ -416,6 +416,22 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo { PropertyRNA *prop; + static const EnumPropertyItem auto_xray_items[] = { + {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_items[] = { + {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + static const EnumPropertyItem object_select_items[] = { {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, {OBJECT_ENCLOSE, @@ -436,8 +452,8 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo "FACE_DEFAULT", 0, "Default", - "Select faces that are touched by the box in near select. Select faces if their center is " - "touched by the box in X-Ray select"}, + "Select faces that are touched by the box in Near Select. Select faces if their center is " + "touched by the box in X-Ray and Select Through"}, {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the box"}, {FACE_CENTER, @@ -460,14 +476,37 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem backface_filter_items[] = { + {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {BACKFACE_NEAR, + "NEAR", + 0, + "Fix Near", + "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " + "filtering"}, + {BACKFACE_XRAY, + "XRAY", + 0, + "Front X-Ray", + "Ignore backfacing mesh in X-Ray and Select Through"}, + {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + WM_operator_properties_border(ot); + prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); if (deselect) { prop = RNA_def_boolean( @@ -572,6 +611,22 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +static const EnumPropertyItem auto_xray_items[] = { + {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, +}; + +static const EnumPropertyItem select_through_items[] = { + {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, +}; + void WM_operator_properties_gesture_lasso(wmOperatorType *ot) { PropertyRNA *prop; @@ -595,8 +650,8 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) "FACE_DEFAULT", 0, "Default", - "Select faces that are touched by the lasso in near select. Select faces if their center " - "is touched by the lasso in X-Ray select"}, + "Select faces that are touched by the lasso in Near Select. Select faces if their center " + "is touched by the lasso in X-Ray and Select Through"}, {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the lasso"}, {FACE_CENTER, @@ -619,14 +674,37 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem backface_filter_items[] = { + {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {BACKFACE_NEAR, + "NEAR", + 0, + "Fix Near", + "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " + "filtering"}, + {BACKFACE_XRAY, + "XRAY", + 0, + "Front X-Ray", + "Ignore backfacing mesh in X-Ray and Select Through"}, + {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + WM_operator_properties_border(ot); + prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } @@ -665,6 +743,22 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) PropertyRNA *prop; const int radius_default = 25; + static const EnumPropertyItem auto_xray_items[] = { + {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_items[] = { + {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + static const EnumPropertyItem object_select_items[] = { {OBJECT_ORIGIN, "OBJECT_ORIGIN", @@ -685,8 +779,8 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) "FACE_DEFAULT", 0, "Default", - "Select faces that are touched by the circle in near select. Select faces if their center " - "is touched by the circle in X-Ray select"}, + "Select faces that are touched by the circle in Near Select. Select faces if their center " + "is touched by the circle in X-Ray and Select Through"}, {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"}, {FACE_ENCLOSE, "FACE_ENCLOSE", @@ -711,6 +805,23 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) {0, nullptr, 0, nullptr, nullptr}, }; + static const EnumPropertyItem backface_filter_items[] = { + {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {BACKFACE_NEAR, + "NEAR", + 0, + "Fix Near", + "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " + "filtering"}, + {BACKFACE_XRAY, + "XRAY", + 0, + "Front X-Ray", + "Ignore backfacing mesh in X-Ray and Select Through"}, + {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + prop = RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX); @@ -720,12 +831,18 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_mouse_select(wmOperatorType *ot) -- 2.30.2 From 258872db17b27b6ba1bafe627ab4789906435b0b Mon Sep 17 00:00:00 2001 From: bla BLA Date: Tue, 14 May 2024 23:42:55 -0700 Subject: [PATCH 5/6] Switch to userprefs so they don't change with workspace, qol features, bugfixes --- scripts/modules/rna_keymap_ui.py | 4 +- scripts/startup/bl_operators/userpref.py | 181 ++ scripts/startup/bl_operators/wm.py | 7 + .../startup/bl_ui/space_toolsystem_toolbar.py | 18 +- scripts/startup/bl_ui/space_userpref.py | 603 +++- scripts/startup/bl_ui/space_view3d.py | 833 +++-- .../blenloader/intern/versioning_defaults.cc | 27 - .../blenloader/intern/versioning_userdef.cc | 7 +- .../editors/gpencil_legacy/gpencil_select.cc | 2 +- source/blender/editors/interface/resources.cc | 2 +- .../blender/editors/mesh/editmesh_select.cc | 20 +- .../blender/editors/space_node/node_select.cc | 3 +- .../editors/space_view3d/view3d_edit.cc | 2680 +++++++++++++++-- .../editors/space_view3d/view3d_intern.h | 2 + .../editors/space_view3d/view3d_ops.cc | 2 + .../editors/space_view3d/view3d_select.cc | 375 ++- source/blender/editors/util/ed_transverts.cc | 7 + .../blender/editors/uvedit/uvedit_select.cc | 2 +- source/blender/makesdna/DNA_scene_defaults.h | 27 - source/blender/makesdna/DNA_scene_types.h | 88 +- source/blender/makesdna/DNA_userdef_types.h | 322 +- source/blender/makesrna/intern/rna_scene.cc | 308 -- source/blender/makesrna/intern/rna_userdef.cc | 1679 +++++++++-- source/blender/windowmanager/WM_api.hh | 2 +- .../windowmanager/intern/wm_cursors.cc | 308 +- .../windowmanager/intern/wm_event_query.cc | 61 +- .../windowmanager/intern/wm_event_system.cc | 2 +- .../windowmanager/intern/wm_gesture_ops.cc | 115 +- .../windowmanager/intern/wm_operator_props.cc | 262 +- 29 files changed, 6164 insertions(+), 1785 deletions(-) diff --git a/scripts/modules/rna_keymap_ui.py b/scripts/modules/rna_keymap_ui.py index 70cb8a3c343..a1154dfb331 100644 --- a/scripts/modules/rna_keymap_ui.py +++ b/scripts/modules/rna_keymap_ui.py @@ -182,7 +182,7 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level): if map_type in {'KEYBOARD', 'MOUSE'} and kmi.value == 'CLICK_DRAG': subrow = sub.row() - if bpy.context.preferences.inputs.click_drag_direction == 'LEFT_RIGHT': + if bpy.context.preferences.inputs.keymap_direction == 'LEFT_RIGHT': if kmi.direction == 'ANY' or kmi.direction == 'EAST' or kmi.direction == 'WEST': subrow.label(text="Direction:") else: @@ -190,7 +190,7 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level): subrow.operator("preferences.set_direction_any", text="Any", depress= kmi.direction == 'ANY').item_id = kmi.id subrow.operator("preferences.set_direction_left", text="Left", depress= kmi.direction == 'WEST').item_id = kmi.id subrow.operator("preferences.set_direction_right", text="Right", depress= kmi.direction == 'EAST').item_id = kmi.id - elif bpy.context.preferences.inputs.click_drag_direction == 'UP_DOWN': + elif bpy.context.preferences.inputs.keymap_direction == 'UP_DOWN': if kmi.direction == 'ANY' or kmi.direction == 'NORTH' or kmi.direction == 'SOUTH': subrow.label(text="Direction:") else: diff --git a/scripts/startup/bl_operators/userpref.py b/scripts/startup/bl_operators/userpref.py index 615bb3d4fea..8e9c25a1ce9 100644 --- a/scripts/startup/bl_operators/userpref.py +++ b/scripts/startup/bl_operators/userpref.py @@ -405,6 +405,185 @@ class PREFERENCES_OT_keyitem_remove(Operator): return {'FINISHED'} +class PREFERENCES_OT_quick_assign(Operator): + """Assign values to the new drag select settings""" + bl_idname = "preferences.quick_assign" + bl_label = "Quick Assign" + + def execute(self, context): + inputs = context.preferences.inputs + + if inputs.quick_assign_mode == 'BETTER': + inputs.drag_control_mode = 'USERPREF' + inputs.userpref_mode = 'EASY' + inputs.object_select_box = 'OBJECT_TOUCH' + inputs.face_select_box = 'FACE_TOUCH' + inputs.edge_select_box = 'EDGE_TOUCH' + inputs.backface_box = 'NEAR' + inputs.auto_xray_box = 'AUTO_XRAY_DISABLE' + inputs.select_through_box = 'SELECT_THROUGH_OBJECT' + inputs.xray_button = 'HIDE' + inputs.object_header = True + inputs.face_header = True + inputs.edge_header = True + inputs.backface_header = True + inputs.auto_xray_header = False + inputs.select_through_header = True + inputs.wireless_touch_object = True + inputs.object_cycle_touch = True + inputs.object_cycle_enclose = True + inputs.object_cycle_origin = False + inputs.face_cycle_default = False + inputs.face_cycle_touch = True + inputs.face_cycle_enclose = True + inputs.face_cycle_center = False + inputs.edge_cycle_default = False + inputs.edge_cycle_touch = True + inputs.edge_cycle_enclose = True + inputs.backface_toggle = 'NEAR' + inputs.select_through_toggle = 'CURRENT' + inputs.object_pie = 'SHOW' + inputs.face_pie = 'SHOW' + inputs.edge_pie = 'SHOW' + inputs.backface_pie = 'SHOW' + inputs.auto_xray_pie = 'HIDE' + inputs.select_through_pie = 'SHOW' + inputs.box_pie = 'CONTEXT' + inputs.circle_pie = 'CONTEXT' + inputs.lasso_pie = 'CONTEXT' + elif inputs.quick_assign_mode == 'AUTO_XRAY': + inputs.drag_control_mode = 'USERPREF' + inputs.userpref_mode = 'EASY' + inputs.object_select_box = 'OBJECT_TOUCH' + inputs.face_select_box = 'FACE_TOUCH' + inputs.edge_select_box = 'EDGE_TOUCH' + inputs.backface_box = 'DEFAULT' + inputs.auto_xray_box = 'AUTO_XRAY_BOTH' + inputs.select_through_box = 'SELECT_THROUGH_OBJECT' + inputs.xray_button = 'SHOW' + inputs.object_header = True + inputs.face_header = True + inputs.edge_header = True + inputs.backface_header = True + inputs.auto_xray_header = True + inputs.select_through_header = False + inputs.object_cycle_touch = True + inputs.object_cycle_enclose = True + inputs.object_cycle_origin = False + inputs.face_cycle_default = False + inputs.face_cycle_touch = True + inputs.face_cycle_enclose = True + inputs.face_cycle_center = False + inputs.edge_cycle_default = False + inputs.edge_cycle_touch = True + inputs.edge_cycle_enclose = True + inputs.auto_xray_toggle = 'BOTH' + inputs.backface_toggle = 'NONE' + inputs.object_pie = 'SHOW' + inputs.face_pie = 'SHOW' + inputs.edge_pie = 'SHOW' + inputs.backface_pie = 'SHOW' + inputs.auto_xray_pie = 'SHOW' + inputs.select_through_pie = 'HIDE' + inputs.box_pie = 'SHOW' + inputs.circle_pie = 'SHOW' + inputs.lasso_pie = 'SHOW' + elif inputs.quick_assign_mode == 'DIRECTIONAL': + inputs.drag_control_mode = 'USERPREF' + inputs.userpref_mode = 'SPLIT' + inputs.drag_direction_box = 'LEFT_RIGHT' + inputs.drag_direction_lasso = 'ANY' + inputs.drag_direction_mode = 'SELECTIVE' + inputs.direction_object = True + inputs.direction_face = True + inputs.direction_edge = True + inputs.direction_backface = False + inputs.direction_auto_xray = False + inputs.direction_select_through = False + inputs.object_select_box = 'OBJECT_TOUCH' + inputs.object_select_downright_box = 'OBJECT_ENCLOSE' + inputs.face_select_box = 'FACE_TOUCH' + inputs.face_select_downright_box = 'FACE_ENCLOSE' + inputs.edge_select_box = 'EDGE_TOUCH' + inputs.edge_select_downright_box = 'EDGE_ENCLOSE' + inputs.backface_box = 'DEFAULT' + inputs.auto_xray_box = 'AUTO_XRAY_DISABLE' + inputs.select_through_box = 'SELECT_THROUGH_OBJECT' + inputs.object_select_circle = 'OBJECT_TOUCH' + inputs.face_select_circle = 'FACE_TOUCH' + inputs.edge_select_circle = 'EDGE_TOUCH' + inputs.backface_circle = 'DEFAULT' + inputs.auto_xray_circle = 'AUTO_XRAY_DISABLE' + inputs.select_through_circle = 'SELECT_THROUGH_OBJECT' + inputs.object_select_lasso = 'OBJECT_TOUCH' + inputs.face_select_lasso = 'FACE_TOUCH' + inputs.edge_select_lasso = 'EDGE_TOUCH' + inputs.backface_lasso = 'DEFAULT' + inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE' + inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT' + inputs.xray_button = 'SHOW' + inputs.object_header = False + inputs.face_header = False + inputs.edge_header = False + inputs.backface_header = False + inputs.auto_xray_header = False + inputs.select_through_header = False + inputs.object_pie = 'HIDE' + inputs.face_pie = 'HIDE' + inputs.edge_pie = 'HIDE' + else: + inputs.drag_control_mode = 'USERPREF' + inputs.userpref_mode = 'SPLIT' + inputs.drag_direction_box = 'ANY' + inputs.drag_direction_lasso = 'ANY' + inputs.object_select_box = 'OBJECT_TOUCH' + inputs.face_select_box = 'FACE_DEFAULT' + inputs.edge_select_box = 'EDGE_DEFAULT' + inputs.backface_box = 'DEFAULT' + inputs.auto_xray_box = 'AUTO_XRAY_DISABLE' + inputs.select_through_box = 'SELECT_THROUGH_OBJECT' + inputs.object_select_circle = 'OBJECT_ORIGIN' + inputs.face_select_circle = 'FACE_DEFAULT' + inputs.edge_select_circle = 'EDGE_TOUCH' + inputs.backface_circle = 'DEFAULT' + inputs.auto_xray_circle = 'AUTO_XRAY_DISABLE' + inputs.select_through_circle = 'SELECT_THROUGH_OBJECT' + inputs.object_select_lasso = 'OBJECT_ORIGIN' + inputs.face_select_lasso = 'FACE_DEFAULT' + inputs.edge_select_lasso = 'EDGE_DEFAULT' + inputs.backface_lasso = 'DEFAULT' + inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE' + inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT' + inputs.xray_button = 'SHOW' + inputs.object_header = False + inputs.face_header = False + inputs.edge_header = False + inputs.backface_header = False + inputs.auto_xray_header = False + inputs.select_through_header = False + inputs.wireless_touch_object = False + inputs.square_select = False + return {'FINISHED'} + + +class PREFERENCES_OT_reset_cursors(Operator): + """Reset mouse cursors""" + bl_idname = "preferences.reset_cursors" + bl_label = "Reset Cursors" + + def execute(self, context): + inputs = context.preferences.inputs + inputs.system_cursor = 'SYSTEM' + inputs.edit_cursor = 'CROSS' + inputs.paint_cursor = 'CROSS_DOT' + inputs.dot_cursor = 'DOT' + inputs.knife_cursor = 'KNIFE' + inputs.eyedropper_cursor = 'EYEDROPPER' + inputs.eraser_cursor = 'ERASER' + inputs.pencil_cursor = 'PENCIL' + return {'FINISHED'} + + class PREFERENCES_OT_set_direction_any(Operator): """Drag in any direction""" bl_idname = "preferences.set_direction_any" @@ -1331,6 +1510,8 @@ classes = ( PREFERENCES_OT_keyconfig_test, PREFERENCES_OT_keyitem_add, PREFERENCES_OT_keyitem_remove, + PREFERENCES_OT_quick_assign, + PREFERENCES_OT_reset_cursors, PREFERENCES_OT_set_direction_any, PREFERENCES_OT_set_direction_left, PREFERENCES_OT_set_direction_right, diff --git a/scripts/startup/bl_operators/wm.py b/scripts/startup/bl_operators/wm.py index 42d5fa6c726..c14bfe93101 100644 --- a/scripts/startup/bl_operators/wm.py +++ b/scripts/startup/bl_operators/wm.py @@ -2312,6 +2312,13 @@ class WM_OT_tool_set_by_id(Operator): space_type = context.space_data.type fn = activate_by_id_or_cycle if self.cycle else activate_by_id + + for area in context.window.screen.areas: + if area.type == 'VIEW_3D': + for region in area.regions: + if region.type == 'HEADER': + region.tag_redraw() + if fn(context, space_type, self.name, as_fallback=self.as_fallback): if self.as_fallback: tool_settings = context.tool_settings diff --git a/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/scripts/startup/bl_ui/space_toolsystem_toolbar.py index dee4b12dde8..f60ba57a87a 100644 --- a/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -427,8 +427,8 @@ class _defs_view3d_select: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) if _context.mode == 'OBJECT': - tool_settings = _context.tool_settings - layout.prop(tool_settings, "wireless_touch_object") + inputs = _context.preferences.inputs + layout.prop(inputs, "wireless_touch_object") return dict( idname="builtin.select_box", label="Select Box", @@ -446,8 +446,8 @@ class _defs_view3d_select: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) if _context.mode == 'OBJECT': - tool_settings = _context.tool_settings - layout.prop(tool_settings, "wireless_touch_object") + inputs = _context.preferences.inputs + layout.prop(inputs, "wireless_touch_object") return dict( idname="builtin.select_lasso", label="Select Lasso", @@ -465,10 +465,10 @@ class _defs_view3d_select: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) layout.prop(props, "radius") - tool_settings = _context.tool_settings - layout.prop(tool_settings, "square_select") + inputs = _context.preferences.inputs if _context.mode == 'OBJECT': - layout.prop(tool_settings, "wireless_touch_object") + layout.prop(inputs, "wireless_touch_object") + layout.prop(inputs, "square_select") def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d @@ -2282,10 +2282,10 @@ class _defs_gpencil_edit: row.use_property_split = False row.prop(props, "mode", text="", expand=True, icon_only=True) layout.prop(props, "radius") - tool_settings = context.tool_settings - layout.prop(tool_settings, "square_select") if _defs_gpencil_edit.is_segment(context): layout.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold") + inputs = context.preferences.inputs + layout.prop(inputs, "square_select") def draw_cursor(_context, tool, xy): from gpu_extras.presets import draw_circle_2d diff --git a/scripts/startup/bl_ui/space_userpref.py b/scripts/startup/bl_ui/space_userpref.py index ba920addc98..0ebf92e346a 100644 --- a/scripts/startup/bl_ui/space_userpref.py +++ b/scripts/startup/bl_ui/space_userpref.py @@ -189,6 +189,587 @@ class CenterAlignMixIn: row.label() # Needed so col above is centered. +# ----------------------------------------------------------------------------- +# Custom Panels + +class CustomPanel: + bl_space_type = 'PREFERENCES' + bl_region_type = 'WINDOW' + bl_context = "custom" + + +class USERPREF_PT_custom_drag_select(CustomPanel, CenterAlignMixIn, Panel): + bl_label = "Drag Select" + + def draw_centered(self, context, layout): + inputs = context.preferences.inputs + + row = layout.row(align=True) + row.prop(inputs, "keymap_direction", expand=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "drag_control_mode", expand=True) + + if inputs.drag_control_mode == 'USERPREF': + tool_settings = context.tool_settings + row = layout.row(align=True) + row.prop(inputs, "userpref_mode", expand=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "quick_assign", text="Quick Assign", emboss=False) + if inputs.quick_assign: + sub = row.row(align=True) + sub.prop(inputs, "quick_assign", icon='DOWNARROW_HLT', emboss=False) + sub = layout.row(align=True) + sub.prop(inputs, "quick_assign_mode") + sub.operator("preferences.quick_assign") + else: + row.prop(inputs, "quick_assign", icon='RIGHTARROW', emboss=False) + + if inputs.userpref_mode == 'SPLIT': + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "direction_controls", text="Drag Direction", emboss=False) + + if inputs.direction_controls: + row.prop(inputs, "direction_controls", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "drag_direction_box", expand=True) + row = layout.row(align=True) + row.prop(inputs, "drag_direction_lasso", expand=True) + row = layout.row(align=True) + sub = row.row(align=True) + sub.enabled = inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY' + sub.prop(inputs, "drag_direction_mode", expand=True) + row = layout.row(align=True) + sub = row.row(align=True) + sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY') + sub.prop(inputs, "direction_object", toggle=True) + sub.prop(inputs, "direction_backface", toggle=True) + row = layout.row(align=True) + sub = row.row(align=True) + sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY') + sub.prop(inputs, "direction_face", toggle=True) + sub.prop(inputs, "direction_auto_xray", toggle=True) + row = layout.row(align=True) + sub = row.row(align=True) + sub.enabled = inputs.drag_direction_mode == 'SELECTIVE' and (inputs.drag_direction_box !='ANY' or inputs.drag_direction_lasso !='ANY') + sub.prop(inputs, "direction_edge", toggle=True) + sub.prop(inputs, "direction_select_through", toggle=True) + else: + row.prop(inputs, "direction_controls", icon='RIGHTARROW', emboss=False) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "box_controls", text="Box", emboss=False) + + if inputs.box_controls: + row.prop(inputs, "box_controls", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "box_controls", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + + if inputs.drag_direction_box == 'LEFT_RIGHT': + row.prop(inputs, "blank_text", text="Left", emboss=False) + row.prop(inputs, "blank_text", text="Right", emboss=False) + elif inputs.drag_direction_box == 'UP_DOWN': + row.prop(inputs, "blank_text", text="Up", emboss=False) + row.prop(inputs, "blank_text", text="Down", emboss=False) + row = layout.row(align=True) + row.prop(inputs, "object_select_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object): + row.prop(inputs, "object_select_downright_box", text="") + row = layout.row(align=True) + row.prop(inputs, "face_select_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face): + row.prop(inputs, "face_select_downright_box", text="") + row = layout.row(align=True) + row.prop(inputs, "edge_select_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge): + row.prop(inputs, "edge_select_downright_box", text="") + row = layout.row(align=True) + row.prop(inputs, "backface_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface): + row.prop(inputs, "backface_downright_box", text="") + row = layout.row(align=True) + row.prop(inputs, "auto_xray_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray): + row.prop(inputs, "auto_xray_downright_box", text="") + row = layout.row(align=True) + row.prop(inputs, "select_through_box") + if inputs.drag_direction_box != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through): + row.prop(inputs, "select_through_downright_box", text="") + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "circle_controls", text="Circle", emboss=False) + + if inputs.circle_controls: + row.prop(inputs, "circle_controls", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "circle_controls", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "object_select_circle") + row = layout.row(align=True) + row.prop(inputs, "face_select_circle") + row = layout.row(align=True) + row.prop(inputs, "edge_select_circle") + row = layout.row(align=True) + row.prop(inputs, "backface_circle") + row = layout.row(align=True) + row.prop(inputs, "auto_xray_circle") + row = layout.row(align=True) + row.prop(inputs, "select_through_circle") + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "lasso_controls", text="Lasso", emboss=False) + if inputs.lasso_controls: + row.prop(inputs, "lasso_controls", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "lasso_controls", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + + if inputs.drag_direction_lasso == 'LEFT_RIGHT': + row.prop(inputs, "blank_text", text="Left", emboss=False) + row.prop(inputs, "blank_text", text="Right", emboss=False) + elif inputs.drag_direction_lasso == 'UP_DOWN': + row.prop(inputs, "blank_text", text="Up", emboss=False) + row.prop(inputs, "blank_text", text="Down", emboss=False) + row = layout.row(align=True) + row.prop(inputs, "object_select_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object): + row.prop(inputs, "object_select_downright_lasso", text="") + row = layout.row(align=True) + row.prop(inputs, "face_select_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face): + row.prop(inputs, "face_select_downright_lasso", text="") + row = layout.row(align=True) + row.prop(inputs, "edge_select_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge): + row.prop(inputs, "edge_select_downright_lasso", text="") + row = layout.row(align=True) + row.prop(inputs, "backface_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface): + row.prop(inputs, "backface_downright_lasso", text="") + row = layout.row(align=True) + row.prop(inputs, "auto_xray_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray): + row.prop(inputs, "auto_xray_downright_lasso", text="") + row = layout.row(align=True) + row.prop(inputs, "select_through_lasso") + if inputs.drag_direction_lasso != 'ANY' and (inputs.drag_direction_mode == 'EVERYTHING' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through): + row.prop(inputs, "select_through_downright_lasso", text="") + else: + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "object_select_box") + row = layout.row(align=True) + row.prop(inputs, "face_select_box") + row = layout.row(align=True) + row.prop(inputs, "edge_select_box") + row = layout.row(align=True) + row.prop(inputs, "backface_box") + row = layout.row(align=True) + row.prop(inputs, "auto_xray_box") + row = layout.row(align=True) + row.prop(inputs, "select_through_box") + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "operator_controls", text="Operator Controls", emboss=False) + if inputs.operator_controls: + row.prop(inputs, "operator_controls", icon='DOWNARROW_HLT', emboss=False) + if inputs.userpref_mode == 'SPLIT': + row = layout.row(align=True, heading="Synchronize") + row.prop(inputs, "sync_box", toggle=True) + row.prop(inputs, "sync_circle", toggle=True) + row.prop(inputs, "sync_lasso", toggle=True) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "object_operator", text="Object Operator", emboss=False) + if inputs.object_operator: + row.prop(inputs, "object_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "object_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "object_header", toggle=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_object) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_object) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + row = layout.row(align=True, heading="Cycle") + elif box_circle: + row = layout.row(align=True, heading="Cycle Box & Circle") + elif box_lasso: + row = layout.row(align=True, heading="Cycle Box & Lasso") + else: + row = layout.row(align=True, heading="Cycle Box") + row.enabled = box_op + row.prop(inputs, "object_cycle_touch", toggle=True) + row.prop(inputs, "object_cycle_enclose", toggle=True) + row.prop(inputs, "object_cycle_origin", toggle=True) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True, heading="Cycle Circle") + row.prop(inputs, "object_cycle_touch_circle", toggle=True) + row.prop(inputs, "object_cycle_enclose_circle", toggle=True) + row.prop(inputs, "object_cycle_origin_circle", toggle=True) + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True, heading="Cycle Lasso & Circle") + else: + row = layout.row(align=True, heading="Cycle Lasso") + row.enabled = lasso_op + row.prop(inputs, "object_cycle_touch_lasso", toggle=True) + row.prop(inputs, "object_cycle_enclose_lasso", toggle=True) + row.prop(inputs, "object_cycle_origin_lasso", toggle=True) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "face_operator", text="Face Operator", emboss=False) + if inputs.face_operator: + row.prop(inputs, "face_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "face_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "face_header", toggle=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_face) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_face) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + row = layout.row(align=True, heading="Cycle") + elif box_circle: + row = layout.row(align=True, heading="Cycle Box & Circle") + elif box_lasso: + row = layout.row(align=True, heading="Cycle Box & Lasso") + else: + row = layout.row(align=True, heading="Cycle Box") + row.enabled = box_op + row.prop(inputs, "face_cycle_default", toggle=True) + row.prop(inputs, "face_cycle_touch", toggle=True) + row.prop(inputs, "face_cycle_enclose", toggle=True) + row.prop(inputs, "face_cycle_center", toggle=True) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True, heading="Cycle Circle") + row.prop(inputs, "face_cycle_default_circle", toggle=True) + row.prop(inputs, "face_cycle_touch_circle", toggle=True) + row.prop(inputs, "face_cycle_enclose_circle", toggle=True) + row.prop(inputs, "face_cycle_center_circle", toggle=True) + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True, heading="Cycle Lasso & Circle") + else: + row = layout.row(align=True, heading="Cycle Lasso") + row.enabled = lasso_op + row.prop(inputs, "face_cycle_default_lasso", toggle=True) + row.prop(inputs, "face_cycle_touch_lasso", toggle=True) + row.prop(inputs, "face_cycle_enclose_lasso", toggle=True) + row.prop(inputs, "face_cycle_center_lasso", toggle=True) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "edge_operator", text="Edge Operator", emboss=False) + if inputs.edge_operator: + row.prop(inputs, "edge_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "edge_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "edge_header", toggle=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_edge) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_edge) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + row = layout.row(align=True, heading="Cycle") + elif box_circle: + row = layout.row(align=True, heading="Cycle Box & Circle") + elif box_lasso: + row = layout.row(align=True, heading="Cycle Box & Lasso") + else: + row = layout.row(align=True, heading="Cycle Box") + row.enabled = box_op + row.prop(inputs, "edge_cycle_default", toggle=True) + row.prop(inputs, "edge_cycle_touch", toggle=True) + row.prop(inputs, "edge_cycle_enclose", toggle=True) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True, heading="Cycle Circle") + row.prop(inputs, "edge_cycle_touch_circle", toggle=True) + row.prop(inputs, "edge_cycle_enclose_circle", toggle=True) + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True, heading="Cycle Lasso & Circle") + else: + row = layout.row(align=True, heading="Cycle Lasso") + row.enabled = lasso_op + row.prop(inputs, "edge_cycle_default_lasso", toggle=True) + row.prop(inputs, "edge_cycle_touch_lasso", toggle=True) + row.prop(inputs, "edge_cycle_enclose_lasso", toggle=True) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "backface_operator", text="Backface Operator", emboss=False) + if inputs.backface_operator: + row.prop(inputs, "backface_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "backface_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "backface_header", toggle=True) + row = layout.row(align=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_backface) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_backface) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + row = layout.row(align=True) + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + proptext="Toggle" + elif box_circle: + proptext="Toggle Box & Circle" + elif box_lasso: + proptext="Toggle Box & Lasso" + else: + proptext="Toggle Box" + row.enabled = box_op + row.prop(inputs, "backface_toggle", text=proptext) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True) + row.prop(inputs, "backface_toggle_circle", text="Toggle Circle") + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True) + proptext="Toggle Lasso & Circle" + else: + row = layout.row(align=True) + proptext="Toggle Lasso" + row.enabled = lasso_op + row.prop(inputs, "backface_toggle_lasso", text=proptext) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "auto_xray_operator", text="Auto X-Ray Operator", emboss=False) + if inputs.auto_xray_operator: + row.prop(inputs, "auto_xray_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "auto_xray_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "auto_xray_header", toggle=True) + row = layout.row(align=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_auto_xray) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_auto_xray) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + row = layout.row(align=True) + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + proptext="Toggle" + elif box_circle: + proptext="Toggle Box & Circle" + elif box_lasso: + proptext="Toggle Box & Lasso" + else: + proptext="Toggle Box" + row.enabled = box_op + row.prop(inputs, "auto_xray_toggle", text=proptext) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True) + row.prop(inputs, "auto_xray_toggle_circle", text="Toggle Circle") + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True) + proptext="Toggle Lasso & Circle" + else: + row = layout.row(align=True) + proptext="Toggle Lasso" + row.enabled = lasso_op + row.prop(inputs, "auto_xray_toggle_lasso", text=proptext) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "select_through_operator", text="Select Through Operator", emboss=False) + if inputs.select_through_operator: + row.prop(inputs, "select_through_operator", icon='RIGHTARROW', emboss=False) + else: + row.prop(inputs, "select_through_operator", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "select_through_header", toggle=True) + row = layout.row(align=True) + box_op = inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_select_through) + lasso_op = inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and not inputs.direction_select_through) + box_circle_lasso = inputs.sync_box and box_op and inputs.sync_circle and inputs.sync_lasso and lasso_op + box_circle = inputs.sync_box and box_op and inputs.sync_circle + box_lasso = inputs.sync_box and box_op and inputs.sync_lasso and lasso_op + circle_lasso = inputs.sync_circle and inputs.sync_lasso and lasso_op + + row = layout.row(align=True) + if inputs.userpref_mode == 'EASY' or box_circle_lasso: + proptext="Toggle" + elif box_circle: + proptext="Toggle Box & Circle" + elif box_lasso: + proptext="Toggle Box & Lasso" + else: + proptext="Toggle Box" + row.enabled = box_op + row.prop(inputs, "select_through_toggle", text=proptext) + + if inputs.userpref_mode == 'SPLIT' and not box_circle_lasso: + if not box_circle and not circle_lasso: + row = layout.row(align=True) + row.prop(inputs, "select_through_toggle_circle", text="Toggle Circle") + + if not box_lasso: + if circle_lasso: + row = layout.row(align=True) + proptext="Toggle Lasso & Circle" + else: + row = layout.row(align=True) + proptext="Toggle Lasso" + row.enabled = lasso_op + row.prop(inputs, "select_through_toggle_lasso", text=proptext) + else: + row.prop(inputs, "operator_controls", icon='RIGHTARROW', emboss=False) + + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "pie_menu_controls", text="Pie Menu Controls", emboss=False) + if inputs.pie_menu_controls: + row.prop(inputs, "pie_menu_controls", icon='DOWNARROW_HLT', emboss=False) + row = layout.row(align=True) + row.prop(inputs, "object_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "face_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "edge_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "backface_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "auto_xray_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "select_through_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "box_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "circle_pie", expand=True) + row = layout.row(align=True) + row.prop(inputs, "lasso_pie", expand=True) + else: + row.prop(inputs, "pie_menu_controls", icon='RIGHTARROW', emboss=False) + + +class USERPREF_PT_custom_mouse(CustomPanel, CenterAlignMixIn, Panel): + bl_label = "Mouse" + + def draw_centered(self, context, layout): + inputs = context.preferences.inputs + + row = layout.row(align=True) + row.prop(inputs, "adjustable_click_select") + if inputs.adjustable_click_select == 'CUSTOM': + row.prop(inputs, "selection_radius") + row = layout.row(align=True) + row.prop(inputs, "select_unbiased", toggle=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "custom_cursor") + if inputs.custom_cursor == 'CUSTOM': + row.operator("preferences.reset_cursors") + row = layout.row(align=True) + row.prop(inputs, "system_cursor") + row = layout.row(align=True) + row.prop(inputs, "edit_cursor") + row = layout.row(align=True) + row.prop(inputs, "paint_cursor") + row = layout.row(align=True) + row.prop(inputs, "dot_cursor") + row = layout.row(align=True) + row.prop(inputs, "knife_cursor") + row = layout.row(align=True) + row.prop(inputs, "pencil_cursor") + row = layout.row(align=True) + row.prop(inputs, "eraser_cursor") + row = layout.row(align=True) + row.prop(inputs, "eyedropper_cursor") + + +class USERPREF_PT_custom_visual(CustomPanel, CenterAlignMixIn, Panel): + bl_label = "Visual" + + def draw_centered(self, context, layout): + inputs = context.preferences.inputs + + row = layout.row(align=True) + row.prop(inputs, "facedot_mode", expand=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "shading_button_mode") + if inputs.shading_button_mode == 'CYCLE': + row.prop(inputs, "shading_cycle_wire", icon='SHADING_WIRE', toggle=True) + row.prop(inputs, "shading_cycle_solid", icon='SHADING_SOLID', toggle=True) + row.prop(inputs, "shading_cycle_material", icon='SHADING_TEXTURE', toggle=True) + row.prop(inputs, "shading_cycle_render", icon='SHADING_RENDERED', toggle=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.enabled = inputs.shading_button_mode != 'XRAY_COMBINE' + row.prop(inputs, "xray_button", expand=True) + row = layout.row(align=True) + row.separator(factor=1.5) + row = layout.row(align=True) + row.prop(inputs, "custom_highlight") + if inputs.custom_highlight == 'CUSTOM': + row.prop(inputs, "header_highlight") + + + + # ----------------------------------------------------------------------------- # Interface Panels @@ -282,7 +863,6 @@ class USERPREF_PT_interface_editors(InterfacePanel, CenterAlignMixIn, Panel): col.prop(view, "color_picker_type") col.row().prop(view, "header_align") col.prop(view, "factor_display_type") - col.prop(prefs.inputs, "header_highlight") class USERPREF_PT_interface_temporary_windows(InterfacePanel, CenterAlignMixIn, Panel): @@ -544,22 +1124,6 @@ class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel): col = layout.column() col.prop(edit, "sculpt_paint_overlay_color", text="Sculpt Overlay Color") - col.separator(factor=1.5) - col = layout.column(heading="Adjustable Click Select") - col.prop(edit, "adjustable_click_select") - colsub = col.column(align=True) - colsub.active = edit.adjustable_click_select - colsub.prop(edit, "select_unbiased") - colsub.prop(edit, "selection_radius") - col.separator(factor=1.5) - col.prop(edit, "system_cursor") - col.prop(edit, "edit_cursor") - col.prop(edit, "paint_cursor") - col.prop(edit, "dot_cursor") - col.prop(edit, "knife_cursor") - col.prop(edit, "pencil_cursor") - col.prop(edit, "eraser_cursor") - col.prop(edit, "eyedropper_cursor") # ----------------------------------------------------------------------------- @@ -1728,7 +2292,6 @@ class USERPREF_PT_input_mouse(InputPanel, CenterAlignMixIn, Panel): flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) - flow.prop(inputs, "click_drag_direction") if sys.platform[:3] == "win": flow.prop(inputs, "use_mouse_emulate_3_button") else: @@ -2746,6 +3309,10 @@ classes = ( USERPREF_MT_view, USERPREF_MT_save_load, + USERPREF_PT_custom_drag_select, + USERPREF_PT_custom_mouse, + USERPREF_PT_custom_visual, + USERPREF_PT_interface_display, USERPREF_PT_interface_editors, USERPREF_PT_interface_temporary_windows, diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index c30e82b16f7..511dd8b0953 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -751,6 +751,7 @@ class VIEW3D_HT_header(Header): layout = self.layout tool_settings = context.tool_settings + inputs = context.preferences.inputs view = context.space_data shading = view.shading @@ -783,45 +784,220 @@ class VIEW3D_HT_header(Header): ) del act_mode_item - if object_mode == 'EDIT' or object_mode == 'OBJECT': - row = layout.row(align=True) - row.template_header_3D_mode() + row = layout.row(align=True) + row.template_header_3D_mode() - if object_mode == 'OBJECT': - if tool_settings.object_select_mode == 'ENCLOSE': - objicon = 'OBJECT_ENCLOSE' - elif tool_settings.object_select_mode == 'ORIGIN': - objicon = 'LIGHTPROBE_SPHERE' + if inputs.drag_control_mode == 'USERPREF': + if (object_mode == 'OBJECT' and (inputs.object_header or inputs.auto_xray_header or inputs.select_through_header)) or (object_mode == 'EDIT' and (inputs.face_header or inputs.edge_header or inputs.backface_header or inputs.select_through_header or inputs.auto_xray_header)): + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + _cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D') + + if tool_settings.workspace_tool_type == 'FALLBACK': + tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname else: - objicon = 'OBJECT_TOUCH' - row.active = tool_settings.select_header - row.operator("view3d.cycle_object", text="", icon=objicon) - else: - if tool_settings.select_header: - if tool_settings.face_button: - if tool_settings.face_select_mode == 'TOUCH': - facicon = 'FACE_TOUCH' - elif tool_settings.face_select_mode == 'ENCLOSE': - facicon = 'FACE_ENCLOSE' - elif tool_settings.face_select_mode == 'CENTER': - facicon = 'LIGHTPROBE_PLANE' - else: - facicon = 'FACE_DEFAULT' - row.operator("view3d.cycle_face", text="", icon=facicon) - if tool_settings.edge_button: - if tool_settings.edge_select_mode == 'TOUCH': - edgicon = 'EDGE_TOUCH' - elif tool_settings.edge_select_mode == 'ENCLOSE': - edgicon = 'EDGE_ENCLOSE' - else: - edgicon = 'EDGE_DEFAULT' - row.operator("view3d.cycle_edge", text="", icon=edgicon) - if tool_settings.backface_button: - row.prop(tool_settings, "backface_select", text="", icon='NORMALS_FACE') + tool = ToolSelectPanelHelper.tool_active_from_context(context).idname - row.popover(panel="VIEW3D_PT_drag_select", text="") - else: - layout.template_header_3D_mode() + enable_auto_xray_button = inputs.auto_xray_header + depress_auto_xray = False + enable_select_through_button = inputs.select_through_header + depress_select_through = False + enable_object_button = inputs.object_header + objicon = 'OBJECT_TOUCH' + enable_face_button = inputs.face_header + facicon = 'FACE_DEFAULT' + enable_edge_button = inputs.edge_header + edgicon = 'EDGE_DEFAULT' + enable_backface_button = inputs.backface_header + depress_bface = False + + if inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_circle": + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.object_select_circle == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_circle == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + + if enable_auto_xray_button: + depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH' + + if enable_select_through_button: + depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_OBJECT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH' + else: + if enable_face_button: + if inputs.face_select_circle == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_circle == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_circle == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + + if enable_edge_button: + if inputs.edge_select_circle == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + edgicon = 'EDGE_TOUCH' + + if enable_auto_xray_button: + depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_EDIT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH' + + if enable_select_through_button: + depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_EDIT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH' + + if enable_backface_button: + depress_bface = inputs.backface_circle != 'DEFAULT' + + elif inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_lasso": + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False: + if inputs.object_select_lasso == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_lasso == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + else: + enable_object_button = False + + if enable_auto_xray_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_OBJECT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + if enable_face_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False: + if inputs.face_select_lasso == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_lasso == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_lasso == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + else: + enable_face_button = False + + if enable_edge_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False: + if inputs.edge_select_lasso == 'EDGE_TOUCH': + edgicon = 'EDGE_TOUCH' + elif inputs.edge_select_lasso == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + enable_edge_button = False + + if enable_backface_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False: + depress_bface = inputs.backface_lasso != 'DEFAULT' + else: + enable_backface_button = False + + if enable_auto_xray_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_EDIT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_EDIT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + + elif (inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_box") or (inputs.userpref_mode == 'EASY' and (tool == "builtin.select_box" or tool == "builtin.select_lasso" or tool == "builtin.select_circle")): + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False): + if inputs.object_select_box == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_box == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + else: + enable_object_button = False + + if enable_auto_xray_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_OBJECT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + if enable_face_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False): + if inputs.face_select_box == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_box == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_box == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + else: + enable_face_button = False + + if enable_edge_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False): + if inputs.edge_select_box == 'EDGE_TOUCH': + edgicon = 'EDGE_TOUCH' + elif inputs.edge_select_box == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + enable_edge_button = False + + if enable_backface_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False): + depress_bface = inputs.backface_box != 'DEFAULT' + else: + enable_backface_button = False + + if enable_auto_xray_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_EDIT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_EDIT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + enable_auto_xray_button = False + enable_select_through_button = False + enable_object_button = False + enable_face_button = False + enable_edge_button = False + enable_backface_button = False + + if object_mode == 'OBJECT': + if inputs.object_header: + sub = row.row(align=True) + sub.enabled = enable_object_button + sub.operator("view3d.cycle_object", text="", icon=objicon) + else: + if inputs.face_header: + sub = row.row(align=True) + sub.enabled = enable_face_button + sub.operator("view3d.cycle_face", text="", icon=facicon) + + if inputs.edge_header: + sub = row.row(align=True) + sub.enabled = enable_edge_button + sub.operator("view3d.cycle_edge", text="", icon=edgicon) + + if inputs.backface_header: + sub = row.row(align=True) + sub.enabled = enable_backface_button + sub.operator("view3d.toggle_backface", text="", icon='NORMALS_FACE', depress=depress_bface) + + del tool, enable_object_button, objicon, enable_face_button, facicon, enable_edge_button, edgicon, enable_backface_button, depress_bface # Contains buttons like Mode, Pivot, Layer, Mesh Select Mode... if obj: @@ -1096,45 +1272,19 @@ class VIEW3D_HT_header(Header): sub.popover(panel="VIEW3D_PT_overlay_bones", text="", icon='POSE_HLT') row = layout.row(align=True) - row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'}) - if object_mode == 'EDIT' or object_mode == 'OBJECT': - if tool_settings.xray_header: - from bl_ui.space_toolsystem_common import ToolSelectPanelHelper - _cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D') + if (object_mode == 'EDIT' or object_mode == 'OBJECT') and inputs.drag_control_mode == 'USERPREF' and (inputs.auto_xray_header or inputs.select_through_header): + if inputs.auto_xray_header: + sub = row.row(align=True) + sub.enabled = enable_auto_xray_button + sub.operator("view3d.toggle_auto_xray", text="", icon='AUTO_XRAY', depress=depress_auto_xray) + + if inputs.select_through_header: + sub = row.row(align=True) + sub.enabled = enable_select_through_button + sub.operator("view3d.toggle_select_through", text="", icon='SELECT_THROUGH', depress=depress_select_through) - if tool_settings.workspace_tool_type == 'FALLBACK': - tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname - else: - tool = ToolSelectPanelHelper.tool_active_from_context(context).idname - - if object_mode in 'EDIT': - mode_match_auto_xray = tool_settings.auto_xray_edit and tool_settings.auto_xray - mode_match_select_through = tool_settings.select_through_edit and tool_settings.select_through - elif object_mode in 'OBJECT': - mode_match_auto_xray = tool_settings.auto_xray_object and tool_settings.auto_xray - mode_match_select_through = tool_settings.select_through_object and tool_settings.select_through - else: - mode_match_auto_xray = False - mode_match_select_through = False - - if tool == "builtin.select_box": - depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_box - depress_select_through = mode_match_select_through and tool_settings.select_through_box - elif tool == "builtin.select_lasso": - depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_lasso - depress_select_through = mode_match_select_through and tool_settings.select_through_lasso - elif tool == "builtin.select_circle": - depress_auto_xray = mode_match_auto_xray and tool_settings.auto_xray_circle - depress_select_through = mode_match_select_through and tool_settings.select_through_circle - else: - depress_auto_xray = False - depress_select_through = False - - if tool_settings.auto_xray_button: - row.operator("view3d.toggle_auto_xray", text="", icon='AUTO_XRAY', depress=depress_auto_xray) - if tool_settings.select_through_button: - row.operator("view3d.toggle_select_through", text="", icon='SELECT_THROUGH', depress=depress_select_through) + del enable_auto_xray_button, depress_auto_xray, enable_select_through_button, depress_select_through # While exposing `shading.show_xray(_wireframe)` is correct. # this hides the key shortcut from users: #70433. @@ -1144,15 +1294,14 @@ class VIEW3D_HT_header(Header): draw_depressed = shading.show_xray_wireframe else: draw_depressed = shading.show_xray - if tool_settings.xray_header: - if tool_settings.xray_button or not tool_settings.auto_xray_button and not tool_settings.select_through_button: - row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed) - else: + if inputs.xray_button != 'HIDE' and inputs.shading_button_mode != 'XRAY_COMBINE': + row.active = (object_mode == 'EDIT') or (shading.type in {'WIREFRAME', 'SOLID'}) row.operator("view3d.toggle_xray", text="", icon='XRAY', depress=draw_depressed) - row.popover(panel="VIEW3D_PT_xray", text="") - row = layout.row(align=True) - if tool_settings.shrink_shading_header: + if not ((inputs.shading_button_mode == 'XRAY_COMBINE' or inputs.xray_button == 'HIDE') and not inputs.select_through_header and not inputs.auto_xray_header): + row = layout.row(align=True) + + if inputs.shading_button_mode != 'DEFAULT': if shading.type == 'SOLID': shadicon = 'SHADING_SOLID' elif shading.type == 'MATERIAL': @@ -1161,7 +1310,10 @@ class VIEW3D_HT_header(Header): shadicon = 'SHADING_RENDERED' else: shadicon = 'SHADING_WIRE' - row.operator("view3d.toggle_xray", text="", icon=shadicon, depress=draw_depressed) + if inputs.shading_button_mode == 'XRAY_COMBINE': + row.operator("view3d.toggle_xray", text="", icon=shadicon, depress=draw_depressed) + else: + row.operator("view3d.cycle_shading", text="", icon=shadicon) else: row.prop(shading, "type", text="", expand=True) sub = row.row(align=True) @@ -1323,15 +1475,316 @@ class ShowHideMenu: # Custom Operators class VIEW3D_box_lasso(bpy.types.Operator): bl_idname = "view3d.box_lasso" - bl_label = "box lasso" + bl_label = "Box-Lasso" def invoke(self, context, event): from bl_ui.space_toolsystem_common import ToolSelectPanelHelper tool = ToolSelectPanelHelper.tool_active_from_context(context) - if tool.idname == "builtin.select_box": - bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso") + tool_settings = context.tool_settings + inputs = context.preferences.inputs + + if tool_settings.workspace_tool_type == 'FALLBACK': + tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname else: - bpy.ops.wm.tool_set_by_id(name="builtin.select_box") + tool = ToolSelectPanelHelper.tool_active_from_context(context).idname + + if tool.idname == "builtin.select_box": + for i in range(2): + bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso") + else: + for i in range(2): + bpy.ops.wm.tool_set_by_id(name="builtin.select_box") + + return {'FINISHED'} + +class VIEW3D_box_select(bpy.types.Operator): + bl_idname = "view3d.box_select" + bl_label = "Box" + bl_description = "Use Box Select" + + def invoke(self, context, event): + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.tool_active_from_context(context) + tool_settings = context.tool_settings + + for i in range(2): + if tool.idname == "builtin.select_circle" or tool.idname == "builtin.select_lasso" or tool.idname == "builtin.select": + bpy.ops.wm.tool_set_by_id(name="builtin.select_box", space_type='VIEW_3D') + elif tool_settings.workspace_tool_type == 'FALLBACK': + bpy.ops.wm.tool_set_by_id(name="builtin.select_box", as_fallback=True, space_type='VIEW_3D') + else: + bpy.ops.wm.tool_set_by_id(name="builtin.select_box", space_type='VIEW_3D') + + return {'FINISHED'} + +class VIEW3D_circle_select(bpy.types.Operator): + bl_idname = "view3d.circle_select" + bl_label = "Circle" + bl_description = "Use Circle Select" + + def invoke(self, context, event): + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.tool_active_from_context(context) + tool_settings = context.tool_settings + + for i in range(2): + if tool.idname == "builtin.select_box" or tool.idname == "builtin.select_lasso" or tool.idname == "builtin.select": + bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", space_type='VIEW_3D') + elif tool_settings.workspace_tool_type == 'FALLBACK': + bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", as_fallback=True, space_type='VIEW_3D') + else: + bpy.ops.wm.tool_set_by_id(name="builtin.select_circle", space_type='VIEW_3D') + + return {'FINISHED'} + +class VIEW3D_lasso_select(bpy.types.Operator): + bl_idname = "view3d.lasso_select" + bl_label = "Lasso" + bl_description = "Use Lasso Select" + + def invoke(self, context, event): + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.tool_active_from_context(context) + tool_settings = context.tool_settings + + for i in range(2): + if tool.idname == "builtin.select_circle" or tool.idname == "builtin.select_box" or tool.idname == "builtin.select": + bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso") + elif tool_settings.workspace_tool_type == 'FALLBACK': + bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso", as_fallback=True) + else: + bpy.ops.wm.tool_set_by_id(name="builtin.select_lasso") + + return {'FINISHED'} + +class VIEW3D_MT_PIE_Drag_Select(Menu): + bl_label = "Drag Select" + + def draw(self, context): + layout = self.layout + tool_settings = context.tool_settings + inputs = context.preferences.inputs + obj = context.active_object + object_mode = 'OBJECT' if obj is None else obj.mode + + if inputs.drag_control_mode == 'USERPREF' and (object_mode == 'OBJECT' or object_mode == 'EDIT'): + enable_auto_xray_button = inputs.auto_xray_pie == 'SHOW' + depress_auto_xray = False + enable_select_through_button = inputs.select_through_pie == 'SHOW' + depress_select_through = False + enable_backface_button = inputs.backface_pie == 'SHOW' + depress_bface = False + enable_object_button = inputs.object_pie == 'SHOW' + objicon = 'OBJECT_TOUCH' + enable_face_button = inputs.face_pie == 'SHOW' + facicon = 'FACE_DEFAULT' + enable_edge_button = inputs.edge_pie == 'SHOW' + edgicon = 'EDGE_DEFAULT' + + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + _cls = ToolSelectPanelHelper._tool_class_from_space_type('VIEW_3D') + + if tool_settings.workspace_tool_type == 'FALLBACK': + tool = _cls._tool_get_by_id_active(context, _cls.tool_fallback_id)[0].idname + else: + tool = ToolSelectPanelHelper.tool_active_from_context(context).idname + + if inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_circle": + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.object_select_circle == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_circle == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + + if enable_auto_xray_button: + depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH' + + if enable_select_through_button: + depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_OBJECT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH' + else: + if enable_face_button: + if inputs.face_select_circle == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_circle == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_circle == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + + if enable_edge_button: + if inputs.edge_select_circle == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + edgicon = 'EDGE_TOUCH' + + if enable_backface_button: + depress_bface = inputs.backface_circle != 'DEFAULT' + + if enable_auto_xray_button: + depress_auto_xray = inputs.auto_xray_circle == 'AUTO_XRAY_EDIT' or inputs.auto_xray_circle == 'AUTO_XRAY_BOTH' + + if enable_select_through_button: + depress_select_through = inputs.select_through_circle == 'SELECT_THROUGH_EDIT' or inputs.select_through_circle == 'SELECT_THROUGH_BOTH' + + elif inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_lasso": + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False: + if inputs.object_select_lasso == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_lasso == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + else: + enable_object_button = False + + if enable_auto_xray_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_OBJECT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + if enable_face_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False: + if inputs.face_select_lasso == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_lasso == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_lasso == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + else: + enable_face_button = False + + if enable_edge_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False: + if inputs.edge_select_lasso == 'EDGE_TOUCH': + edgicon = 'EDGE_TOUCH' + elif inputs.edge_select_lasso == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + enable_edge_button = False + + if enable_backface_button: + if inputs.drag_direction_lasso == 'ANY' or inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False: + depress_bface = inputs.backface_lasso != 'DEFAULT' + else: + enable_backface_button = False + + if enable_auto_xray_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_lasso == 'AUTO_XRAY_EDIT' or inputs.auto_xray_lasso == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.drag_direction_lasso == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_lasso == 'SELECT_THROUGH_EDIT' or inputs.select_through_lasso == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + + elif (inputs.userpref_mode == 'SPLIT' and tool == "builtin.select_box") or (inputs.userpref_mode == 'EASY' and (tool == "builtin.select_box" or tool == "builtin.select_lasso" or tool == "builtin.select_circle")): + if object_mode == 'OBJECT': + if enable_object_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_object == False): + if inputs.object_select_box == 'OBJECT_ENCLOSE': + objicon = 'OBJECT_ENCLOSE' + elif inputs.object_select_box == 'OBJECT_ORIGIN': + objicon = 'LIGHTPROBE_SPHERE' + else: + enable_object_button = False + + if enable_auto_xray_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_OBJECT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_OBJECT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + if enable_face_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_face == False): + if inputs.face_select_box == 'FACE_TOUCH': + facicon = 'FACE_TOUCH' + elif inputs.face_select_box == 'FACE_ENCLOSE': + facicon = 'FACE_ENCLOSE' + elif inputs.face_select_box == 'FACE_CENTER': + facicon = 'LIGHTPROBE_PLANE' + else: + enable_face_button = False + + if enable_edge_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_edge == False): + if inputs.edge_select_box == 'EDGE_TOUCH': + edgicon = 'EDGE_TOUCH' + elif inputs.edge_select_box == 'EDGE_ENCLOSE': + edgicon = 'EDGE_ENCLOSE' + else: + enable_edge_button = False + + if enable_backface_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_backface == False): + depress_bface = inputs.backface_box != 'DEFAULT' + else: + enable_backface_button = False + + if enable_auto_xray_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_auto_xray == False): + depress_auto_xray = inputs.auto_xray_box == 'AUTO_XRAY_EDIT' or inputs.auto_xray_box == 'AUTO_XRAY_BOTH' + else: + enable_auto_xray_button = False + + if enable_select_through_button: + if inputs.userpref_mode == 'EASY' or inputs.drag_direction_box == 'ANY' or (inputs.drag_direction_mode == 'SELECTIVE' and inputs.direction_select_through == False): + depress_select_through = inputs.select_through_box == 'SELECT_THROUGH_EDIT' or inputs.select_through_box == 'SELECT_THROUGH_BOTH' + else: + enable_select_through_button = False + else: + enable_auto_xray_button = False + enable_select_through_button = False + enable_object_button = False + enable_face_button = False + enable_edge_button = False + enable_backface_button = False + + pie = layout.menu_pie() + + if enable_auto_xray_button: + pie.operator("view3d.toggle_auto_xray", icon='AUTO_XRAY', depress=depress_auto_xray) + if enable_select_through_button: + pie.operator("view3d.toggle_select_through", icon='SELECT_THROUGH', depress=depress_select_through) + if inputs.box_pie == 'SHOW' or tool != "builtin.select_box" and inputs.box_pie == 'CONTEXT': + pie.operator("view3d.box_select", icon='SELECT_SET') + if inputs.circle_pie == 'SHOW' or tool != "builtin.select_circle" and inputs.circle_pie == 'CONTEXT': + pie.operator("view3d.circle_select", icon='MESH_CIRCLE') + if inputs.lasso_pie == 'SHOW' or tool != "builtin.select_lasso" and inputs.lasso_pie == 'CONTEXT': + pie.operator("view3d.lasso_select", icon='MOD_DASH') + + if object_mode == 'OBJECT': + if enable_object_button: + pie.operator("view3d.cycle_object", text="Object", icon=objicon) + else: + if enable_backface_button: + pie.operator("view3d.toggle_backface", text="Backface", icon='NORMALS_FACE', depress=depress_bface) + if enable_face_button: + pie.operator("view3d.cycle_face", text="Face", icon=facicon) + if enable_edge_button: + pie.operator("view3d.cycle_edge", text="Edge", icon=edgicon) + +class VIEW3D_pie_drag_select(bpy.types.Operator): + bl_idname = "view3d.pie_drag_select" + bl_label = "Drag Select" + + def invoke(self, context, event): + bpy.ops.wm.call_menu_pie(name="VIEW3D_MT_PIE_Drag_Select") return {'FINISHED'} @@ -6595,13 +7048,6 @@ class VIEW3D_PT_shading(Panel): def draw(self, _context): layout = self.layout layout.label(text="Viewport Shading") - tool_settings = _context.tool_settings - shading = VIEW3D_PT_shading.get_shading(_context) - - row = layout.row(align=True) - row.prop(tool_settings, "shrink_shading_header", toggle=True) - if tool_settings.shrink_shading_header: - row.prop(shading, "type", text="", expand=True) class VIEW3D_PT_shading_lighting(Panel): @@ -6793,7 +7239,17 @@ class VIEW3D_PT_shading_options(Panel): row = col.row(align=True) - if shading.type == 'SOLID': + if shading.type == 'WIREFRAME': + row.prop(shading, "show_xray_wireframe", text="") + sub = row.row() + sub.active = shading.show_xray_wireframe + sub.prop(shading, "xray_alpha_wireframe", text="X-Ray") + elif shading.type == 'SOLID': + row.prop(shading, "show_xray", text="") + sub = row.row() + sub.active = shading.show_xray + sub.prop(shading, "xray_alpha", text="X-Ray") + # X-ray mode is off when alpha is 1.0 xray_active = shading.show_xray and shading.xray_alpha != 1 row = col.row(align=True) @@ -6837,6 +7293,61 @@ class VIEW3D_PT_shading_options(Panel): row = col.row() row.active = not xray_active row.prop(shading, "use_dof", text="Depth of Field") + else: + if shading.type == 'WIREFRAME': + row.prop(shading, "show_xray_wireframe", text="") + sub = row.row() + sub.active = shading.show_xray_wireframe + sub.prop(shading, "xray_alpha_wireframe", text="X-Ray") + elif shading.type == 'SOLID': + row.prop(shading, "show_xray", text="") + sub = row.row() + sub.active = shading.show_xray + sub.prop(shading, "xray_alpha", text="X-Ray") + # X-ray mode is off when alpha is 1.0 + xray_active = shading.show_xray and shading.xray_alpha != 1 + + row = col.row(align=True) + row.prop(shading, "show_shadows", text="") + row.active = not xray_active + sub = row.row(align=True) + sub.active = shading.show_shadows + sub.prop(shading, "shadow_intensity", text="Shadow") + sub.popover( + panel="VIEW3D_PT_shading_options_shadow", + icon='PREFERENCES', + text="", + ) + + col = layout.column() + + row = col.row() + row.active = not xray_active + row.prop(shading, "show_cavity") + + if shading.show_cavity and not xray_active: + row.prop(shading, "cavity_type", text="Type") + + if shading.cavity_type in {'WORLD', 'BOTH'}: + col.label(text="World Space") + sub = col.row(align=True) + sub.prop(shading, "cavity_ridge_factor", text="Ridge") + sub.prop(shading, "cavity_valley_factor", text="Valley") + sub.popover( + panel="VIEW3D_PT_shading_options_ssao", + icon='PREFERENCES', + text="", + ) + + if shading.cavity_type in {'SCREEN', 'BOTH'}: + col.label(text="Screen Space") + sub = col.row(align=True) + sub.prop(shading, "curvature_ridge_factor", text="Ridge") + sub.prop(shading, "curvature_valley_factor", text="Valley") + + row = col.row() + row.active = not xray_active + row.prop(shading, "use_dof", text="Depth of Field") if shading.type in {'WIREFRAME', 'SOLID'}: row = layout.split() @@ -6978,135 +7489,6 @@ class VIEW3D_PT_gizmo_display(Panel): col.prop(view, "show_gizmo_camera_dof_distance", text="Focus Distance") -class VIEW3D_PT_drag_select(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'HEADER' - bl_label = "Drag Select Settings" - bl_ui_units_x = 12 - - def draw(self, context): - obj = context.active_object - object_mode = 'OBJECT' if obj is None else obj.mode - tool_settings = context.tool_settings - layout = self.layout - layout.label(text="Drag Select Settings") - - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Selection Control", emboss=False) - if tool_settings.select_header: - row.prop(tool_settings, "select_header", text="Header", toggle=True) - if object_mode == 'OBJECT': - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Object Select", emboss=False) - row.prop(tool_settings, "object_select_mode", text="") - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Object Header Button Modes", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "object_cycle_touch", toggle=True) - row.prop(tool_settings, "object_cycle_enclose", toggle=True) - row.prop(tool_settings, "object_cycle_origin", toggle=True) - else: - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Face Select", emboss=False) - row.prop(tool_settings, "face_select_mode", text="") - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Edge Select", emboss=False) - row.prop(tool_settings, "edge_select_mode", text="") - row = layout.row(align=True) - row.prop(tool_settings, "backface_select", toggle=True) - if tool_settings.backface_select: - row.prop(tool_settings, "backface_select_mode", text="") - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Header Buttons", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "face_button", toggle=True) - row.prop(tool_settings, "edge_button", toggle=True) - row.prop(tool_settings, "backface_button", toggle=True) - if tool_settings.face_button: - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Face Header Button Modes", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "face_cycle_default", toggle=True) - row.prop(tool_settings, "face_cycle_touch", toggle=True) - row.prop(tool_settings, "face_cycle_enclose", toggle=True) - row.prop(tool_settings, "face_cycle_center", toggle=True) - if tool_settings.edge_button: - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Edge Header Button Modes", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "edge_cycle_default", toggle=True) - row.prop(tool_settings, "edge_cycle_touch", toggle=True) - row.prop(tool_settings, "edge_cycle_enclose", toggle=True) - else: - row.prop(tool_settings, "select_header", text="Keymap", toggle=True) - - -class VIEW3D_PT_xray(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'HEADER' - bl_label = "X-Ray Settings" - bl_ui_units_x = 14 - - def draw(self, context): - tool_settings = context.tool_settings - shading = VIEW3D_PT_shading.get_shading(context) - layout = self.layout - layout.label(text="X-Ray Settings") - - row = layout.row(align=True) - if shading.type == 'WIREFRAME': - row.prop(shading, "show_xray_wireframe", text="X-Ray Wireframe", toggle=True) - if shading.show_xray_wireframe: - row.prop(shading, "xray_alpha_wireframe", text="") - elif shading.type == 'SOLID': - row.prop(shading, "show_xray", text="X-Ray Solid", toggle=True) - if shading.show_xray: - row.prop(shading, "xray_alpha", text="") - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="X-Ray Control", emboss=False) - if tool_settings.xray_header: - row.prop(tool_settings, "xray_header", text="Header", toggle=True) - - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Automatic X-Ray", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "auto_xray") - sub = row.row(align=True) - sub.active = tool_settings.auto_xray - sub.prop(tool_settings, "auto_xray_object") - sub.prop(tool_settings, "auto_xray_edit") - row = layout.row(align=True) - sub = row.row(align=True) - sub.active = tool_settings.auto_xray - sub.prop(tool_settings, "auto_xray_box", toggle=True) - sub.prop(tool_settings, "auto_xray_lasso", toggle=True) - sub.prop(tool_settings, "auto_xray_circle", toggle=True) - - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Select Through", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "select_through") - sub = row.row(align=True) - sub.active = tool_settings.select_through - sub.prop(tool_settings, "select_through_object") - sub.prop(tool_settings, "select_through_edit") - row = layout.row(align=True) - sub = row.row(align=True) - sub.active = tool_settings.select_through - sub.prop(tool_settings, "select_through_box", toggle=True) - sub.prop(tool_settings, "select_through_lasso", toggle=True) - sub.prop(tool_settings, "select_through_circle", toggle=True) - - row = layout.row(align=True) - row.prop(tool_settings, "blank_text", text="Header Buttons", emboss=False) - row = layout.row(align=True) - row.prop(tool_settings, "auto_xray_button", toggle=True) - row.prop(tool_settings, "select_through_button", toggle=True) - row.prop(tool_settings, "xray_button", toggle=True) - - else: - row.prop(tool_settings, "xray_header", text="Keymap", toggle=True) - class VIEW3D_PT_overlay(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' @@ -9261,6 +9643,11 @@ classes = ( VIEW3D_MT_wpaint_vgroup_lock_pie, VIEW3D_MT_sculpt_face_sets_edit_pie, VIEW3D_box_lasso, + VIEW3D_box_select, + VIEW3D_circle_select, + VIEW3D_lasso_select, + VIEW3D_MT_PIE_Drag_Select, + VIEW3D_pie_drag_select, VIEW3D_MT_sculpt_curves, VIEW3D_PT_active_tool, VIEW3D_PT_active_tool_duplicate, @@ -9285,8 +9672,6 @@ classes = ( VIEW3D_PT_shading_render_pass, VIEW3D_PT_shading_compositor, VIEW3D_PT_gizmo_display, - VIEW3D_PT_drag_select, - VIEW3D_PT_xray, VIEW3D_PT_overlay, VIEW3D_PT_overlay_guides, VIEW3D_PT_overlay_object, diff --git a/source/blender/blenloader/intern/versioning_defaults.cc b/source/blender/blenloader/intern/versioning_defaults.cc index fa41c6a5461..3c77e3796d1 100644 --- a/source/blender/blenloader/intern/versioning_defaults.cc +++ b/source/blender/blenloader/intern/versioning_defaults.cc @@ -394,33 +394,6 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) if (ts->unified_paint_settings.input_samples == 0) { ts->unified_paint_settings.input_samples = 1; } - - /* Drag Select. */ - ts->xray_button = true; - ts->auto_xray_object = true; - ts->auto_xray_edit = true; - ts->auto_xray_box = true; - ts->auto_xray_lasso = true; - ts->auto_xray_circle = true; - ts->select_through = true; - ts->select_through_object = true; - ts->select_through_box = true; - ts->select_through_lasso = true; - ts->select_through_circle = true; - ts->object_cycle_touch = true; - ts->object_cycle_enclose = true; - ts->object_cycle_origin = true; - ts->face_cycle_default = true; - ts->face_cycle_touch = true; - ts->face_cycle_enclose = true; - ts->face_cycle_center = true; - ts->edge_cycle_default = true; - ts->edge_cycle_touch = true; - ts->edge_cycle_enclose = true; - ts->object_select_mode = 1; - ts->face_select_mode = 1; - ts->edge_select_mode = 1; - ts->backface_select_mode = 2; } void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) diff --git a/source/blender/blenloader/intern/versioning_userdef.cc b/source/blender/blenloader/intern/versioning_userdef.cc index 9029ab621ce..65913bab522 100644 --- a/source/blender/blenloader/intern/versioning_userdef.cc +++ b/source/blender/blenloader/intern/versioning_userdef.cc @@ -490,8 +490,9 @@ void blo_do_versions_userdef(UserDef *userdef) if (!USER_VERSION_ATLEAST(278, 6)) { /* Clear preference flags for re-use. */ - userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | (1 << 2) | USER_FLAG_UNUSED_6 | - USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 | USER_DEVELOPER_UI); + userdef->flag &= ~(USER_FLAG_NUMINPUT_ADVANCED | (1 << 2) | USER_FLAG_UNUSED_3 | + USER_FLAG_UNUSED_6 | USER_FLAG_UNUSED_7 | USER_FLAG_UNUSED_9 | + USER_DEVELOPER_UI); userdef->uiflag &= ~(USER_HEADER_BOTTOM); userdef->transopts &= ~(USER_TR_UNUSED_3 | USER_TR_UNUSED_4 | USER_TR_UNUSED_6 | USER_TR_UNUSED_7); @@ -580,6 +581,8 @@ void blo_do_versions_userdef(UserDef *userdef) copy_v3_fl3(userdef->light_ambient, 0.025000, 0.025000, 0.025000); + userdef->flag &= ~(USER_FLAG_UNUSED_4); + userdef->uiflag &= ~(USER_HEADER_FROM_PREF | USER_REGISTER_ALL_USERS); } diff --git a/source/blender/editors/gpencil_legacy/gpencil_select.cc b/source/blender/editors/gpencil_legacy/gpencil_select.cc index 759c337c077..46764de9d7f 100644 --- a/source/blender/editors/gpencil_legacy/gpencil_select.cc +++ b/source/blender/editors/gpencil_legacy/gpencil_select.cc @@ -1678,7 +1678,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); const bool is_curve_edit = bool(GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd)); - const bool square = ts->square_select; + const bool square = U.square_select; int selectmode; if (ob && ob->mode == OB_MODE_SCULPT_GPENCIL_LEGACY) { diff --git a/source/blender/editors/interface/resources.cc b/source/blender/editors/interface/resources.cc index 24cafb88dee..b51f3bef494 100644 --- a/source/blender/editors/interface/resources.cc +++ b/source/blender/editors/interface/resources.cc @@ -248,7 +248,7 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_HEADER_ACTIVE: { cp = ts->header; - const int factor = U.header_highlight; + const int factor = U.custom_highlight ? U.header_highlight : 5; /* Lighten the header color when editor is active. */ header_active[0] = cp[0] > 245 ? cp[0] - factor : cp[0] + factor; header_active[1] = cp[1] > 245 ? cp[1] - factor : cp[1] + factor; diff --git a/source/blender/editors/mesh/editmesh_select.cc b/source/blender/editors/mesh/editmesh_select.cc index 3cfbd6435e8..7cc0714c008 100644 --- a/source/blender/editors/mesh/editmesh_select.cc +++ b/source/blender/editors/mesh/editmesh_select.cc @@ -246,8 +246,8 @@ static void findnearestvert__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && - data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) + if (!(U.adjustable_click_select && U.select_unbiased) && data->use_select_bias && + BM_elem_flag_test(eve, BM_ELEM_SELECT)) { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -457,8 +457,8 @@ static void find_nearest_edge__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && - data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) + if (!(U.adjustable_click_select && U.select_unbiased) && data->use_select_bias && + BM_elem_flag_test(eed, BM_ELEM_SELECT)) { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -692,8 +692,8 @@ static void findnearestface__doClosest(void *user_data, dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT && U.flag & USER_SELECT_UNBIASED) && - data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) + if (!(U.adjustable_click_select && U.select_unbiased) && data->use_select_bias && + BM_elem_flag_test(efa, BM_ELEM_SELECT)) { dist_test_bias += FIND_NEAR_SELECT_BIAS; } @@ -736,7 +736,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, uint dist_px_manhattan_test = 0; { - if (U.flag & USER_ADJUSTABLE_CLICK_SELECT || + if (U.adjustable_click_select || *dist_px_manhattan_p != 0.0f && (use_zbuf_single_px == false)) { dist_px_manhattan_test = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, @@ -745,7 +745,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, DRW_select_buffer_context_create(vc->depsgraph, bases, SCE_SELECT_FACE); - if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_px_manhattan_test == 0) { + if (!(U.adjustable_click_select) && dist_px_manhattan_test == 0) { index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval); } else { @@ -784,14 +784,14 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc, /* end exception */ if (efa) { - if (U.flag & USER_ADJUSTABLE_CLICK_SELECT && dist_px_manhattan_test < *dist_px_manhattan_p) { + if (U.adjustable_click_select && dist_px_manhattan_test < *dist_px_manhattan_p) { if (r_base_index) { *r_base_index = base_index; } *dist_px_manhattan_p = dist_px_manhattan_test; return efa; } - else if (!(U.flag & USER_ADJUSTABLE_CLICK_SELECT) && dist_test < *dist_px_manhattan_p) { + else if (!U.adjustable_click_select && dist_test < *dist_px_manhattan_p) { if (r_base_index) { *r_base_index = base_index; } diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 93e280e7dd5..86aed7fee5c 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -875,8 +875,7 @@ static int node_circleselect_exec(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); ARegion *region = CTX_wm_region(C); bNodeTree &node_tree = *snode->edittree; - ToolSettings *ts = CTX_data_tool_settings(C); - const bool square = ts->square_select; + const bool square = U.square_select; int x, y, radius; float2 offset; diff --git a/source/blender/editors/space_view3d/view3d_edit.cc b/source/blender/editors/space_view3d/view3d_edit.cc index ab4155918cd..e3f68205b07 100644 --- a/source/blender/editors/space_view3d/view3d_edit.cc +++ b/source/blender/editors/space_view3d/view3d_edit.cc @@ -1251,96 +1251,352 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot) static int toggle_auto_xray_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - ToolSettings *ts = CTX_data_tool_settings(C); Object *obedit = CTX_data_edit_object(C); bToolRef *tref = area->runtime.tool; - const bool mode_match = obedit ? ts->auto_xray_edit : ts->auto_xray_object; - if (STREQ(tref->idname, "builtin.select_box") || - STREQ(tref->idname_fallback, "builtin.select_box")) - { - if (mode_match && ts->auto_xray && ts->auto_xray_box) { - ts->auto_xray ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->auto_xray_edit ^= true; + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_auto_xray; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_auto_xray; + const bool box_circle_lasso = U.sync_box && box_op && U.sync_circle && U.sync_lasso && lasso_op; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + /* Off in the active mode and On in the other mode = Both */ + if (obedit && U.auto_xray_box == 1 || !obedit && U.auto_xray_box == 2) { + U.auto_xray_box = 3; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.auto_xray_circle = 3; + } + } + /* if toggle mode == Current, Off Edit = On Edit, Both Object = Edit only */ + else if (U.auto_xray_toggle == 1 && + (obedit && U.auto_xray_box == 0 || !obedit && U.auto_xray_box == 3)) + { + U.auto_xray_box = 2; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.auto_xray_circle = 2; + } + } + /* if toggle mode == Current, Off Object = On Object, Both Edit = Object only */ + else if (U.auto_xray_toggle == 1 && + (!obedit && U.auto_xray_box == 0 || obedit && U.auto_xray_box == 3)) + { + U.auto_xray_box = 1; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.auto_xray_circle = 1; + } + } + /* otherwise On = Off */ + else if (U.auto_xray_box != 0) { + U.auto_xray_box = 0; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.auto_xray_circle = 0; + } + } + /* and Off = Both */ + else { + U.auto_xray_box = 3; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.auto_xray_circle = 3; + } + } + } + else if (lasso) { + if (obedit && U.auto_xray_lasso == 1 || !obedit && U.auto_xray_lasso == 2) { + U.auto_xray_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_circle = 3; + } + } + else if (U.auto_xray_toggle == 1 && + (obedit && U.auto_xray_lasso == 0 || !obedit && U.auto_xray_lasso == 3)) + { + U.auto_xray_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_circle = 2; + } + } + else if (U.auto_xray_toggle == 1 && + (!obedit && U.auto_xray_lasso == 0 || obedit && U.auto_xray_lasso == 3)) + { + U.auto_xray_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_circle = 1; + } + } + else if (U.auto_xray_lasso != 0) { + U.auto_xray_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_circle = 0; + } + } + else { + U.auto_xray_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.auto_xray_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_circle = 3; + } + } } else { - ts->auto_xray_object ^= true; + if (obedit && U.auto_xray_circle == 1 || !obedit && U.auto_xray_circle == 2) { + U.auto_xray_circle = 3; + + if (box_circle_lasso || box_circle) { + U.auto_xray_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_lasso = 3; + } + } + else if (U.auto_xray_toggle == 1 && + (obedit && U.auto_xray_circle == 0 || !obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 2; + + if (box_circle_lasso || box_circle) { + U.auto_xray_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_lasso = 2; + } + } + else if (U.auto_xray_toggle == 1 && + (!obedit && U.auto_xray_circle == 0 || obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 1; + + if (box_circle_lasso || box_circle) { + U.auto_xray_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_lasso = 1; + } + } + else if (U.auto_xray_circle != 0) { + U.auto_xray_circle = 0; + + if (box_circle_lasso || box_circle) { + U.auto_xray_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_lasso = 0; + } + } + else { + U.auto_xray_circle = 3; + + if (box_circle_lasso || box_circle) { + U.auto_xray_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.auto_xray_lasso = 3; + } + } } } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (obedit && U.auto_xray_lasso == 1 || !obedit && U.auto_xray_lasso == 2) { + U.auto_xray_lasso = 3; - if (!ts->auto_xray) { - ts->auto_xray ^= true; - } + if (circle_lasso) { + U.auto_xray_circle = 3; + } + } + else if (U.auto_xray_toggle_lasso == 1 && + (obedit && U.auto_xray_lasso == 0 || !obedit && U.auto_xray_lasso == 3)) + { + U.auto_xray_lasso = 2; - if (!ts->auto_xray_box) { - ts->auto_xray_box ^= true; - } - } - } - else if (STREQ(tref->idname, "builtin.select_lasso") || - STREQ(tref->idname_fallback, "builtin.select_lasso")) - { - if (mode_match && ts->auto_xray && ts->auto_xray_lasso) { - ts->auto_xray ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->auto_xray_edit ^= true; + if (circle_lasso) { + U.auto_xray_circle = 2; + } + } + else if (U.auto_xray_toggle_lasso == 1 && + (!obedit && U.auto_xray_lasso == 0 || obedit && U.auto_xray_lasso == 3)) + { + U.auto_xray_lasso = 1; + + if (circle_lasso) { + U.auto_xray_circle = 1; + } + } + else if (U.auto_xray_lasso != 0) { + U.auto_xray_lasso = 0; + + if (circle_lasso) { + U.auto_xray_circle = 0; + } + } + else { + U.auto_xray_lasso = 3; + + if (circle_lasso) { + U.auto_xray_circle = 3; + } + } } else { - ts->auto_xray_object ^= true; + if (obedit && U.auto_xray_circle == 1 || !obedit && U.auto_xray_circle == 2) { + U.auto_xray_circle = 3; + + if (circle_lasso) { + U.auto_xray_lasso = 3; + } + } + else if (U.auto_xray_toggle_lasso == 1 && + (obedit && U.auto_xray_circle == 0 || !obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 2; + + if (circle_lasso) { + U.auto_xray_lasso = 2; + } + } + else if (U.auto_xray_toggle_lasso == 1 && + (!obedit && U.auto_xray_circle == 0 || obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 1; + + if (circle_lasso) { + U.auto_xray_lasso = 1; + } + } + else if (U.auto_xray_circle != 0) { + U.auto_xray_circle = 0; + + if (circle_lasso) { + U.auto_xray_lasso = 0; + } + } + else { + U.auto_xray_circle = 3; + + if (circle_lasso) { + U.auto_xray_lasso = 3; + } + } } } - - if (!ts->auto_xray) { - ts->auto_xray ^= true; - } - - if (!ts->auto_xray_lasso) { - ts->auto_xray_lasso ^= true; - } - } - } - else if (STREQ(tref->idname, "builtin.select_circle") || - STREQ(tref->idname_fallback, "builtin.select_circle")) - { - if (mode_match && ts->auto_xray && ts->auto_xray_circle) { - ts->auto_xray ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->auto_xray_edit ^= true; + else if (circle) { + if (obedit && U.auto_xray_circle == 1 || !obedit && U.auto_xray_circle == 2) { + U.auto_xray_circle = 3; + } + else if (U.auto_xray_toggle_circle == 1 && + (obedit && U.auto_xray_circle == 0 || !obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 2; + } + else if (U.auto_xray_toggle_circle == 1 && + (!obedit && U.auto_xray_circle == 0 || obedit && U.auto_xray_circle == 3)) + { + U.auto_xray_circle = 1; + } + else if (U.auto_xray_circle != 0) { + U.auto_xray_circle = 0; } else { - ts->auto_xray_object ^= true; + U.auto_xray_circle = 3; } } - - if (!ts->auto_xray) { - ts->auto_xray ^= true; + } + else { + if (obedit && U.auto_xray_box == 1 || !obedit && U.auto_xray_box == 2) { + U.auto_xray_box = 3; } - - if (!ts->auto_xray_circle) { - ts->auto_xray_circle ^= true; + else if (U.auto_xray_toggle == 1 && + (obedit && U.auto_xray_box == 0 || !obedit && U.auto_xray_box == 3)) + { + U.auto_xray_box = 2; + } + else if (U.auto_xray_toggle == 1 && + (!obedit && U.auto_xray_box == 0 || obedit && U.auto_xray_box == 3)) + { + U.auto_xray_box = 1; + } + else if (U.auto_xray_box != 0) { + U.auto_xray_box = 0; + } + else { + U.auto_xray_box = 3; } } + ED_area_tag_redraw(area); } - - ED_area_tag_redraw(area); - return OPERATOR_FINISHED; } void VIEW3D_OT_toggle_auto_xray(wmOperatorType *ot) { /* identifiers */ - ot->name = "Toggle Automatic X-Ray"; + ot->name = "Auto X-Ray"; ot->idname = "VIEW3D_OT_toggle_auto_xray"; ot->description = "Transparent scene display during box, lasso, and circle select"; @@ -1358,98 +1614,355 @@ void VIEW3D_OT_toggle_auto_xray(wmOperatorType *ot) static int toggle_select_through_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - ToolSettings *ts = CTX_data_tool_settings(C); Object *obedit = CTX_data_edit_object(C); bToolRef *tref = area->runtime.tool; - const bool mode_match = obedit ? ts->select_through_edit : ts->select_through_object; - if (STREQ(tref->idname, "builtin.select_box") || - STREQ(tref->idname_fallback, "builtin.select_box")) - { - if (mode_match && ts->select_through && ts->select_through_box) { - ts->select_through ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->select_through_edit ^= true; + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_select_through; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_select_through; + const bool box_circle_lasso = U.sync_box && box_op && U.sync_circle && U.sync_lasso && lasso_op; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + /* Off in the active mode and On in the other mode = Both */ + if (obedit && U.select_through_box == 1 || !obedit && U.select_through_box == 2) { + U.select_through_box = 3; + + if (box_circle_lasso || box_lasso) { + U.select_through_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.select_through_circle = 3; + } + } + /* if toggle mode == Current, Off Edit = On Edit, Both Object = Edit only */ + else if (U.select_through_toggle == 1 && + (obedit && U.select_through_box == 0 || !obedit && U.select_through_box == 3)) + { + U.select_through_box = 2; + + if (box_circle_lasso || box_lasso) { + U.select_through_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.select_through_circle = 2; + } + } + /* if toggle mode == Current, Off Object = On Object, Both Edit = Object only */ + else if (U.select_through_toggle == 1 && + (!obedit && U.select_through_box == 0 || obedit && U.select_through_box == 3)) + { + U.select_through_box = 1; + + if (box_circle_lasso || box_lasso) { + U.select_through_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.select_through_circle = 1; + } + } + /* otherwise On = Off */ + else if (U.select_through_box != 0) { + U.select_through_box = 0; + + if (box_circle_lasso || box_lasso) { + U.select_through_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.select_through_circle = 0; + } + } + /* and Off = Both */ + else { + U.select_through_box = 3; + + if (box_circle_lasso || box_lasso) { + U.select_through_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.select_through_circle = 3; + } + } + } + else if (lasso) { + if (obedit && U.select_through_lasso == 1 || !obedit && U.select_through_lasso == 2) { + U.select_through_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.select_through_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_circle = 3; + } + } + else if (U.select_through_toggle == 1 && (obedit && U.select_through_lasso == 0 || + !obedit && U.select_through_lasso == 3)) + { + U.select_through_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.select_through_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_circle = 2; + } + } + else if (U.select_through_toggle == 1 && (!obedit && U.select_through_lasso == 0 || + obedit && U.select_through_lasso == 3)) + { + U.select_through_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.select_through_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_circle = 1; + } + } + else if (U.select_through_lasso != 0) { + U.select_through_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.select_through_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_circle = 0; + } + } + else { + U.select_through_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.select_through_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_circle = 3; + } + } } else { - ts->select_through_object ^= true; + if (obedit && U.select_through_circle == 1 || !obedit && U.select_through_circle == 2) { + U.select_through_circle = 3; + + if (box_circle_lasso || box_circle) { + U.select_through_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_lasso = 3; + } + } + else if (U.select_through_toggle == 1 && (obedit && U.select_through_circle == 0 || + !obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 2; + + if (box_circle_lasso || box_circle) { + U.select_through_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_lasso = 2; + } + } + else if (U.select_through_toggle == 1 && (!obedit && U.select_through_circle == 0 || + obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 1; + + if (box_circle_lasso || box_circle) { + U.select_through_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_lasso = 1; + } + } + else if (U.select_through_circle != 0) { + U.select_through_circle = 0; + + if (box_circle_lasso || box_circle) { + U.select_through_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_lasso = 0; + } + } + else { + U.select_through_circle = 3; + + if (box_circle_lasso || box_circle) { + U.select_through_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.select_through_lasso = 3; + } + } } } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (obedit && U.select_through_lasso == 1 || !obedit && U.select_through_lasso == 2) { + U.select_through_lasso = 3; - if (!ts->select_through) { - ts->select_through ^= true; - } + if (circle_lasso) { + U.select_through_circle = 3; + } + } + else if (U.select_through_toggle_lasso == 1 && (obedit && U.select_through_lasso == 0 || + !obedit && U.select_through_lasso == 3)) + { + U.select_through_lasso = 2; - if (!ts->select_through_box) { - ts->select_through_box ^= true; - } - } - } - else if (STREQ(tref->idname, "builtin.select_lasso") || - STREQ(tref->idname_fallback, "builtin.select_lasso")) - { - if (mode_match && ts->select_through && ts->select_through_lasso) { - ts->select_through ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->select_through_edit ^= true; + if (circle_lasso) { + U.select_through_circle = 2; + } + } + else if (U.select_through_toggle_lasso == 1 && (!obedit && U.select_through_lasso == 0 || + obedit && U.select_through_lasso == 3)) + { + U.select_through_lasso = 1; + + if (circle_lasso) { + U.select_through_circle = 1; + } + } + else if (U.select_through_lasso != 0) { + U.select_through_lasso = 0; + + if (circle_lasso) { + U.select_through_circle = 0; + } + } + else { + U.select_through_lasso = 3; + + if (circle_lasso) { + U.select_through_circle = 3; + } + } } else { - ts->select_through_object ^= true; + if (obedit && U.select_through_circle == 1 || !obedit && U.select_through_circle == 2) { + U.select_through_circle = 3; + + if (circle_lasso) { + U.select_through_lasso = 3; + } + } + else if (U.select_through_toggle_lasso == 1 && (obedit && U.select_through_circle == 0 || + !obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 2; + + if (circle_lasso) { + U.select_through_lasso = 2; + } + } + else if (U.select_through_toggle_lasso == 1 && + (!obedit && U.select_through_circle == 0 || + obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 1; + + if (circle_lasso) { + U.select_through_lasso = 1; + } + } + else if (U.select_through_circle != 0) { + U.select_through_circle = 0; + + if (circle_lasso) { + U.select_through_lasso = 0; + } + } + else { + U.select_through_circle = 3; + + if (circle_lasso) { + U.select_through_lasso = 3; + } + } } } - - if (!ts->select_through) { - ts->select_through ^= true; - } - - if (!ts->select_through_lasso) { - ts->select_through_lasso ^= true; - } - } - } - else if (STREQ(tref->idname, "builtin.select_circle") || - STREQ(tref->idname_fallback, "builtin.select_circle")) - { - if (mode_match && ts->select_through && ts->select_through_circle) { - ts->select_through ^= true; - } - else { - if (!mode_match) { - if (obedit) { - ts->select_through_edit ^= true; + else if (circle) { + if (obedit && U.select_through_circle == 1 || !obedit && U.select_through_circle == 2) { + U.select_through_circle = 3; + } + else if (U.select_through_toggle_circle == 1 && (obedit && U.select_through_circle == 0 || + !obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 2; + } + else if (U.select_through_toggle_circle == 1 && (!obedit && U.select_through_circle == 0 || + obedit && U.select_through_circle == 3)) + { + U.select_through_circle = 1; + } + else if (U.select_through_circle != 0) { + U.select_through_circle = 0; } else { - ts->select_through_object ^= true; + U.select_through_circle = 3; } } - - if (!ts->select_through) { - ts->select_through ^= true; + } + else { + if (obedit && U.select_through_box == 1 || !obedit && U.select_through_box == 2) { + U.select_through_box = 3; } - - if (!ts->select_through_circle) { - ts->select_through_circle ^= true; + else if (U.select_through_toggle == 1 && + (obedit && U.select_through_box == 0 || !obedit && U.select_through_box == 3)) + { + U.select_through_box = 2; + } + else if (U.select_through_toggle == 1 && + (!obedit && U.select_through_box == 0 || obedit && U.select_through_box == 3)) + { + U.select_through_box = 1; + } + else if (U.select_through_box != 0) { + U.select_through_box = 0; + } + else { + U.select_through_box = 3; } } + ED_area_tag_redraw(area); } - - ED_area_tag_redraw(area); - return OPERATOR_FINISHED; } void VIEW3D_OT_toggle_select_through(wmOperatorType *ot) { /* identifiers */ - ot->name = "Toggle Select Through"; + ot->name = "Select Through"; ot->idname = "VIEW3D_OT_toggle_select_through"; - ot->description = "Select occluded objects and mesh elements with box, lasso, and circle select"; + ot->description = "Select occluded objects and mesh with box, lasso, and circle select"; /* api callbacks */ ot->exec = toggle_select_through_exec; @@ -1458,6 +1971,232 @@ void VIEW3D_OT_toggle_select_through(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Toggle Backface Filter + * \{ */ + +static int toggle_backface_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + Object *obedit = CTX_data_edit_object(C); + bToolRef *tref = area->runtime.tool; + + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_backface; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_backface; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_circle_lasso = (box || circle || lasso) && U.sync_box && box_op && + U.sync_circle && U.sync_lasso && lasso_op; + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + if (U.backface_box != 0) { + U.backface_box = 0; + + if (box_circle_lasso || box_lasso) { + U.backface_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 0; + } + } + else if (U.backface_toggle == 1) { + U.backface_box = 2; + + if (box_circle_lasso || box_lasso) { + U.backface_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 2; + } + } + else { + U.backface_box = 1; + + if (box_circle_lasso || box_lasso) { + U.backface_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 1; + } + } + } + else if (lasso) { + if (U.backface_lasso != 0) { + U.backface_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.backface_box = 0; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 0; + } + } + else if (U.backface_toggle == 1) { + U.backface_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.backface_box = 2; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 2; + } + } + else { + U.backface_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.backface_box = 1; + } + + if (box_circle_lasso || box_circle) { + U.backface_circle = 1; + } + } + } + else { + if (U.backface_circle != 0) { + U.backface_circle = 0; + + if (box_circle_lasso || box_circle) { + U.backface_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.backface_lasso = 0; + } + } + else if (U.backface_toggle == 1) { + U.backface_circle = 2; + + if (box_circle_lasso || box_circle) { + U.backface_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.backface_lasso = 2; + } + } + else { + U.backface_circle = 1; + + if (box_circle_lasso || box_circle) { + U.backface_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.backface_lasso = 1; + } + } + } + } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (U.backface_lasso != 0) { + U.backface_lasso = 0; + + if (circle_lasso) { + U.backface_circle = 0; + } + } + else if (U.backface_toggle_lasso == 1) { + U.backface_lasso = 2; + + if (circle_lasso) { + U.backface_circle = 2; + } + } + else { + U.backface_lasso = 1; + + if (circle_lasso) { + U.backface_circle = 1; + } + } + } + else { + if (U.backface_circle != 0) { + U.backface_circle = 0; + + if (circle_lasso) { + U.backface_lasso = 0; + } + } + else if (U.backface_toggle_lasso == 1) { + U.backface_circle = 2; + + if (circle_lasso) { + U.backface_lasso = 2; + } + } + else { + U.backface_circle = 1; + + if (circle_lasso) { + U.backface_lasso = 1; + } + } + } + } + else if (circle) { + if (U.backface_circle != 0) { + U.backface_circle = 0; + } + else if (U.backface_toggle_circle == 1) { + U.backface_circle = 2; + } + else { + U.backface_circle = 1; + } + } + } + else { + if (U.backface_box != 0) { + U.backface_box = 0; + } + else if (U.backface_toggle == 1) { + U.backface_box = 2; + } + else { + U.backface_box = 1; + } + } + ED_area_tag_redraw(area); + } + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_toggle_backface(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Backface Filter"; + ot->idname = "VIEW3D_OT_toggle_backface"; + ot->description = + "Select mesh based on the direciton of their normals with box, lasso, and circle select"; + + /* api callbacks */ + ot->exec = toggle_backface_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Toggle Facedots * \{ */ @@ -1466,12 +2205,20 @@ static int toggle_facedots_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); View3D *v3d = CTX_wm_view3d(C); - if (!XRAY_FLAG_ENABLED(v3d)) { + const bool solid = v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT; + const bool xray = v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT_XRAY; + + if (U.facedot_mode == 1 && xray == solid) { v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT; - } - else { v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT_XRAY; } + else if (XRAY_FLAG_ENABLED(v3d)) { + v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT_XRAY; + } + else { + v3d->overlay.edit_flag ^= V3D_OVERLAY_EDIT_FACE_DOT; + } + ED_area_tag_redraw(area); return OPERATOR_FINISHED; } @@ -1489,6 +2236,77 @@ void VIEW3D_OT_toggle_facedots(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Cycle Shading Mode + * \{ */ + +static int cycle_shading_exec(bContext *C, wmOperator *op) +{ + ScrArea *area = CTX_wm_area(C); + View3D *v3d = CTX_wm_view3d(C); + + if (v3d->shading.type == OB_WIRE) { + if (U.shading_cycle_solid) { + v3d->shading.type = OB_SOLID; + } + else if (U.shading_cycle_material) { + v3d->shading.type = OB_MATERIAL; + } + else if (U.shading_cycle_render) { + v3d->shading.type = OB_RENDER; + } + } + else if (v3d->shading.type == OB_SOLID) { + if (U.shading_cycle_material) { + v3d->shading.type = OB_MATERIAL; + } + else if (U.shading_cycle_render) { + v3d->shading.type = OB_RENDER; + } + else if (U.shading_cycle_wire) { + v3d->shading.type = OB_WIRE; + } + } + else if (v3d->shading.type == OB_MATERIAL) { + if (U.shading_cycle_render) { + v3d->shading.type = OB_RENDER; + } + else if (U.shading_cycle_wire) { + v3d->shading.type = OB_WIRE; + } + else if (U.shading_cycle_solid) { + v3d->shading.type = OB_SOLID; + } + } + else { + if (U.shading_cycle_wire) { + v3d->shading.type = OB_WIRE; + } + else if (U.shading_cycle_solid) { + v3d->shading.type = OB_SOLID; + } + else if (U.shading_cycle_material) { + v3d->shading.type = OB_MATERIAL; + } + } + + ED_area_tag_redraw(area); + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_cycle_shading(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Cycle Shading Mode"; + ot->idname = "VIEW3D_OT_cycle_shading"; + ot->description = "Switch to the next shading mode in the cycle"; + /* api callbacks */ + ot->exec = cycle_shading_exec; + ot->poll = ED_operator_view3d_active; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Cycle Object Mode * \{ */ @@ -1496,37 +2314,407 @@ void VIEW3D_OT_toggle_facedots(wmOperatorType *ot) static int cycle_object_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - ToolSettings *ts = CTX_data_tool_settings(C); + bToolRef *tref = area->runtime.tool; - if (ts->object_select_mode == 2) { - if (ts->object_cycle_origin) { - ts->object_select_mode = 4; - } - else if (ts->object_cycle_touch) { - ts->object_select_mode = 1; - } - } - else if (ts->object_select_mode == 4) { - if (ts->object_cycle_touch) { - ts->object_select_mode = 1; - } - else if (ts->object_cycle_enclose) { - ts->object_select_mode = 2; - } - } - else { - if (ts->object_cycle_enclose) { - ts->object_select_mode = 2; - } - else if (ts->object_cycle_origin) { - ts->object_select_mode = 4; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_object; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_object; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_circle_lasso = (box || circle || lasso) && U.sync_box && box_op && + U.sync_circle && U.sync_lasso && lasso_op; + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + if (U.object_select_box == 1) { + if (U.object_cycle_origin) { + U.object_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 2; + } + } + else if (U.object_cycle_touch) { + U.object_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 0; + } + } + } + else if (U.object_select_box == 2) { + if (U.object_cycle_touch) { + U.object_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 0; + } + } + else if (U.object_cycle_enclose) { + U.object_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 1; + } + } + } + else { + if (U.object_cycle_enclose) { + U.object_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 1; + } + } + else if (U.object_cycle_origin) { + U.object_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.object_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.object_select_circle = 2; + } + } + } + } + else if (lasso) { + if (U.object_select_lasso == 1) { + if (U.object_cycle_origin) { + U.object_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 2; + } + } + else if (U.object_cycle_touch) { + U.object_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 0; + } + } + } + else if (U.object_select_lasso == 2) { + if (U.object_cycle_touch) { + U.object_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 0; + } + } + else if (U.object_cycle_enclose) { + U.object_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 1; + } + } + } + else { + if (U.object_cycle_enclose) { + U.object_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 1; + } + } + else if (U.object_cycle_origin) { + U.object_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.object_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_circle = 2; + } + } + } + } + else { + if (U.object_select_circle == 1) { + if (U.object_cycle_origin) { + U.object_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 2; + } + } + else if (U.object_cycle_touch) { + U.object_select_circle = 0; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 0; + } + } + } + else if (U.object_select_circle == 2) { + if (U.object_cycle_touch) { + U.object_select_circle = 0; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 0; + } + } + else if (U.object_cycle_enclose) { + U.object_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 1; + } + } + } + else { + if (U.object_cycle_enclose) { + U.object_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 1; + } + } + else if (U.object_cycle_origin) { + U.object_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.object_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.object_select_lasso = 2; + } + } + } + } + } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (U.object_select_lasso == 1) { + if (U.object_cycle_origin_lasso) { + U.object_select_lasso = 2; + + if (circle_lasso) { + U.object_select_circle = 2; + } + } + else if (U.object_cycle_touch_lasso) { + U.object_select_lasso = 0; + + if (circle_lasso) { + U.object_select_circle = 0; + } + } + } + else if (U.object_select_lasso == 2) { + if (U.object_cycle_touch_lasso) { + U.object_select_lasso = 0; + + if (circle_lasso) { + U.object_select_circle = 0; + } + } + else if (U.object_cycle_enclose_lasso) { + U.object_select_lasso = 1; + + if (circle_lasso) { + U.object_select_circle = 1; + } + } + } + else { + if (U.object_cycle_enclose_lasso) { + U.object_select_lasso = 1; + + if (circle_lasso) { + U.object_select_circle = 1; + } + } + else if (U.object_cycle_origin_lasso) { + U.object_select_lasso = 2; + + if (circle_lasso) { + U.object_select_circle = 2; + } + } + } + } + else { + if (U.object_select_circle == 1) { + if (U.object_cycle_origin_lasso) { + U.object_select_circle = 2; + + if (circle_lasso) { + U.object_select_lasso = 2; + } + } + else if (U.object_cycle_touch_lasso) { + U.object_select_circle = 0; + + if (circle_lasso) { + U.object_select_lasso = 0; + } + } + } + else if (U.object_select_circle == 2) { + if (U.object_cycle_touch_lasso) { + U.object_select_circle = 0; + + if (circle_lasso) { + U.object_select_lasso = 0; + } + } + else if (U.object_cycle_enclose_lasso) { + U.object_select_circle = 1; + + if (circle_lasso) { + U.object_select_lasso = 1; + } + } + } + else { + if (U.object_cycle_enclose_lasso) { + U.object_select_circle = 1; + + if (circle_lasso) { + U.object_select_lasso = 1; + } + } + else if (U.object_cycle_origin_lasso) { + U.object_select_circle = 2; + + if (circle_lasso) { + U.object_select_lasso = 2; + } + } + } + } + } + else if (circle) { + if (U.object_select_circle == 1) { + if (U.object_cycle_origin_circle) { + U.object_select_circle = 2; + } + else if (U.object_cycle_touch_circle) { + U.object_select_circle = 0; + } + } + else if (U.object_select_circle == 2) { + if (U.object_cycle_touch_circle) { + U.object_select_circle = 0; + } + else if (U.object_cycle_enclose_circle) { + U.object_select_circle = 1; + } + } + else { + if (U.object_cycle_enclose_circle) { + U.object_select_circle = 1; + } + else if (U.object_cycle_origin_circle) { + U.object_select_circle = 2; + } + } + } } else { - ts->object_select_mode = 1; + if (U.object_select_box == 1) { + if (U.object_cycle_origin) { + U.object_select_box = 2; + } + else if (U.object_cycle_touch) { + U.object_select_box = 0; + } + } + else if (U.object_select_box == 2) { + if (U.object_cycle_touch) { + U.object_select_box = 0; + } + else if (U.object_cycle_enclose) { + U.object_select_box = 1; + } + } + else { + if (U.object_cycle_enclose) { + U.object_select_box = 1; + } + else if (U.object_cycle_origin) { + U.object_select_box = 2; + } + } } + ED_area_tag_redraw(area); } - - ED_area_tag_redraw(area); return OPERATOR_FINISHED; } @@ -1550,57 +2738,739 @@ void VIEW3D_OT_cycle_object(wmOperatorType *ot) static int cycle_face_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - ToolSettings *ts = CTX_data_tool_settings(C); + bToolRef *tref = area->runtime.tool; - if (ts->face_select_mode == 2) { - if (ts->face_cycle_enclose) { - ts->face_select_mode = 4; - } - else if (ts->face_cycle_center) { - ts->face_select_mode = 8; - } - else if (ts->face_cycle_default) { - ts->face_select_mode = 1; - } - } - else if (ts->face_select_mode == 4) { - if (ts->face_cycle_center) { - ts->face_select_mode = 8; - } - else if (ts->face_cycle_default) { - ts->face_select_mode = 1; - } - else if (ts->face_cycle_touch) { - ts->face_select_mode = 2; - } - } - else if (ts->face_select_mode == 8) { - if (ts->face_cycle_default) { - ts->face_select_mode = 1; - } - else if (ts->face_cycle_touch) { - ts->face_select_mode = 2; - } - else if (ts->face_cycle_enclose) { - ts->face_select_mode = 4; - } - } - else { - if (ts->face_cycle_touch) { - ts->face_select_mode = 2; - } - else if (ts->face_cycle_enclose) { - ts->face_select_mode = 4; - } - else if (ts->face_cycle_center) { - ts->face_select_mode = 8; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_face; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_face; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_circle_lasso = (box || circle || lasso) && U.sync_box && box_op && + U.sync_circle && U.sync_lasso && lasso_op; + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + if (U.face_select_box == 1) { + if (U.face_cycle_enclose) { + U.face_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_box = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 0; + } + } + } + else if (U.face_select_box == 2) { + if (U.face_cycle_center) { + U.face_select_box = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 1; + } + } + } + else if (U.face_select_box == 3) { + if (U.face_cycle_default) { + U.face_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 2; + } + } + } + else { + if (U.face_cycle_touch) { + U.face_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_box = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_lasso = 3; + } + + if (box_circle_lasso || box_circle) { + U.face_select_circle = 3; + } + } + } + } + else if (lasso) { + if (U.face_select_lasso == 1) { + if (U.face_cycle_enclose) { + U.face_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 0; + } + } + } + else if (U.face_select_lasso == 2) { + if (U.face_cycle_center) { + U.face_select_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 1; + } + } + } + else if (U.face_select_lasso == 3) { + if (U.face_cycle_default) { + U.face_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 2; + } + } + } + else { + if (U.face_cycle_touch) { + U.face_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_lasso = 3; + + if (box_circle_lasso || box_lasso) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_circle = 3; + } + } + } + } + else { + if (U.face_select_circle == 1) { + if (U.face_cycle_enclose) { + U.face_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_circle = 3; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_circle = 0; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 0; + } + } + } + else if (U.face_select_circle == 2) { + if (U.face_cycle_center) { + U.face_select_circle = 3; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 3; + } + } + else if (U.face_cycle_default) { + U.face_select_circle = 0; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 1; + } + } + } + else if (U.face_select_circle == 3) { + if (U.face_cycle_default) { + U.face_select_circle = 0; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 0; + } + } + else if (U.face_cycle_touch) { + U.face_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 2; + } + } + } + else { + if (U.face_cycle_touch) { + U.face_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 1; + } + } + else if (U.face_cycle_enclose) { + U.face_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 2; + } + } + else if (U.face_cycle_center) { + U.face_select_circle = 3; + + if (box_circle_lasso || box_circle) { + U.face_select_box = 3; + } + + if (box_circle_lasso || circle_lasso) { + U.face_select_lasso = 3; + } + } + } + } + } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (U.face_select_lasso == 1) { + if (U.face_cycle_enclose_lasso) { + U.face_select_lasso = 2; + + if (circle_lasso) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center_lasso) { + U.face_select_lasso = 3; + + if (circle_lasso) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default_lasso) { + U.face_select_lasso = 0; + + if (circle_lasso) { + U.face_select_circle = 0; + } + } + } + else if (U.face_select_lasso == 2) { + if (U.face_cycle_center_lasso) { + U.face_select_lasso = 3; + + if (circle_lasso) { + U.face_select_circle = 3; + } + } + else if (U.face_cycle_default_lasso) { + U.face_select_lasso = 0; + + if (circle_lasso) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch_lasso) { + U.face_select_lasso = 1; + + if (circle_lasso) { + U.face_select_circle = 1; + } + } + } + else if (U.face_select_lasso == 3) { + if (U.face_cycle_default_lasso) { + U.face_select_lasso = 0; + + if (circle_lasso) { + U.face_select_circle = 0; + } + } + else if (U.face_cycle_touch_lasso) { + U.face_select_lasso = 1; + + if (circle_lasso) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose_lasso) { + U.face_select_lasso = 2; + + if (circle_lasso) { + U.face_select_circle = 2; + } + } + } + else { + if (U.face_cycle_touch_lasso) { + U.face_select_lasso = 1; + + if (circle_lasso) { + U.face_select_circle = 1; + } + } + else if (U.face_cycle_enclose_lasso) { + U.face_select_lasso = 2; + + if (circle_lasso) { + U.face_select_circle = 2; + } + } + else if (U.face_cycle_center_lasso) { + U.face_select_lasso = 3; + + if (circle_lasso) { + U.face_select_circle = 3; + } + } + } + } + else { + if (U.face_select_circle == 1) { + if (U.face_cycle_enclose_lasso) { + U.face_select_circle = 2; + + if (circle_lasso) { + U.face_select_lasso = 2; + } + } + else if (U.face_cycle_center_lasso) { + U.face_select_circle = 3; + + if (circle_lasso) { + U.face_select_lasso = 3; + } + } + else if (U.face_cycle_default_lasso) { + U.face_select_circle = 0; + + if (circle_lasso) { + U.face_select_lasso = 0; + } + } + } + else if (U.face_select_circle == 2) { + if (U.face_cycle_center_lasso) { + U.face_select_circle = 3; + + if (circle_lasso) { + U.face_select_lasso = 3; + } + } + else if (U.face_cycle_default_lasso) { + U.face_select_circle = 0; + + if (circle_lasso) { + U.face_select_lasso = 0; + } + } + else if (U.face_cycle_touch_lasso) { + U.face_select_circle = 1; + + if (circle_lasso) { + U.face_select_lasso = 1; + } + } + } + else if (U.face_select_circle == 3) { + if (U.face_cycle_default_lasso) { + U.face_select_circle = 0; + + if (circle_lasso) { + U.face_select_lasso = 0; + } + } + else if (U.face_cycle_touch_lasso) { + U.face_select_circle = 1; + + if (circle_lasso) { + U.face_select_lasso = 1; + } + } + else if (U.face_cycle_enclose_lasso) { + U.face_select_circle = 2; + + if (circle_lasso) { + U.face_select_lasso = 2; + } + } + } + else { + if (U.face_cycle_touch_lasso) { + U.face_select_circle = 1; + + if (circle_lasso) { + U.face_select_lasso = 1; + } + } + else if (U.face_cycle_enclose_lasso) { + U.face_select_circle = 2; + + if (circle_lasso) { + U.face_select_lasso = 2; + } + } + else if (U.face_cycle_center_lasso) { + U.face_select_circle = 3; + + if (circle_lasso) { + U.face_select_lasso = 3; + } + } + } + } + } + else if (circle) { + if (U.face_select_circle == 1) { + if (U.face_cycle_enclose_circle) { + U.face_select_circle = 2; + } + else if (U.face_cycle_center_circle) { + U.face_select_circle = 3; + } + else if (U.face_cycle_default_circle) { + U.face_select_circle = 0; + } + } + else if (U.face_select_circle == 2) { + if (U.face_cycle_center_circle) { + U.face_select_circle = 3; + } + else if (U.face_cycle_default_circle) { + U.face_select_circle = 0; + } + else if (U.face_cycle_touch_circle) { + U.face_select_circle = 1; + } + } + else if (U.face_select_circle == 3) { + if (U.face_cycle_default_circle) { + U.face_select_circle = 0; + } + else if (U.face_cycle_touch_circle) { + U.face_select_circle = 1; + } + else if (U.face_cycle_enclose_circle) { + U.face_select_circle = 2; + } + } + else { + if (U.face_cycle_touch_circle) { + U.face_select_circle = 1; + } + else if (U.face_cycle_enclose_circle) { + U.face_select_circle = 2; + } + else if (U.face_cycle_center_circle) { + U.face_select_circle = 3; + } + } + } } else { - ts->face_select_mode = 1; + if (U.face_select_box == 1) { + if (U.face_cycle_enclose) { + U.face_select_box = 2; + } + else if (U.face_cycle_center) { + U.face_select_box = 3; + } + else if (U.face_cycle_default) { + U.face_select_box = 0; + } + } + else if (U.face_select_box == 2) { + if (U.face_cycle_center) { + U.face_select_box = 3; + } + else if (U.face_cycle_default) { + U.face_select_box = 0; + } + else if (U.face_cycle_touch) { + U.face_select_box = 1; + } + } + else if (U.face_select_box == 3) { + if (U.face_cycle_default) { + U.face_select_box = 0; + } + else if (U.face_cycle_touch) { + U.face_select_box = 1; + } + else if (U.face_cycle_enclose) { + U.face_select_box = 2; + } + } + else { + if (U.face_cycle_touch) { + U.face_select_box = 1; + } + else if (U.face_cycle_enclose) { + U.face_select_box = 2; + } + else if (U.face_cycle_center) { + U.face_select_box = 3; + } + } } + ED_area_tag_redraw(area); } - - ED_area_tag_redraw(area); return OPERATOR_FINISHED; } @@ -1624,37 +3494,391 @@ void VIEW3D_OT_cycle_face(wmOperatorType *ot) static int cycle_edge_exec(bContext *C, wmOperator *op) { ScrArea *area = CTX_wm_area(C); - ToolSettings *ts = CTX_data_tool_settings(C); + bToolRef *tref = area->runtime.tool; - if (ts->edge_select_mode == 2) { - if (ts->edge_cycle_enclose) { - ts->edge_select_mode = 4; - } - else if (ts->edge_cycle_default) { - ts->edge_select_mode = 1; - } - } - else if (ts->edge_select_mode == 4) { - if (ts->edge_cycle_default) { - ts->edge_select_mode = 1; - } - else if (ts->edge_cycle_touch) { - ts->edge_select_mode = 2; - } - } - else { - if (ts->edge_cycle_touch) { - ts->edge_select_mode = 2; - } - else if (ts->edge_cycle_enclose) { - ts->edge_select_mode = 4; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1) { + const bool box_op = U.drag_direction_box == 0 || + U.drag_direction_mode == 1 && !U.direction_edge; + const bool lasso_op = U.drag_direction_lasso == 0 || + U.drag_direction_mode == 1 && !U.direction_edge; + const bool box = STREQ(tref->idname, "builtin.select_box") || + STREQ(tref->idname_fallback, "builtin.select_box"); + const bool lasso = STREQ(tref->idname, "builtin.select_lasso") || + STREQ(tref->idname_fallback, "builtin.select_lasso"); + const bool circle = STREQ(tref->idname, "builtin.select_circle") || + STREQ(tref->idname_fallback, "builtin.select_circle"); + const bool box_circle_lasso = (box || circle || lasso) && U.sync_box && box_op && + U.sync_circle && U.sync_lasso && lasso_op; + const bool box_lasso = (box || lasso) && lasso_op && U.sync_lasso && box_op && U.sync_box; + const bool box_circle = (box || circle) && U.sync_circle && box_op && U.sync_box; + const bool circle_lasso = (lasso || circle) && U.sync_circle && lasso_op && U.sync_lasso; + + if (box && box_op || box_circle_lasso || box_lasso || box_circle) { + if (box) { + if (U.edge_select_box == 1) { + if (U.edge_cycle_enclose) { + U.edge_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 2; + } + } + else if (U.edge_cycle_default) { + U.edge_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 1; + } + } + } + else if (U.edge_select_box == 2) { + if (U.edge_cycle_default) { + U.edge_select_box = 0; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 0; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_touch) { + U.edge_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 1; + } + } + } + else { + if (U.edge_cycle_touch) { + U.edge_select_box = 1; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 1; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_enclose) { + U.edge_select_box = 2; + + if (box_circle_lasso || box_lasso) { + U.edge_select_lasso = 2; + } + + if (box_circle_lasso || box_circle) { + U.edge_select_circle = 2; + } + } + } + } + else if (lasso) { + if (U.edge_select_lasso == 1) { + if (U.edge_cycle_enclose) { + U.edge_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 2; + } + } + else if (U.edge_cycle_default) { + U.edge_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 1; + } + } + } + else if (U.edge_select_lasso == 2) { + if (U.edge_cycle_default) { + U.edge_select_lasso = 0; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_touch) { + U.edge_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 1; + } + } + } + else { + if (U.edge_cycle_touch) { + U.edge_select_lasso = 1; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_enclose) { + U.edge_select_lasso = 2; + + if (box_circle_lasso || box_lasso) { + U.edge_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_circle = 2; + } + } + } + } + else { + if (U.edge_select_circle == 1) { + if (U.edge_cycle_enclose) { + U.edge_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 2; + } + } + else if (U.edge_cycle_default) { + U.edge_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 0; + } + } + } + else if (U.edge_select_circle == 2) { + if (U.edge_cycle_default) { + U.edge_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 0; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 0; + } + } + else if (U.edge_cycle_touch) { + U.edge_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 1; + } + } + } + else { + if (U.edge_cycle_touch) { + U.edge_select_circle = 1; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 1; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 1; + } + } + else if (U.edge_cycle_enclose) { + U.edge_select_circle = 2; + + if (box_circle_lasso || box_circle) { + U.edge_select_box = 2; + } + + if (box_circle_lasso || circle_lasso) { + U.edge_select_lasso = 2; + } + } + } + } + } + else if (lasso && lasso_op || circle_lasso) { + if (lasso) { + if (U.edge_select_lasso == 1) { + if (U.edge_cycle_enclose_lasso) { + U.edge_select_lasso = 2; + + if (circle_lasso) { + U.edge_select_circle = 2; + } + } + else if (U.edge_cycle_default_lasso) { + U.edge_select_lasso = 0; + + if (circle_lasso) { + U.edge_select_circle = 1; + } + } + } + else if (U.edge_select_lasso == 2) { + if (U.edge_cycle_default_lasso) { + U.edge_select_lasso = 0; + + if (circle_lasso) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_touch_lasso) { + U.edge_select_lasso = 1; + + if (circle_lasso) { + U.edge_select_circle = 1; + } + } + } + else { + if (U.edge_cycle_touch_lasso) { + U.edge_select_lasso = 1; + + if (circle_lasso) { + U.edge_select_circle = 1; + } + } + else if (U.edge_cycle_enclose_lasso) { + U.edge_select_lasso = 2; + + if (circle_lasso) { + U.edge_select_circle = 2; + } + } + } + } + else { + if (U.edge_select_circle == 1) { + if (U.edge_cycle_enclose_lasso) { + U.edge_select_circle = 2; + + if (circle_lasso) { + U.edge_select_lasso = 2; + } + } + else if (U.edge_cycle_default_lasso) { + U.edge_select_circle = 1; + + if (circle_lasso) { + U.edge_select_lasso = 0; + } + } + } + else if (U.edge_select_circle == 2) { + if (U.edge_cycle_default_lasso) { + U.edge_select_circle = 1; + + if (circle_lasso) { + U.edge_select_lasso = 0; + } + } + else if (U.edge_cycle_touch_lasso) { + U.edge_select_circle = 1; + + if (circle_lasso) { + U.edge_select_lasso = 1; + } + } + } + else { + if (U.edge_cycle_touch_lasso) { + U.edge_select_circle = 1; + + if (circle_lasso) { + U.edge_select_lasso = 1; + } + } + else if (U.edge_cycle_enclose_lasso) { + U.edge_select_circle = 2; + + if (circle_lasso) { + U.edge_select_lasso = 2; + } + } + } + } + } + else if (circle) { + if (U.edge_select_circle == 1) { + if (U.edge_cycle_enclose_circle) { + U.edge_select_circle = 2; + } + } + else if (U.edge_cycle_touch_circle) { + U.edge_select_circle = 1; + } + } } else { - ts->edge_select_mode = 1; + if (U.edge_select_box == 1) { + if (U.edge_cycle_enclose) { + U.edge_select_box = 2; + } + else if (U.edge_cycle_default) { + U.edge_select_box = 0; + } + } + else if (U.edge_select_box == 2) { + if (U.edge_cycle_default) { + U.edge_select_box = 0; + } + else if (U.edge_cycle_touch) { + U.edge_select_box = 1; + } + } + else { + if (U.edge_cycle_touch) { + U.edge_select_box = 1; + } + else if (U.edge_cycle_enclose) { + U.edge_select_box = 2; + } + } } + ED_area_tag_redraw(area); } - - ED_area_tag_redraw(area); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 2440ee78929..59210e490ea 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -63,7 +63,9 @@ void VIEW3D_OT_toggle_shading(struct wmOperatorType *ot); void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot); void VIEW3D_OT_toggle_auto_xray(struct wmOperatorType *ot); void VIEW3D_OT_toggle_select_through(struct wmOperatorType *ot); +void VIEW3D_OT_toggle_backface(struct wmOperatorType *ot); void VIEW3D_OT_toggle_facedots(struct wmOperatorType *ot); +void VIEW3D_OT_cycle_shading(struct wmOperatorType *ot); void VIEW3D_OT_cycle_object(struct wmOperatorType *ot); void VIEW3D_OT_cycle_face(struct wmOperatorType *ot); void VIEW3D_OT_cycle_edge(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.cc b/source/blender/editors/space_view3d/view3d_ops.cc index a0fdc748789..698f1d37532 100644 --- a/source/blender/editors/space_view3d/view3d_ops.cc +++ b/source/blender/editors/space_view3d/view3d_ops.cc @@ -225,7 +225,9 @@ void view3d_operatortypes() WM_operatortype_append(VIEW3D_OT_toggle_matcap_flip); WM_operatortype_append(VIEW3D_OT_toggle_auto_xray); WM_operatortype_append(VIEW3D_OT_toggle_select_through); + WM_operatortype_append(VIEW3D_OT_toggle_backface); WM_operatortype_append(VIEW3D_OT_toggle_facedots); + WM_operatortype_append(VIEW3D_OT_cycle_shading); WM_operatortype_append(VIEW3D_OT_cycle_object); WM_operatortype_append(VIEW3D_OT_cycle_face); WM_operatortype_append(VIEW3D_OT_cycle_edge); diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 00a3d8cde2c..d0392e2d81a 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -116,8 +116,10 @@ using namespace blender; float ED_view3d_select_dist_px() { - if (U.flag & USER_ADJUSTABLE_CLICK_SELECT) { - return U.selection_radius * U.pixelsize; + const float radius = U.selection_radius == 0 ? 0.1f : (float)U.selection_radius; + + if (U.adjustable_click_select == 1) { + return radius * U.pixelsize; } else { return 75.0f * U.pixelsize; @@ -726,19 +728,10 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, float view[3], mesh_co[3], mesh_no[3]; bool mesh_facing = false; - for (int i = 0; i < 3; i++) { - if (persp) { - view[i] = vc->rv3d->viewinv[3][i]; - } - else { - view[i] = vc->rv3d->viewmat[i][2]; - } - } - if (persp) { if (face) { BMIter iter; - BMVert *eve; + BMVert *v; int vcount = 0; mesh_no[0] = efa->no[0]; mesh_no[1] = efa->no[1]; @@ -746,20 +739,20 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, if (efa->len == 3) { float tri[3][3]; - BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { - tri[vcount][0] = eve->co[0]; - tri[vcount][1] = eve->co[1]; - tri[vcount][2] = eve->co[2]; + BM_ITER_ELEM (v, &iter, efa, BM_VERTS_OF_FACE) { + tri[vcount][0] = v->co[0]; + tri[vcount][1] = v->co[1]; + tri[vcount][2] = v->co[2]; vcount++; } mid_v3_v3v3v3(mesh_co, tri[0], tri[1], tri[2]); } else if (efa->len == 4) { float quad[4][3]; - BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { - quad[vcount][0] = eve->co[0]; - quad[vcount][1] = eve->co[1]; - quad[vcount][2] = eve->co[2]; + BM_ITER_ELEM (v, &iter, efa, BM_VERTS_OF_FACE) { + quad[vcount][0] = v->co[0]; + quad[vcount][1] = v->co[1]; + quad[vcount][2] = v->co[2]; vcount++; } mid_v3_v3v3v3v3(mesh_co, quad[0], quad[1], quad[2], quad[3]); @@ -767,10 +760,10 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, else { float(*ngon)[3] = static_cast( MEM_mallocN(sizeof(float) * 3 * efa->len, __func__)); - BM_ITER_ELEM (eve, &iter, efa, BM_VERTS_OF_FACE) { - ngon[vcount][0] = eve->co[0]; - ngon[vcount][1] = eve->co[1]; - ngon[vcount][2] = eve->co[2]; + BM_ITER_ELEM (v, &iter, efa, BM_VERTS_OF_FACE) { + ngon[vcount][0] = v->co[0]; + ngon[vcount][1] = v->co[1]; + ngon[vcount][2] = v->co[2]; vcount++; } mid_v3_v3_array(mesh_co, ngon, efa->len); @@ -787,15 +780,9 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, mesh_co[i] = eve->co[i]; } } - - mesh_co[0] -= view[0]; - mesh_co[1] -= view[1]; - mesh_co[2] -= view[2]; - normalize_v3(mesh_co); } else { float plane[3], meshmat[3][3]; - if (vert) { edbm_vert_orientation(eve, mesh_no, plane, meshmat); } @@ -826,40 +813,127 @@ bool edbm_mesh_facing_viewport(ViewContext *vc, mesh_no[2] = meshmat[2][2]; } - if (persp) { - mesh_facing = dot_v3v3(mesh_no, mesh_co) < 0.0f; - } - else { - mesh_facing = dot_v3v3(mesh_no, view) > 0.0f; + for (int i = 0; i < 3; i++) { + if (persp) { + mesh_co[i] += vc->obact->object_to_world[3][i]; + view[i] = vc->rv3d->viewinv[3][i] - mesh_co[i]; + + if (i == 2) { + normalize_v3(view); + } + } + else { + view[i] = vc->rv3d->viewmat[i][2]; + } } + mesh_facing = dot_v3v3(mesh_no, view) > 0.0f; + return mesh_facing; } -bool edbm_check_mesh_facing(ToolSettings *ts, wmOperator *op, const bool zbuf) +bool edbm_check_mesh_facing( + wmOperator *op, const bool zbuf, const bool lasso, const bool circle, const bool zbuf_vert) { bool check_facing = false; - if (ts->select_header) { - check_facing = zbuf ? ts->backface_select && - (ts->backface_select_mode == 2 || ts->backface_select_mode == 8) : - ts->backface_select && - (ts->backface_select_mode == 4 || ts->backface_select_mode == 8); + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && lasso) { + if (zbuf) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_backface)) { + check_facing = zbuf_vert ? + U.backface_downright_lasso == 1 : + U.backface_downright_lasso == 1 || U.backface_downright_lasso == 2; + } + else { + check_facing = zbuf_vert ? U.backface_lasso == 1 : + U.backface_lasso == 1 || U.backface_lasso == 2; + } + } + else { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_backface)) { + check_facing = U.backface_downright_lasso == 1; + } + else { + check_facing = U.backface_lasso == 1; + } + } + } + else if (U.userpref_mode == 1 && circle) { + if (zbuf) { + check_facing = zbuf_vert ? U.backface_circle == 1 : + U.backface_circle == 1 || U.backface_circle == 2; + } + else { + check_facing = U.backface_circle == 1; + } + } + else { + if (zbuf) { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_backface)) + { + check_facing = zbuf_vert ? + U.backface_downright_box == 1 : + U.backface_downright_box == 1 || U.backface_downright_box == 2; + } + else { + check_facing = zbuf_vert ? U.backface_box == 1 : + U.backface_box == 1 || U.backface_box == 2; + } + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_backface)) + { + check_facing = U.backface_downright_box == 1; + } + else { + check_facing = U.backface_box == 1; + } + } + } } else { const int mode = RNA_enum_get(op->ptr, "backface_filter"); - check_facing = zbuf ? mode == 2 || mode == 8 : mode == 4 || mode == 8; + + if (zbuf) { + check_facing = zbuf_vert ? mode == 2 : mode == 2 || mode == 4; + } + else { + check_facing = mode == 2; + } } return check_facing; } -int object_style(ToolSettings *ts, wmOperator *op) +int object_style(wmOperator *op, const bool lasso, const bool circle) { int type = 0; - if (ts->select_header) { - type = ts->object_select_mode; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && lasso) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_object)) { + type = U.object_select_downright_lasso * 2; + } + else { + type = U.object_select_lasso * 2; + } + } + else if (U.userpref_mode == 1 && circle) { + type = U.object_select_circle * 2; + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_object)) + { + type = U.object_select_downright_box * 2; + } + else { + type = U.object_select_box * 2; + } + } } else { type = RNA_enum_get(op->ptr, "object_type"); @@ -872,12 +946,36 @@ int object_style(ToolSettings *ts, wmOperator *op) return type; } -int face_style(ToolSettings *ts, wmOperator *op) +int face_style(wmOperator *op, const bool lasso, const bool circle) { int type = 0; - if (ts->select_header) { - type = ts->face_select_mode; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && lasso) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_face)) { + type = U.face_select_downright_lasso * 2; + } + else { + type = U.face_select_lasso * 2; + } + } + else if (U.userpref_mode == 1 && circle) { + type = U.face_select_circle * 2; + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_face)) + { + type = U.face_select_downright_box * 2; + } + else { + type = U.face_select_box * 2; + } + } + + if (type == 6) { + type = 8; + } } else { type = RNA_enum_get(op->ptr, "face_type"); @@ -890,12 +988,32 @@ int face_style(ToolSettings *ts, wmOperator *op) return type; } -int edge_style(ToolSettings *ts, wmOperator *op) +int edge_style(wmOperator *op, const bool lasso, const bool circle) { int type = 0; - if (ts->select_header) { - type = ts->edge_select_mode; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && lasso) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_edge)) { + type = U.edge_select_downright_lasso * 2; + } + else { + type = U.edge_select_lasso * 2; + } + } + else if (U.userpref_mode == 1 && circle) { + type = U.edge_select_circle * 2; + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_edge)) + { + type = U.edge_select_downright_box * 2; + } + else { + type = U.edge_select_box * 2; + } + } } else { type = RNA_enum_get(op->ptr, "edge_type"); @@ -908,12 +1026,8 @@ int edge_style(ToolSettings *ts, wmOperator *op) return type; } -bool drag_select_through(View3D *v3d, - ToolSettings *ts, - wmOperator *op, - const bool mesh, - const bool lasso, - const bool circle) +bool drag_select_through( + View3D *v3d, wmOperator *op, const bool mesh, const bool lasso, const bool circle) { if (XRAY_FLAG_ENABLED(v3d)) { return true; @@ -921,13 +1035,58 @@ bool drag_select_through(View3D *v3d, bool select_through = false; - if (ts->xray_header) { - if (ts->select_through && mesh && ts->select_through_edit || - ts->select_through && !mesh && ts->select_through_object) - { - select_through = lasso ? ts->select_through_lasso : - circle ? ts->select_through_circle : - ts->select_through_box; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && circle) { + if (mesh) { + select_through = U.select_through_circle == 2 || U.select_through_circle == 3; + } + else { + select_through = U.select_through_circle == 1 || U.select_through_circle == 3; + } + } + else if (U.userpref_mode == 1 && lasso) { + if (mesh) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) { + select_through = U.select_through_downright_lasso == 2 || + U.select_through_downright_lasso == 3; + } + else { + select_through = U.select_through_lasso == 2 || U.select_through_lasso == 3; + } + } + else { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) { + select_through = U.select_through_downright_lasso == 1 || + U.select_through_downright_lasso == 3; + } + else { + select_through = U.select_through_lasso == 1 || U.select_through_lasso == 3; + } + } + } + else { + if (mesh) { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_auto_xray)) + { + select_through = U.select_through_downright_box == 2 || + U.select_through_downright_box == 3; + } + else { + select_through = U.select_through_box == 2 || U.select_through_box == 3; + } + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_auto_xray)) + { + select_through = U.select_through_downright_box == 1 || + U.select_through_downright_box == 3; + } + else { + select_through = U.select_through_box == 1 || U.select_through_box == 3; + } + } } } else { @@ -1237,17 +1396,19 @@ bool edbm_center_face(ViewContext *vc, } static bool edbm_backbuf_check_and_select_verts(ViewContext *vc, + wmOperator *op, EditSelectBuf_Cache *esel, Depsgraph *depsgraph, Object *ob, BMEditMesh *em, - const eSelectOp sel_op) + const eSelectOp sel_op, + const bool lasso, + const bool circle) { BMVert *eve; BMIter iter; - ToolSettings *ts = vc->scene->toolsettings; const int totface = em->bm->totface; - const bool check_mesh_facing = ts->backface_select && ts->backface_select_mode == 8; + const bool check_mesh_facing = edbm_check_mesh_facing(op, true, lasso, circle, true); blender::BitVector<> visited_face; blender::BitVector<> front_face; bool changed = false; @@ -1328,11 +1489,10 @@ static bool edbm_backbuf_check_and_select_edges(void *userData, { CircleSelectUserData *data = static_cast(userData); ViewContext *vc = data->vc; - ToolSettings *ts = vc->scene->toolsettings; BMEdge *eed; BMIter iter; bool changed = false; - const bool check_mesh_facing = edbm_check_mesh_facing(ts, op, true); + const bool check_mesh_facing = edbm_check_mesh_facing(op, true, false, true, false); const BLI_bitmap *select_bitmap = esel->select_bitmap; uint index = DRW_select_buffer_context_offset_for_object_elem(depsgraph, ob, SCE_SELECT_EDGE); @@ -1411,13 +1571,14 @@ static bool edbm_backbuf_check_and_select_faces(ViewContext *vc, void *lasso_data, void *circle_data) { - ToolSettings *ts = vc->scene->toolsettings; + // ToolSettings *ts = vc->scene->toolsettings; BMIter iter, viter; BMFace *efa; BMVert *eve; rctf rectf; bool changed = false; - const bool check_mesh_facing = edbm_check_mesh_facing(ts, op, true); + const bool check_mesh_facing = edbm_check_mesh_facing( + op, true, lasso_data != nullptr, circle_data != nullptr, false); const BLI_bitmap *select_bitmap = esel->select_bitmap; LassoSelectUserData *ldata = static_cast(lasso_data); CircleSelectUserData *cdata = static_cast(circle_data); @@ -1692,11 +1853,10 @@ static bool do_lasso_select_objects(ViewContext *vc, wmOperator *op) { View3D *v3d = vc->v3d; - ToolSettings *ts = vc->scene->toolsettings; bool changed = false; float region_co[2]; - const int object_type = object_style(ts, op); - const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && + const int object_type = object_style(op, true, false); + const bool wireless_touch = U.wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -1744,7 +1904,7 @@ static bool do_lasso_select_objects(ViewContext *vc, const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); - if (drag_select_through(v3d, ts, op, false, true, false)) { + if (drag_select_through(v3d, op, false, true, false)) { hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_PICK_ALL, select_filter); } else { @@ -2167,15 +2327,20 @@ static bool do_lasso_select_mesh(ViewContext *vc, LassoSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; rcti rect; - const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init( - &data, vc, &rect, mcoords, mcoords_len, sel_op, mesh_type[0], mesh_type[1]); + view3d_userdata_lassoselect_init(&data, + vc, + &rect, + mcoords, + mcoords_len, + sel_op, + edge_style(op, true, false), + face_style(op, true, false)); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -2189,7 +2354,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, true, false); + const bool use_zbuf = !drag_select_through(vc->v3d, op, true, true, false); EditSelectBuf_Cache *esel = static_cast(wm_userdata->data); if (use_zbuf) { @@ -2211,7 +2376,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(op, use_zbuf, true, false, false); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -2225,7 +2390,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( - vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + vc, op, esel, vc->depsgraph, vc->obedit, vc->em, sel_op, true, false); } else { mesh_foreachScreenVert( @@ -5355,9 +5520,9 @@ static bool do_mesh_box_select(ViewContext *vc, { BoxSelectUserData data; ToolSettings *ts = vc->scene->toolsettings; - const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op, mesh_type[0], mesh_type[1]); + view3d_userdata_boxselect_init( + &data, vc, rect, sel_op, edge_style(op, false, square), face_style(op, false, square)); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -5371,7 +5536,7 @@ static bool do_mesh_box_select(ViewContext *vc, GPU_matrix_set(vc->rv3d->viewmat); - const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, false, square); + const bool use_zbuf = !drag_select_through(vc->v3d, op, true, false, square); if (use_zbuf) { /* for near enclose face */ @@ -5396,7 +5561,7 @@ static bool do_mesh_box_select(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(op, use_zbuf, false, false, false); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -5410,7 +5575,7 @@ static bool do_mesh_box_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { data.is_changed |= edbm_backbuf_check_and_select_verts( - vc, esel, vc->depsgraph, vc->obedit, vc->em, sel_op); + vc, op, esel, vc->depsgraph, vc->obedit, vc->em, sel_op, false, false); } else { mesh_foreachScreenVert( @@ -5627,10 +5792,9 @@ static bool do_object_box_select(bContext *C, const rcti *rect, const eSelectOp sel_op, wmOperator *op, - bool square) + const bool square) { View3D *v3d = vc->v3d; - ToolSettings *ts = vc->scene->toolsettings; GPUSelectBuffer buffer; const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); @@ -5640,8 +5804,8 @@ static bool do_object_box_select(bContext *C, int hits = 0; bool changed = false; float region_co[2]; - const int object_type = object_style(ts, op); - const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && + const int object_type = object_style(op, false, square); + const bool wireless_touch = U.wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); bool select; int select_flag; @@ -5655,7 +5819,7 @@ static bool do_object_box_select(bContext *C, changed |= object_deselect_all_visible(vc->scene, vc->view_layer, vc->v3d); } - if (drag_select_through(v3d, ts, op, false, false, square)) { + if (drag_select_through(v3d, op, false, false, square)) { hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter); } else { @@ -6231,7 +6395,6 @@ static bool mesh_circle_select(ViewContext *vc, ToolSettings *ts = vc->scene->toolsettings; CircleSelectUserData data; vc->em = BKE_editmesh_from_object(vc->obedit); - const int mesh_type[2] = {edge_style(ts, op), face_style(ts, op)}; bool changed = false; if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -6247,9 +6410,10 @@ static bool mesh_circle_select(ViewContext *vc, ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - view3d_userdata_circleselect_init(&data, vc, select, mval, rad, mesh_type[0], mesh_type[1]); + view3d_userdata_circleselect_init( + &data, vc, select, mval, rad, edge_style(op, false, true), face_style(op, false, true)); - const bool use_zbuf = !drag_select_through(vc->v3d, ts, op, true, false, true); + const bool use_zbuf = !drag_select_through(vc->v3d, op, true, false, true); if (use_zbuf) { if (wm_userdata->data == nullptr) { @@ -6266,7 +6430,7 @@ static bool mesh_circle_select(ViewContext *vc, } if (ts->selectmode & SCE_SELECT_EDGE || !use_zbuf) { - data.check_mesh_direction = edbm_check_mesh_facing(ts, op, use_zbuf); + data.check_mesh_direction = edbm_check_mesh_facing(op, use_zbuf, false, true, false); if (data.check_mesh_direction) { const int totface = vc->em->bm->totface; @@ -6280,8 +6444,15 @@ static bool mesh_circle_select(ViewContext *vc, if (ts->selectmode & SCE_SELECT_VERTEX) { if (use_zbuf) { if (esel->select_bitmap != nullptr) { - changed |= edbm_backbuf_check_and_select_verts( - vc, esel, vc->depsgraph, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + changed |= edbm_backbuf_check_and_select_verts(vc, + op, + esel, + vc->depsgraph, + vc->obedit, + vc->em, + select ? SEL_OP_ADD : SEL_OP_SUB, + false, + true); } } else { @@ -6997,13 +7168,12 @@ static bool object_circle_select( Scene *scene = vc->scene; ViewLayer *view_layer = vc->view_layer; View3D *v3d = vc->v3d; - ToolSettings *ts = scene->toolsettings; float region_co[2]; const int circle_data[3] = {mval[0], mval[1], int(rad)}; float mval_fl[2] = {float(mval[0]), float(mval[1])}; float radius_squared = rad * rad; - const int object_type = object_style(ts, op); - const bool wireless_touch = ts->wireless_touch_object && object_type == 1 && + const int object_type = object_style(op, false, true); + const bool wireless_touch = U.wireless_touch_object && object_type == 1 && v3d->shading.type == OB_WIRE && XRAY_FLAG_ENABLED(v3d); const bool select = (sel_op != SEL_OP_SUB); const int select_flag = select ? BASE_SELECTED : 0; @@ -7070,7 +7240,7 @@ static bool object_circle_select( const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(scene, vc->obact); - if (drag_select_through(v3d, ts, op, false, false, true)) { + if (drag_select_through(v3d, op, false, false, true)) { hits = view3d_opengl_select(vc, &buffer, &rect, VIEW3D_SELECT_ALL, select_filter); } else { @@ -7206,8 +7376,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op) static_cast(RNA_enum_get(op->ptr, "mode")), WM_gesture_is_modal_first(gesture)); ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph); - ToolSettings *ts = vc.scene->toolsettings; - bool square = ts->square_select; + bool square = U.square_select; rcti rect; Object *obact = vc.obact; diff --git a/source/blender/editors/util/ed_transverts.cc b/source/blender/editors/util/ed_transverts.cc index 98766ba5306..bd06d6f9414 100644 --- a/source/blender/editors/util/ed_transverts.cc +++ b/source/blender/editors/util/ed_transverts.cc @@ -315,6 +315,13 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, const Object *obedit, editmesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP); } } + + /* Fix vert indices for backfacing mesh filter */ + int index = 0; + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + BM_elem_index_set(eve, index); + index++; + } } else if (obedit->type == OB_ARMATURE) { bArmature *arm = static_cast(obedit->data); diff --git a/source/blender/editors/uvedit/uvedit_select.cc b/source/blender/editors/uvedit/uvedit_select.cc index 51171585309..1ac45afa113 100644 --- a/source/blender/editors/uvedit/uvedit_select.cc +++ b/source/blender/editors/uvedit/uvedit_select.cc @@ -3734,7 +3734,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op) (ts->uv_selectmode == UV_SELECT_EDGE)); const bool use_select_linked = !(ts->uv_flag & UV_SYNC_SELECTION) && (ts->uv_selectmode == UV_SELECT_ISLAND); - const bool square = ts->square_select; + const bool square = U.square_select; /* get operator properties */ x = RNA_int_get(op->ptr, "x"); diff --git a/source/blender/makesdna/DNA_scene_defaults.h b/source/blender/makesdna/DNA_scene_defaults.h index 9ca8dd51ffb..29661489c52 100644 --- a/source/blender/makesdna/DNA_scene_defaults.h +++ b/source/blender/makesdna/DNA_scene_defaults.h @@ -408,33 +408,6 @@ /* Placement */ \ .snap_mode_tools = SCE_SNAP_TO_GEOM,\ .plane_axis = 2,\ -\ - /* Drag Select */ \ - .xray_button = true, \ - .auto_xray_object = true, \ - .auto_xray_edit = true, \ - .auto_xray_box = true, \ - .auto_xray_lasso = true, \ - .auto_xray_circle = true, \ - .select_through = true, \ - .select_through_object = true, \ - .select_through_box = true, \ - .select_through_lasso = true, \ - .select_through_circle = true, \ - .object_cycle_touch = true, \ - .object_cycle_enclose = true, \ - .object_cycle_origin = true, \ - .face_cycle_default = true, \ - .face_cycle_touch = true, \ - .face_cycle_enclose = true, \ - .face_cycle_center = true, \ - .edge_cycle_default = true, \ - .edge_cycle_touch = true, \ - .edge_cycle_enclose = true, \ - .object_select_mode = 1, \ - .face_select_mode = 1, \ - .edge_select_mode = 1, \ - .backface_select_mode = 2, \ } #define _DNA_DEFAULT_Sculpt \ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3ba9e7d6a55..078b35eb734 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1599,48 +1599,6 @@ typedef struct ToolSettings { char gpencil_selectmode_edit; /** Stroke selection mode for Sculpt. */ char gpencil_selectmode_sculpt; - - /** LCB Options */ - char xray_button; - char xray_header; - char auto_xray; - char auto_xray_button; - char auto_xray_reset; - char auto_xray_object; - char auto_xray_edit; - char auto_xray_box; - char auto_xray_lasso; - char auto_xray_circle; - char select_through; - char select_through_button; - char select_through_object; - char select_through_edit; - char select_through_box; - char select_through_lasso; - char select_through_circle; - char wireless_touch_object; - char square_select; - char shrink_shading_header; - char select_header; - char object_select_mode; - char face_select_mode; - char edge_select_mode; - char backface_select; - char backface_select_mode; - char face_button; - char edge_button; - char backface_button; - char object_cycle_touch; - char object_cycle_enclose; - char object_cycle_origin; - char face_cycle_default; - char face_cycle_touch; - char face_cycle_enclose; - char face_cycle_center; - char edge_cycle_default; - char edge_cycle_touch; - char edge_cycle_enclose; - char blank_text; char _pad0[6]; /** Grease Pencil Sculpt. */ @@ -2493,50 +2451,12 @@ typedef enum eSnapTransformMode { SCE_SNAP_TRANSFORM_MODE_SCALE = (1 << 2), } eSnapTransformMode; -/** #Ignore backface select mode */ -enum { - BACKFACE_DEFAULT = (1 << 0), - BACKFACE_NEAR = (1 << 1), - BACKFACE_XRAY = (1 << 2), - BACKFACE_NONE = (1 << 3), -}; - -/** #Object select style */ -enum { - OBJECT_TOUCH = (1 << 0), - OBJECT_ENCLOSE = (1 << 1), - OBJECT_ORIGIN = (1 << 2), -}; - -/** #Face select style */ -enum { - FACE_DEFAULT = (1 << 0), - FACE_TOUCH = (1 << 1), - FACE_ENCLOSE = (1 << 2), - FACE_CENTER = (1 << 3), -}; - -/** #Edge select style */ -enum { - EDGE_DEFAULT = (1 << 0), - EDGE_TOUCH = (1 << 1), - EDGE_ENCLOSE = (1 << 2), -}; - /** #Auto X-Ray mode */ enum { - AUTO_XRAY_DISABLE = (1 << 0), - AUTO_XRAY_OBJECT = (1 << 1), - AUTO_XRAY_EDIT = (1 << 2), - AUTO_XRAY_BOTH = (1 << 3), -}; - -/** #Select through mode */ -enum { - SELECT_THROUGH_DISABLE = (1 << 0), - SELECT_THROUGH_OBJECT = (1 << 1), - SELECT_THROUGH_EDIT = (1 << 2), - SELECT_THROUGH_BOTH = (1 << 3), + OPERATOR_MODE_A = (1 << 0), + OPERATOR_MODE_B = (1 << 1), + OPERATOR_MODE_C = (1 << 2), + OPERATOR_MODE_D = (1 << 3), }; /** #ToolSettings::selectmode */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index f51b87942ed..0df439048d8 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -886,9 +886,7 @@ typedef struct UserDef { char gizmo_size; /** Navigate gizmo size. */ char gizmo_size_navigate_v3d; - /** Header highlight */ - char header_highlight; - char _pad3[4]; + char _pad3[5]; short edit_studio_light; short lookdev_sphere_size; short vbotimeout, vbocollectrate; @@ -931,10 +929,7 @@ typedef struct UserDef { /** Number of samples for FPS display calculations. */ short playback_fps_samples; - /** Keymap click-drag direction style. */ - char click_drag_direction; - - char _pad7[1]; + char _pad7[2]; /** Private, defaults to 20 for 72 DPI setting. */ short widget_unit; @@ -972,6 +967,7 @@ typedef struct UserDef { /** Flags for which channels to insert keys at. */ short key_insert_channels; // eKeyInsertChannels char _pad15[6]; + /** Flags for animation. */ short animation_flag; @@ -997,22 +993,6 @@ typedef struct UserDef { char drag_threshold; char move_threshold; - /** Adjustable selection radius. */ - float selection_radius; - char adjustable_click_select; - char select_unbiased; - - /** Mouse cursor styles. **/ - char system_cursor; - char edit_cursor; - char paint_cursor; - char dot_cursor; - char knife_cursor; - char pencil_cursor; - char eraser_cursor; - char eyedropper_cursor; - char _pad9[2]; - char font_path_ui[1024]; char font_path_ui_mono[1024]; @@ -1056,11 +1036,152 @@ typedef struct UserDef { float collection_instance_empty_size; char text_flag; - char _pad10[1]; char file_preview_type; /* eUserpref_File_Preview_Type */ char statusbar_flag; /* eUserpref_StatusBar_Flag */ + /** Luke's Custom Build Options */ + char keymap_direction; + char custom_highlight; + char header_highlight; + char xray_button; + char direction_downright_box; + char direction_downright_lasso; + char auto_xray_reset; + char custom_cursor; + char system_cursor; + char edit_cursor; + char paint_cursor; + char dot_cursor; + char knife_cursor; + char pencil_cursor; + char eraser_cursor; + char eyedropper_cursor; + char adjustable_click_select; + char selection_radius; + char select_unbiased; + char blank_text; + char drag_control_mode; + char userpref_mode; + char drag_direction_box; + char drag_direction_lasso; + char auto_xray_box; + char auto_xray_downright_box; + char select_through_box; + char select_through_downright_box; + char object_select_box; + char object_select_downright_box; + char face_select_box; + char face_select_downright_box; + char edge_select_box; + char edge_select_downright_box; + char backface_box; + char backface_downright_box; + char auto_xray_lasso; + char auto_xray_downright_lasso; + char select_through_lasso; + char select_through_downright_lasso; + char object_select_lasso; + char object_select_downright_lasso; + char face_select_lasso; + char face_select_downright_lasso; + char edge_select_lasso; + char edge_select_downright_lasso; + char backface_lasso; + char backface_downright_lasso; + char auto_xray_circle; + char select_through_circle; + char object_select_circle; + char face_select_circle; + char edge_select_circle; + char backface_circle; + char object_header; + char object_cycle_touch; + char object_cycle_enclose; + char object_cycle_origin; + char face_header; + char face_cycle_default; + char face_cycle_touch; + char face_cycle_enclose; + char face_cycle_center; + char edge_header; + char edge_cycle_default; + char edge_cycle_touch; + char edge_cycle_enclose; + char backface_header; + char auto_xray_header; + char select_through_header; + char object_cycle_touch_circle; + char object_cycle_enclose_circle; + char object_cycle_origin_circle; + char face_cycle_default_circle; + char face_cycle_touch_circle; + char face_cycle_enclose_circle; + char face_cycle_center_circle; + char edge_cycle_touch_circle; + char edge_cycle_enclose_circle; + char backface_toggle_circle; + char auto_xray_toggle_circle; + char select_through_toggle_circle; + char object_cycle_touch_lasso; + char object_cycle_enclose_lasso; + char object_cycle_origin_lasso; + char face_cycle_default_lasso; + char face_cycle_touch_lasso; + char face_cycle_enclose_lasso; + char face_cycle_center_lasso; + char edge_cycle_default_lasso; + char edge_cycle_touch_lasso; + char edge_cycle_enclose_lasso; + char backface_toggle_lasso; + char auto_xray_toggle_lasso; + char select_through_toggle_lasso; + char quick_assign; + char quick_assign_mode; + char operator_controls; + char box_controls; + char circle_controls; + char lasso_controls; + char backface_toggle; + char auto_xray_toggle; + char select_through_toggle; + char direction_controls; + char drag_direction_mode; + char direction_object; + char direction_face; + char direction_edge; + char direction_backface; + char direction_auto_xray; + char direction_select_through; + char object_pie; + char face_pie; + char edge_pie; + char backface_pie; + char auto_xray_pie; + char select_through_pie; + char box_pie; + char circle_pie; + char lasso_pie; + char pie_menu_controls; + char object_operator; + char face_operator; + char edge_operator; + char backface_operator; + char auto_xray_operator; + char select_through_operator; + char wireless_touch_object; + char square_select; + char sync_box; + char sync_circle; + char sync_lasso; + char facedot_mode; + char shading_button_mode; + char shading_cycle_wire; + char shading_cycle_solid; + char shading_cycle_material; + char shading_cycle_render; + char _pad9[6]; + struct WalkNavigation walk_navigation; /** The UI for the user preferences. */ @@ -1103,6 +1224,7 @@ typedef enum eUserPref_Section { USER_SECTION_FILE_PATHS = 15, USER_SECTION_EXPERIMENTAL = 16, USER_SECTION_EXTENSIONS = 17, + USER_SECTION_CUSTOM = 18, } eUserPref_Section; /** #UserDef_SpaceData.flag (State of the user preferences UI). */ @@ -1117,8 +1239,8 @@ typedef enum eUserPref_Flag { USER_AUTOSAVE = (1 << 0), USER_FLAG_NUMINPUT_ADVANCED = (1 << 1), USER_FLAG_RECENT_SEARCHES_DISABLE = (1 << 2), - USER_ADJUSTABLE_CLICK_SELECT = (1 << 3), - USER_SELECT_UNBIASED = (1 << 4), + USER_FLAG_UNUSED_3 = (1 << 3), /* cleared */ + USER_FLAG_UNUSED_4 = (1 << 4), /* cleared */ USER_TRACKBALL = (1 << 5), USER_FLAG_UNUSED_6 = (1 << 6), /* cleared */ USER_FLAG_UNUSED_7 = (1 << 7), /* cleared */ @@ -1268,130 +1390,32 @@ typedef enum eUserpref_TableAPI { USER_TABLET_WINTAB = 2, } eUserpref_TabletAPI; -/** #UserDef.click_drag_direction_types */ -typedef enum eUserpref_Click_Drag_Direction { - USER_CLICK_DRAG_DIRECTION_EIGHT_WAY = 0, - USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT = 1, - USER_CLICK_DRAG_DIRECTION_UP_DOWN = 2, -} eUserpref_Click_Drag_Direction; +/** #UserDef.mode */ +typedef enum eUserpref_Mode { + USER_MODE_A = 0, + USER_MODE_B = 1, + USER_MODE_C = 2, + USER_MODE_D = 3, +} eUserpref_Mode; -/** #UserDef.system_cursor_types */ -typedef enum eUserpref_System_Cursor_Types { - USER_SYSTEM_CURSOR_SYSTEM = 0, - USER_SYSTEM_CURSOR_CROSS = 1, - USER_SYSTEM_CURSOR_POINTER = 2, - USER_SYSTEM_CURSOR_CROSS_OPEN = 3, - USER_SYSTEM_CURSOR_CROSS_DOT = 4, - USER_SYSTEM_CURSOR_CROSS_MIN = 5, - USER_SYSTEM_CURSOR_BOX = 6, - USER_SYSTEM_CURSOR_BOX_DOT = 7, - USER_SYSTEM_CURSOR_BOX_POINTER = 8, - USER_SYSTEM_CURSOR_DOT = 9, -} eUserpref_System_Cursor_Types; - -/** #UserDef.edit_cursor_types */ -typedef enum eUserpref_Edit_Cursor_Types { - USER_EDIT_CURSOR_CROSS = 0, - USER_EDIT_CURSOR_SYSTEM = 1, - USER_EDIT_CURSOR_POINTER = 2, - USER_EDIT_CURSOR_CROSS_OPEN = 3, - USER_EDIT_CURSOR_CROSS_DOT = 4, - USER_EDIT_CURSOR_CROSS_MIN = 5, - USER_EDIT_CURSOR_BOX = 6, - USER_EDIT_CURSOR_BOX_DOT = 7, - USER_EDIT_CURSOR_BOX_POINTER = 8, - USER_EDIT_CURSOR_DOT = 9, -} eUserpref_Edit_Cursor_Types; - -/** #UserDef.paint_cursor_types */ -typedef enum eUserpref_Paint_Cursor_Types { - USER_PAINT_CURSOR_CROSS_DOT = 0, - USER_PAINT_CURSOR_CROSS = 1, - USER_PAINT_CURSOR_SYSTEM = 2, - USER_PAINT_CURSOR_POINTER = 3, - USER_PAINT_CURSOR_CROSS_OPEN = 4, - USER_PAINT_CURSOR_CROSS_MIN = 5, - USER_PAINT_CURSOR_BOX = 6, - USER_PAINT_CURSOR_BOX_DOT = 7, - USER_PAINT_CURSOR_BOX_POINTER = 8, - USER_PAINT_CURSOR_DOT = 9, - USER_PAINT_CURSOR_BLANK = 10, -} eUserpref_Paint_Cursor_Types; - -/** #UserDef.dot_cursor_types */ -typedef enum eUserpref_Dot_Cursor_Types { - USER_DOT_CURSOR_DOT = 0, - USER_DOT_CURSOR_CROSS = 1, - USER_DOT_CURSOR_SYSTEM = 2, - USER_DOT_CURSOR_POINTER = 3, - USER_DOT_CURSOR_CROSS_OPEN = 4, - USER_DOT_CURSOR_CROSS_DOT = 5, - USER_DOT_CURSOR_CROSS_MIN = 6, - USER_DOT_CURSOR_BOX = 7, - USER_DOT_CURSOR_BOX_DOT = 8, - USER_DOT_CURSOR_BOX_POINTER = 9, - USER_DOT_CURSOR_BLANK = 10, -} eUserpref_Dot_Cursor_Types; - -/** #UserDef.knife_cursor_types */ -typedef enum eUserpref_Knife_Cursor_Types { - USER_KNIFE_CURSOR_KNIFE = 0, - USER_KNIFE_CURSOR_CROSS = 1, - USER_KNIFE_CURSOR_SYSTEM = 2, - USER_KNIFE_CURSOR_POINTER = 3, - USER_KNIFE_CURSOR_CROSS_OPEN = 4, - USER_KNIFE_CURSOR_CROSS_DOT = 5, - USER_KNIFE_CURSOR_CROSS_MIN = 6, - USER_KNIFE_CURSOR_BOX = 7, - USER_KNIFE_CURSOR_BOX_DOT = 8, - USER_KNIFE_CURSOR_BOX_POINTER = 9, - USER_KNIFE_CURSOR_DOT = 10, -} eUserpref_Knife_Cursor_Types; - -/** #UserDef.pencil_cursor_types */ -typedef enum eUserpref_Pencil_Cursor_Types { - USER_PENCIL_CURSOR_PENCIL = 0, - USER_PENCIL_CURSOR_CROSS = 1, - USER_PENCIL_CURSOR_SYSTEM = 2, - USER_PENCIL_CURSOR_POINTER = 3, - USER_PENCIL_CURSOR_CROSS_OPEN = 4, - USER_PENCIL_CURSOR_CROSS_DOT = 5, - USER_PENCIL_CURSOR_CROSS_MIN = 6, - USER_PENCIL_CURSOR_BOX = 7, - USER_PENCIL_CURSOR_BOX_DOT = 8, - USER_PENCIL_CURSOR_BOX_POINTER = 9, - USER_PENCIL_CURSOR_DOT = 10, -} eUserpref_Pencil_Cursor_Types; - -/** #UserDef.eraser_cursor_types */ -typedef enum eUserpref_Eraser_Cursor_Types { - USER_ERASER_CURSOR_ERASER = 0, - USER_ERASER_CURSOR_CROSS = 1, - USER_ERASER_CURSOR_SYSTEM = 2, - USER_ERASER_CURSOR_POINTER = 3, - USER_ERASER_CURSOR_CROSS_OPEN = 4, - USER_ERASER_CURSOR_CROSS_DOT = 5, - USER_ERASER_CURSOR_CROSS_MIN = 6, - USER_ERASER_CURSOR_BOX = 7, - USER_ERASER_CURSOR_BOX_DOT = 8, - USER_ERASER_CURSOR_BOX_POINTER = 9, - USER_ERASER_CURSOR_DOT = 10, -} eUserpref_Eraser_Cursor_Types; - -/** #UserDef.eyedropper_cursor_types */ -typedef enum eUserpref_Eyedropper_Cursor_Types { - USER_EYEDROPPER_CURSOR_EYEDROPPER = 0, - USER_EYEDROPPER_CURSOR_CROSS = 1, - USER_EYEDROPPER_CURSOR_SYSTEM = 2, - USER_EYEDROPPER_CURSOR_POINTER = 3, - USER_EYEDROPPER_CURSOR_CROSS_OPEN = 4, - USER_EYEDROPPER_CURSOR_CROSS_DOT = 5, - USER_EYEDROPPER_CURSOR_CROSS_MIN = 6, - USER_EYEDROPPER_CURSOR_BOX = 7, - USER_EYEDROPPER_CURSOR_BOX_DOT = 8, - USER_EYEDROPPER_CURSOR_BOX_POINTER = 9, - USER_EYEDROPPER_CURSOR_DOT = 10, -} eUserpref_Eyedropper_Cursor_Types; +/** #UserDef.cursor_types */ +typedef enum eUserpref_Cursor_Types { + USER_CURSOR_SYSTEM = 0, + USER_CURSOR_CROSS = 1, + USER_CURSOR_POINTER = 2, + USER_CURSOR_CROSS_OPEN = 3, + USER_CURSOR_CROSS_DOT = 4, + USER_CURSOR_CROSS_MIN = 5, + USER_CURSOR_BOX = 6, + USER_CURSOR_BOX_DOT = 7, + USER_CURSOR_BOX_POINTER = 8, + USER_CURSOR_DOT = 9, + USER_CURSOR_BLANK = 10, + USER_CURSOR_KNIFE = 11, + USER_CURSOR_PENCIL = 12, + USER_CURSOR_ERASER = 13, + USER_CURSOR_EYEDROPPER = 14, +} eUserpref_Cursor_Types; /** #UserDef.app_flag */ typedef enum eUserpref_APP_Flag { diff --git a/source/blender/makesrna/intern/rna_scene.cc b/source/blender/makesrna/intern/rna_scene.cc index 2fb83eb2b9d..bbe87c44ad1 100644 --- a/source/blender/makesrna/intern/rna_scene.cc +++ b/source/blender/makesrna/intern/rna_scene.cc @@ -3186,85 +3186,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; - static const EnumPropertyItem object_select_items[] = { - {OBJECT_TOUCH, - "TOUCH", - ICON_OBJECT_TOUCH, - "Touch", - "Select objects that are touched by the selection area"}, - {OBJECT_ENCLOSE, - "ENCLOSE", - ICON_OBJECT_ENCLOSE, - "Enclose", - "Select objects that are fully inside the selection area"}, - {OBJECT_ORIGIN, - "ORIGIN", - ICON_LIGHTPROBE_SPHERE, - "Origin", - "Select objects if their origin is touched by the selection area"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem face_select_items[] = { - {FACE_DEFAULT, - "DEFAULT", - ICON_FACE_DEFAULT, - "Default", - "Select faces that are touched by the selection area in Near Select. Select faces if their " - "center is touched by the selection area in X-Ray and Select Through"}, - {FACE_TOUCH, - "TOUCH", - ICON_FACE_TOUCH, - "Touch", - "Select faces that are touched by the selection area"}, - {FACE_ENCLOSE, - "ENCLOSE", - ICON_FACE_ENCLOSE, - "Enclose", - "Select faces that are fully inside the selection area"}, - {FACE_CENTER, - "CENTER", - ICON_LIGHTPROBE_PLANE, - "Center", - "Select faces if their center is touched by the selection area"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem edge_select_items[] = { - {EDGE_DEFAULT, - "DEFAULT", - ICON_EDGE_DEFAULT, - "Default", - "Select edges that are fully inside the selection area. If no edges are fully inside, " - "select edges that are touched by the selection area"}, - {EDGE_TOUCH, - "TOUCH", - ICON_EDGE_TOUCH, - "Touch", - "Select edges that are touched by the selection area"}, - {EDGE_ENCLOSE, - "ENCLOSE", - ICON_EDGE_ENCLOSE, - "Enclose", - "Select edges that are fully inside the selection area"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem backface_select_items[] = { - {BACKFACE_NEAR, - "NEAR", - 0, - "Fix Near", - "Ignore backfacing mesh when not using X-Ray or Select Through, verts won't be filtered"}, - {BACKFACE_XRAY, - "XRAY", - 0, - "Front X-Ray", - "Ignore backfacing mesh in X-Ray and Select Through"}, - {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, - {0, nullptr, 0, nullptr, nullptr}, - }; - srna = RNA_def_struct(brna, "ToolSettings", nullptr); RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); @@ -4120,235 +4041,6 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply"); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3); - /* Square Select */ - prop = RNA_def_property(srna, "square_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "square_select", 0); - RNA_def_property_ui_text( - prop, - "Square Select", - "Change selection shape to a square with side length equal to the circle diameter"); - - /* Wireless Touch Object */ - prop = RNA_def_property(srna, "wireless_touch_object", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "wireless_touch_object", 0); - RNA_def_property_ui_text(prop, - "Wireless Touch Object", - "If using Touch select with X-Ray and Wireframe shading, select " - "objects if inside them but not intersecting any wires"); - - /* Shrink Shading Header */ - prop = RNA_def_property(srna, "shrink_shading_header", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "shrink_shading_header", 0); - RNA_def_property_ui_text( - prop, - "Shrink Header", - "Combine the four Shading Header buttons into one button that also toggles X-Ray"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - /* Blank Text, for ui formatting */ - prop = RNA_def_property(srna, "blank_text", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "blank_text", 0); - RNA_def_property_ui_text(prop, "", ""); - - /* Drag Select Options */ - prop = RNA_def_property(srna, "select_header", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_header", 0); - RNA_def_property_ui_text( - prop, - "Selection Control", - "Use either the header or keymap to control additional selection options"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "object_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "object_select_mode"); - RNA_def_property_enum_items(prop, object_select_items); - RNA_def_property_ui_text(prop, "Object", "Object Select Style"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "face_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "face_select_mode"); - RNA_def_property_enum_items(prop, face_select_items); - RNA_def_property_ui_text(prop, "Face", "Face Select Style"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "edge_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "edge_select_mode"); - RNA_def_property_enum_items(prop, edge_select_items); - RNA_def_property_ui_text(prop, "Edge", "Edge Select Style"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "backface_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "backface_select", 0); - RNA_def_property_ui_text( - prop, "Backface Filter", "Select mesh based on the direction of their normals"); - - prop = RNA_def_property(srna, "backface_select_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, nullptr, "backface_select_mode"); - RNA_def_property_enum_items(prop, backface_select_items); - RNA_def_property_ui_text(prop, "Mode", "Backface Filter Style"); - - prop = RNA_def_property(srna, "face_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "face_button", 0); - RNA_def_property_ui_text( - prop, "Face", "Show header button that cycles through face selection modes"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "edge_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "edge_button", 0); - RNA_def_property_ui_text( - prop, "Edge", "Show header button that cycles through edge selection modes"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "backface_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "backface_button", 0); - RNA_def_property_ui_text( - prop, "Backface", "Show header button that toggles the backface filter"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "object_cycle_touch", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_touch", 0); - RNA_def_property_ui_text( - prop, "Touch", "Object header button will include touch mode in its cycle"); - - prop = RNA_def_property(srna, "object_cycle_enclose", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_enclose", 0); - RNA_def_property_ui_text( - prop, "Enclose", "Object header button will include enclose mode in its cycle"); - - prop = RNA_def_property(srna, "object_cycle_origin", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_origin", 0); - RNA_def_property_ui_text( - prop, "Origin", "Object header button will include origin mode in its cycle"); - - prop = RNA_def_property(srna, "face_cycle_default", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_default", 0); - RNA_def_property_ui_text( - prop, "Default", "Face header button will include default mode in its cycle"); - - prop = RNA_def_property(srna, "face_cycle_touch", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_touch", 0); - RNA_def_property_ui_text( - prop, "Touch", "Face header button will include touch mode in its cycle"); - - prop = RNA_def_property(srna, "face_cycle_enclose", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_enclose", 0); - RNA_def_property_ui_text( - prop, "Enclose", "Face header button will include enclose mode in its cycle"); - - prop = RNA_def_property(srna, "face_cycle_center", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_center", 0); - RNA_def_property_ui_text( - prop, "Center", "Face header button will include center mode in its cycle"); - - prop = RNA_def_property(srna, "edge_cycle_default", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_default", 0); - RNA_def_property_ui_text( - prop, "Default", "Edge header button will include default mode in its cycle"); - - prop = RNA_def_property(srna, "edge_cycle_touch", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_touch", 0); - RNA_def_property_ui_text( - prop, "Touch", "Edge header button will include touch mode in its cycle"); - - prop = RNA_def_property(srna, "edge_cycle_enclose", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_enclose", 0); - RNA_def_property_ui_text( - prop, "Enclose", "Edge header button will include enclose mode in its cycle"); - - /* X-Ray Options */ - prop = RNA_def_property(srna, "xray_header", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "xray_header", 0); - RNA_def_property_ui_text(prop, - "X-Ray Control", - "Use either the header or keymap to control additional X-Ray options"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "xray_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "xray_button", 0); - RNA_def_property_ui_text(prop, "X-Ray", "Show button for X-Ray in viewport header"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray", 0); - RNA_def_property_ui_text(prop, "Enable", "Transparent scene display during drag select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_button", 0); - RNA_def_property_ui_text( - prop, "Auto X-Ray", "Show button for automatic X-Ray in viewport header"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_reset", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_reset", 0); - RNA_def_property_ui_text(prop, "Auto X-Ray Reset", "Helper that turns xray off for autoxray"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_object", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_object", 0); - RNA_def_property_ui_text(prop, "Object", "Automatic X-Ray in object mode"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_edit", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_edit", 0); - RNA_def_property_ui_text(prop, "Edit", "Automatic X-Ray in edit mode"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_box", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_box", 0); - RNA_def_property_ui_text(prop, "Box", "Transparent scene display during box select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_lasso", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_lasso", 0); - RNA_def_property_ui_text(prop, "Lasso", "Transparent scene display during lasso select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "auto_xray_circle", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_circle", 0); - RNA_def_property_ui_text(prop, "Circle", "Transparent scene display during circle select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through", 0); - RNA_def_property_ui_text( - prop, "Enable", "Select occluded objects and mesh elements with drag select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_button", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_button", 0); - RNA_def_property_ui_text( - prop, "Select Through", "Show button for select through in viewport header"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_object", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_object", 0); - RNA_def_property_ui_text(prop, "Object", "Select through in object mode"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_edit", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_edit", 0); - RNA_def_property_ui_text(prop, "Edit", "Select through in edit mode"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_box", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_box", 0); - RNA_def_property_ui_text( - prop, "Box", "Select occluded objects and mesh elements with box select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_lasso", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_lasso", 0); - RNA_def_property_ui_text( - prop, "Lasso", "Select occluded objects and mesh elements with lasso select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - - prop = RNA_def_property(srna, "select_through_circle", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "select_through_circle", 0); - RNA_def_property_ui_text( - prop, "Circle", "Select occluded objects and mesh elements with circle select"); - RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); - /* Unified Paint Settings */ prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_userdef.cc b/source/blender/makesrna/intern/rna_userdef.cc index e05d1a0c09a..9cd4e2c9858 100644 --- a/source/blender/makesrna/intern/rna_userdef.cc +++ b/source/blender/makesrna/intern/rna_userdef.cc @@ -74,6 +74,7 @@ const EnumPropertyItem rna_enum_preference_section_items[] = { {USER_SECTION_FILE_PATHS, "FILE_PATHS", 0, "File Paths", ""}, RNA_ENUM_ITEM_SEPR, {USER_SECTION_EXPERIMENTAL, "EXPERIMENTAL", 0, "Experimental", ""}, + {USER_SECTION_CUSTOM, "CUSTOM", 0, "Luke's Custom Build", ""}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -5366,124 +5367,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; - static const EnumPropertyItem system_cursor_items[] = { - {USER_SYSTEM_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_SYSTEM_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_SYSTEM_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_SYSTEM_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_SYSTEM_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_SYSTEM_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_SYSTEM_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_SYSTEM_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_SYSTEM_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_SYSTEM_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem edit_cursor_items[] = { - {USER_EDIT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_EDIT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_EDIT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_EDIT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_EDIT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_EDIT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_EDIT_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_EDIT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_EDIT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_EDIT_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem paint_cursor_items[] = { - {USER_PAINT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_PAINT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_PAINT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_PAINT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_PAINT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_PAINT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_PAINT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_PAINT_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_PAINT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_PAINT_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {USER_PAINT_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem dot_cursor_items[] = { - {USER_DOT_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {USER_DOT_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_DOT_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_DOT_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_DOT_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_DOT_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_DOT_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_DOT_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_DOT_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_DOT_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_DOT_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem knife_cursor_items[] = { - {USER_KNIFE_CURSOR_KNIFE, "KNIFE", 0, "Knife", ""}, - {USER_KNIFE_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_KNIFE_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_KNIFE_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_KNIFE_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_KNIFE_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_KNIFE_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_KNIFE_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_KNIFE_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_KNIFE_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_KNIFE_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem eyedropper_cursor_items[] = { - {USER_EYEDROPPER_CURSOR_EYEDROPPER, "EYEDROPPER", 0, "Eyedropper", ""}, - {USER_EYEDROPPER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_EYEDROPPER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_EYEDROPPER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_EYEDROPPER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_EYEDROPPER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_EYEDROPPER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_EYEDROPPER_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_EYEDROPPER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_EYEDROPPER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_EYEDROPPER_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem eraser_cursor_items[] = { - {USER_ERASER_CURSOR_ERASER, "ERASER", 0, "Eraser", ""}, - {USER_ERASER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_ERASER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_ERASER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_ERASER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_ERASER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_ERASER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_ERASER_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_ERASER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_ERASER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_ERASER_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - - static const EnumPropertyItem pencil_cursor_items[] = { - {USER_PENCIL_CURSOR_PENCIL, "PENCIL", 0, "Pencil", ""}, - {USER_PENCIL_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, - {USER_PENCIL_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, - {USER_PENCIL_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, - {USER_PENCIL_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, - {USER_PENCIL_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, - {USER_PENCIL_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, - {USER_PENCIL_CURSOR_BOX, "BOX", 0, "Box", ""}, - {USER_PENCIL_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, - {USER_PENCIL_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, - {USER_PENCIL_CURSOR_DOT, "DOT", 0, "Dot", ""}, - {0, nullptr, 0, nullptr, nullptr}, - }; - srna = RNA_def_struct(brna, "PreferencesEdit", nullptr); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "Preferences"); @@ -5858,60 +5741,6 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, nullptr, "uiflag", USER_DEPTH_CURSOR); RNA_def_property_ui_text( prop, "Cursor Surface Project", "Use the surface depth for cursor placement"); - - prop = RNA_def_property(srna, "adjustable_click_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_ADJUSTABLE_CLICK_SELECT); - RNA_def_property_ui_text(prop, "Enable", "Use additional options for single-click select"); - - prop = RNA_def_property(srna, "select_unbiased", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_SELECT_UNBIASED); - RNA_def_property_ui_text( - prop, "Select Unbiased", "Click-select will not favor unselected mesh elements"); - - prop = RNA_def_property(srna, "selection_radius", PROP_FLOAT, PROP_FACTOR); - RNA_def_property_range(prop, 0.1f, 150.0f); - RNA_def_property_ui_range(prop, 0.1f, 150.0f, 0.01f, 2); - RNA_def_property_ui_text(prop, "Radius", "Size of single-click selection radius"); - - prop = RNA_def_property(srna, "system_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, system_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "system_cursor"); - RNA_def_property_ui_text(prop, "System Cursor", "System mode cursor style"); - - prop = RNA_def_property(srna, "edit_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, edit_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "edit_cursor"); - RNA_def_property_ui_text(prop, "Edit Cursor", "Edit mode cursor style"); - - prop = RNA_def_property(srna, "paint_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, paint_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "paint_cursor"); - RNA_def_property_ui_text(prop, "Paint Cursor", "Paint mode cursor style"); - - prop = RNA_def_property(srna, "dot_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, dot_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "dot_cursor"); - RNA_def_property_ui_text(prop, "2D Cursor", "2D mode cursor style"); - - prop = RNA_def_property(srna, "knife_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, knife_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "knife_cursor"); - RNA_def_property_ui_text(prop, "Knife Cursor", "Knife cursor style"); - - prop = RNA_def_property(srna, "eyedropper_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, eyedropper_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "eyedropper_cursor"); - RNA_def_property_ui_text(prop, "Eyedropper Cursor", "Eyedropper cursor style"); - - prop = RNA_def_property(srna, "eraser_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, eraser_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "eraser_cursor"); - RNA_def_property_ui_text(prop, "Eraser Cursor", "Eraser cursor style"); - - prop = RNA_def_property(srna, "pencil_cursor", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, pencil_cursor_items); - RNA_def_property_enum_sdna(prop, nullptr, "pencil_cursor"); - RNA_def_property_ui_text(prop, "Pencil Cursor", "Pencil cursor style"); } static void rna_def_userdef_system(BlenderRNA *brna) @@ -6382,14 +6211,771 @@ static void rna_def_userdef_input(BlenderRNA *brna) {0, nullptr, 0, nullptr, nullptr}, }; - static const EnumPropertyItem click_drag_direction_types[] = { - {USER_CLICK_DRAG_DIRECTION_EIGHT_WAY, - "EIGHT_WAY", + static const EnumPropertyItem keymap_direction_items[] = { + {USER_MODE_A, "EIGHT", 0, "Eight", "Eight directions (N, NE, E, SE, S, SW, W, NW)"}, + {USER_MODE_B, "LEFT_RIGHT", 0, "Left Right", "Left and right"}, + {USER_MODE_C, "UP_DOWN", 0, "Up Down", "Up and down"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem quick_assign_mode_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Blender default"}, + {USER_MODE_B, "BETTER", 0, "Better", "Improved selection settings"}, + {USER_MODE_C, "AUTO_XRAY", 0, "Auto X-Ray", "Auto X-Ray with Touch object and mesh"}, + {USER_MODE_D, + "DIRECTIONAL", 0, - "Eight", - "Eight directions (N, NE, E, SE, S, SW, W, NW)"}, - {USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT, "LEFT_RIGHT", 0, "Left Right", "Left and right"}, - {USER_CLICK_DRAG_DIRECTION_UP_DOWN, "UP_DOWN", 0, "Up Down", "Up and down"}, + "Directional", + "Use drag directional control for Touch/Enlocse object and mesh with Box Select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem user_direction_box_items[] = { + {USER_MODE_A, "ANY", 0, "Any", "Any direction"}, + {USER_MODE_B, "LEFT_RIGHT", 0, "Left Right", "Left and right"}, + {USER_MODE_C, "UP_DOWN", 0, "Up Down", "Up and down"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem user_direction_lasso_items[] = { + {USER_MODE_A, "ANY", 0, "Any", "Any direction"}, + {USER_MODE_B, "LEFT_RIGHT", 0, "Left Right", "Left and right"}, + {USER_MODE_C, "UP_DOWN", 0, "Up Down", "Up and down"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem user_direction_mode_items[] = { + {USER_MODE_A, "EVERYTHING", 0, "Everything", "Drag direction for every feature"}, + {USER_MODE_B, + "SELECTIVE", + 0, + "Selective", + "Drag direction only affects the features you opt into"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem drag_control_mode_items[] = { + {USER_MODE_A, + "KEYMAP", + 0, + "Keymap", + "The keymap will control additional selection options for box, circle, and lasso"}, + {USER_MODE_B, + "USERPREF", + 0, + "UserPref", + "User Preferences will control additional selection options for box, circle, and lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem userpref_mode_items[] = { + {USER_MODE_A, + "EASY", + 0, + "Easy", + "Box, Circle, and Lasso use the same settings, no directional control"}, + {USER_MODE_B, + "SPLIT", + 0, + "Split", + "Box, Circle, and Lasso have separate settings, directional control is available for Box " + "and Lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem xray_button_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Toggle X-Ray operator in the viewport header"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Toggle X-Ray operator in the viewport header"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem facedot_mode_items[] = { + {USER_MODE_A, + "CURRENT", + 0, + "Current", + "Toggle face centers in the current shading mode (X-Ray or Solid)"}, + {USER_MODE_B, "BOTH", 0, "Both", "Toggle face centers in both X-Ray and Solid shading"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem shading_button_mode_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Multiple buttons that change shading mode"}, + {USER_MODE_B, "XRAY_COMBINE", 0, "X-Ray", "Combine the X-Ray and Shading header buttons"}, + {USER_MODE_C, + "CYCLE", + 0, + "Cycle", + "One button that cycles through your choice of shading modes"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem adjustable_click_select_items[] = { + {USER_MODE_A, + "DEFAULT", + 0, + "Default", + "Click selection of mesh has a radius of 75, except faces which have a radius of 0"}, + {USER_MODE_B, "CUSTOM", 0, "Custom", "Choose your own radius for click selection of mesh"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem custom_cursor_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Default mouse cursors"}, + {USER_MODE_B, "CUSTOM", 0, "Custom", "Choose your own mouse cursors"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem custom_highlight_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "The header of the active window gets brighter by 5"}, + {USER_MODE_B, + "CUSTOM", + 0, + "Custom", + "Choose your own brightness for the active window's header"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem system_cursor_items[] = { + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edit_cursor_items[] = { + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem paint_cursor_items[] = { + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {USER_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem dot_cursor_items[] = { + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_BLANK, "BLANK", 0, "Blank", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem knife_cursor_items[] = { + {USER_CURSOR_KNIFE, "KNIFE", 0, "Knife", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem eyedropper_cursor_items[] = { + {USER_CURSOR_EYEDROPPER, "EYEDROPPER", 0, "Eyedropper", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem eraser_cursor_items[] = { + {USER_CURSOR_ERASER, "ERASER", 0, "Eraser", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem pencil_cursor_items[] = { + {USER_CURSOR_PENCIL, "PENCIL", 0, "Pencil", ""}, + {USER_CURSOR_CROSS, "CROSS", 0, "Cross", ""}, + {USER_CURSOR_SYSTEM, "SYSTEM", 0, "System", ""}, + {USER_CURSOR_POINTER, "POINTER", 0, "Pointer", ""}, + {USER_CURSOR_CROSS_OPEN, "CROSS_OPEN", 0, "Cross Open", ""}, + {USER_CURSOR_CROSS_DOT, "CROSS_DOT", 0, "Cross Dot", ""}, + {USER_CURSOR_CROSS_MIN, "CROSS_MIN", 0, "Cross Minimal", ""}, + {USER_CURSOR_BOX, "BOX", 0, "Box", ""}, + {USER_CURSOR_BOX_DOT, "BOX_DOT", 0, "Box Dot", ""}, + {USER_CURSOR_BOX_POINTER, "BOX_POINTER", 0, "Box Pointer", ""}, + {USER_CURSOR_DOT, "DOT", 0, "Dot", ""}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Cycle Object operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Cycle Object operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Cycle Face operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Cycle Face operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Cycle Edge operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Cycle Edge operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Toggle Backface operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Toggle Backface operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Toggle Auto X-Ray operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Toggle Auto X-Ray operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Toggle Select Through operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Toggle Select Through operator in the pie menu"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem box_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Box Select operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Box Select operator in the pie menu"}, + {USER_MODE_C, + "CONTEXT", + 0, + "Context", + "Show the Box Select operator in the pie menu if it is not the active tool"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem circle_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Circle Select operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Circle Select operator in the pie menu"}, + {USER_MODE_C, + "CONTEXT", + 0, + "Context", + "Show the Circle Select operator in the pie menu if it is not the active tool"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem lasso_pie_items[] = { + {USER_MODE_A, "SHOW", 0, "Show", "Show the Lasso Select operator in the pie menu"}, + {USER_MODE_B, "HIDE", 0, "Hide", "Hide the Lasso Select operator in the pie menu"}, + {USER_MODE_C, + "CONTEXT", + 0, + "Context", + "Show the Lasso Select operator in the pie menu if it is not the active tool"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_toggle_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Automatic X-Ray for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Automatic X-Ray for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_toggle_circle_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Automatic X-Ray for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Automatic X-Ray for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_toggle_lasso_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Automatic X-Ray for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Automatic X-Ray for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_toggle_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Select Through for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Select Through for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_toggle_circle_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Select Through for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Select Through for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_toggle_lasso_items[] = { + {USER_MODE_A, "BOTH", 0, "Both", "Toggle Select Through for Object and Edit mode"}, + {USER_MODE_B, + "CURRENT", + 0, + "Current", + "Toggle Select Through for the mode that is currently active (Object or Edit)"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_toggle_items[] = { + {USER_MODE_A, + "NONE", + 0, + "No Backface", + "Toggle the backfacing mesh filter in No Backface mode"}, + {USER_MODE_B, + "NEAR", + 0, + "Edge & Face Near", + "Toggle the backfacing mesh filter in Edge & Face Near mode"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_toggle_circle_items[] = { + {USER_MODE_A, + "NONE", + 0, + "No Backface", + "Toggle the backfacing mesh filter in No Backface mode"}, + {USER_MODE_B, + "NEAR", + 0, + "Edge & Face Near", + "Toggle the backfacing mesh filter in Edge & Face Near mode"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_toggle_lasso_items[] = { + {USER_MODE_A, + "NONE", + 0, + "No Backface", + "Toggle the backfacing mesh filter in No Backface mode"}, + {USER_MODE_B, + "NEAR", + 0, + "Edge & Face Near", + "Toggle the backfacing mesh filter in Edge & Face Near mode"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_box_items[] = { + {USER_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {USER_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {USER_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {USER_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_downright_box_items[] = { + {USER_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {USER_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {USER_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {USER_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_box_items[] = { + {USER_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {USER_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {USER_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {USER_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_downright_box_items[] = { + {USER_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {USER_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {USER_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {USER_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_select_box_items[] = { + {USER_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, + {USER_MODE_B, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the box"}, + {USER_MODE_C, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_select_downright_box_items[] = { + {USER_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, + {USER_MODE_B, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the box"}, + {USER_MODE_C, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_box_items[] = { + {USER_MODE_A, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the box in Near Select. Select faces if their center is " + "touched by the box in X-Ray and Select Through"}, + {USER_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, + {USER_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the box"}, + {USER_MODE_D, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_downright_box_items[] = { + {USER_MODE_A, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the box in Near Select. Select faces if their center is " + "touched by the box in X-Ray and Select Through"}, + {USER_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, + {USER_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the box"}, + {USER_MODE_D, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_box_items[] = { + {USER_MODE_A, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the box. If no edges are fully inside the box, select " + "edges that are touched by the box"}, + {USER_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"}, + {USER_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_downright_box_items[] = { + {USER_MODE_A, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the box. If no edges are fully inside the box, select " + "edges that are touched by the box"}, + {USER_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"}, + {USER_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the box"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_box_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Select backfacing mesh"}, + {USER_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {USER_MODE_C, + "NEAR", + 0, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_downright_box_items[] = { + {USER_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {USER_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {USER_MODE_C, + "NEAR", + 0, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_lasso_items[] = { + {USER_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {USER_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {USER_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {USER_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_downright_lasso_items[] = { + {USER_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {USER_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {USER_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {USER_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_lasso_items[] = { + {USER_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {USER_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {USER_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {USER_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_downright_lasso_items[] = { + {USER_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {USER_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {USER_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {USER_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_select_lasso_items[] = { + {USER_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the lasso"}, + {USER_MODE_B, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the lasso"}, + {USER_MODE_C, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_select_downright_lasso_items[] = { + {USER_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the lasso"}, + {USER_MODE_B, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the lasso"}, + {USER_MODE_C, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_lasso_items[] = { + {USER_MODE_A, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the lasso in Near Select. Select faces if their center " + "is " + "touched by the lasso in X-Ray and Select Through"}, + {USER_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, + {USER_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the lasso"}, + {USER_MODE_D, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_downright_lasso_items[] = { + {USER_MODE_A, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the lasso in Near Select. Select faces if their center " + "is " + "touched by the lasso in X-Ray and Select Through"}, + {USER_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, + {USER_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the lasso"}, + {USER_MODE_D, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_lasso_items[] = { + {USER_MODE_A, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the lasso. If no edges are fully inside the lasso, " + "select " + "edges that are touched by the lasso"}, + {USER_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"}, + {USER_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_downright_lasso_items[] = { + {USER_MODE_A, + "EDGE_DEFAULT", + 0, + "Default", + "Select edges that are fully inside the lasso. If no edges are fully inside the lasso, " + "select " + "edges that are touched by the lasso"}, + {USER_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"}, + {USER_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the lasso"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_lasso_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Select backfacing mesh"}, + {USER_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {USER_MODE_C, + "NEAR", + 0, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_downright_lasso_items[] = { + {USER_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {USER_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {USER_MODE_C, + "NEAR", + 0, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem auto_xray_circle_items[] = { + {USER_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {USER_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {USER_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {USER_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem select_through_circle_items[] = { + {USER_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {USER_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {USER_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {USER_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem object_select_circle_items[] = { + {USER_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the circle"}, + {USER_MODE_B, + "OBJECT_ENCLOSE", + 0, + "Enclose", + "Select objects that are fully inside the circle"}, + {USER_MODE_C, + "OBJECT_ORIGIN", + 0, + "Origin", + "Select objects if their origin is touched by the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem face_select_circle_items[] = { + {USER_MODE_A, + "FACE_DEFAULT", + 0, + "Default", + "Select faces that are touched by the circle in Near Select. Select faces if their center " + "is " + "touched by the circle in X-Ray and Select Through"}, + {USER_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"}, + {USER_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the circle"}, + {USER_MODE_D, + "FACE_CENTER", + 0, + "Center", + "Select faces if their center is touched by the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem edge_select_circle_items[] = { + {USER_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the circle"}, + {USER_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the circle"}, + {0, nullptr, 0, nullptr, nullptr}, + }; + + static const EnumPropertyItem backface_circle_items[] = { + {USER_MODE_A, "DEFAULT", 0, "Default", "Select backfacing mesh"}, + {USER_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {USER_MODE_C, + "NEAR", + 0, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -6499,11 +7085,736 @@ static void rna_def_userdef_input(BlenderRNA *brna) "Release Confirms", "Moving things with a mouse drag confirms when releasing the button"); - prop = RNA_def_property(srna, "click_drag_direction", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, click_drag_direction_types); + /* Drag Select Options */ + prop = RNA_def_property(srna, "auto_xray_reset", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_reset", 0); + RNA_def_property_ui_text(prop, "Auto X-Ray Reset", "Helper that turns xray off for autoxray"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_downright_box", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_downright_box", 0); + RNA_def_property_ui_text(prop, "", ""); + + prop = RNA_def_property(srna, "direction_downright_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_downright_lasso", 0); + RNA_def_property_ui_text(prop, "", ""); + + prop = RNA_def_property(srna, "facedot_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, facedot_mode_items); + RNA_def_property_enum_sdna(prop, nullptr, "facedot_mode"); + RNA_def_property_ui_text(prop, + "Facedot Toggle", + "Toggle face centers in both solid and X-Ray shading, or only the " + "shading mode that is currently in use"); + + prop = RNA_def_property(srna, "shading_button_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, shading_button_mode_items); + RNA_def_property_enum_sdna(prop, nullptr, "shading_button_mode"); + RNA_def_property_ui_text(prop, "Shading Button", "Shading button style in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "shading_cycle_wire", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "shading_cycle_wire", 0); + RNA_def_property_ui_text( + prop, "", "The viewport shading button will include wireframe shading in its cycle"); + + prop = RNA_def_property(srna, "shading_cycle_solid", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "shading_cycle_solid", 0); + RNA_def_property_ui_text( + prop, "", "The viewport shading button will include solid shading in its cycle"); + + prop = RNA_def_property(srna, "shading_cycle_material", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "shading_cycle_material", 0); + RNA_def_property_ui_text( + prop, "", "The viewport shading button will include material preview shading in its cycle"); + + prop = RNA_def_property(srna, "shading_cycle_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "shading_cycle_render", 0); + RNA_def_property_ui_text( + prop, "", "The viewport shading button will include rendered shading in its cycle"); + + prop = RNA_def_property(srna, "sync_box", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "sync_box", 0); + RNA_def_property_ui_text(prop, + "Box", + "Keep box select properties the same as other synchronized selection " + "tools when changing them via operator and pie menu"); + + prop = RNA_def_property(srna, "sync_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "sync_circle", 0); + RNA_def_property_ui_text(prop, + "Circle", + "Keep circle select properties the same as other synchronized " + "selection tools when changing them via operator and pie menu"); + + prop = RNA_def_property(srna, "sync_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "sync_lasso", 0); + RNA_def_property_ui_text(prop, + "Lasso", + "Keep lasso select properties the same as other synchronized selection " + "tools when changing them via operator and pie menu"); + + prop = RNA_def_property(srna, "square_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "square_select", 0); + RNA_def_property_ui_text( + prop, + "Square", + "Change selection shape to a square with side length equal to the circle diameter"); + + prop = RNA_def_property(srna, "wireless_touch_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "wireless_touch_object", 0); + RNA_def_property_ui_text(prop, + "Wireless Touch", + "If using Touch select with X-Ray and Wireframe shading, select " + "objects if inside them but not intersecting any wires"); + + prop = RNA_def_property(srna, "adjustable_click_select", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, adjustable_click_select_items); + RNA_def_property_enum_sdna(prop, nullptr, "adjustable_click_select"); + RNA_def_property_ui_text( + prop, "Click Select", "Use additional options for single-click selection"); + + prop = RNA_def_property(srna, "select_unbiased", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_unbiased", 0); + RNA_def_property_ui_text( + prop, "Select Unbiased", "Click-select will not favor unselected mesh elements"); + + prop = RNA_def_property(srna, "selection_radius", PROP_INT, PROP_FACTOR); + RNA_def_property_range(prop, 0, 150); + RNA_def_property_ui_range(prop, 0, 150, 1, -1); + RNA_def_property_ui_text(prop, "Radius", "Size of single-click selection radius"); + + prop = RNA_def_property(srna, "custom_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, custom_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "custom_cursor"); + RNA_def_property_ui_text(prop, "Mouse Cursors", "Use custom mouse cursors"); + + prop = RNA_def_property(srna, "system_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, system_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "system_cursor"); + RNA_def_property_ui_text(prop, "System", "System mode cursor style"); + + prop = RNA_def_property(srna, "edit_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edit_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "edit_cursor"); + RNA_def_property_ui_text(prop, "Edit", "Edit mode cursor style"); + + prop = RNA_def_property(srna, "paint_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, paint_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "paint_cursor"); + RNA_def_property_ui_text(prop, "Paint", "Paint mode cursor style"); + + prop = RNA_def_property(srna, "dot_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, dot_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "dot_cursor"); + RNA_def_property_ui_text(prop, "2D", "2D mode cursor style"); + + prop = RNA_def_property(srna, "knife_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, knife_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "knife_cursor"); + RNA_def_property_ui_text(prop, "Knife", "Knife cursor style"); + + prop = RNA_def_property(srna, "eyedropper_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, eyedropper_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "eyedropper_cursor"); + RNA_def_property_ui_text(prop, "Eyedropper", "Eyedropper cursor style"); + + prop = RNA_def_property(srna, "eraser_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, eraser_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "eraser_cursor"); + RNA_def_property_ui_text(prop, "Eraser", "Eraser cursor style"); + + prop = RNA_def_property(srna, "pencil_cursor", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, pencil_cursor_items); + RNA_def_property_enum_sdna(prop, nullptr, "pencil_cursor"); + RNA_def_property_ui_text(prop, "Pencil", "Pencil cursor style"); + + prop = RNA_def_property(srna, "blank_text", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "blank_text", 0); + RNA_def_property_ui_text(prop, "", ""); + + prop = RNA_def_property(srna, "keymap_direction", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, keymap_direction_items); RNA_def_property_ui_text( prop, "Keymap Drag Directions", "Style of click-drag direction the keymap will use"); + prop = RNA_def_property(srna, "custom_highlight", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, custom_highlight_items); + RNA_def_property_ui_text( + prop, "Header Highlights", "Change the brightness of the active header"); + + prop = RNA_def_property(srna, "header_highlight", PROP_INT, PROP_FACTOR); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_range(prop, 0, 10, 1, -1); + RNA_def_property_ui_text(prop, "Amount", "How much brighter the header of the active window is"); + + prop = RNA_def_property(srna, "drag_control_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, drag_control_mode_items); + RNA_def_property_ui_text(prop, + "Control Style", + "Use either the keymap or user preferences to control additional " + "selection options for box, circle and lasso"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "userpref_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, userpref_mode_items); + RNA_def_property_ui_text(prop, "Userpref Mode", "Complexity of the userpref control style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "xray_button", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, xray_button_items); + RNA_def_property_ui_text( + prop, + "X-Ray Button", + "Show an operator that toggles transparent scene display in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_pie_items); + RNA_def_property_ui_text( + prop, + "Object Pie", + "Show an operator that cycles object select modes in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "face_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_pie_items); + RNA_def_property_ui_text( + prop, + "Face Pie", + "Show an operator that cycles face select modes in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "edge_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_pie_items); + RNA_def_property_ui_text( + prop, + "Edge Pie", + "Show an operator that cycles edge select modes in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "backface_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_pie_items); + RNA_def_property_ui_text(prop, + "Backface Pie", + "Show an operator that toggles the backfacing mesh filter in the pie " + "menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "auto_xray_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_pie_items); + RNA_def_property_ui_text( + prop, + "Auto X-Ray Pie", + "Show an operator that toggles Automatic X-Ray in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "select_through_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_pie_items); + RNA_def_property_ui_text( + prop, + "Select_Through Pie", + "Show an operator that toggles Select Through in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "box_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, box_pie_items); + RNA_def_property_ui_text( + prop, + "Box Pie", + "Show an operator that switches to box select in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "circle_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, circle_pie_items); + RNA_def_property_ui_text( + prop, + "Circle Pie", + "Show an operator that switches to circle select in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "lasso_pie", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, lasso_pie_items); + RNA_def_property_ui_text( + prop, + "Lasso Pie", + "Show an operator that switches to lasso select in the pie menu (view3d.pie_drag_select)"); + + prop = RNA_def_property(srna, "quick_assign", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "quick_assign", 0); + RNA_def_property_ui_text(prop, "", "Quickly assign values to the drag select settings"); + + prop = RNA_def_property(srna, "operator_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "operator_controls", 0); + RNA_def_property_ui_text(prop, "", "Operator settings"); + + prop = RNA_def_property(srna, "box_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "box_controls", 0); + RNA_def_property_ui_text(prop, "", "Box settings"); + + prop = RNA_def_property(srna, "circle_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "circle_controls", 0); + RNA_def_property_ui_text(prop, "", "Circle settings"); + + prop = RNA_def_property(srna, "lasso_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "lasso_controls", 0); + RNA_def_property_ui_text(prop, "", "Lasso settings"); + + prop = RNA_def_property(srna, "pie_menu_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "pie_menu_controls", 0); + RNA_def_property_ui_text(prop, "", "Pie Menu settings"); + + prop = RNA_def_property(srna, "object_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_operator", 0); + RNA_def_property_ui_text(prop, "", "Object operator"); + + prop = RNA_def_property(srna, "face_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_operator", 0); + RNA_def_property_ui_text(prop, "", "Face operator"); + + prop = RNA_def_property(srna, "edge_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_operator", 0); + RNA_def_property_ui_text(prop, "", "Edge operator"); + + prop = RNA_def_property(srna, "backface_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "backface_operator", 0); + RNA_def_property_ui_text(prop, "", "Backface operator"); + + prop = RNA_def_property(srna, "auto_xray_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_operator", 0); + RNA_def_property_ui_text(prop, "", "Auto X-Ray operator"); + + prop = RNA_def_property(srna, "select_through_operator", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_operator", 0); + RNA_def_property_ui_text(prop, "", "Select Through operator"); + + prop = RNA_def_property(srna, "object_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_header", 0); + RNA_def_property_ui_text( + prop, + "Object Header Button", + "Show an operator that cycles object selection modes in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "The object selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The object selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_origin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_origin", 0); + RNA_def_property_ui_text( + prop, "Origin", "The object selection operator will include origin mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_touch_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_touch_circle", 0); + RNA_def_property_ui_text( + prop, "Touch", "The object selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_enclose_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_enclose_circle", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The object selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_origin_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_origin_circle", 0); + RNA_def_property_ui_text( + prop, "Origin", "The object selection operator will include origin mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_touch_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_touch_lasso", 0); + RNA_def_property_ui_text( + prop, "Touch", "The object selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_enclose_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_enclose_lasso", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The object selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "object_cycle_origin_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "object_cycle_origin_lasso", 0); + RNA_def_property_ui_text( + prop, "Origin", "The object selection operator will include origin mode in its cycle"); + + prop = RNA_def_property(srna, "face_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_header", 0); + RNA_def_property_ui_text( + prop, + "Face Header Button", + "Show an operator that cycles face selection modes in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "face_cycle_default", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_default", 0); + RNA_def_property_ui_text( + prop, "Default", "The face selection operator will include default mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "The face selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The face selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_center", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_center", 0); + RNA_def_property_ui_text( + prop, "Center", "The face selection operator will include center mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_default_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_default_circle", 0); + RNA_def_property_ui_text( + prop, "Default", "The face selection operator will include default mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_touch_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_touch_circle", 0); + RNA_def_property_ui_text( + prop, "Touch", "The face selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_enclose_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_enclose_circle", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The face selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_center_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_center_circle", 0); + RNA_def_property_ui_text( + prop, "Center", "The face selection operator will include center mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_default_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_default_lasso", 0); + RNA_def_property_ui_text( + prop, "Default", "The face selection operator will include default mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_touch_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_touch_lasso", 0); + RNA_def_property_ui_text( + prop, "Touch", "The face selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_enclose_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_enclose_lasso", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The face selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "face_cycle_center_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "face_cycle_center_lasso", 0); + RNA_def_property_ui_text( + prop, "Center", "The face selection operator will include center mode in its cycle"); + + prop = RNA_def_property(srna, "edge_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_header", 0); + RNA_def_property_ui_text( + prop, + "Edge Header Button", + "Show an operator that cycles edge selection modes in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_cycle_default", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_default", 0); + RNA_def_property_ui_text( + prop, "Default", "The edge selection operator will include default mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_touch", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_touch", 0); + RNA_def_property_ui_text( + prop, "Touch", "The edge selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_enclose", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_enclose", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The edge selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_touch_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_touch_circle", 0); + RNA_def_property_ui_text( + prop, "Touch", "The edge selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_enclose_circle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_enclose_circle", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The edge selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_default_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_default_lasso", 0); + RNA_def_property_ui_text( + prop, "Default", "The edge selection operator will include default mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_touch_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_touch_lasso", 0); + RNA_def_property_ui_text( + prop, "Touch", "The edge selection operator will include touch mode in its cycle"); + + prop = RNA_def_property(srna, "edge_cycle_enclose_lasso", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "edge_cycle_enclose_lasso", 0); + RNA_def_property_ui_text( + prop, "Enclose", "The edge selection operator will include enclose mode in its cycle"); + + prop = RNA_def_property(srna, "auto_xray_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "auto_xray_header", 0); + RNA_def_property_ui_text(prop, + "Auto X-Ray Header Button", + "Show an operator that toggles Automatic X-Ray in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_toggle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_toggle_items); + RNA_def_property_ui_text( + prop, "Box Toggle", "Which mode the Automatic X-Ray operator will toggle"); + + prop = RNA_def_property(srna, "auto_xray_toggle_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_toggle_circle_items); + RNA_def_property_ui_text( + prop, "Circle Toggle", "Which mode the Automatic X-Ray operator will toggle"); + + prop = RNA_def_property(srna, "auto_xray_toggle_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_toggle_lasso_items); + RNA_def_property_ui_text( + prop, "Lasso Toggle", "Which mode the Automatic X-Ray operator will toggle"); + + prop = RNA_def_property(srna, "select_through_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "select_through_header", 0); + RNA_def_property_ui_text(prop, + "Select Through Header Button", + "Show an operator that toggles Select Through in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_toggle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_toggle_items); + RNA_def_property_ui_text( + prop, "Box Toggle", "Which mode the Select Through operator will toggle"); + + prop = RNA_def_property(srna, "select_through_toggle_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_toggle_circle_items); + RNA_def_property_ui_text( + prop, "Circle Toggle", "Which mode the Select Through operator will toggle"); + + prop = RNA_def_property(srna, "select_through_toggle_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_toggle_lasso_items); + RNA_def_property_ui_text( + prop, "Lasso Toggle", "Which mode the Select Through operator will toggle"); + + prop = RNA_def_property(srna, "backface_header", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "backface_header", 0); + RNA_def_property_ui_text( + prop, + "Backface Header Button", + "Show an operator that toggles the backfacing mesh filter in the viewport header"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_toggle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_toggle_items); + RNA_def_property_ui_text( + prop, "Box Toggle", "Which mode the backfacing mesh filter operator will toggle"); + + prop = RNA_def_property(srna, "backface_toggle_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_toggle_circle_items); + RNA_def_property_ui_text( + prop, "Circle Toggle", "Which mode the backfacing mesh filter operator will toggle"); + + prop = RNA_def_property(srna, "backface_toggle_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_toggle_lasso_items); + RNA_def_property_ui_text( + prop, "Lasso Toggle", "Which mode the backfacing mesh filter operator will toggle"); + + prop = RNA_def_property(srna, "quick_assign_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, quick_assign_mode_items); + RNA_def_property_ui_text( + prop, "Quick Assign Mode", "Which preset the quick assign operator will apply"); + + prop = RNA_def_property(srna, "drag_direction_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, user_direction_box_items); + RNA_def_property_ui_text(prop, "Box Direction", "Use directional control with box select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "drag_direction_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, user_direction_lasso_items); + RNA_def_property_ui_text(prop, "Lasso Direction", "Use directional control with lasso select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "drag_direction_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, user_direction_mode_items); + RNA_def_property_ui_text( + prop, "Direction Affects", "Opt out of directional control for different features"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_controls", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_controls", 0); + RNA_def_property_ui_text(prop, "", "Drag direction settings"); + + prop = RNA_def_property(srna, "direction_object", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_object", 0); + RNA_def_property_ui_text(prop, "Object", "Directional control will affect object select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_face", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_face", 0); + RNA_def_property_ui_text(prop, "Face", "Directional control will affect face select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_edge", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_edge", 0); + RNA_def_property_ui_text(prop, "Edge", "Directional control will affect edge select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_backface", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_backface", 0); + RNA_def_property_ui_text(prop, "Backface", "Directional control will affect backface select"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_auto_xray", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_auto_xray", 0); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Directional control will affect auto xray"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "direction_select_through", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "direction_select_through", 0); + RNA_def_property_ui_text( + prop, "Select Through", "Directional control will affect select through"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_box_items); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during selection"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_downright_box_items); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during selection"); + + prop = RNA_def_property(srna, "select_through_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_box_items); + RNA_def_property_ui_text(prop, "Select Through", "Select occluded objects and mesh"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_downright_box_items); + RNA_def_property_ui_text(prop, "Select Through", "Select occluded objects and mesh"); + + prop = RNA_def_property(srna, "object_select_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_select_box_items); + RNA_def_property_ui_text(prop, "Object", "Object selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_select_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_select_downright_box_items); + RNA_def_property_ui_text(prop, "Object", "Object selection style"); + + prop = RNA_def_property(srna, "face_select_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_select_box_items); + RNA_def_property_ui_text(prop, "Face", "Face selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "face_select_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_select_downright_box_items); + RNA_def_property_ui_text(prop, "Face", "Face selection style"); + + prop = RNA_def_property(srna, "edge_select_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_select_box_items); + RNA_def_property_ui_text(prop, "Edge", "Edge selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_select_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_select_downright_box_items); + RNA_def_property_ui_text(prop, "Edge", "Edge selection style"); + + prop = RNA_def_property(srna, "backface_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_box_items); + RNA_def_property_ui_text( + prop, "Backface", "Select mesh based on the direction of their normals"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_downright_box", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_downright_box_items); + RNA_def_property_ui_text( + prop, "Backface", "Select mesh based on the direction of their normals"); + + prop = RNA_def_property(srna, "auto_xray_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_lasso_items); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during selection"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "auto_xray_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_downright_lasso_items); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during selection"); + + prop = RNA_def_property(srna, "select_through_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_lasso_items); + RNA_def_property_ui_text(prop, "Select Through", "Select occluded objects and mesh"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_downright_lasso_items); + RNA_def_property_ui_text(prop, "Select Through", "Select occluded objects and mesh"); + + prop = RNA_def_property(srna, "object_select_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_select_lasso_items); + RNA_def_property_ui_text(prop, "Object", "Object selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_select_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_select_downright_lasso_items); + RNA_def_property_ui_text(prop, "Object", "Object selection style"); + + prop = RNA_def_property(srna, "face_select_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_select_lasso_items); + RNA_def_property_ui_text(prop, "Face", "Face selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "face_select_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_select_downright_lasso_items); + RNA_def_property_ui_text(prop, "Face", "Face selection style"); + + prop = RNA_def_property(srna, "edge_select_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_select_lasso_items); + RNA_def_property_ui_text(prop, "Edge", "Edge selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_select_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_select_downright_lasso_items); + RNA_def_property_ui_text(prop, "Edge", "Edge selection style"); + + prop = RNA_def_property(srna, "backface_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_lasso_items); + RNA_def_property_ui_text( + prop, "Backface", "Select mesh based on the direction of their normals"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_downright_lasso", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_downright_lasso_items); + RNA_def_property_ui_text( + prop, "Backface", "Select mesh based on the direction of their normals"); + + prop = RNA_def_property(srna, "auto_xray_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, auto_xray_circle_items); + RNA_def_property_ui_text(prop, "Auto X-Ray", "Transparent scene display during selection"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "select_through_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, select_through_circle_items); + RNA_def_property_ui_text(prop, "Select Through", "Select occluded objects and mesh"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "object_select_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, object_select_circle_items); + RNA_def_property_ui_text(prop, "Object", "Object selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "face_select_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, face_select_circle_items); + RNA_def_property_ui_text(prop, "Face", "Face selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "edge_select_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, edge_select_circle_items); + RNA_def_property_ui_text(prop, "Edge", "Edge selection style"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "backface_circle", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, backface_circle_items); + RNA_def_property_ui_text( + prop, "Backface", "Select mesh based on the direction of their normals"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + prop = RNA_def_property(srna, "use_numeric_input_advanced", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_FLAG_NUMINPUT_ADVANCED); RNA_def_property_ui_text(prop, @@ -6568,12 +7879,6 @@ static void rna_def_userdef_input(BlenderRNA *brna) "Number of pixels to before the cursor is considered to have moved " "(used for cycling selected items on successive clicks)"); - prop = RNA_def_property(srna, "header_highlight", PROP_INT, PROP_FACTOR); - RNA_def_property_range(prop, 0, 10); - RNA_def_property_ui_range(prop, 0, 10, 1, -1); - RNA_def_property_ui_text( - prop, "Header Highlight", "How much brighter the header of the active window is"); - /* tablet pressure curve */ prop = RNA_def_property(srna, "pressure_threshold_max", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0f, 1.0f); diff --git a/source/blender/windowmanager/WM_api.hh b/source/blender/windowmanager/WM_api.hh index 661ec9e6ac2..f175824ed9d 100644 --- a/source/blender/windowmanager/WM_api.hh +++ b/source/blender/windowmanager/WM_api.hh @@ -1746,7 +1746,7 @@ bool WM_event_is_modal_drag_exit(const wmEvent *event, short init_event_val); bool WM_event_is_mouse_drag(const wmEvent *event); bool WM_event_is_mouse_drag_or_press(const wmEvent *event); -int WM_event_drag_direction(const wmEvent *event); +int WM_event_drag_direction(bContext *C, const wmEvent *event); char WM_event_utf8_to_ascii(const wmEvent *event) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; /** diff --git a/source/blender/windowmanager/intern/wm_cursors.cc b/source/blender/windowmanager/intern/wm_cursors.cc index cbab9c1a06d..b2c9bf22894 100644 --- a/source/blender/windowmanager/intern/wm_cursors.cc +++ b/source/blender/windowmanager/intern/wm_cursors.cc @@ -41,45 +41,64 @@ struct BCursor { static BCursor *BlenderCursor[WM_CURSOR_NUM] = {nullptr}; +static GHOST_TStandardCursor window_get_custom_cursor(const int cursor) +{ + if (cursor == 1) { + return GHOST_kStandardCursorCrosshair; + } + else if (cursor == 2) { + return GHOST_kStandardCursorPointer; + } + else if (cursor == 3) { + return GHOST_kStandardCursorCrosshairD; + } + else if (cursor == 4) { + return GHOST_kStandardCursorCrosshairA; + } + else if (cursor == 5) { + return GHOST_kStandardCursorCrosshairC; + } + else if (cursor == 6) { + return GHOST_kStandardCursorBox; + } + else if (cursor == 7) { + return GHOST_kStandardCursorBoxDot; + } + else if (cursor == 8) { + return GHOST_kStandardCursorBoxPointer; + } + else if (cursor == 9) { + return GHOST_kStandardCursorCrosshairB; + } + else if (cursor == 10) { + return GHOST_kStandardCursorBlank; + } + else if (cursor == 11) { + return GHOST_kStandardCursorKnife; + } + else if (cursor == 12) { + return GHOST_kStandardCursorPencil; + } + else if (cursor == 13) { + return GHOST_kStandardCursorEraser; + } + else if (cursor == 14) { + return GHOST_kStandardCursorEyedropper; + } + else { + return GHOST_kStandardCursorDefault; + } +} + /* Blender cursor to GHOST standard cursor conversion. */ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) { - const int system_style = U.system_cursor; - const int edit_style = U.edit_cursor; - const int paint_style = U.paint_cursor; - const int dot_style = U.dot_cursor; - const int knife_style = U.knife_cursor; - const int pencil_style = U.pencil_cursor; - const int eraser_style = U.eraser_cursor; - const int eyedropper_style = U.eyedropper_cursor; + GHOST_TStandardCursor cursor = GHOST_kStandardCursorDefault; switch (curs) { case WM_CURSOR_DEFAULT: - if (system_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (system_style == 2) { - return GHOST_kStandardCursorPointer; - } - else if (system_style == 3) { - return GHOST_kStandardCursorCrosshairD; - } - else if (system_style == 4) { - return GHOST_kStandardCursorCrosshairA; - } - else if (system_style == 5) { - return GHOST_kStandardCursorCrosshairC; - } - else if (system_style == 6) { - return GHOST_kStandardCursorBox; - } - else if (system_style == 7) { - return GHOST_kStandardCursorBoxDot; - } - else if (system_style == 8) { - return GHOST_kStandardCursorBoxPointer; - } - else if (system_style == 9) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.system_cursor); + return cursor; } else { return GHOST_kStandardCursorDefault; @@ -88,32 +107,9 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) return GHOST_kStandardCursorWait; case WM_CURSOR_EDIT: case WM_CURSOR_CROSS: - if (edit_style == 1) { - return GHOST_kStandardCursorDefault; - } - else if (edit_style == 2) { - return GHOST_kStandardCursorPointer; - } - else if (edit_style == 3) { - return GHOST_kStandardCursorCrosshairD; - } - else if (edit_style == 4) { - return GHOST_kStandardCursorCrosshairA; - } - else if (edit_style == 5) { - return GHOST_kStandardCursorCrosshairC; - } - else if (edit_style == 6) { - return GHOST_kStandardCursorBox; - } - else if (edit_style == 7) { - return GHOST_kStandardCursorBoxDot; - } - else if (edit_style == 8) { - return GHOST_kStandardCursorBoxPointer; - } - else if (edit_style == 9) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.edit_cursor); + return cursor; } else { return GHOST_kStandardCursorCrosshair; @@ -133,35 +129,9 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_STOP: return GHOST_kStandardCursorStop; case WM_CURSOR_KNIFE: - if (knife_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (knife_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (knife_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (knife_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (knife_style == 5) { - return GHOST_kStandardCursorCrosshairA; - } - else if (knife_style == 6) { - return GHOST_kStandardCursorCrosshairC; - } - else if (knife_style == 7) { - return GHOST_kStandardCursorBox; - } - else if (knife_style == 8) { - return GHOST_kStandardCursorBoxDot; - } - else if (knife_style == 9) { - return GHOST_kStandardCursorBoxPointer; - } - else if (knife_style == 10) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.knife_cursor); + return cursor; } else { return GHOST_kStandardCursorKnife; @@ -173,35 +143,9 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_EW_SCROLL: return GHOST_kStandardCursorEWScroll; case WM_CURSOR_EYEDROPPER: - if (eyedropper_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (eyedropper_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (eyedropper_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (eyedropper_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (eyedropper_style == 5) { - return GHOST_kStandardCursorCrosshairA; - } - else if (eyedropper_style == 6) { - return GHOST_kStandardCursorCrosshairC; - } - else if (eyedropper_style == 7) { - return GHOST_kStandardCursorBox; - } - else if (eyedropper_style == 8) { - return GHOST_kStandardCursorBoxDot; - } - else if (eyedropper_style == 9) { - return GHOST_kStandardCursorBoxPointer; - } - else if (eyedropper_style == 10) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.eyedropper_cursor); + return cursor; } else { return GHOST_kStandardCursorEyedropper; @@ -211,69 +155,17 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_S_ARROW: return GHOST_kStandardCursorDownArrow; case WM_CURSOR_PAINT: - if (paint_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (paint_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (paint_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (paint_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (paint_style == 5) { - return GHOST_kStandardCursorCrosshairC; - } - else if (paint_style == 6) { - return GHOST_kStandardCursorBox; - } - else if (paint_style == 7) { - return GHOST_kStandardCursorBoxDot; - } - else if (paint_style == 8) { - return GHOST_kStandardCursorBoxPointer; - } - else if (paint_style == 9) { - return GHOST_kStandardCursorCrosshairB; - } - else if (paint_style == 10) { - return GHOST_kStandardCursorBlank; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.paint_cursor); + return cursor; } else { return GHOST_kStandardCursorCrosshairA; } case WM_CURSOR_DOT: - if (dot_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (dot_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (dot_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (dot_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (dot_style == 5) { - return GHOST_kStandardCursorCrosshairA; - } - else if (dot_style == 6) { - return GHOST_kStandardCursorCrosshairC; - } - else if (dot_style == 7) { - return GHOST_kStandardCursorBox; - } - else if (dot_style == 8) { - return GHOST_kStandardCursorBoxDot; - } - else if (dot_style == 9) { - return GHOST_kStandardCursorBoxPointer; - } - else if (dot_style == 10) { - return GHOST_kStandardCursorBlank; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.dot_cursor); + return cursor; } else { return GHOST_kStandardCursorCrosshairB; @@ -281,35 +173,9 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_CROSSC: return GHOST_kStandardCursorCrosshairC; case WM_CURSOR_ERASER: - if (eraser_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (eraser_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (eraser_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (eraser_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (eraser_style == 5) { - return GHOST_kStandardCursorCrosshairA; - } - else if (eraser_style == 6) { - return GHOST_kStandardCursorCrosshairC; - } - else if (eraser_style == 7) { - return GHOST_kStandardCursorBox; - } - else if (eraser_style == 8) { - return GHOST_kStandardCursorBoxDot; - } - else if (eraser_style == 9) { - return GHOST_kStandardCursorBoxPointer; - } - else if (eraser_style == 10) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.eraser_cursor); + return cursor; } else { return GHOST_kStandardCursorEraser; @@ -321,35 +187,9 @@ static GHOST_TStandardCursor convert_to_ghost_standard_cursor(WMCursorType curs) case WM_CURSOR_TEXT_EDIT: return GHOST_kStandardCursorText; case WM_CURSOR_PAINT_BRUSH: - if (pencil_style == 1) { - return GHOST_kStandardCursorCrosshair; - } - else if (pencil_style == 2) { - return GHOST_kStandardCursorDefault; - } - else if (pencil_style == 3) { - return GHOST_kStandardCursorPointer; - } - else if (pencil_style == 4) { - return GHOST_kStandardCursorCrosshairD; - } - else if (pencil_style == 5) { - return GHOST_kStandardCursorCrosshairA; - } - else if (pencil_style == 6) { - return GHOST_kStandardCursorCrosshairC; - } - else if (pencil_style == 7) { - return GHOST_kStandardCursorBox; - } - else if (pencil_style == 8) { - return GHOST_kStandardCursorBoxDot; - } - else if (pencil_style == 9) { - return GHOST_kStandardCursorBoxPointer; - } - else if (pencil_style == 10) { - return GHOST_kStandardCursorCrosshairB; + if (U.custom_cursor) { + cursor = window_get_custom_cursor(U.pencil_cursor); + return cursor; } else { return GHOST_kStandardCursorPencil; diff --git a/source/blender/windowmanager/intern/wm_event_query.cc b/source/blender/windowmanager/intern/wm_event_query.cc index 3ccc2b11c96..bf962401530 100644 --- a/source/blender/windowmanager/intern/wm_event_query.cc +++ b/source/blender/windowmanager/intern/wm_event_query.cc @@ -267,28 +267,65 @@ bool WM_event_is_mouse_drag_or_press(const wmEvent *event) (ISMOUSE_BUTTON(event->type) && (event->val == KM_PRESS)); } -int WM_event_drag_direction(const wmEvent *event) +int WM_event_drag_direction(bContext *C, const wmEvent *event) { const int delta[2] = { event->xy[0] - event->prev_press_xy[0], event->xy[1] - event->prev_press_xy[1], }; - const bool left_right = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_LEFT_RIGHT; - const bool up_down = U.click_drag_direction & USER_CLICK_DRAG_DIRECTION_UP_DOWN; - int val = up_down ? KM_DIRECTION_S : KM_DIRECTION_W; + const bool box_left_right = U.drag_direction_box == 1 && U.drag_control_mode == 1; + const bool box_up_down = U.drag_direction_box == 2 && U.drag_control_mode == 1; + const bool lasso_left_right = U.drag_direction_lasso == 1 && U.drag_control_mode == 1; + const bool lasso_up_down = U.drag_direction_lasso == 2 && U.drag_control_mode == 1; + const bool left_right = U.keymap_direction == 1; + const bool up_down = U.keymap_direction == 2; + int val = up_down ? KM_DIRECTION_N : KM_DIRECTION_W; - if (left_right || up_down) { - float thetaf = 4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI; - if (left_right && thetaf > -2.0f && thetaf < 2.0f) { - val = KM_DIRECTION_E; + if (left_right || up_down || box_left_right || box_up_down || lasso_left_right || lasso_up_down) + { + const float thetaf = 4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI; + + if (U.direction_downright_box) { + U.direction_downright_box ^= true; } - else if (up_down && thetaf > 0.0f) { - val = KM_DIRECTION_N; + + if (U.direction_downright_lasso) { + U.direction_downright_lasso ^= true; + } + + if (thetaf > -2.0f && thetaf < 2.0f) { + if (left_right) { + val = KM_DIRECTION_E; + } + + if (box_left_right) { + U.direction_downright_box ^= true; + } + + if (lasso_left_right) { + U.direction_downright_lasso ^= true; + } + } + + if (thetaf < 0.0f) { + if (up_down) { + val = KM_DIRECTION_S; + } + + if (box_up_down) { + U.direction_downright_box ^= true; + } + + if (lasso_up_down) { + U.direction_downright_lasso ^= true; + } } } - else { - int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / (float)M_PI); + + if (!left_right && !up_down) { + const int theta = round_fl_to_int(4.0f * atan2f((float)delta[1], (float)delta[0]) / + (float)M_PI); if (theta == 0) { val = KM_DIRECTION_E; } diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index bff6edb91a4..92294e2de16 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -3475,7 +3475,7 @@ static eHandlerActionFlag wm_handlers_do(bContext *C, wmEvent *event, ListBase * WM_event_drag_test(event, event->prev_press_xy)) { win->event_queue_check_drag_handled = true; - const int direction = WM_event_drag_direction(event); + const int direction = WM_event_drag_direction(C, event); /* Intentionally leave `event->xy` as-is, event users are expected to use * `event->prev_press_xy` if they need to access the drag start location. */ diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.cc b/source/blender/windowmanager/intern/wm_gesture_ops.cc index a57ea112a11..bc7a407ee3a 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.cc +++ b/source/blender/windowmanager/intern/wm_gesture_ops.cc @@ -91,34 +91,73 @@ static void gesture_modal_state_to_operator(wmOperator *op, int modal_state) static void gesture_toggle_xray(bContext *C) { wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_toggle_xray", true); - ToolSettings *ts = CTX_data_tool_settings(C); BLI_assert(ot); PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr, nullptr); WM_operator_properties_free(&ptr); - ts->auto_xray_reset ^= true; + U.auto_xray_reset ^= true; } -static void gesture_auto_xray(bContext *C, - View3D *v3d, - ToolSettings *ts, - wmOperator *op, - const bool mesh, - const bool lasso, - const bool circle) +static void gesture_auto_xray(bContext *C, wmOperator *op, const bool lasso, const bool circle) { + View3D *v3d = CTX_wm_view3d(C); + if (!v3d || XRAY_FLAG_ENABLED(v3d)) { return; } + Object *mesh = CTX_data_edit_object(C); bool auto_xray = false; - if (ts->xray_header) { - if (ts->auto_xray && mesh && ts->auto_xray_edit || - ts->auto_xray && !mesh && ts->auto_xray_object) - { - auto_xray = lasso ? ts->auto_xray_lasso : circle ? ts->auto_xray_circle : ts->auto_xray_box; + if (U.drag_control_mode == 1) { + if (U.userpref_mode == 1 && circle) { + if (mesh) { + auto_xray = U.auto_xray_circle == 2 || U.auto_xray_circle == 3; + } + else { + auto_xray = U.auto_xray_circle == 1 || U.auto_xray_circle == 3; + } + } + else if (U.userpref_mode == 1 && lasso) { + if (mesh) { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) { + auto_xray = U.auto_xray_downright_lasso == 2 || U.auto_xray_downright_lasso == 3; + } + else { + auto_xray = U.auto_xray_lasso == 2 || U.auto_xray_lasso == 3; + } + } + else { + if (U.direction_downright_lasso && (U.drag_direction_mode == 0 || U.direction_auto_xray)) { + auto_xray = U.auto_xray_downright_lasso == 1 || U.auto_xray_downright_lasso == 3; + } + else { + auto_xray = U.auto_xray_lasso == 1 || U.auto_xray_lasso == 3; + } + } + } + else { + if (mesh) { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_auto_xray)) + { + auto_xray = U.auto_xray_downright_box == 2 || U.auto_xray_downright_box == 3; + } + else { + auto_xray = U.auto_xray_box == 2 || U.auto_xray_box == 3; + } + } + else { + if (U.userpref_mode == 1 && U.direction_downright_box && + (U.drag_direction_mode == 0 || U.direction_auto_xray)) + { + auto_xray = U.auto_xray_downright_box == 1 || U.auto_xray_downright_box == 3; + } + else { + auto_xray = U.auto_xray_box == 1 || U.auto_xray_box == 3; + } + } } } else { @@ -126,8 +165,8 @@ static void gesture_auto_xray(bContext *C, auto_xray = mesh ? mode == 4 || mode == 8 : mode == 2 || mode == 8; } - if (ts->auto_xray_reset) { - ts->auto_xray_reset ^= true; + if (U.auto_xray_reset) { + U.auto_xray_reset ^= true; } if (auto_xray) { @@ -213,14 +252,11 @@ static bool gesture_box_apply(bContext *C, wmOperator *op) int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - View3D *v3d = CTX_wm_view3d(C); - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); const ARegion *region = CTX_wm_region(C); const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) && RNA_boolean_get(op->ptr, "wait_for_input"); - gesture_auto_xray(C, v3d, ts, op, obedit, false, false); + gesture_auto_xray(C, op, false, false); if (wait_for_input) { op->customdata = WM_gesture_new(win, region, event, WM_GESTURE_CROSS_RECT); @@ -245,11 +281,8 @@ int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event) int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - View3D *v3d = CTX_wm_view3d(C); wmGesture *gesture = static_cast(op->customdata); rcti *rect = static_cast(gesture->customdata); - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -272,20 +305,20 @@ int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event) gesture->modal_state = event->val; } if (gesture_box_apply(C, op)) { - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } gesture_modal_end(C, op); return OPERATOR_FINISHED; } - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } gesture_modal_end(C, op); return OPERATOR_CANCELLED; } case GESTURE_MODAL_CANCEL: { - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } gesture_modal_end(C, op); @@ -353,15 +386,11 @@ static void gesture_circle_apply(bContext *C, wmOperator *op); int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - View3D *v3d = CTX_wm_view3d(C); const bool wait_for_input = !WM_event_is_mouse_drag_or_press(event) && RNA_boolean_get(op->ptr, "wait_for_input"); + gesture_auto_xray(C, op, false, true); - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = static_cast(win->scene->toolsettings); - gesture_auto_xray(C, v3d, ts, op, obedit, false, true); - - if (ts->square_select) { + if (U.square_select) { op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_SQUARE); } else { @@ -423,11 +452,8 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - View3D *v3d = CTX_wm_view3d(C); wmGesture *gesture = static_cast(op->customdata); rcti *rect = static_cast(gesture->customdata); - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = static_cast(win->scene->toolsettings); if (event->type == MOUSEMOVE) { @@ -496,7 +522,7 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (is_finished) { - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } gesture_modal_end(C, op); @@ -561,12 +587,9 @@ void WM_OT_circle_gesture(wmOperatorType *ot) int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); - View3D *v3d = CTX_wm_view3d(C); PropertyRNA *prop; - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = static_cast(win->scene->toolsettings); - gesture_auto_xray(C, v3d, ts, op, obedit, true, false); + gesture_auto_xray(C, op, true, false); op->customdata = WM_gesture_new(win, CTX_wm_region(C), event, WM_GESTURE_LASSO); @@ -606,10 +629,6 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op) int retval = OPERATOR_FINISHED; wmGesture *gesture = static_cast(op->customdata); PointerRNA itemptr; - View3D *v3d = CTX_wm_view3d(C); - Object *obedit = CTX_data_edit_object(C); - wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = static_cast(win->scene->toolsettings); float loc[2]; int i; const short *lasso = static_cast(gesture->customdata); @@ -631,7 +650,7 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op) OPERATOR_RETVAL_CHECK(retval); } - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } @@ -641,10 +660,6 @@ static int gesture_lasso_apply(bContext *C, wmOperator *op) int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = static_cast(op->customdata); - View3D *v3d = CTX_wm_view3d(C); - Object *obedit = CTX_data_edit_object(C); - wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = static_cast(win->scene->toolsettings); if (event->type == EVT_MODAL_MAP) { switch (event->val) { @@ -698,7 +713,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) break; } case EVT_ESCKEY: { - if (ts->auto_xray_reset) { + if (U.auto_xray_reset) { gesture_toggle_xray(C); } gesture_modal_end(C, op); diff --git a/source/blender/windowmanager/intern/wm_operator_props.cc b/source/blender/windowmanager/intern/wm_operator_props.cc index 40a4baa3441..6a0989fad11 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.cc +++ b/source/blender/windowmanager/intern/wm_operator_props.cc @@ -417,29 +417,29 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo PropertyRNA *prop; static const EnumPropertyItem auto_xray_items[] = { - {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, - {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, - {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, - {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem select_through_items[] = { - {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, - {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, - {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, - {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem object_select_items[] = { - {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, - {OBJECT_ENCLOSE, + {OPERATOR_MODE_A, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the box"}, + {OPERATOR_MODE_B, "OBJECT_ENCLOSE", 0, "Enclose", "Select objects that are fully inside the box"}, - {OBJECT_ORIGIN, + {OPERATOR_MODE_C, "OBJECT_ORIGIN", 0, "Origin", @@ -448,15 +448,19 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo }; static const EnumPropertyItem face_select_items[] = { - {FACE_DEFAULT, + {OPERATOR_MODE_A, "FACE_DEFAULT", 0, "Default", "Select faces that are touched by the box in Near Select. Select faces if their center is " "touched by the box in X-Ray and Select Through"}, - {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, - {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the box"}, - {FACE_CENTER, + {OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the box"}, + {OPERATOR_MODE_C, + "FACE_ENCLOSE", + 0, + "Enclose", + "Select faces that are fully inside the box"}, + {OPERATOR_MODE_D, "FACE_CENTER", 0, "Center", @@ -465,47 +469,61 @@ void WM_operator_properties_gesture_box_ex(wmOperatorType *ot, bool deselect, bo }; static const EnumPropertyItem edge_select_items[] = { - {EDGE_DEFAULT, + {OPERATOR_MODE_A, "EDGE_DEFAULT", 0, "Default", "Select edges that are fully inside the box. If no edges are fully inside the box, select " "edges that are touched by the box"}, - {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"}, - {EDGE_ENCLOSE, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the box"}, + {OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the box"}, + {OPERATOR_MODE_C, + "EDGE_ENCLOSE", + 0, + "Enclose", + "Select edges that are fully inside the box"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem backface_filter_items[] = { - {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, - {BACKFACE_NEAR, + {OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {OPERATOR_MODE_C, "NEAR", 0, - "Fix Near", - "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " - "filtering"}, - {BACKFACE_XRAY, - "XRAY", - 0, - "Front X-Ray", - "Ignore backfacing mesh in X-Ray and Select Through"}, - {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, {0, nullptr, 0, nullptr, nullptr}, }; WM_operator_properties_border(ot); - prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + prop = RNA_def_enum(ot->srna, + "auto_xray", + auto_xray_items, + 0, + "Auto X-Ray", + "Transparent scene display during selection"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + prop = RNA_def_enum(ot->srna, + "select_through", + select_through_items, + 0, + "Select Through", + "Select occluded objects and mesh"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + prop = RNA_def_enum( + ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + prop = RNA_def_enum(ot->srna, + "backface_filter", + backface_filter_items, + 0, + "Backface", + "Select mesh based on the direction of their normals"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); if (deselect) { @@ -612,18 +630,18 @@ void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot) } static const EnumPropertyItem auto_xray_items[] = { - {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, - {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, - {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, - {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem select_through_items[] = { - {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, - {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, - {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, - {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -631,13 +649,17 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) { PropertyRNA *prop; static const EnumPropertyItem object_select_items[] = { - {OBJECT_ORIGIN, + {OPERATOR_MODE_C, "OBJECT_ORIGIN", 0, "Origin", "Select objects if their origin is touched by the lasso"}, - {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the lasso"}, - {OBJECT_ENCLOSE, + {OPERATOR_MODE_A, + "OBJECT_TOUCH", + 0, + "Touch", + "Select objects that are touched by the lasso"}, + {OPERATOR_MODE_B, "OBJECT_ENCLOSE", 0, "Enclose", @@ -646,15 +668,19 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) }; static const EnumPropertyItem face_select_items[] = { - {FACE_DEFAULT, + {OPERATOR_MODE_A, "FACE_DEFAULT", 0, "Default", "Select faces that are touched by the lasso in Near Select. Select faces if their center " "is touched by the lasso in X-Ray and Select Through"}, - {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, - {FACE_ENCLOSE, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the lasso"}, - {FACE_CENTER, + {OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the lasso"}, + {OPERATOR_MODE_C, + "FACE_ENCLOSE", + 0, + "Enclose", + "Select faces that are fully inside the lasso"}, + {OPERATOR_MODE_D, "FACE_CENTER", 0, "Center", @@ -663,47 +689,61 @@ void WM_operator_properties_gesture_lasso(wmOperatorType *ot) }; static const EnumPropertyItem edge_select_items[] = { - {EDGE_DEFAULT, + {OPERATOR_MODE_A, "EDGE_DEFAULT", 0, "Default", "Select edges that are fully inside the lasso. If no edges are fully inside the lasso, " "select edges that are touched by the lasso"}, - {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"}, - {EDGE_ENCLOSE, "EDGE_ENCLOSE", 0, "Enclose", "Select edges that are fully inside the lasso"}, + {OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the lasso"}, + {OPERATOR_MODE_C, + "EDGE_ENCLOSE", + 0, + "Enclose", + "Select edges that are fully inside the lasso"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem backface_filter_items[] = { - {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, - {BACKFACE_NEAR, + {OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {OPERATOR_MODE_C, "NEAR", 0, - "Fix Near", - "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " - "filtering"}, - {BACKFACE_XRAY, - "XRAY", - 0, - "Front X-Ray", - "Ignore backfacing mesh in X-Ray and Select Through"}, - {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, {0, nullptr, 0, nullptr, nullptr}, }; WM_operator_properties_border(ot); - prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + prop = RNA_def_enum(ot->srna, + "auto_xray", + auto_xray_items, + 0, + "Auto X-Ray", + "Transparent scene display during selection"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + prop = RNA_def_enum(ot->srna, + "select_through", + select_through_items, + 0, + "Select Through", + "Select occluded objects and mesh"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + prop = RNA_def_enum( + ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + prop = RNA_def_enum(ot->srna, + "backface_filter", + backface_filter_items, + 0, + "Backface", + "Select mesh based on the direction of their normals"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); prop = RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); @@ -744,29 +784,33 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) const int radius_default = 25; static const EnumPropertyItem auto_xray_items[] = { - {AUTO_XRAY_DISABLE, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, - {AUTO_XRAY_OBJECT, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, - {AUTO_XRAY_EDIT, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, - {AUTO_XRAY_BOTH, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, + {OPERATOR_MODE_A, "AUTO_XRAY_DISABLE", 0, "Disable", "No Auto X-Ray"}, + {OPERATOR_MODE_B, "AUTO_XRAY_OBJECT", 0, "Object", "X-Ray during object select"}, + {OPERATOR_MODE_C, "AUTO_XRAY_EDIT", 0, "Mesh", "X-Ray during mesh select"}, + {OPERATOR_MODE_D, "AUTO_XRAY_BOTH", 0, "Both", "X-Ray during object and mesh select"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem select_through_items[] = { - {SELECT_THROUGH_OBJECT, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, - {SELECT_THROUGH_EDIT, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, - {SELECT_THROUGH_BOTH, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, - {SELECT_THROUGH_DISABLE, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, + {OPERATOR_MODE_B, "SELECT_THROUGH_OBJECT", 0, "Object", "Select through objects"}, + {OPERATOR_MODE_C, "SELECT_THROUGH_EDIT", 0, "Mesh", "Select through mesh"}, + {OPERATOR_MODE_D, "SELECT_THROUGH_BOTH", 0, "Both", "Select through objects and mesh"}, + {OPERATOR_MODE_A, "SELECT_THROUGH_DISABLE", 0, "Disable", "No select through"}, {0, nullptr, 0, nullptr, nullptr}, }; static const EnumPropertyItem object_select_items[] = { - {OBJECT_ORIGIN, + {OPERATOR_MODE_C, "OBJECT_ORIGIN", 0, "Origin", "Select objects if their origin is touched by the circle"}, - {OBJECT_TOUCH, "OBJECT_TOUCH", 0, "Touch", "Select objects that are touched by the circle"}, - {OBJECT_ENCLOSE, + {OPERATOR_MODE_A, + "OBJECT_TOUCH", + 0, + "Touch", + "Select objects that are touched by the circle"}, + {OPERATOR_MODE_B, "OBJECT_ENCLOSE", 0, "Enclose", @@ -775,19 +819,19 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) }; static const EnumPropertyItem face_select_items[] = { - {FACE_DEFAULT, + {OPERATOR_MODE_A, "FACE_DEFAULT", 0, "Default", "Select faces that are touched by the circle in Near Select. Select faces if their center " "is touched by the circle in X-Ray and Select Through"}, - {FACE_TOUCH, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"}, - {FACE_ENCLOSE, + {OPERATOR_MODE_B, "FACE_TOUCH", 0, "Touch", "Select faces that are touched by the circle"}, + {OPERATOR_MODE_C, "FACE_ENCLOSE", 0, "Enclose", "Select faces that are fully inside the circle"}, - {FACE_CENTER, + {OPERATOR_MODE_D, "FACE_CENTER", 0, "Center", @@ -796,8 +840,8 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) }; static const EnumPropertyItem edge_select_items[] = { - {EDGE_TOUCH, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the circle"}, - {EDGE_ENCLOSE, + {OPERATOR_MODE_B, "EDGE_TOUCH", 0, "Touch", "Select edges that are touched by the circle"}, + {OPERATOR_MODE_C, "EDGE_ENCLOSE", 0, "Enclose", @@ -806,19 +850,13 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) }; static const EnumPropertyItem backface_filter_items[] = { - {BACKFACE_DEFAULT, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, - {BACKFACE_NEAR, + {OPERATOR_MODE_A, "BACKFACE_DEFAULT", 0, "Default", "Select backfacing mesh"}, + {OPERATOR_MODE_B, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + {OPERATOR_MODE_C, "NEAR", 0, - "Fix Near", - "Ignore backfacing mesh when not using X-Ray or Select Through, verts don't need " - "filtering"}, - {BACKFACE_XRAY, - "XRAY", - 0, - "Front X-Ray", - "Ignore backfacing mesh in X-Ray and Select Through"}, - {BACKFACE_NONE, "NONE", 0, "No Backface", "Don't select backfacing mesh"}, + "Edge & Face Near", + "Ignore backfacing edges and faces when not using X-Ray or Select Through"}, {0, nullptr, 0, nullptr, nullptr}, }; @@ -831,17 +869,33 @@ void WM_operator_properties_gesture_circle(wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "auto_xray", auto_xray_items, 0, "Auto X-Ray", ""); + prop = RNA_def_enum(ot->srna, + "auto_xray", + auto_xray_items, + 0, + "Auto X-Ray", + "Transparent scene display during selection"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "select_through", select_through_items, 0, "Select Through", ""); + prop = RNA_def_enum(ot->srna, + "select_through", + select_through_items, + 0, + "Select Through", + "Select occluded objects and mesh"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "object_type", object_select_items, 0, "Object", ""); + prop = RNA_def_enum( + ot->srna, "object_type", object_select_items, 0, "Object", "Object selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", ""); + prop = RNA_def_enum(ot->srna, "face_type", face_select_items, 0, "Face", "Face selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", ""); + prop = RNA_def_enum(ot->srna, "edge_type", edge_select_items, 0, "Edge", "Edge selection style"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "backface_filter", backface_filter_items, 0, "Backface", ""); + prop = RNA_def_enum(ot->srna, + "backface_filter", + backface_filter_items, + 0, + "Backface", + "Select mesh based on the direction of their normals"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -- 2.30.2 From 3e37113569e76cad6910c773bccb3211bc27b83d Mon Sep 17 00:00:00 2001 From: bla BLA Date: Wed, 15 May 2024 01:01:53 -0700 Subject: [PATCH 6/6] quick assign changes --- scripts/startup/bl_operators/userpref.py | 54 ++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/scripts/startup/bl_operators/userpref.py b/scripts/startup/bl_operators/userpref.py index 8e9c25a1ce9..fd9ba0a2cbc 100644 --- a/scripts/startup/bl_operators/userpref.py +++ b/scripts/startup/bl_operators/userpref.py @@ -422,7 +422,6 @@ class PREFERENCES_OT_quick_assign(Operator): inputs.backface_box = 'NEAR' inputs.auto_xray_box = 'AUTO_XRAY_DISABLE' inputs.select_through_box = 'SELECT_THROUGH_OBJECT' - inputs.xray_button = 'HIDE' inputs.object_header = True inputs.face_header = True inputs.edge_header = True @@ -460,7 +459,6 @@ class PREFERENCES_OT_quick_assign(Operator): inputs.backface_box = 'DEFAULT' inputs.auto_xray_box = 'AUTO_XRAY_BOTH' inputs.select_through_box = 'SELECT_THROUGH_OBJECT' - inputs.xray_button = 'SHOW' inputs.object_header = True inputs.face_header = True inputs.edge_header = True @@ -521,7 +519,6 @@ class PREFERENCES_OT_quick_assign(Operator): inputs.backface_lasso = 'DEFAULT' inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE' inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT' - inputs.xray_button = 'SHOW' inputs.object_header = False inputs.face_header = False inputs.edge_header = False @@ -554,13 +551,62 @@ class PREFERENCES_OT_quick_assign(Operator): inputs.backface_lasso = 'DEFAULT' inputs.auto_xray_lasso = 'AUTO_XRAY_DISABLE' inputs.select_through_lasso = 'SELECT_THROUGH_OBJECT' - inputs.xray_button = 'SHOW' + inputs.sync_box = False + inputs.sync_circle = False + inputs.sync_lasso = False inputs.object_header = False inputs.face_header = False inputs.edge_header = False inputs.backface_header = False inputs.auto_xray_header = False inputs.select_through_header = False + inputs.object_cycle_touch = True + inputs.object_cycle_enclose = True + inputs.object_cycle_origin = True + inputs.object_cycle_touch_circle = True + inputs.object_cycle_enclose_circle = True + inputs.object_cycle_origin_circle = True + inputs.object_cycle_touch_lasso = True + inputs.object_cycle_enclose_lasso = True + inputs.object_cycle_origin_lasso = True + inputs.face_cycle_default = True + inputs.face_cycle_touch = True + inputs.face_cycle_enclose = True + inputs.face_cycle_center = True + inputs.face_cycle_default_circle = True + inputs.face_cycle_touch_circle = True + inputs.face_cycle_enclose_circle = True + inputs.face_cycle_center_circle = True + inputs.face_cycle_default_lasso = True + inputs.face_cycle_touch_lasso = True + inputs.face_cycle_enclose_lasso = True + inputs.face_cycle_center_lasso = True + inputs.edge_cycle_default = True + inputs.edge_cycle_touch = True + inputs.edge_cycle_enclose = True + inputs.edge_cycle_touch_circle = True + inputs.edge_cycle_enclose_circle = True + inputs.edge_cycle_default_lasso = True + inputs.edge_cycle_touch_lasso = True + inputs.edge_cycle_enclose_lasso = True + inputs.backface_toggle = 'NONE' + inputs.backface_toggle_circle = 'NONE' + inputs.backface_toggle_lasso = 'NONE' + inputs.select_through_toggle = 'BOTH' + inputs.select_through_toggle_circle = 'BOTH' + inputs.select_through_toggle_lasso = 'BOTH' + inputs.auto_xray_toggle = 'BOTH' + inputs.auto_xray_toggle_circle = 'BOTH' + inputs.auto_xray_toggle_lasso = 'BOTH' + inputs.object_pie = 'SHOW' + inputs.face_pie = 'SHOW' + inputs.edge_pie = 'SHOW' + inputs.backface_pie = 'SHOW' + inputs.auto_xray_pie = 'SHOW' + inputs.select_through_pie = 'SHOW' + inputs.box_pie = 'SHOW' + inputs.circle_pie = 'SHOW' + inputs.lasso_pie = 'SHOW' inputs.wireless_touch_object = False inputs.square_select = False return {'FINISHED'} -- 2.30.2