diff options
Diffstat (limited to 'source/blender/editors/space_view3d')
30 files changed, 21544 insertions, 20540 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 837671d6f94..279c6913064 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -16,84 +16,84 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ../include - ../../blenfont - ../../blenkernel - ../../blenlib - ../../blentranslation - ../../bmesh - ../../draw - ../../gpu - ../../imbuf - ../../makesdna - ../../makesrna - ../../render/extern/include - ../../windowmanager - ../../depsgraph - ../../../../intern/guardedalloc - ../../../../intern/glew-mx - ../../../../intern/smoke/extern + ../include + ../../blenfont + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../bmesh + ../../draw + ../../gpu + ../../imbuf + ../../makesdna + ../../makesrna + ../../render/extern/include + ../../windowmanager + ../../depsgraph + ../../../../intern/guardedalloc + ../../../../intern/glew-mx + ../../../../intern/smoke/extern ) set(INC_SYS - ${GLEW_INCLUDE_PATH} + ${GLEW_INCLUDE_PATH} ) set(SRC - drawobject.c - space_view3d.c - view3d_buttons.c - view3d_camera_control.c - view3d_draw.c - view3d_draw_legacy.c - view3d_edit.c - view3d_fly.c - view3d_gizmo_armature.c - view3d_gizmo_camera.c - view3d_gizmo_empty.c - view3d_gizmo_forcefield.c - view3d_gizmo_light.c - view3d_gizmo_navigate.c - view3d_gizmo_navigate_type.c - view3d_gizmo_preselect.c - view3d_gizmo_preselect_type.c - view3d_gizmo_ruler.c - view3d_header.c - view3d_iterators.c - view3d_ops.c - view3d_project.c - view3d_select.c - view3d_snap.c - view3d_toolbar.c - view3d_utils.c - view3d_view.c - view3d_walk.c + drawobject.c + space_view3d.c + view3d_buttons.c + view3d_camera_control.c + view3d_draw.c + view3d_draw_legacy.c + view3d_edit.c + view3d_fly.c + view3d_gizmo_armature.c + view3d_gizmo_camera.c + view3d_gizmo_empty.c + view3d_gizmo_forcefield.c + view3d_gizmo_light.c + view3d_gizmo_navigate.c + view3d_gizmo_navigate_type.c + view3d_gizmo_preselect.c + view3d_gizmo_preselect_type.c + view3d_gizmo_ruler.c + view3d_header.c + view3d_iterators.c + view3d_ops.c + view3d_project.c + view3d_select.c + view3d_snap.c + view3d_toolbar.c + view3d_utils.c + view3d_view.c + view3d_walk.c - view3d_intern.h + view3d_intern.h ) set(LIB - bf_editor_lattice - bf_editor_mesh + bf_editor_lattice + bf_editor_mesh ) if(WITH_PYTHON) - blender_include_dirs(../../python) - add_definitions(-DWITH_PYTHON) + blender_include_dirs(../../python) + add_definitions(-DWITH_PYTHON) endif() add_definitions(${GL_DEFINITIONS}) if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() if(WITH_FREESTYLE) - add_definitions(-DWITH_FREESTYLE) + add_definitions(-DWITH_FREESTYLE) endif() if(WITH_MOD_SMOKE) - add_definitions(-DWITH_SMOKE) + add_definitions(-DWITH_SMOKE) endif() blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index d4745247ae3..c304642c4c3 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -49,34 +49,34 @@ #include "DRW_engine.h" -#include "view3d_intern.h" /* bad level include */ +#include "view3d_intern.h" /* bad level include */ -#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ +#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */ int view3d_effective_drawtype(const struct View3D *v3d) { - if (v3d->shading.type == OB_RENDER) { - return v3d->shading.prev_type; - } - return v3d->shading.type; + if (v3d->shading.type == OB_RENDER) { + return v3d->shading.prev_type; + } + return v3d->shading.type; } static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) { - if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) { - return false; - } + if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) { + return false; + } - if (G.f & G_FLAG_BACKBUFSEL) { - return false; - } + if (G.f & G_FLAG_BACKBUFSEL) { + return false; + } - /* if its drawing textures with zbuf sel, then don't draw dots */ - if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { - return false; - } + /* if its drawing textures with zbuf sel, then don't draw dots */ + if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) { + return false; + } - return true; + return true; } /* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */ @@ -84,102 +84,51 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) #define CIRCLE_RESOL 32 static const float sinval[CIRCLE_RESOL] = { - 0.00000000, - 0.20129852, - 0.39435585, - 0.57126821, - 0.72479278, - 0.84864425, - 0.93775213, - 0.98846832, - 0.99871650, - 0.96807711, - 0.89780453, - 0.79077573, - 0.65137248, - 0.48530196, - 0.29936312, - 0.10116832, - -0.10116832, - -0.29936312, - -0.48530196, - -0.65137248, - -0.79077573, - -0.89780453, - -0.96807711, - -0.99871650, - -0.98846832, - -0.93775213, - -0.84864425, - -0.72479278, - -0.57126821, - -0.39435585, - -0.20129852, - 0.00000000, + 0.00000000, 0.20129852, 0.39435585, 0.57126821, 0.72479278, 0.84864425, 0.93775213, + 0.98846832, 0.99871650, 0.96807711, 0.89780453, 0.79077573, 0.65137248, 0.48530196, + 0.29936312, 0.10116832, -0.10116832, -0.29936312, -0.48530196, -0.65137248, -0.79077573, + -0.89780453, -0.96807711, -0.99871650, -0.98846832, -0.93775213, -0.84864425, -0.72479278, + -0.57126821, -0.39435585, -0.20129852, 0.00000000, }; /* 32 values of cos function (still same result!) */ static const float cosval[CIRCLE_RESOL] = { - 1.00000000, - 0.97952994, - 0.91895781, - 0.82076344, - 0.68896691, - 0.52896401, - 0.34730525, - 0.15142777, - -0.05064916, - -0.25065253, - -0.44039415, - -0.61210598, - -0.75875812, - -0.87434661, - -0.95413925, - -0.99486932, - -0.99486932, - -0.95413925, - -0.87434661, - -0.75875812, - -0.61210598, - -0.44039415, - -0.25065253, - -0.05064916, - 0.15142777, - 0.34730525, - 0.52896401, - 0.68896691, - 0.82076344, - 0.91895781, - 0.97952994, - 1.00000000, + 1.00000000, 0.97952994, 0.91895781, 0.82076344, 0.68896691, 0.52896401, 0.34730525, + 0.15142777, -0.05064916, -0.25065253, -0.44039415, -0.61210598, -0.75875812, -0.87434661, + -0.95413925, -0.99486932, -0.99486932, -0.95413925, -0.87434661, -0.75875812, -0.61210598, + -0.44039415, -0.25065253, -0.05064916, 0.15142777, 0.34730525, 0.52896401, 0.68896691, + 0.82076344, 0.91895781, 0.97952994, 1.00000000, }; -static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3], float rad, const float tmat[4][4]) +static void circball_array_fill(float verts[CIRCLE_RESOL][3], + const float cent[3], + float rad, + const float tmat[4][4]) { - float vx[3], vy[3]; - float *viter = (float *)verts; + float vx[3], vy[3]; + float *viter = (float *)verts; - mul_v3_v3fl(vx, tmat[0], rad); - mul_v3_v3fl(vy, tmat[1], rad); + mul_v3_v3fl(vx, tmat[0], rad); + mul_v3_v3fl(vy, tmat[1], rad); - for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) { - viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0]; - viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1]; - viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2]; - } + for (uint a = 0; a < CIRCLE_RESOL; a++, viter += 3) { + viter[0] = cent[0] + sinval[a] * vx[0] + cosval[a] * vy[0]; + viter[1] = cent[1] + sinval[a] * vx[1] + cosval[a] * vy[1]; + viter[2] = cent[2] + sinval[a] * vx[2] + cosval[a] * vy[2]; + } } void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos) { - float verts[CIRCLE_RESOL][3]; + float verts[CIRCLE_RESOL][3]; - circball_array_fill(verts, cent, rad, tmat); + circball_array_fill(verts, cent, rad, tmat); - immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL); - for (int i = 0; i < CIRCLE_RESOL; ++i) { - immVertex3fv(pos, verts[i]); - } - immEnd(); + immBegin(GPU_PRIM_LINE_LOOP, CIRCLE_RESOL); + for (int i = 0; i < CIRCLE_RESOL; ++i) { + immVertex3fv(pos, verts[i]); + } + immEnd(); } #ifdef VIEW3D_CAMERA_BORDER_HACK @@ -192,344 +141,359 @@ bool view3d_camera_border_hack_test = false; /** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */ static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) { - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); + GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); } static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) { - GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); + GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); } static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4]) { - GPU_line_width(1.0f); - glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", offset); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - - glProvokingVertex(GL_LAST_VERTEX_CONVENTION); + GPU_line_width(1.0f); + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", offset); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); } /* two options, facecolors or black */ -static void bbs_mesh_face(GPUBatch *batch, const bool use_select, const float world_clip_planes[6][4]) +static void bbs_mesh_face(GPUBatch *batch, + const bool use_select, + const float world_clip_planes[6][4]) { - if (use_select) { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } - else { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "id", 0); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); - } + if (use_select) { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", 1); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } + else { + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "id", 0); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); + } } static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4]) { - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); - GPU_batch_uniform_1ui(batch, "offset", 1); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - GPU_batch_draw(batch); + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg); + GPU_batch_uniform_1ui(batch, "offset", 1); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + GPU_batch_draw(batch); } -static void bbs_mesh_solid_verts( - Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene), Object *ob, const float world_clip_planes[6][4]) +static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), + Scene *UNUSED(scene), + Object *ob, + const float world_clip_planes[6][4]) { - Mesh *me = ob->data; + Mesh *me = ob->data; - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - bbs_mesh_face(geom_faces, false, world_clip_planes); - bbs_mesh_verts(geom_verts, 1, world_clip_planes); + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + bbs_mesh_face(geom_faces, false, world_clip_planes); + bbs_mesh_verts(geom_verts, 1, world_clip_planes); - bm_vertoffs = me->totvert + 1; + bm_vertoffs = me->totvert + 1; } -static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob, const float world_clip_planes[6][4]) +static void bbs_mesh_solid_faces(Scene *UNUSED(scene), + Object *ob, + const float world_clip_planes[6][4]) { - Mesh *me = ob->data; - Mesh *me_orig = DEG_get_original_object(ob)->data; + Mesh *me = ob->data; + Mesh *me_orig = DEG_get_original_object(ob)->data; - const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); - GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide); + const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide); - bbs_mesh_face(geom_faces, true, world_clip_planes); + bbs_mesh_face(geom_faces, true, world_clip_planes); } -void draw_object_select_id( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, - short select_mode) +void draw_object_select_id(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + Object *ob, + short select_mode) { - ToolSettings *ts = scene->toolsettings; - if (select_mode == -1) { - select_mode = ts->selectmode; - } - - GPU_matrix_mul(ob->obmat); - GPU_depth_test(true); - - const float (*world_clip_planes)[4] = NULL; - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_local(rv3d, ob->obmat); - world_clip_planes = rv3d->clip_local; - } - - switch (ob->type) { - case OB_MESH: - if (ob->mode & OB_MODE_EDIT) { - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt); - const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; - - BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - - GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; - geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); - if (select_mode & SCE_SELECT_EDGE) { - geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); - } - if (select_mode & SCE_SELECT_VERTEX) { - geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); - } - if (draw_facedot) { - geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); - } - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes); - - if (use_faceselect && draw_facedot) { - bbs_mesh_face_dot(geom_facedots, world_clip_planes); - } - - if (select_mode & SCE_SELECT_FACE) { - bm_solidoffs = 1 + em->bm->totface; - } - else { - bm_solidoffs = 1; - } - - ED_view3d_polygon_offset(rv3d, 1.0); - - /* we draw edges if edge select mode */ - if (select_mode & SCE_SELECT_EDGE) { - bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes); - bm_wireoffs = bm_solidoffs + em->bm->totedge; - } - else { - /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */ - bm_wireoffs = bm_solidoffs; - } - - ED_view3d_polygon_offset(rv3d, 1.1); - - /* we draw verts if vert select mode. */ - if (select_mode & SCE_SELECT_VERTEX) { - bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes); - bm_vertoffs = bm_wireoffs + em->bm->totvert; - } - else { - bm_vertoffs = bm_wireoffs; - } - - ED_view3d_polygon_offset(rv3d, 0.0); - } - else { - Mesh *me = DEG_get_original_object(ob)->data; - if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && - /* currently vertex select supports weight paint and vertex paint*/ - ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) - { - bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes); - } - else { - bbs_mesh_solid_faces(scene, ob, world_clip_planes); - } - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); + ToolSettings *ts = scene->toolsettings; + if (select_mode == -1) { + select_mode = ts->selectmode; + } + + GPU_matrix_mul(ob->obmat); + GPU_depth_test(true); + + const float(*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_local(rv3d, ob->obmat); + world_clip_planes = rv3d->clip_local; + } + + switch (ob->type) { + case OB_MESH: + if (ob->mode & OB_MODE_EDIT) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt); + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; + + BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); + + GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes); + + if (use_faceselect && draw_facedot) { + bbs_mesh_face_dot(geom_facedots, world_clip_planes); + } + + if (select_mode & SCE_SELECT_FACE) { + bm_solidoffs = 1 + em->bm->totface; + } + else { + bm_solidoffs = 1; + } + + ED_view3d_polygon_offset(rv3d, 1.0); + + /* we draw edges if edge select mode */ + if (select_mode & SCE_SELECT_EDGE) { + bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes); + bm_wireoffs = bm_solidoffs + em->bm->totedge; + } + else { + /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */ + bm_wireoffs = bm_solidoffs; + } + + ED_view3d_polygon_offset(rv3d, 1.1); + + /* we draw verts if vert select mode. */ + if (select_mode & SCE_SELECT_VERTEX) { + bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes); + bm_vertoffs = bm_wireoffs + em->bm->totvert; + } + else { + bm_vertoffs = bm_wireoffs; + } + + ED_view3d_polygon_offset(rv3d, 0.0); + } + else { + Mesh *me = DEG_get_original_object(ob)->data; + if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && + /* currently vertex select supports weight paint and vertex paint*/ + ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) { + bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes); + } + else { + bbs_mesh_solid_faces(scene, ob, world_clip_planes); + } + } + break; + case OB_CURVE: + case OB_SURF: + break; + } + + GPU_matrix_set(rv3d->viewmat); } void draw_object_depth(RegionView3D *rv3d, Object *ob) { - GPU_matrix_mul(ob->obmat); - GPU_depth_test(true); - - const float (*world_clip_planes)[4] = NULL; - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_local(rv3d, ob->obmat); - world_clip_planes = rv3d->clip_local; - } - - switch (ob->type) { - case OB_MESH: - { - GPUBatch *batch; - - Mesh *me = ob->data; - - if (ob->mode & OB_MODE_EDIT) { - batch = DRW_mesh_batch_cache_get_edit_triangles(me); - } - else { - batch = DRW_mesh_batch_cache_get_surface(me); - } - - DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - - DRW_opengl_context_enable(); - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; - GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); - if (world_clip_planes != NULL) { - bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); - } - - GPU_batch_draw(batch); - DRW_opengl_context_disable(); - } - break; - case OB_CURVE: - case OB_SURF: - break; - } - - GPU_matrix_set(rv3d->viewmat); + GPU_matrix_mul(ob->obmat); + GPU_depth_test(true); + + const float(*world_clip_planes)[4] = NULL; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_local(rv3d, ob->obmat); + world_clip_planes = rv3d->clip_local; + } + + switch (ob->type) { + case OB_MESH: { + GPUBatch *batch; + + Mesh *me = ob->data; + + if (ob->mode & OB_MODE_EDIT) { + batch = DRW_mesh_batch_cache_get_edit_triangles(me); + } + else { + batch = DRW_mesh_batch_cache_get_surface(me); + } + + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + DRW_opengl_context_enable(); + const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; + GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); + if (world_clip_planes != NULL) { + bbs_world_clip_planes_from_rv3d(batch, world_clip_planes); + } + + GPU_batch_draw(batch); + DRW_opengl_context_disable(); + } break; + case OB_CURVE: + case OB_SURF: + break; + } + + GPU_matrix_set(rv3d->viewmat); } - -void ED_draw_object_facemap( - Depsgraph *depsgraph, Object *ob, const float col[4], const int facemap) +void ED_draw_object_facemap(Depsgraph *depsgraph, + Object *ob, + const float col[4], + const int facemap) { - /* happens on undo */ - if (ob->type != OB_MESH || !ob->data) { - return; - } - - Mesh *me = ob->data; - { - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - if (ob_eval->runtime.mesh_eval) { - me = ob_eval->runtime.mesh_eval; - } - } - - glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); - - /* Just to create the data to pass to immediate mode, grr! */ - const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); - if (facemap_data) { - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - const MVert *mvert = me->mvert; - const MPoly *mpoly = me->mpoly; - const MLoop *mloop = me->mloop; - - int mpoly_len = me->totpoly; - int mloop_len = me->totloop; - - facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); - - /* use gawain immediate mode fore now */ - const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); - const int vbo_len_capacity = looptris_len * 3; - int vbo_len_used = 0; - - GPUVertFormat format_pos = { 0 }; - const uint pos_id = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - GPUVertBuf *vbo_pos = GPU_vertbuf_create_with_format(&format_pos); - GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity); - - GPUVertBufRaw pos_step; - GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step); - - const MPoly *mp; - int i; - if (me->runtime.looptris.array) { - MLoopTri *mlt = me->runtime.looptris.array; - for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { - if (facemap_data[i] == facemap) { - for (int j = 2; j < mp->totloop; j++) { - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[0]].v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[1]].v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[2]].v].co); - vbo_len_used += 3; - mlt++; - } - } - else { - mlt += mp->totloop - 2; - } - } - } - else { - /* No tessellation data, fan-fill. */ - for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { - if (facemap_data[i] == facemap) { - const MLoop *ml_start = &mloop[mp->loopstart]; - const MLoop *ml_a = ml_start + 1; - const MLoop *ml_b = ml_start + 2; - for (int j = 2; j < mp->totloop; j++) { - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_start->v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_a->v].co); - copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_b->v].co); - vbo_len_used += 3; - - ml_a++; - ml_b++; - } - } - } - } - - if (vbo_len_capacity != vbo_len_used) { - GPU_vertbuf_data_resize(vbo_pos, vbo_len_used); - } - - GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_TRIS, vbo_pos, NULL); - GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_uniform_4fv(draw_batch, "color", col); - GPU_batch_draw(draw_batch); - GPU_batch_discard(draw_batch); - GPU_vertbuf_discard(vbo_pos); - - GPU_blend(false); - } + /* happens on undo */ + if (ob->type != OB_MESH || !ob->data) { + return; + } + + Mesh *me = ob->data; + { + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + if (ob_eval->runtime.mesh_eval) { + me = ob_eval->runtime.mesh_eval; + } + } + + glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); + + /* Just to create the data to pass to immediate mode, grr! */ + const int *facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + if (facemap_data) { + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + + const MVert *mvert = me->mvert; + const MPoly *mpoly = me->mpoly; + const MLoop *mloop = me->mloop; + + int mpoly_len = me->totpoly; + int mloop_len = me->totloop; + + facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP); + + /* use gawain immediate mode fore now */ + const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len); + const int vbo_len_capacity = looptris_len * 3; + int vbo_len_used = 0; + + GPUVertFormat format_pos = {0}; + const uint pos_id = GPU_vertformat_attr_add( + &format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + GPUVertBuf *vbo_pos = GPU_vertbuf_create_with_format(&format_pos); + GPU_vertbuf_data_alloc(vbo_pos, vbo_len_capacity); + + GPUVertBufRaw pos_step; + GPU_vertbuf_attr_get_raw_data(vbo_pos, pos_id, &pos_step); + + const MPoly *mp; + int i; + if (me->runtime.looptris.array) { + MLoopTri *mlt = me->runtime.looptris.array; + for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + if (facemap_data[i] == facemap) { + for (int j = 2; j < mp->totloop; j++) { + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[0]].v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[1]].v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop[mlt->tri[2]].v].co); + vbo_len_used += 3; + mlt++; + } + } + else { + mlt += mp->totloop - 2; + } + } + } + else { + /* No tessellation data, fan-fill. */ + for (mp = mpoly, i = 0; i < mpoly_len; i++, mp++) { + if (facemap_data[i] == facemap) { + const MLoop *ml_start = &mloop[mp->loopstart]; + const MLoop *ml_a = ml_start + 1; + const MLoop *ml_b = ml_start + 2; + for (int j = 2; j < mp->totloop; j++) { + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_start->v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_a->v].co); + copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[ml_b->v].co); + vbo_len_used += 3; + + ml_a++; + ml_b++; + } + } + } + } + + if (vbo_len_capacity != vbo_len_used) { + GPU_vertbuf_data_resize(vbo_pos, vbo_len_used); + } + + GPUBatch *draw_batch = GPU_batch_create(GPU_PRIM_TRIS, vbo_pos, NULL); + GPU_batch_program_set_builtin(draw_batch, GPU_SHADER_3D_UNIFORM_COLOR); + GPU_batch_uniform_4fv(draw_batch, "color", col); + GPU_batch_draw(draw_batch); + GPU_batch_discard(draw_batch); + GPU_vertbuf_discard(vbo_pos); + + GPU_blend(false); + } } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 42860b62ae5..434f379c6fe 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -21,7 +21,6 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> @@ -79,75 +78,75 @@ #include "DEG_depsgraph.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* ******************** manage regions ********************* */ ARegion *view3d_has_buttons_region(ScrArea *sa) { - ARegion *ar, *arnew; + ARegion *ar, *arnew; - ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); - if (ar) { - return ar; - } + ar = BKE_area_find_region_type(sa, RGN_TYPE_UI); + if (ar) { + return ar; + } - /* add subdiv level; after header */ - ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + /* add subdiv level; after header */ + ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); - /* is error! */ - if (ar == NULL) { - return NULL; - } + /* is error! */ + if (ar == NULL) { + return NULL; + } - arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d"); + arnew = MEM_callocN(sizeof(ARegion), "buttons for view3d"); - BLI_insertlinkafter(&sa->regionbase, ar, arnew); - arnew->regiontype = RGN_TYPE_UI; - arnew->alignment = RGN_ALIGN_RIGHT; + BLI_insertlinkafter(&sa->regionbase, ar, arnew); + arnew->regiontype = RGN_TYPE_UI; + arnew->alignment = RGN_ALIGN_RIGHT; - arnew->flag = RGN_FLAG_HIDDEN; + arnew->flag = RGN_FLAG_HIDDEN; - return arnew; + return arnew; } ARegion *view3d_has_tools_region(ScrArea *sa) { - ARegion *ar, *artool = NULL, *arhead; - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_TOOLS) { - artool = ar; - } - } - - /* tool region hide/unhide also hides props */ - if (artool) { - return artool; - } - - if (artool == NULL) { - /* add subdiv level; after header */ - for (arhead = sa->regionbase.first; arhead; arhead = arhead->next) { - if (arhead->regiontype == RGN_TYPE_HEADER) { - break; - } - } - - /* is error! */ - if (arhead == NULL) { - return NULL; - } - - artool = MEM_callocN(sizeof(ARegion), "tools for view3d"); - - BLI_insertlinkafter(&sa->regionbase, arhead, artool); - artool->regiontype = RGN_TYPE_TOOLS; - artool->alignment = RGN_ALIGN_LEFT; - artool->flag = RGN_FLAG_HIDDEN; - } - - return artool; + ARegion *ar, *artool = NULL, *arhead; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_TOOLS) { + artool = ar; + } + } + + /* tool region hide/unhide also hides props */ + if (artool) { + return artool; + } + + if (artool == NULL) { + /* add subdiv level; after header */ + for (arhead = sa->regionbase.first; arhead; arhead = arhead->next) { + if (arhead->regiontype == RGN_TYPE_HEADER) { + break; + } + } + + /* is error! */ + if (arhead == NULL) { + return NULL; + } + + artool = MEM_callocN(sizeof(ARegion), "tools for view3d"); + + BLI_insertlinkafter(&sa->regionbase, arhead, artool); + artool->regiontype = RGN_TYPE_TOOLS; + artool->alignment = RGN_ALIGN_LEFT; + artool->flag = RGN_FLAG_HIDDEN; + } + + return artool; } /* ****************************************************** */ @@ -155,74 +154,75 @@ ARegion *view3d_has_tools_region(ScrArea *sa) /* function to always find a regionview3d context inside 3D window */ RegionView3D *ED_view3d_context_rv3d(bContext *C) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - - if (rv3d == NULL) { - ScrArea *sa = CTX_wm_area(C); - if (sa && sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_active_win(sa); - if (ar) { - rv3d = ar->regiondata; - } - } - } - return rv3d; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + if (rv3d == NULL) { + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacetype == SPACE_VIEW3D) { + ARegion *ar = BKE_area_find_region_active_win(sa); + if (ar) { + rv3d = ar->regiondata; + } + } + } + return rv3d; } /* ideally would return an rv3d but in some cases the region is needed too * so return that, the caller can then access the ar->regiondata */ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar) { - ScrArea *sa = CTX_wm_area(C); - - *r_v3d = NULL; - *r_ar = NULL; - - if (sa && sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = (View3D *)sa->spacedata.first; - - if (ar) { - RegionView3D *rv3d; - if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) { - *r_v3d = v3d; - *r_ar = ar; - return true; - } - else { - ARegion *ar_unlock_user = NULL; - ARegion *ar_unlock = NULL; - for (ar = sa->regionbase.first; ar; ar = ar->next) { - /* find the first unlocked rv3d */ - if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) { - rv3d = ar->regiondata; - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - ar_unlock = ar; - if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) { - ar_unlock_user = ar; - break; - } - } - } - } - - /* camera/perspective view get priority when the active region is locked */ - if (ar_unlock_user) { - *r_v3d = v3d; - *r_ar = ar_unlock_user; - return true; - } - - if (ar_unlock) { - *r_v3d = v3d; - *r_ar = ar_unlock; - return true; - } - } - } - } - - return false; + ScrArea *sa = CTX_wm_area(C); + + *r_v3d = NULL; + *r_ar = NULL; + + if (sa && sa->spacetype == SPACE_VIEW3D) { + ARegion *ar = CTX_wm_region(C); + View3D *v3d = (View3D *)sa->spacedata.first; + + if (ar) { + RegionView3D *rv3d; + if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && + (rv3d->viewlock & RV3D_LOCKED) == 0) { + *r_v3d = v3d; + *r_ar = ar; + return true; + } + else { + ARegion *ar_unlock_user = NULL; + ARegion *ar_unlock = NULL; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + /* find the first unlocked rv3d */ + if (ar->regiondata && ar->regiontype == RGN_TYPE_WINDOW) { + rv3d = ar->regiondata; + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + ar_unlock = ar; + if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) { + ar_unlock_user = ar; + break; + } + } + } + } + + /* camera/perspective view get priority when the active region is locked */ + if (ar_unlock_user) { + *r_v3d = v3d; + *r_ar = ar_unlock_user; + return true; + } + + if (ar_unlock) { + *r_v3d = v3d; + *r_ar = ar_unlock; + return true; + } + } + } + } + + return false; } /* Most of the time this isn't needed since you could assume the view matrix was @@ -238,1325 +238,1340 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar) */ void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d) { - /* local viewmat and persmat, to calculate projections */ - mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat); - mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat); + /* local viewmat and persmat, to calculate projections */ + mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat); + mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat); - /* initializes object space clipping, speeds up clip tests */ - ED_view3d_clipping_local(rv3d, ob->obmat); + /* initializes object space clipping, speeds up clip tests */ + ED_view3d_clipping_local(rv3d, ob->obmat); } void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d) { - ED_view3d_init_mats_rv3d(ob, rv3d); + ED_view3d_init_mats_rv3d(ob, rv3d); - /* we have to multiply instead of loading viewmatob to make - * it work with duplis using displists, otherwise it will - * override the dupli-matrix */ - GPU_matrix_mul(ob->obmat); + /* we have to multiply instead of loading viewmatob to make + * it work with duplis using displists, otherwise it will + * override the dupli-matrix */ + GPU_matrix_mul(ob->obmat); } #ifdef DEBUG /* ensure we correctly initialize */ void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d) { - zero_m4(rv3d->viewmatob); - zero_m4(rv3d->persmatob); + zero_m4(rv3d->viewmatob); + zero_m4(rv3d->persmatob); } void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d) { - BLI_ASSERT_ZERO_M4(rv3d->viewmatob); - BLI_ASSERT_ZERO_M4(rv3d->persmatob); + BLI_ASSERT_ZERO_M4(rv3d->viewmatob); + BLI_ASSERT_ZERO_M4(rv3d->persmatob); } #endif void ED_view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; + RegionView3D *rv3d = ar->regiondata; - if (rv3d->render_engine) { + if (rv3d->render_engine) { #ifdef WITH_PYTHON - BPy_BEGIN_ALLOW_THREADS; + BPy_BEGIN_ALLOW_THREADS; #endif - WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW); + WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW); #ifdef WITH_PYTHON - BPy_END_ALLOW_THREADS; + BPy_END_ALLOW_THREADS; #endif - RE_engine_free(rv3d->render_engine); - rv3d->render_engine = NULL; - } + RE_engine_free(rv3d->render_engine); + rv3d->render_engine = NULL; + } } void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa) { - wmWindowManager *wm = bmain->wm.first; - - if (v3d->shading.type != OB_RENDER) { - ARegion *ar; - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) { - ED_view3d_stop_render_preview(wm, ar); - break; - } - } - } + wmWindowManager *wm = bmain->wm.first; + + if (v3d->shading.type != OB_RENDER) { + ARegion *ar; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) { + ED_view3d_stop_render_preview(wm, ar); + break; + } + } + } } /* ******************** default callbacks for view3d space ***************** */ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene) { - ARegion *ar; - View3D *v3d; - RegionView3D *rv3d; - - v3d = MEM_callocN(sizeof(View3D), "initview3d"); - v3d->spacetype = SPACE_VIEW3D; - if (scene) { - v3d->camera = scene->camera; - } - v3d->scenelock = true; - v3d->grid = 1.0f; - v3d->gridlines = 16; - v3d->gridsubdiv = 10; - BKE_screen_view3d_shading_init(&v3d->shading); - - v3d->overlay.wireframe_threshold = 1.0f; - v3d->overlay.xray_alpha_bone = 0.5f; - v3d->overlay.texture_paint_mode_opacity = 1.0f; - v3d->overlay.weight_paint_mode_opacity = 1.0f; - v3d->overlay.vertex_paint_mode_opacity = 1.0f; - v3d->overlay.edit_flag = V3D_OVERLAY_EDIT_FACES | - V3D_OVERLAY_EDIT_SEAMS | - V3D_OVERLAY_EDIT_SHARP | - V3D_OVERLAY_EDIT_FREESTYLE_EDGE | - V3D_OVERLAY_EDIT_FREESTYLE_FACE | - V3D_OVERLAY_EDIT_EDGES | - V3D_OVERLAY_EDIT_CREASES | - V3D_OVERLAY_EDIT_BWEIGHTS | - V3D_OVERLAY_EDIT_CU_HANDLES | - V3D_OVERLAY_EDIT_CU_NORMALS; - - v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR; - - v3d->flag = V3D_SELECT_OUTLINE; - v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_ANNOTATION; - - v3d->lens = 50.0f; - v3d->clip_start = 0.01f; - v3d->clip_end = 1000.0f; - - v3d->overlay.gpencil_paper_opacity = 0.5f; - v3d->overlay.gpencil_grid_opacity = 0.9f; - - v3d->bundle_size = 0.2f; - v3d->bundle_drawtype = OB_PLAINAXES; - - /* stereo */ - v3d->stereo3d_camera = STEREO_3D_ID; - v3d->stereo3d_flag |= V3D_S3D_DISPPLANE; - v3d->stereo3d_convergence_alpha = 0.15f; - v3d->stereo3d_volume_alpha = 0.05f; - - /* grease pencil settings */ - v3d->vertex_opacity = 1.0f; - v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; - - /* header */ - ar = MEM_callocN(sizeof(ARegion), "header for view3d"); - - BLI_addtail(&v3d->regionbase, ar); - ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; - - /* tool shelf */ - ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d"); - - BLI_addtail(&v3d->regionbase, ar); - ar->regiontype = RGN_TYPE_TOOLS; - ar->alignment = RGN_ALIGN_LEFT; - ar->flag = RGN_FLAG_HIDDEN; - - /* buttons/list view */ - ar = MEM_callocN(sizeof(ARegion), "buttons for view3d"); - - BLI_addtail(&v3d->regionbase, ar); - ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_RIGHT; - ar->flag = RGN_FLAG_HIDDEN; - - /* main region */ - ar = MEM_callocN(sizeof(ARegion), "main region for view3d"); - - BLI_addtail(&v3d->regionbase, ar); - ar->regiontype = RGN_TYPE_WINDOW; - - ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d"); - rv3d = ar->regiondata; - rv3d->viewquat[0] = 1.0f; - rv3d->persp = RV3D_PERSP; - rv3d->view = RV3D_VIEW_USER; - rv3d->dist = 10.0; - - return (SpaceLink *)v3d; + ARegion *ar; + View3D *v3d; + RegionView3D *rv3d; + + v3d = MEM_callocN(sizeof(View3D), "initview3d"); + v3d->spacetype = SPACE_VIEW3D; + if (scene) { + v3d->camera = scene->camera; + } + v3d->scenelock = true; + v3d->grid = 1.0f; + v3d->gridlines = 16; + v3d->gridsubdiv = 10; + BKE_screen_view3d_shading_init(&v3d->shading); + + v3d->overlay.wireframe_threshold = 1.0f; + v3d->overlay.xray_alpha_bone = 0.5f; + v3d->overlay.texture_paint_mode_opacity = 1.0f; + v3d->overlay.weight_paint_mode_opacity = 1.0f; + v3d->overlay.vertex_paint_mode_opacity = 1.0f; + v3d->overlay.edit_flag = V3D_OVERLAY_EDIT_FACES | V3D_OVERLAY_EDIT_SEAMS | + V3D_OVERLAY_EDIT_SHARP | V3D_OVERLAY_EDIT_FREESTYLE_EDGE | + V3D_OVERLAY_EDIT_FREESTYLE_FACE | V3D_OVERLAY_EDIT_EDGES | + V3D_OVERLAY_EDIT_CREASES | V3D_OVERLAY_EDIT_BWEIGHTS | + V3D_OVERLAY_EDIT_CU_HANDLES | V3D_OVERLAY_EDIT_CU_NORMALS; + + v3d->gridflag = V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_FLOOR; + + v3d->flag = V3D_SELECT_OUTLINE; + v3d->flag2 = V3D_SHOW_RECONSTRUCTION | V3D_SHOW_ANNOTATION; + + v3d->lens = 50.0f; + v3d->clip_start = 0.01f; + v3d->clip_end = 1000.0f; + + v3d->overlay.gpencil_paper_opacity = 0.5f; + v3d->overlay.gpencil_grid_opacity = 0.9f; + + v3d->bundle_size = 0.2f; + v3d->bundle_drawtype = OB_PLAINAXES; + + /* stereo */ + v3d->stereo3d_camera = STEREO_3D_ID; + v3d->stereo3d_flag |= V3D_S3D_DISPPLANE; + v3d->stereo3d_convergence_alpha = 0.15f; + v3d->stereo3d_volume_alpha = 0.05f; + + /* grease pencil settings */ + v3d->vertex_opacity = 1.0f; + v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; + + /* header */ + ar = MEM_callocN(sizeof(ARegion), "header for view3d"); + + BLI_addtail(&v3d->regionbase, ar); + ar->regiontype = RGN_TYPE_HEADER; + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + + /* tool shelf */ + ar = MEM_callocN(sizeof(ARegion), "toolshelf for view3d"); + + BLI_addtail(&v3d->regionbase, ar); + ar->regiontype = RGN_TYPE_TOOLS; + ar->alignment = RGN_ALIGN_LEFT; + ar->flag = RGN_FLAG_HIDDEN; + + /* buttons/list view */ + ar = MEM_callocN(sizeof(ARegion), "buttons for view3d"); + + BLI_addtail(&v3d->regionbase, ar); + ar->regiontype = RGN_TYPE_UI; + ar->alignment = RGN_ALIGN_RIGHT; + ar->flag = RGN_FLAG_HIDDEN; + + /* main region */ + ar = MEM_callocN(sizeof(ARegion), "main region for view3d"); + + BLI_addtail(&v3d->regionbase, ar); + ar->regiontype = RGN_TYPE_WINDOW; + + ar->regiondata = MEM_callocN(sizeof(RegionView3D), "region view3d"); + rv3d = ar->regiondata; + rv3d->viewquat[0] = 1.0f; + rv3d->persp = RV3D_PERSP; + rv3d->view = RV3D_VIEW_USER; + rv3d->dist = 10.0; + + return (SpaceLink *)v3d; } /* not spacelink itself */ static void view3d_free(SpaceLink *sl) { - View3D *vd = (View3D *) sl; - - if (vd->localvd) { - MEM_freeN(vd->localvd); - } - - if (vd->runtime.properties_storage) { - MEM_freeN(vd->runtime.properties_storage); - } - - if (vd->fx_settings.ssao) { - MEM_freeN(vd->fx_settings.ssao); - } - if (vd->fx_settings.dof) { - MEM_freeN(vd->fx_settings.dof); - } + View3D *vd = (View3D *)sl; + + if (vd->localvd) { + MEM_freeN(vd->localvd); + } + + if (vd->runtime.properties_storage) { + MEM_freeN(vd->runtime.properties_storage); + } + + if (vd->fx_settings.ssao) { + MEM_freeN(vd->fx_settings.ssao); + } + if (vd->fx_settings.dof) { + MEM_freeN(vd->fx_settings.dof); + } } - /* spacetype; init callback */ static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) { - } static SpaceLink *view3d_duplicate(SpaceLink *sl) { - View3D *v3do = (View3D *)sl; - View3D *v3dn = MEM_dupallocN(sl); + View3D *v3do = (View3D *)sl; + View3D *v3dn = MEM_dupallocN(sl); - /* clear or remove stuff from old */ + /* clear or remove stuff from old */ - if (v3dn->localvd) { - v3dn->localvd = NULL; - v3dn->runtime.properties_storage = NULL; - } + if (v3dn->localvd) { + v3dn->localvd = NULL; + v3dn->runtime.properties_storage = NULL; + } - if (v3dn->shading.type == OB_RENDER) { - v3dn->shading.type = OB_SOLID; - } + if (v3dn->shading.type == OB_RENDER) { + v3dn->shading.type = OB_SOLID; + } - /* copy or clear inside new stuff */ + /* copy or clear inside new stuff */ - v3dn->runtime.properties_storage = NULL; - if (v3dn->fx_settings.dof) { - v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof); - } - if (v3dn->fx_settings.ssao) { - v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao); - } + v3dn->runtime.properties_storage = NULL; + if (v3dn->fx_settings.dof) { + v3dn->fx_settings.dof = MEM_dupallocN(v3do->fx_settings.dof); + } + if (v3dn->fx_settings.ssao) { + v3dn->fx_settings.ssao = MEM_dupallocN(v3do->fx_settings.ssao); + } - return (SpaceLink *)v3dn; + return (SpaceLink *)v3dn; } /* add handlers, stuff you only do once or on area/region changes */ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar) { - ListBase *lb; - wmKeyMap *keymap; - - /* object ops. */ + ListBase *lb; + wmKeyMap *keymap; - /* important to be before Pose keymap since they can both be enabled at once */ - keymap = WM_keymap_ensure(wm->defaultconf, "Face Mask", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* object ops. */ + /* important to be before Pose keymap since they can both be enabled at once */ + keymap = WM_keymap_ensure(wm->defaultconf, "Face Mask", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint Vertex Selection", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - /* pose is not modal, operator poll checks for this */ - keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* pose is not modal, operator poll checks for this */ + keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Object Mode", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Vertex Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Weight Paint", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Sculpt", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Mesh", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Mesh", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Armature", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Armature", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Pose", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Metaball", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Lattice", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Particle", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - /* editfont keymap swallows all... */ - keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* editfont keymap swallows all... */ + keymap = WM_keymap_ensure(wm->defaultconf, "Font", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Object Non-modal", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "Frames", 0, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - /* own keymap, last so modes can override it */ - keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + /* own keymap, last so modes can override it */ + keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "3D View", SPACE_VIEW3D, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); - /* add drop boxes */ - lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); - - WM_event_add_dropbox_handler(&ar->handlers, lb); + /* add drop boxes */ + lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); + WM_event_add_dropbox_handler(&ar->handlers, lb); } static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar) { - ED_view3d_stop_render_preview(wm, ar); + ED_view3d_stop_render_preview(wm, ar); } -static bool view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) +static bool view3d_ob_drop_poll(bContext *UNUSED(C), + wmDrag *drag, + const wmEvent *UNUSED(event), + const char **UNUSED(tooltip)) { - return WM_drag_ID(drag, ID_OB) != NULL; + return WM_drag_ID(drag, ID_OB) != NULL; } -static bool view3d_collection_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) +static bool view3d_collection_drop_poll(bContext *UNUSED(C), + wmDrag *drag, + const wmEvent *UNUSED(event), + const char **UNUSED(tooltip)) { - return WM_drag_ID(drag, ID_GR) != NULL; + return WM_drag_ID(drag, ID_GR) != NULL; } -static bool view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) +static bool view3d_mat_drop_poll(bContext *UNUSED(C), + wmDrag *drag, + const wmEvent *UNUSED(event), + const char **UNUSED(tooltip)) { - return WM_drag_ID(drag, ID_MA) != NULL; + return WM_drag_ID(drag, ID_MA) != NULL; } -static bool view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), const char **UNUSED(tooltip)) +static bool view3d_ima_drop_poll(bContext *UNUSED(C), + wmDrag *drag, + const wmEvent *UNUSED(event), + const char **UNUSED(tooltip)) { - if (drag->type == WM_DRAG_PATH) { - /* rule might not work? */ - return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); - } - else { - return WM_drag_ID(drag, ID_IM) != NULL; - } + if (drag->type == WM_DRAG_PATH) { + /* rule might not work? */ + return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); + } + else { + return WM_drag_ID(drag, ID_IM) != NULL; + } } static bool view3d_ima_bg_is_camera_view(bContext *C) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if ((rv3d && (rv3d->persp == RV3D_CAMOB))) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d && v3d->camera && v3d->camera->type == OB_CAMERA) { - return true; - } - } - return false; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if ((rv3d && (rv3d->persp == RV3D_CAMOB))) { + View3D *v3d = CTX_wm_view3d(C); + if (v3d && v3d->camera && v3d->camera->type == OB_CAMERA) { + return true; + } + } + return false; } -static bool view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip) +static bool view3d_ima_bg_drop_poll(bContext *C, + wmDrag *drag, + const wmEvent *event, + const char **tooltip) { - if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { - return false; - } + if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { + return false; + } - if (ED_view3d_is_object_under_cursor(C, event->mval)) { - return false; - } + if (ED_view3d_is_object_under_cursor(C, event->mval)) { + return false; + } - return view3d_ima_bg_is_camera_view(C); + return view3d_ima_bg_is_camera_view(C); } -static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, const char **tooltip) +static bool view3d_ima_empty_drop_poll(bContext *C, + wmDrag *drag, + const wmEvent *event, + const char **tooltip) { - if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { - return false; - } + if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { + return false; + } - Object *ob = ED_view3d_give_object_under_cursor(C, event->mval); + Object *ob = ED_view3d_give_object_under_cursor(C, event->mval); - if (ob == NULL) { - return true; - } + if (ob == NULL) { + return true; + } - if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { - return true; - } + if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { + return true; + } - return false; + return false; } static void view3d_ob_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, ID_OB); + ID *id = WM_drag_ID(drag, ID_OB); - RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, ID_GR); + ID *id = WM_drag_ID(drag, ID_GR); - drop->opcontext = WM_OP_EXEC_DEFAULT; - RNA_string_set(drop->ptr, "name", id->name + 2); + drop->opcontext = WM_OP_EXEC_DEFAULT; + RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); + ID *id = WM_drag_ID(drag, 0); - RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_string_set(drop->ptr, "name", id->name + 2); } static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_ID(drag, 0); - - if (id) { - RNA_string_set(drop->ptr, "name", id->name + 2); - RNA_struct_property_unset(drop->ptr, "filepath"); - } - else if (drag->path[0]) { - RNA_string_set(drop->ptr, "filepath", drag->path); - RNA_struct_property_unset(drop->ptr, "image"); - } + ID *id = WM_drag_ID(drag, 0); + + if (id) { + RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_struct_property_unset(drop->ptr, "filepath"); + } + else if (drag->path[0]) { + RNA_string_set(drop->ptr, "filepath", drag->path); + RNA_struct_property_unset(drop->ptr, "image"); + } } static void view3d_lightcache_update(bContext *C) { - PointerRNA op_ptr; + PointerRNA op_ptr; - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - if (strcmp(scene->r.engine, RE_engine_id_BLENDER_EEVEE) != 0) { - /* Only do auto bake if eevee is the active engine */ - return; - } + if (strcmp(scene->r.engine, RE_engine_id_BLENDER_EEVEE) != 0) { + /* Only do auto bake if eevee is the active engine */ + return; + } - WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake"); - RNA_int_set(&op_ptr, "delay", 200); - RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY"); + WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake"); + RNA_int_set(&op_ptr, "delay", 200); + RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY"); - WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr); - WM_operator_properties_free(&op_ptr); + WM_operator_properties_free(&op_ptr); } /* region dropbox definition */ static void view3d_dropboxes(void) { - ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); - - WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy); - WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy); - WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy); - WM_dropbox_add(lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy); - WM_dropbox_add(lb, "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy); + ListBase *lb = WM_dropboxmap_find("View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW); + + WM_dropbox_add(lb, "OBJECT_OT_add_named", view3d_ob_drop_poll, view3d_ob_drop_copy); + WM_dropbox_add(lb, "OBJECT_OT_drop_named_material", view3d_mat_drop_poll, view3d_id_drop_copy); + WM_dropbox_add( + lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, view3d_id_path_drop_copy); + WM_dropbox_add( + lb, "OBJECT_OT_drop_named_image", view3d_ima_empty_drop_poll, view3d_id_path_drop_copy); + WM_dropbox_add(lb, + "OBJECT_OT_collection_instance_add", + view3d_collection_drop_poll, + view3d_collection_drop_copy); } static void view3d_widgets(void) { - wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure( - &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW}); - - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image); - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline); - - WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo); - WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage); - WM_gizmogrouptype_append(VIEW3D_GGT_xform_shear); - WM_gizmogrouptype_append(VIEW3D_GGT_xform_extrude); - WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_elem); - WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering); - - WM_gizmogrouptype_append(VIEW3D_GGT_ruler); - WM_gizmotype_append(VIEW3D_GT_ruler_item); - - WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate); - WM_gizmotype_append(VIEW3D_GT_navigate_rotate); + wmGizmoMapType *gzmap_type = WM_gizmomaptype_ensure( + &(const struct wmGizmoMapType_Params){SPACE_VIEW3D, RGN_TYPE_WINDOW}); + + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_xform_gizmo_context); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_spot); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_area); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_light_target); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_force_field); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image); + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline); + + WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo); + WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage); + WM_gizmogrouptype_append(VIEW3D_GGT_xform_shear); + WM_gizmogrouptype_append(VIEW3D_GGT_xform_extrude); + WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_elem); + WM_gizmogrouptype_append(VIEW3D_GGT_mesh_preselect_edgering); + + WM_gizmogrouptype_append(VIEW3D_GGT_ruler); + WM_gizmotype_append(VIEW3D_GT_ruler_item); + + WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_navigate); + WM_gizmotype_append(VIEW3D_GT_navigate_rotate); } - /* type callback, not region itself */ static void view3d_main_region_free(ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d) { - if (rv3d->localvd) { - MEM_freeN(rv3d->localvd); - } - if (rv3d->clipbb) { - MEM_freeN(rv3d->clipbb); - } - - if (rv3d->render_engine) { - RE_engine_free(rv3d->render_engine); - } - - if (rv3d->depths) { - if (rv3d->depths->depths) { - MEM_freeN(rv3d->depths->depths); - } - MEM_freeN(rv3d->depths); - } - if (rv3d->sms) { - MEM_freeN(rv3d->sms); - } - - MEM_freeN(rv3d); - ar->regiondata = NULL; - } + RegionView3D *rv3d = ar->regiondata; + + if (rv3d) { + if (rv3d->localvd) { + MEM_freeN(rv3d->localvd); + } + if (rv3d->clipbb) { + MEM_freeN(rv3d->clipbb); + } + + if (rv3d->render_engine) { + RE_engine_free(rv3d->render_engine); + } + + if (rv3d->depths) { + if (rv3d->depths->depths) { + MEM_freeN(rv3d->depths->depths); + } + MEM_freeN(rv3d->depths); + } + if (rv3d->sms) { + MEM_freeN(rv3d->sms); + } + + MEM_freeN(rv3d); + ar->regiondata = NULL; + } } /* copy regiondata */ static void *view3d_main_region_duplicate(void *poin) { - if (poin) { - RegionView3D *rv3d = poin, *new; - - new = MEM_dupallocN(rv3d); - if (rv3d->localvd) { - new->localvd = MEM_dupallocN(rv3d->localvd); - } - if (rv3d->clipbb) { - new->clipbb = MEM_dupallocN(rv3d->clipbb); - } - - new->depths = NULL; - new->render_engine = NULL; - new->sms = NULL; - new->smooth_timer = NULL; - - return new; - } - return NULL; + if (poin) { + RegionView3D *rv3d = poin, *new; + + new = MEM_dupallocN(rv3d); + if (rv3d->localvd) { + new->localvd = MEM_dupallocN(rv3d->localvd); + } + if (rv3d->clipbb) { + new->clipbb = MEM_dupallocN(rv3d->clipbb); + } + + new->depths = NULL; + new->render_engine = NULL; + new->sms = NULL; + new->smooth_timer = NULL; + + return new; + } + return NULL; } static void view3d_main_region_listener( - wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, - wmNotifier *wmn, const Scene *scene) + wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *scene) { - View3D *v3d = sa->spacedata.first; - RegionView3D *rv3d = ar->regiondata; - wmGizmoMap *gzmap = ar->gizmo_map; - - /* context changes */ - switch (wmn->category) { - case NC_WM: - if (ELEM(wmn->data, ND_UNDO)) { - WM_gizmomap_tag_refresh(gzmap); - } - break; - case NC_ANIMATION: - switch (wmn->data) { - case ND_KEYFRAME_PROP: - case ND_NLA_ACTCHANGE: - ED_region_tag_redraw(ar); - break; - case ND_NLA: - case ND_KEYFRAME: - if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) { - ED_region_tag_redraw(ar); - } - break; - case ND_ANIMCHAN: - if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) { - ED_region_tag_redraw(ar); - } - break; - } - break; - case NC_SCENE: - switch (wmn->data) { - case ND_SCENEBROWSE: - case ND_LAYER_CONTENT: - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - break; - case ND_LAYER: - if (wmn->reference) { - BKE_screen_view3d_sync(v3d, wmn->reference); - } - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - break; - case ND_OB_ACTIVE: - case ND_OB_SELECT: - ATTR_FALLTHROUGH; - case ND_FRAME: - case ND_TRANSFORM: - case ND_OB_VISIBLE: - case ND_RENDER_OPTIONS: - case ND_MARKERS: - case ND_MODE: - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - break; - case ND_WORLD: - /* handled by space_view3d_listener() for v3d access */ - break; - case ND_DRAW_RENDER_VIEWPORT: - { - if (v3d->camera && (scene == wmn->reference)) { - if (rv3d->persp == RV3D_CAMOB) { - ED_region_tag_redraw(ar); - } - } - break; - } - } - if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); - } - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_BONE_ACTIVE: - case ND_BONE_SELECT: - case ND_TRANSFORM: - case ND_POSE: - case ND_DRAW: - case ND_MODIFIER: - case ND_CONSTRAINT: - case ND_KEYS: - case ND_PARTICLE: - case ND_POINTCACHE: - case ND_LOD: - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - break; - } - switch (wmn->action) { - case NA_ADDED: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_GEOM: - switch (wmn->data) { - case ND_SELECT: - { - WM_gizmomap_tag_refresh(gzmap); - ATTR_FALLTHROUGH; - } - case ND_DATA: - case ND_VERTEX_GROUP: - ED_region_tag_redraw(ar); - break; - } - switch (wmn->action) { - case NA_EDITED: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_CAMERA: - switch (wmn->data) { - case ND_DRAW_RENDER_VIEWPORT: - { - if (v3d->camera && (v3d->camera->data == wmn->reference)) { - if (rv3d->persp == RV3D_CAMOB) { - ED_region_tag_redraw(ar); - } - } - break; - } - } - break; - case NC_GROUP: - /* all group ops for now */ - ED_region_tag_redraw(ar); - break; - case NC_BRUSH: - switch (wmn->action) { - case NA_EDITED: - ED_region_tag_redraw_overlay(ar); - break; - case NA_SELECTED: - /* used on brush changes - needed because 3d cursor - * has to be drawn if clone brush is selected */ - ED_region_tag_redraw(ar); - break; - } - break; - case NC_MATERIAL: - switch (wmn->data) { - case ND_SHADING: - case ND_NODES: - /* TODO(sergey) This is a bit too much updates, but needed to - * have proper material drivers update in the viewport. - * - * How to solve? - */ - ED_region_tag_redraw(ar); - break; - case ND_SHADING_DRAW: - case ND_SHADING_LINKS: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_WORLD: - switch (wmn->data) { - case ND_WORLD_DRAW: - /* handled by space_view3d_listener() for v3d access */ - break; - case ND_WORLD: - /* Needed for updating world materials */ - ED_region_tag_redraw(ar); - break; - } - break; - case NC_LAMP: - switch (wmn->data) { - case ND_LIGHTING: - /* TODO(sergey): This is a bit too much, but needed to - * handle updates from new depsgraph. - */ - ED_region_tag_redraw(ar); - break; - case ND_LIGHTING_DRAW: - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - break; - } - break; - case NC_LIGHTPROBE: - ED_area_tag_refresh(sa); - break; - case NC_IMAGE: - /* this could be more fine grained checks if we had - * more context than just the region */ - ED_region_tag_redraw(ar); - break; - case NC_TEXTURE: - /* same as above */ - ED_region_tag_redraw(ar); - break; - case NC_MOVIECLIP: - if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_VIEW3D) { - if (wmn->subtype == NS_VIEW3D_GPU) { - rv3d->rflag |= RV3D_GPULIGHT_UPDATE; - } - ED_region_tag_redraw(ar); - WM_gizmomap_tag_refresh(gzmap); - } - break; - case NC_ID: - if (wmn->action == NA_RENAME) { - ED_region_tag_redraw(ar); - } - break; - case NC_SCREEN: - switch (wmn->data) { - case ND_ANIMPLAY: - case ND_SKETCH: - ED_region_tag_redraw(ar); - break; - case ND_LAYOUTBROWSE: - case ND_LAYOUTDELETE: - case ND_LAYOUTSET: - WM_gizmomap_tag_refresh(gzmap); - ED_region_tag_redraw(ar); - break; - case ND_LAYER: - ED_region_tag_redraw(ar); - break; - } - - break; - case NC_GPENCIL: - if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); - } - break; - } + View3D *v3d = sa->spacedata.first; + RegionView3D *rv3d = ar->regiondata; + wmGizmoMap *gzmap = ar->gizmo_map; + + /* context changes */ + switch (wmn->category) { + case NC_WM: + if (ELEM(wmn->data, ND_UNDO)) { + WM_gizmomap_tag_refresh(gzmap); + } + break; + case NC_ANIMATION: + switch (wmn->data) { + case ND_KEYFRAME_PROP: + case ND_NLA_ACTCHANGE: + ED_region_tag_redraw(ar); + break; + case ND_NLA: + case ND_KEYFRAME: + if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) { + ED_region_tag_redraw(ar); + } + break; + case ND_ANIMCHAN: + if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED, NA_SELECTED)) { + ED_region_tag_redraw(ar); + } + break; + } + break; + case NC_SCENE: + switch (wmn->data) { + case ND_SCENEBROWSE: + case ND_LAYER_CONTENT: + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + break; + case ND_LAYER: + if (wmn->reference) { + BKE_screen_view3d_sync(v3d, wmn->reference); + } + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + break; + case ND_OB_ACTIVE: + case ND_OB_SELECT: + ATTR_FALLTHROUGH; + case ND_FRAME: + case ND_TRANSFORM: + case ND_OB_VISIBLE: + case ND_RENDER_OPTIONS: + case ND_MARKERS: + case ND_MODE: + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + break; + case ND_WORLD: + /* handled by space_view3d_listener() for v3d access */ + break; + case ND_DRAW_RENDER_VIEWPORT: { + if (v3d->camera && (scene == wmn->reference)) { + if (rv3d->persp == RV3D_CAMOB) { + ED_region_tag_redraw(ar); + } + } + break; + } + } + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw(ar); + } + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_TRANSFORM: + case ND_POSE: + case ND_DRAW: + case ND_MODIFIER: + case ND_CONSTRAINT: + case ND_KEYS: + case ND_PARTICLE: + case ND_POINTCACHE: + case ND_LOD: + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + break; + } + switch (wmn->action) { + case NA_ADDED: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_GEOM: + switch (wmn->data) { + case ND_SELECT: { + WM_gizmomap_tag_refresh(gzmap); + ATTR_FALLTHROUGH; + } + case ND_DATA: + case ND_VERTEX_GROUP: + ED_region_tag_redraw(ar); + break; + } + switch (wmn->action) { + case NA_EDITED: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_CAMERA: + switch (wmn->data) { + case ND_DRAW_RENDER_VIEWPORT: { + if (v3d->camera && (v3d->camera->data == wmn->reference)) { + if (rv3d->persp == RV3D_CAMOB) { + ED_region_tag_redraw(ar); + } + } + break; + } + } + break; + case NC_GROUP: + /* all group ops for now */ + ED_region_tag_redraw(ar); + break; + case NC_BRUSH: + switch (wmn->action) { + case NA_EDITED: + ED_region_tag_redraw_overlay(ar); + break; + case NA_SELECTED: + /* used on brush changes - needed because 3d cursor + * has to be drawn if clone brush is selected */ + ED_region_tag_redraw(ar); + break; + } + break; + case NC_MATERIAL: + switch (wmn->data) { + case ND_SHADING: + case ND_NODES: + /* TODO(sergey) This is a bit too much updates, but needed to + * have proper material drivers update in the viewport. + * + * How to solve? + */ + ED_region_tag_redraw(ar); + break; + case ND_SHADING_DRAW: + case ND_SHADING_LINKS: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_WORLD: + switch (wmn->data) { + case ND_WORLD_DRAW: + /* handled by space_view3d_listener() for v3d access */ + break; + case ND_WORLD: + /* Needed for updating world materials */ + ED_region_tag_redraw(ar); + break; + } + break; + case NC_LAMP: + switch (wmn->data) { + case ND_LIGHTING: + /* TODO(sergey): This is a bit too much, but needed to + * handle updates from new depsgraph. + */ + ED_region_tag_redraw(ar); + break; + case ND_LIGHTING_DRAW: + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + break; + } + break; + case NC_LIGHTPROBE: + ED_area_tag_refresh(sa); + break; + case NC_IMAGE: + /* this could be more fine grained checks if we had + * more context than just the region */ + ED_region_tag_redraw(ar); + break; + case NC_TEXTURE: + /* same as above */ + ED_region_tag_redraw(ar); + break; + case NC_MOVIECLIP: + if (wmn->data == ND_DISPLAY || wmn->action == NA_EDITED) { + ED_region_tag_redraw(ar); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_VIEW3D) { + if (wmn->subtype == NS_VIEW3D_GPU) { + rv3d->rflag |= RV3D_GPULIGHT_UPDATE; + } + ED_region_tag_redraw(ar); + WM_gizmomap_tag_refresh(gzmap); + } + break; + case NC_ID: + if (wmn->action == NA_RENAME) { + ED_region_tag_redraw(ar); + } + break; + case NC_SCREEN: + switch (wmn->data) { + case ND_ANIMPLAY: + case ND_SKETCH: + ED_region_tag_redraw(ar); + break; + case ND_LAYOUTBROWSE: + case ND_LAYOUTDELETE: + case ND_LAYOUTSET: + WM_gizmomap_tag_refresh(gzmap); + ED_region_tag_redraw(ar); + break; + case ND_LAYER: + ED_region_tag_redraw(ar); + break; + } + + break; + case NC_GPENCIL: + if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + ED_region_tag_redraw(ar); + } + break; + } } -static void view3d_main_region_message_subscribe( - const struct bContext *C, - struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), struct ScrArea *sa, struct ARegion *ar, - struct wmMsgBus *mbus) +static void view3d_main_region_message_subscribe(const struct bContext *C, + struct WorkSpace *UNUSED(workspace), + struct Scene *UNUSED(scene), + struct bScreen *UNUSED(screen), + struct ScrArea *sa, + struct ARegion *ar, + struct wmMsgBus *mbus) { - /* Developer note: there are many properties that impact 3D view drawing, - * so instead of subscribing to individual properties, just subscribe to types - * accepting some redundant redraws. - * - * For other space types we might try avoid this, keep the 3D view as an exceptional case! */ - wmMsgParams_RNA msg_key_params = {{{0}}}; - - /* Only subscribe to types. */ - StructRNA *type_array[] = { - &RNA_Window, - - /* These object have properties that impact drawing. */ - &RNA_AreaLight, - &RNA_Camera, - &RNA_Light, - &RNA_Speaker, - &RNA_SunLight, - - /* General types the 3D view depends on. */ - &RNA_Object, - &RNA_UnitSettings, /* grid-floor */ - - &RNA_View3DOverlay, - &RNA_View3DShading, - &RNA_World, - }; - - wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { - .owner = ar, - .user_data = ar, - .notify = ED_region_do_msg_notify_tag_redraw, - }; - - for (int i = 0; i < ARRAY_SIZE(type_array); i++) { - msg_key_params.ptr.type = type_array[i]; - WM_msg_subscribe_rna_params( - mbus, - &msg_key_params, - &msg_sub_value_region_tag_redraw, - __func__); - } - - /* Subscribe to a handful of other properties. */ - RegionView3D *rv3d = ar->regiondata; - - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw); - if (rv3d->persp == RV3D_CAMOB) { - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw); - } - - WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw); - WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw); - - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = OBACT(view_layer); - if (obact != NULL) { - switch (obact->mode) { - case OB_MODE_PARTICLE_EDIT: - WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw); - break; - default: - break; - } - } - - { - wmMsgSubscribeValue msg_sub_value_region_tag_refresh = { - .owner = ar, - .user_data = sa, - .notify = WM_toolsystem_do_msg_notify_tag_refresh, - }; - WM_msg_subscribe_rna_anon_prop( - mbus, Object, mode, - &msg_sub_value_region_tag_refresh); - WM_msg_subscribe_rna_anon_prop( - mbus, LayerObjects, active, - &msg_sub_value_region_tag_refresh); - } + /* Developer note: there are many properties that impact 3D view drawing, + * so instead of subscribing to individual properties, just subscribe to types + * accepting some redundant redraws. + * + * For other space types we might try avoid this, keep the 3D view as an exceptional case! */ + wmMsgParams_RNA msg_key_params = {{{0}}}; + + /* Only subscribe to types. */ + StructRNA *type_array[] = { + &RNA_Window, + + /* These object have properties that impact drawing. */ + &RNA_AreaLight, + &RNA_Camera, + &RNA_Light, + &RNA_Speaker, + &RNA_SunLight, + + /* General types the 3D view depends on. */ + &RNA_Object, + &RNA_UnitSettings, /* grid-floor */ + + &RNA_View3DOverlay, + &RNA_View3DShading, + &RNA_World, + }; + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__); + } + + /* Subscribe to a handful of other properties. */ + RegionView3D *rv3d = ar->regiondata; + + WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, engine, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw); + if (rv3d->persp == RV3D_CAMOB) { + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw); + } + + WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw); + WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw); + + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact != NULL) { + switch (obact->mode) { + case OB_MODE_PARTICLE_EDIT: + WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw); + break; + default: + break; + } + } + + { + wmMsgSubscribeValue msg_sub_value_region_tag_refresh = { + .owner = ar, + .user_data = sa, + .notify = WM_toolsystem_do_msg_notify_tag_refresh, + }; + WM_msg_subscribe_rna_anon_prop(mbus, Object, mode, &msg_sub_value_region_tag_refresh); + WM_msg_subscribe_rna_anon_prop(mbus, LayerObjects, active, &msg_sub_value_region_tag_refresh); + } } /* concept is to retrieve cursor type context-less */ static void view3d_main_region_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) { - if (WM_cursor_set_from_tool(win, sa, ar)) { - return; - } - - ViewLayer *view_layer = WM_window_get_active_view_layer(win); - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - if (obedit) { - WM_cursor_set(win, CURSOR_EDIT); - } - else { - WM_cursor_set(win, CURSOR_STD); - } + if (WM_cursor_set_from_tool(win, sa, ar)) { + return; + } + + ViewLayer *view_layer = WM_window_get_active_view_layer(win); + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obedit) { + WM_cursor_set(win, CURSOR_EDIT); + } + else { + WM_cursor_set(win, CURSOR_STD); + } } /* add handlers, stuff you only do once or on area/region changes */ static void view3d_header_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); + wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(&ar->handlers, keymap); - ED_region_header_init(ar); + ED_region_header_init(ar); } static void view3d_header_region_draw(const bContext *C, ARegion *ar) { - ED_region_header(C, ar); + ED_region_header(C, ar); } -static void view3d_header_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void view3d_header_region_listener(wmWindow *UNUSED(win), + ScrArea *UNUSED(sa), + ARegion *ar, + wmNotifier *wmn, + const Scene *UNUSED(scene)) { - /* context changes */ - switch (wmn->category) { - case NC_SCENE: - switch (wmn->data) { - case ND_FRAME: - case ND_OB_ACTIVE: - case ND_OB_SELECT: - case ND_OB_VISIBLE: - case ND_MODE: - case ND_LAYER: - case ND_TOOLSETTINGS: - case ND_LAYER_CONTENT: - case ND_RENDER_OPTIONS: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_VIEW3D) { - ED_region_tag_redraw(ar); - } - break; - case NC_GPENCIL: - if (wmn->data & ND_GPENCIL_EDITMODE) { - ED_region_tag_redraw(ar); - } - break; - } + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + case ND_FRAME: + case ND_OB_ACTIVE: + case ND_OB_SELECT: + case ND_OB_VISIBLE: + case ND_MODE: + case ND_LAYER: + case ND_TOOLSETTINGS: + case ND_LAYER_CONTENT: + case ND_RENDER_OPTIONS: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_VIEW3D) { + ED_region_tag_redraw(ar); + } + break; + case NC_GPENCIL: + if (wmn->data & ND_GPENCIL_EDITMODE) { + ED_region_tag_redraw(ar); + } + break; + } } -static void view3d_header_region_message_subscribe( - const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar, - struct wmMsgBus *mbus) +static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C), + struct WorkSpace *UNUSED(workspace), + struct Scene *UNUSED(scene), + struct bScreen *UNUSED(screen), + struct ScrArea *UNUSED(sa), + struct ARegion *ar, + struct wmMsgBus *mbus) { - wmMsgParams_RNA msg_key_params = {{{0}}}; - - /* Only subscribe to types. */ - StructRNA *type_array[] = { - &RNA_View3DShading, - }; - - wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { - .owner = ar, - .user_data = ar, - .notify = ED_region_do_msg_notify_tag_redraw, - }; - - for (int i = 0; i < ARRAY_SIZE(type_array); i++) { - msg_key_params.ptr.type = type_array[i]; - WM_msg_subscribe_rna_params( - mbus, - &msg_key_params, - &msg_sub_value_region_tag_redraw, - __func__); - } + wmMsgParams_RNA msg_key_params = {{{0}}}; + + /* Only subscribe to types. */ + StructRNA *type_array[] = { + &RNA_View3DShading, + }; + + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = ar, + .user_data = ar, + .notify = ED_region_do_msg_notify_tag_redraw, + }; + + for (int i = 0; i < ARRAY_SIZE(type_array); i++) { + msg_key_params.ptr.type = type_array[i]; + WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__); + } } - /* add handlers, stuff you only do once or on area/region changes */ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap; + wmKeyMap *keymap; - ED_region_panels_init(wm, ar); + ED_region_panels_init(wm, ar); - keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void view3d_buttons_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); + ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true); } -static void view3d_buttons_region_listener( - wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar, - wmNotifier *wmn, const Scene *UNUSED(scene)) +static void view3d_buttons_region_listener(wmWindow *UNUSED(win), + ScrArea *UNUSED(sa), + ARegion *ar, + wmNotifier *wmn, + const Scene *UNUSED(scene)) { - /* context changes */ - switch (wmn->category) { - case NC_ANIMATION: - switch (wmn->data) { - case ND_KEYFRAME_PROP: - case ND_NLA_ACTCHANGE: - ED_region_tag_redraw(ar); - break; - case ND_NLA: - case ND_KEYFRAME: - if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) { - ED_region_tag_redraw(ar); - } - break; - } - break; - case NC_SCENE: - switch (wmn->data) { - case ND_FRAME: - case ND_OB_ACTIVE: - case ND_OB_SELECT: - case ND_OB_VISIBLE: - case ND_MODE: - case ND_LAYER: - case ND_LAYER_CONTENT: - case ND_TOOLSETTINGS: - ED_region_tag_redraw(ar); - break; - } - switch (wmn->action) { - case NA_EDITED: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_OBJECT: - switch (wmn->data) { - case ND_BONE_ACTIVE: - case ND_BONE_SELECT: - case ND_TRANSFORM: - case ND_POSE: - case ND_DRAW: - case ND_KEYS: - case ND_MODIFIER: - ED_region_tag_redraw(ar); - break; - } - break; - case NC_GEOM: - switch (wmn->data) { - case ND_DATA: - case ND_VERTEX_GROUP: - case ND_SELECT: - ED_region_tag_redraw(ar); - break; - } - if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); - } - break; - case NC_TEXTURE: - case NC_MATERIAL: - /* for brush textures */ - ED_region_tag_redraw(ar); - break; - case NC_BRUSH: - /* NA_SELECTED is used on brush changes */ - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); - } - break; - case NC_SPACE: - if (wmn->data == ND_SPACE_VIEW3D) { - ED_region_tag_redraw(ar); - } - break; - case NC_ID: - if (wmn->action == NA_RENAME) { - ED_region_tag_redraw(ar); - } - break; - case NC_GPENCIL: - if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) { - ED_region_tag_redraw(ar); - } - break; - case NC_IMAGE: - /* Update for the image layers in texture paint. */ - if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); - } - break; - } + /* context changes */ + switch (wmn->category) { + case NC_ANIMATION: + switch (wmn->data) { + case ND_KEYFRAME_PROP: + case ND_NLA_ACTCHANGE: + ED_region_tag_redraw(ar); + break; + case ND_NLA: + case ND_KEYFRAME: + if (ELEM(wmn->action, NA_EDITED, NA_ADDED, NA_REMOVED)) { + ED_region_tag_redraw(ar); + } + break; + } + break; + case NC_SCENE: + switch (wmn->data) { + case ND_FRAME: + case ND_OB_ACTIVE: + case ND_OB_SELECT: + case ND_OB_VISIBLE: + case ND_MODE: + case ND_LAYER: + case ND_LAYER_CONTENT: + case ND_TOOLSETTINGS: + ED_region_tag_redraw(ar); + break; + } + switch (wmn->action) { + case NA_EDITED: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_OBJECT: + switch (wmn->data) { + case ND_BONE_ACTIVE: + case ND_BONE_SELECT: + case ND_TRANSFORM: + case ND_POSE: + case ND_DRAW: + case ND_KEYS: + case ND_MODIFIER: + ED_region_tag_redraw(ar); + break; + } + break; + case NC_GEOM: + switch (wmn->data) { + case ND_DATA: + case ND_VERTEX_GROUP: + case ND_SELECT: + ED_region_tag_redraw(ar); + break; + } + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw(ar); + } + break; + case NC_TEXTURE: + case NC_MATERIAL: + /* for brush textures */ + ED_region_tag_redraw(ar); + break; + case NC_BRUSH: + /* NA_SELECTED is used on brush changes */ + if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + ED_region_tag_redraw(ar); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_VIEW3D) { + ED_region_tag_redraw(ar); + } + break; + case NC_ID: + if (wmn->action == NA_RENAME) { + ED_region_tag_redraw(ar); + } + break; + case NC_GPENCIL: + if ((wmn->data & (ND_DATA | ND_GPENCIL_EDITMODE)) || (wmn->action == NA_EDITED)) { + ED_region_tag_redraw(ar); + } + break; + case NC_IMAGE: + /* Update for the image layers in texture paint. */ + if (wmn->action == NA_EDITED) { + ED_region_tag_redraw(ar); + } + break; + } } /* add handlers, stuff you only do once or on area/region changes */ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar) { - wmKeyMap *keymap; + wmKeyMap *keymap; - ED_region_panels_init(wm, ar); + ED_region_panels_init(wm, ar); - keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + keymap = WM_keymap_ensure(wm->defaultconf, "3D View Generic", SPACE_VIEW3D, 0); + WM_event_add_keymap_handler(&ar->handlers, keymap); } static void view3d_tools_region_draw(const bContext *C, ARegion *ar) { - ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true); + ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true); } /* area (not region) level listener */ -static void space_view3d_listener( - wmWindow *UNUSED(win), ScrArea *sa, struct wmNotifier *wmn, Scene *UNUSED(scene)) +static void space_view3d_listener(wmWindow *UNUSED(win), + ScrArea *sa, + struct wmNotifier *wmn, + Scene *UNUSED(scene)) { - View3D *v3d = sa->spacedata.first; - - /* context changes */ - switch (wmn->category) { - case NC_SCENE: - switch (wmn->data) { - case ND_WORLD: - if (v3d->flag2 & V3D_HIDE_OVERLAYS) { - ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); - } - break; - } - break; - case NC_WORLD: - switch (wmn->data) { - case ND_WORLD_DRAW: - case ND_WORLD: - if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { - ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); - } - break; - } - break; - case NC_MATERIAL: - switch (wmn->data) { - case ND_NODES: - if (v3d->shading.type == OB_TEXTURE) { - ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); - } - break; - } - break; - } + View3D *v3d = sa->spacedata.first; + + /* context changes */ + switch (wmn->category) { + case NC_SCENE: + switch (wmn->data) { + case ND_WORLD: + if (v3d->flag2 & V3D_HIDE_OVERLAYS) { + ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); + } + break; + } + break; + case NC_WORLD: + switch (wmn->data) { + case ND_WORLD_DRAW: + case ND_WORLD: + if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { + ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); + } + break; + } + break; + case NC_MATERIAL: + switch (wmn->data) { + case ND_NODES: + if (v3d->shading.type == OB_TEXTURE) { + ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); + } + break; + } + break; + } } static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(sa)) { - Scene *scene = CTX_data_scene(C); - LightCache *lcache = scene->eevee.light_cache; + Scene *scene = CTX_data_scene(C); + LightCache *lcache = scene->eevee.light_cache; - if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) { - lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO; - view3d_lightcache_update((bContext *)C); - } + if (lcache && (lcache->flag & LIGHTCACHE_UPDATE_AUTO) != 0) { + lcache->flag &= ~LIGHTCACHE_UPDATE_AUTO; + view3d_lightcache_update((bContext *)C); + } } const char *view3d_context_dir[] = { - "active_base", "active_object", NULL, + "active_base", + "active_object", + NULL, }; static int view3d_context(const bContext *C, const char *member, bContextDataResult *result) { - /* fallback to the scene layer, - * allows duplicate and other object operators to run outside the 3d view */ - - if (CTX_data_dir(member)) { - CTX_data_dir_set(result, view3d_context_dir); - } - else if (CTX_data_equals(member, "active_base")) { - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - if (view_layer->basact) { - Object *ob = view_layer->basact->object; - /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) { - CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); - } - } - - return 1; - } - else if (CTX_data_equals(member, "active_object")) { - ViewLayer *view_layer = CTX_data_view_layer(C); - if (view_layer->basact) { - Object *ob = view_layer->basact->object; - /* if hidden but in edit mode, we still display, can happen with animation */ - if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { - CTX_data_id_pointer_set(result, &ob->id); - } - } - - return 1; - } - else { - return 0; /* not found */ - } - - return -1; /* found but not available */ + /* fallback to the scene layer, + * allows duplicate and other object operators to run outside the 3d view */ + + if (CTX_data_dir(member)) { + CTX_data_dir_set(result, view3d_context_dir); + } + else if (CTX_data_equals(member, "active_base")) { + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + if (view_layer->basact) { + Object *ob = view_layer->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT)) { + CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact); + } + } + + return 1; + } + else if (CTX_data_equals(member, "active_object")) { + ViewLayer *view_layer = CTX_data_view_layer(C); + if (view_layer->basact) { + Object *ob = view_layer->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((view_layer->basact->flag & BASE_VISIBLE) != 0 || (ob->mode & OB_MODE_EDIT) != 0) { + CTX_data_id_pointer_set(result, &ob->id); + } + } + + return 1; + } + else { + return 0; /* not found */ + } + + return -1; /* found but not available */ } static void view3d_id_remap(ScrArea *sa, SpaceLink *slink, ID *old_id, ID *new_id) { - View3D *v3d; - ARegion *ar; - bool is_local = false; - - if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) { - return; - } - - for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) { - if ((ID *)v3d->camera == old_id) { - v3d->camera = (Object *)new_id; - if (!new_id) { - /* 3D view might be inactive, in that case needs to use slink->regionbase */ - ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase : &slink->regionbase; - for (ar = regionbase->first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : ar->regiondata; - if (rv3d && (rv3d->persp == RV3D_CAMOB)) { - rv3d->persp = RV3D_PERSP; - } - } - } - } - } - - /* Values in local-view aren't used, see: T52663 */ - if (is_local == false) { - if ((ID *)v3d->ob_centre == old_id) { - v3d->ob_centre = (Object *)new_id; - /* Otherwise, bonename may remain valid... - * We could be smart and check this, too? */ - if (new_id == NULL) { - v3d->ob_centre_bone[0] = '\0'; - } - } - } - - if (is_local) { - break; - } - } + View3D *v3d; + ARegion *ar; + bool is_local = false; + + if (!ELEM(GS(old_id->name), ID_OB, ID_MA, ID_IM, ID_MC)) { + return; + } + + for (v3d = (View3D *)slink; v3d; v3d = v3d->localvd, is_local = true) { + if ((ID *)v3d->camera == old_id) { + v3d->camera = (Object *)new_id; + if (!new_id) { + /* 3D view might be inactive, in that case needs to use slink->regionbase */ + ListBase *regionbase = (slink == sa->spacedata.first) ? &sa->regionbase : + &slink->regionbase; + for (ar = regionbase->first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = is_local ? ((RegionView3D *)ar->regiondata)->localvd : + ar->regiondata; + if (rv3d && (rv3d->persp == RV3D_CAMOB)) { + rv3d->persp = RV3D_PERSP; + } + } + } + } + } + + /* Values in local-view aren't used, see: T52663 */ + if (is_local == false) { + if ((ID *)v3d->ob_centre == old_id) { + v3d->ob_centre = (Object *)new_id; + /* Otherwise, bonename may remain valid... + * We could be smart and check this, too? */ + if (new_id == NULL) { + v3d->ob_centre_bone[0] = '\0'; + } + } + } + + if (is_local) { + break; + } + } } /* only called once, from space/spacetypes.c */ void ED_spacetype_view3d(void) { - SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d"); - ARegionType *art; - - st->spaceid = SPACE_VIEW3D; - strncpy(st->name, "View3D", BKE_ST_MAXNAME); - - st->new = view3d_new; - st->free = view3d_free; - st->init = view3d_init; - st->listener = space_view3d_listener; - st->refresh = space_view3d_refresh; - st->duplicate = view3d_duplicate; - st->operatortypes = view3d_operatortypes; - st->keymap = view3d_keymap; - st->dropboxes = view3d_dropboxes; - st->gizmos = view3d_widgets; - st->context = view3d_context; - st->id_remap = view3d_id_remap; - - /* regions: main window */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region"); - art->regionid = RGN_TYPE_WINDOW; - art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL; - art->draw = view3d_main_region_draw; - art->init = view3d_main_region_init; - art->exit = view3d_main_region_exit; - art->free = view3d_main_region_free; - art->duplicate = view3d_main_region_duplicate; - art->listener = view3d_main_region_listener; - art->message_subscribe = view3d_main_region_message_subscribe; - art->cursor = view3d_main_region_cursor; - art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */ - BLI_addhead(&st->regiontypes, art); - - /* regions: listview/buttons */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region"); - art->regionid = RGN_TYPE_UI; - art->prefsizex = 180; /* XXX */ - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; - art->listener = view3d_buttons_region_listener; - art->init = view3d_buttons_region_init; - art->draw = view3d_buttons_region_draw; - BLI_addhead(&st->regiontypes, art); - - view3d_buttons_register(art); - - /* regions: tool(bar) */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); - art->regionid = RGN_TYPE_TOOLS; - art->prefsizex = 58; /* XXX */ - art->prefsizey = 50; /* XXX */ - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; - art->listener = view3d_buttons_region_listener; - art->message_subscribe = ED_region_generic_tools_region_message_subscribe; - art->snap_size = ED_region_generic_tools_region_snap_size; - art->init = view3d_tools_region_init; - art->draw = view3d_tools_region_draw; - BLI_addhead(&st->regiontypes, art); - - /* regions: header */ - art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); - art->regionid = RGN_TYPE_HEADER; - art->prefsizey = HEADERY; - art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; - art->listener = view3d_header_region_listener; - art->init = view3d_header_region_init; - art->draw = view3d_header_region_draw; - art->message_subscribe = view3d_header_region_message_subscribe; - BLI_addhead(&st->regiontypes, art); - - /* regions: hud */ - art = ED_area_type_hud(st->spaceid); - BLI_addhead(&st->regiontypes, art); - - BKE_spacetype_register(st); + SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype view3d"); + ARegionType *art; + + st->spaceid = SPACE_VIEW3D; + strncpy(st->name, "View3D", BKE_ST_MAXNAME); + + st->new = view3d_new; + st->free = view3d_free; + st->init = view3d_init; + st->listener = space_view3d_listener; + st->refresh = space_view3d_refresh; + st->duplicate = view3d_duplicate; + st->operatortypes = view3d_operatortypes; + st->keymap = view3d_keymap; + st->dropboxes = view3d_dropboxes; + st->gizmos = view3d_widgets; + st->context = view3d_context; + st->id_remap = view3d_id_remap; + + /* regions: main window */ + art = MEM_callocN(sizeof(ARegionType), "spacetype view3d main region"); + art->regionid = RGN_TYPE_WINDOW; + art->keymapflag = ED_KEYMAP_GIZMO | ED_KEYMAP_TOOL | ED_KEYMAP_GPENCIL; + art->draw = view3d_main_region_draw; + art->init = view3d_main_region_init; + art->exit = view3d_main_region_exit; + art->free = view3d_main_region_free; + art->duplicate = view3d_main_region_duplicate; + art->listener = view3d_main_region_listener; + art->message_subscribe = view3d_main_region_message_subscribe; + art->cursor = view3d_main_region_cursor; + art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */ + BLI_addhead(&st->regiontypes, art); + + /* regions: listview/buttons */ + art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region"); + art->regionid = RGN_TYPE_UI; + art->prefsizex = 180; /* XXX */ + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->listener = view3d_buttons_region_listener; + art->init = view3d_buttons_region_init; + art->draw = view3d_buttons_region_draw; + BLI_addhead(&st->regiontypes, art); + + view3d_buttons_register(art); + + /* regions: tool(bar) */ + art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region"); + art->regionid = RGN_TYPE_TOOLS; + art->prefsizex = 58; /* XXX */ + art->prefsizey = 50; /* XXX */ + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES; + art->listener = view3d_buttons_region_listener; + art->message_subscribe = ED_region_generic_tools_region_message_subscribe; + art->snap_size = ED_region_generic_tools_region_snap_size; + art->init = view3d_tools_region_init; + art->draw = view3d_tools_region_draw; + BLI_addhead(&st->regiontypes, art); + + /* regions: header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); + art->regionid = RGN_TYPE_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->listener = view3d_header_region_listener; + art->init = view3d_header_region_init; + art->draw = view3d_header_region_draw; + art->message_subscribe = view3d_header_region_message_subscribe; + BLI_addhead(&st->regiontypes, art); + + /* regions: hud */ + art = ED_area_type_hud(st->spaceid); + BLI_addhead(&st->regiontypes, art); + + BKE_spacetype_register(st); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index ca30e3d3b01..abe36b1d563 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -21,7 +21,6 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -70,49 +69,47 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "view3d_intern.h" /* own include */ - +#include "view3d_intern.h" /* own include */ /* ******************* view3d space & buttons ************** */ enum { - B_REDR = 2, - B_TRANSFORM_PANEL_MEDIAN = 1008, - B_TRANSFORM_PANEL_DIMS = 1009, + B_REDR = 2, + B_TRANSFORM_PANEL_MEDIAN = 1008, + B_TRANSFORM_PANEL_DIMS = 1009, }; /* All must start w/ location */ typedef struct { - float location[3]; + float location[3]; } TransformMedian_Generic; typedef struct { - float location[3], bv_weight, be_weight, skin[2], crease; + float location[3], bv_weight, be_weight, skin[2], crease; } TransformMedian_Mesh; typedef struct { - float location[3], weight, b_weight, radius, tilt; + float location[3], weight, b_weight, radius, tilt; } TransformMedian_Curve; typedef struct { - float location[3], weight; + float location[3], weight; } TransformMedian_Lattice; - typedef union { - TransformMedian_Generic generic; - TransformMedian_Mesh mesh; - TransformMedian_Curve curve; - TransformMedian_Lattice lattice; + TransformMedian_Generic generic; + TransformMedian_Mesh mesh; + TransformMedian_Curve curve; + TransformMedian_Lattice lattice; } TransformMedian; /* temporary struct for storing transform properties */ typedef struct { - float ob_dims_orig[3]; - float ob_dims[3]; - /* Floats only (treated as an array). */ - TransformMedian ve_median, median; + float ob_dims_orig[3]; + float ob_dims[3]; + /* Floats only (treated as an array). */ + TransformMedian ve_median, median; } TransformProperties; #define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float)) @@ -124,30 +121,30 @@ typedef struct { */ static float compute_scale_factor(const float ve_median, const float median) { - if (ve_median <= 0.0f) { - return 0.0f; - } - else if (ve_median >= 1.0f) { - return 1.0f; - } - else { - /* Scale value to target median. */ - float median_new = ve_median; - float median_orig = ve_median - median; /* Previous median value. */ - - /* In case of floating point error. */ - CLAMP(median_orig, 0.0f, 1.0f); - CLAMP(median_new, 0.0f, 1.0f); - - if (median_new <= median_orig) { - /* Scale down. */ - return median_new / median_orig; - } - else { - /* Scale up, negative to indicate it... */ - return -(1.0f - median_new) / (1.0f - median_orig); - } - } + if (ve_median <= 0.0f) { + return 0.0f; + } + else if (ve_median >= 1.0f) { + return 1.0f; + } + else { + /* Scale value to target median. */ + float median_new = ve_median; + float median_orig = ve_median - median; /* Previous median value. */ + + /* In case of floating point error. */ + CLAMP(median_orig, 0.0f, 1.0f); + CLAMP(median_new, 0.0f, 1.0f); + + if (median_new <= median_orig) { + /* Scale down. */ + return median_new / median_orig; + } + else { + /* Scale up, negative to indicate it... */ + return -(1.0f - median_new) / (1.0f - median_orig); + } + } } /* Apply helpers. @@ -156,1167 +153,1531 @@ static float compute_scale_factor(const float ve_median, const float median) */ static void apply_raw_diff(float *val, const int tot, const float ve_median, const float median) { - *val = (tot == 1) ? ve_median : (*val + median); + *val = (tot == 1) ? ve_median : (*val + median); } -static void apply_raw_diff_v3(float val[3], const int tot, const float ve_median[3], const float median[3]) +static void apply_raw_diff_v3(float val[3], + const int tot, + const float ve_median[3], + const float median[3]) { - if (tot == 1) { - copy_v3_v3(val, ve_median); - } - else { - add_v3_v3(val, median); - } + if (tot == 1) { + copy_v3_v3(val, ve_median); + } + else { + add_v3_v3(val, median); + } } -static void apply_scale_factor(float *val, const int tot, const float ve_median, const float median, const float sca) +static void apply_scale_factor( + float *val, const int tot, const float ve_median, const float median, const float sca) { - if (tot == 1 || ve_median == median) { - *val = ve_median; - } - else { - *val *= sca; - } + if (tot == 1 || ve_median == median) { + *val = ve_median; + } + else { + *val *= sca; + } } -static void apply_scale_factor_clamp(float *val, const int tot, const float ve_median, const float sca) +static void apply_scale_factor_clamp(float *val, + const int tot, + const float ve_median, + const float sca) { - if (tot == 1) { - *val = ve_median; - CLAMP(*val, 0.0f, 1.0f); - } - else if (ELEM(sca, 0.0f, 1.0f)) { - *val = sca; - } - else { - *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca)); - CLAMP(*val, 0.0f, 1.0f); - } + if (tot == 1) { + *val = ve_median; + CLAMP(*val, 0.0f, 1.0f); + } + else if (ELEM(sca, 0.0f, 1.0f)) { + *val = sca; + } + else { + *val = (sca > 0.0f) ? (*val * sca) : (1.0f + ((1.0f - *val) * sca)); + CLAMP(*val, 0.0f, 1.0f); + } } static TransformProperties *v3d_transform_props_ensure(View3D *v3d) { - if (v3d->runtime.properties_storage == NULL) { - v3d->runtime.properties_storage = MEM_callocN(sizeof(TransformProperties), "TransformProperties"); - } - return v3d->runtime.properties_storage; + if (v3d->runtime.properties_storage == NULL) { + v3d->runtime.properties_storage = MEM_callocN(sizeof(TransformProperties), + "TransformProperties"); + } + return v3d->runtime.properties_storage; } /* is used for both read and write... */ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim) { - uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL; - TransformProperties *tfp = v3d_transform_props_ensure(v3d); - TransformMedian median_basis, ve_median_basis; - int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight; - bool has_meshdata = false; - bool has_skinradius = false; - PointerRNA data_ptr; - - copy_vn_fl((float *)&median_basis, TRANSFORM_MEDIAN_ARRAY_LEN, 0.0f); - tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0; - - if (ob->type == OB_MESH) { - TransformMedian_Mesh *median = &median_basis.mesh; - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - BMesh *bm = em->bm; - BMVert *eve; - BMEdge *eed; - BMIter iter; - - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - - has_skinradius = (cd_vert_skin_offset != -1); - - if (bm->totvertsel) { - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - tot++; - add_v3_v3(median->location, eve->co); - - if (cd_vert_bweight_offset != -1) { - median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset); - } - - if (has_skinradius) { - MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); - add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */ - } - } - } - } - - if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) { - if (bm->totedgesel) { - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - if (cd_edge_bweight_offset != -1) { - median->be_weight += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset); - } - - if (cd_edge_crease_offset != -1) { - median->crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset); - } - - totedgedata++; - } - } - } - } - else { - totedgedata = bm->totedgesel; - } - - has_meshdata = (tot || totedgedata); - } - else if (ob->type == OB_CURVE || ob->type == OB_SURF) { - TransformMedian_Curve *median = &median_basis.curve; - Curve *cu = ob->data; - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - ListBase *nurbs = BKE_curve_editNurbs_get(cu); - StructRNA *seltype = NULL; - void *selp = NULL; - - nu = nurbs->first; - while (nu) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (bezt->f2 & SELECT) { - add_v3_v3(median->location, bezt->vec[1]); - tot++; - median->weight += bezt->weight; - median->radius += bezt->radius; - median->tilt += bezt->tilt; - if (!totcurvedata) { /* I.e. first time... */ - selp = bezt; - seltype = &RNA_BezierSplinePoint; - } - totcurvedata++; - } - else { - if (bezt->f1 & SELECT) { - add_v3_v3(median->location, bezt->vec[0]); - tot++; - } - if (bezt->f3 & SELECT) { - add_v3_v3(median->location, bezt->vec[2]); - tot++; - } - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->f1 & SELECT) { - add_v3_v3(median->location, bp->vec); - median->b_weight += bp->vec[3]; - totcurvebweight++; - tot++; - median->weight += bp->weight; - median->radius += bp->radius; - median->tilt += bp->tilt; - if (!totcurvedata) { /* I.e. first time... */ - selp = bp; - seltype = &RNA_SplinePoint; - } - totcurvedata++; - } - bp++; - } - } - nu = nu->next; - } - - if (totcurvedata == 1) { - RNA_pointer_create(&cu->id, seltype, selp, &data_ptr); - } - } - else if (ob->type == OB_LATTICE) { - Lattice *lt = ob->data; - TransformMedian_Lattice *median = &median_basis.lattice; - BPoint *bp; - int a; - StructRNA *seltype = NULL; - void *selp = NULL; - - a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - bp = lt->editlatt->latt->def; - while (a--) { - if (bp->f1 & SELECT) { - add_v3_v3(median->location, bp->vec); - tot++; - median->weight += bp->weight; - if (!totlattdata) { /* I.e. first time... */ - selp = bp; - seltype = &RNA_LatticePoint; - } - totlattdata++; - } - bp++; - } - - if (totlattdata == 1) { - RNA_pointer_create(<->id, seltype, selp, &data_ptr); - } - } - - if (tot == 0) { - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Nothing selected"), 0, 130, 200, 20, NULL, 0, 0, 0, 0, ""); - return; - } - - /* Location, X/Y/Z */ - mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot); - if (v3d->flag & V3D_GLOBAL_STATS) { - mul_m4_v3(ob->obmat, median_basis.generic.location); - } - - if (has_meshdata) { - TransformMedian_Mesh *median = &median_basis.mesh; - if (totedgedata) { - median->crease /= (float)totedgedata; - median->be_weight /= (float)totedgedata; - } - if (tot) { - median->bv_weight /= (float)tot; - if (has_skinradius) { - median->skin[0] /= (float)tot; - median->skin[1] /= (float)tot; - } - } - } - else if (totcurvedata) { - TransformMedian_Curve *median = &median_basis.curve; - if (totcurvebweight) { - median->b_weight /= (float)totcurvebweight; - } - median->weight /= (float)totcurvedata; - median->radius /= (float)totcurvedata; - median->tilt /= (float)totcurvedata; - } - else if (totlattdata) { - TransformMedian_Lattice *median = &median_basis.lattice; - median->weight /= (float)totlattdata; - } - - if (block) { /* buttons */ - uiBut *but; - int yi = 200; - const float tilt_limit = DEG2RADF(21600.0f); - const int butw = 200; - const int buth = 20 * UI_DPI_FAC; - const int but_margin = 2; - const char *c; - - memcpy(&tfp->ve_median, &median_basis, sizeof(tfp->ve_median)); - - UI_block_align_begin(block); - if (tot == 1) { - if (totcurvedata) { - /* Curve */ - c = IFACE_("Control Point:"); - } - else { - /* Mesh or lattice */ - c = IFACE_("Vertex:"); - } - } - else { - c = IFACE_("Median:"); - } - uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, ""); - - UI_block_align_begin(block); - - /* Should be no need to translate these. */ - but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("X:"), 0, yi -= buth, butw, buth, - &tfp->ve_median.generic.location[0], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); - UI_but_unit_type_set(but, PROP_UNIT_LENGTH); - but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Y:"), 0, yi -= buth, butw, buth, - &tfp->ve_median.generic.location[1], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); - UI_but_unit_type_set(but, PROP_UNIT_LENGTH); - but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Z:"), 0, yi -= buth, butw, buth, - &tfp->ve_median.generic.location[2], -lim, lim, 10, RNA_TRANSLATION_PREC_DEFAULT, ""); - UI_but_unit_type_set(but, PROP_UNIT_LENGTH); - - if (totcurvebweight == tot) { - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("W:"), 0, yi -= buth, butw, buth, - &(tfp->ve_median.curve.b_weight), 0.01, 100.0, 1, 3, ""); - } - - UI_block_align_begin(block); - uiDefButBitS(block, UI_BTYPE_TOGGLE, V3D_GLOBAL_STATS, B_REDR, IFACE_("Global"), - 0, yi -= buth + but_margin, 100, buth, - &v3d->flag, 0, 0, 0, 0, TIP_("Displays global values")); - uiDefButBitS(block, UI_BTYPE_TOGGLE_N, V3D_GLOBAL_STATS, B_REDR, IFACE_("Local"), - 100, yi, 100, buth, - &v3d->flag, 0, 0, 0, 0, TIP_("Displays local values")); - UI_block_align_end(block); - - /* Meshes... */ - if (has_meshdata) { - TransformMedian_Mesh *ve_median = &tfp->ve_median.mesh; - if (tot) { - uiDefBut(block, UI_BTYPE_LABEL, 0, tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"), - 0, yi -= buth + but_margin, butw, buth, NULL, 0.0, 0.0, 0, 0, ""); - /* customdata layer added on demand */ - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, - tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->bv_weight, 0.0, 1.0, 1, 2, TIP_("Vertex weight used by Bevel modifier")); - } - if (has_skinradius) { - UI_block_align_begin(block); - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, - tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->skin[0], 0.0, 100.0, 1, 3, TIP_("X radius used by Skin modifier")); - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, - tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->skin[1], 0.0, 100.0, 1, 3, TIP_("Y radius used by Skin modifier")); - UI_block_align_end(block); - } - if (totedgedata) { - uiDefBut(block, UI_BTYPE_LABEL, 0, totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"), - 0, yi -= buth + but_margin, butw, buth, NULL, 0.0, 0.0, 0, 0, ""); - /* customdata layer added on demand */ - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, - totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->be_weight, 0.0, 1.0, 1, 2, TIP_("Edge weight used by Bevel modifier")); - /* customdata layer added on demand */ - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, - totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->crease, 0.0, 1.0, 1, 2, TIP_("Weight used by the Subdivision Surface modifier")); - } - } - /* Curve... */ - else if (totcurvedata) { - TransformMedian_Curve *ve_median = &tfp->ve_median.curve; - if (totcurvedata == 1) { - uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, butw, buth, - &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); - uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Radius:"), 0, yi -= buth + but_margin, butw, buth, - &data_ptr, "radius", 0, 0.0, 100.0, 1, 3, NULL); - uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Tilt:"), 0, yi -= buth + but_margin, butw, buth, - &data_ptr, "tilt", 0, -tilt_limit, tilt_limit, 1, 3, NULL); - } - else if (totcurvedata > 1) { - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Weight:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->weight, 0.0, 1.0, 1, 3, TIP_("Weight used for Soft Body Goal")); - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Radius:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->radius, 0.0, 100.0, 1, 3, TIP_("Radius of curve control points")); - but = uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Tilt:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->tilt, -tilt_limit, tilt_limit, 1, 3, - TIP_("Tilt of curve control points")); - UI_but_unit_type_set(but, PROP_UNIT_ROTATION); - } - } - /* Lattice... */ - else if (totlattdata) { - TransformMedian_Lattice *ve_median = &tfp->ve_median.lattice; - if (totlattdata == 1) { - uiDefButR(block, UI_BTYPE_NUM, 0, IFACE_("Weight:"), 0, yi -= buth + but_margin, butw, buth, - &data_ptr, "weight_softbody", 0, 0.0, 1.0, 1, 3, NULL); - } - else if (totlattdata > 1) { - uiDefButF(block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_MEDIAN, IFACE_("Mean Weight:"), - 0, yi -= buth + but_margin, butw, buth, - &ve_median->weight, 0.0, 1.0, 1, 3, TIP_("Weight used for Soft Body Goal")); - } - } - - UI_block_align_end(block); - } - else { /* apply */ - memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); - - if (v3d->flag & V3D_GLOBAL_STATS) { - invert_m4_m4(ob->imat, ob->obmat); - mul_m4_v3(ob->imat, median_basis.generic.location); - mul_m4_v3(ob->imat, ve_median_basis.generic.location); - } - sub_vn_vnvn( - (float *)&median_basis, - (float *)&ve_median_basis, - (float *)&median_basis, - TRANSFORM_MEDIAN_ARRAY_LEN); - - /* Note with a single element selected, we always do. */ - const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f); - - if ((ob->type == OB_MESH) && - (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.skin[0] || median_basis.mesh.skin[1] || - median_basis.mesh.be_weight || median_basis.mesh.crease)) - { - const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh; - Mesh *me = ob->data; - BMEditMesh *em = me->edit_mesh; - BMesh *bm = em->bm; - BMIter iter; - BMVert *eve; - BMEdge *eed; - - int cd_vert_bweight_offset = -1; - int cd_vert_skin_offset = -1; - int cd_edge_bweight_offset = -1; - int cd_edge_crease_offset = -1; - - float scale_bv_weight = 1.0f; - float scale_skin[2] = {1.0f, 1.0f}; - float scale_be_weight = 1.0f; - float scale_crease = 1.0f; - - /* Vertices */ - - if (apply_vcos || median->bv_weight || median->skin[0] || median->skin[1]) { - if (median->bv_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); - cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - BLI_assert(cd_vert_bweight_offset != -1); - - scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight); - } - - for (int i = 0; i < 2; i++) { - if (median->skin[i]) { - cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); - BLI_assert(cd_vert_skin_offset != -1); - - if (ve_median->skin[i] != median->skin[i]) { - scale_skin[i] = ve_median->skin[i] / (ve_median->skin[i] - median->skin[i]); - } - } - } - - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - if (apply_vcos) { - apply_raw_diff_v3(eve->co, tot, ve_median->location, median->location); - } - - if (cd_vert_bweight_offset != -1) { - float *b_weight = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset); - apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight); - } - - if (cd_vert_skin_offset != -1) { - MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); - - /* That one is not clamped to [0.0, 1.0]. */ - for (int i = 0; i < 2; i++) { - if (median->skin[i] != 0.0f) { - apply_scale_factor( - &vs->radius[i], tot, ve_median->skin[i], median->skin[i], - scale_skin[i]); - } - } - } - } - } - } - - if (apply_vcos) { - EDBM_mesh_normals_update(em); - } - - /* Edges */ - - if (median->be_weight || median->crease) { - if (median->be_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); - cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - BLI_assert(cd_edge_bweight_offset != -1); - - scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight); - } - - if (median->crease) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); - cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - BLI_assert(cd_edge_crease_offset != -1); - - scale_crease = compute_scale_factor(ve_median->crease, median->crease); - } - - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - if (median->be_weight != 0.0f) { - float *b_weight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset); - apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight); - } - - if (median->crease != 0.0f) { - float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset); - apply_scale_factor_clamp(crease, tot, ve_median->crease, scale_crease); - } - } - } - } - } - else if (ELEM(ob->type, OB_CURVE, OB_SURF) && - (apply_vcos || - median_basis.curve.b_weight || - median_basis.curve.weight || - median_basis.curve.radius || - median_basis.curve.tilt)) - { - const TransformMedian_Curve *median = &median_basis.curve, *ve_median = &ve_median_basis.curve; - Curve *cu = ob->data; - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - ListBase *nurbs = BKE_curve_editNurbs_get(cu); - const float scale_w = compute_scale_factor(ve_median->weight, median->weight); - - nu = nurbs->first; - while (nu) { - if (nu->type == CU_BEZIER) { - for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { - if (bezt->f2 & SELECT) { - if (apply_vcos) { - /* Here we always have to use the diff... :/ - * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327), - * unless we use doubles. - */ - add_v3_v3(bezt->vec[0], median->location); - add_v3_v3(bezt->vec[1], median->location); - add_v3_v3(bezt->vec[2], median->location); - } - if (median->weight) { - apply_scale_factor_clamp(&bezt->weight, tot, ve_median->weight, scale_w); - } - if (median->radius) { - apply_raw_diff(&bezt->radius, tot, ve_median->radius, median->radius); - } - if (median->tilt) { - apply_raw_diff(&bezt->tilt, tot, ve_median->tilt, median->tilt); - } - } - else if (apply_vcos) { - /* Handles can only have their coordinates changed here. */ - if (bezt->f1 & SELECT) { - apply_raw_diff_v3(bezt->vec[0], tot, ve_median->location, median->location); - } - if (bezt->f3 & SELECT) { - apply_raw_diff_v3(bezt->vec[2], tot, ve_median->location, median->location); - } - } - } - } - else { - for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) { - if (bp->f1 & SELECT) { - if (apply_vcos) { - apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location); - } - if (median->b_weight) { - apply_raw_diff(&bp->vec[3], tot, ve_median->b_weight, median->b_weight); - } - if (median->weight) { - apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w); - } - if (median->radius) { - apply_raw_diff(&bp->radius, tot, ve_median->radius, median->radius); - } - if (median->tilt) { - apply_raw_diff(&bp->tilt, tot, ve_median->tilt, median->tilt); - } - } - } - } - BKE_nurb_test_2d(nu); - BKE_nurb_handles_test(nu, true); /* test for bezier too */ - - nu = nu->next; - } - } - else if ((ob->type == OB_LATTICE) && - (apply_vcos || median_basis.lattice.weight)) - { - const TransformMedian_Lattice *median = &median_basis.lattice, *ve_median = &ve_median_basis.lattice; - Lattice *lt = ob->data; - BPoint *bp; - int a; - const float scale_w = compute_scale_factor(ve_median->weight, median->weight); - - a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - bp = lt->editlatt->latt->def; - while (a--) { - if (bp->f1 & SELECT) { - if (apply_vcos) { - apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location); - } - if (median->weight) { - apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w); - } - } - bp++; - } - } - -/* ED_undo_push(C, "Transform properties"); */ - } + uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL; + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + TransformMedian median_basis, ve_median_basis; + int tot, totedgedata, totcurvedata, totlattdata, totcurvebweight; + bool has_meshdata = false; + bool has_skinradius = false; + PointerRNA data_ptr; + + copy_vn_fl((float *)&median_basis, TRANSFORM_MEDIAN_ARRAY_LEN, 0.0f); + tot = totedgedata = totcurvedata = totlattdata = totcurvebweight = 0; + + if (ob->type == OB_MESH) { + TransformMedian_Mesh *median = &median_basis.mesh; + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + BMesh *bm = em->bm; + BMVert *eve; + BMEdge *eed; + BMIter iter; + + const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); + const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + + has_skinradius = (cd_vert_skin_offset != -1); + + if (bm->totvertsel) { + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + tot++; + add_v3_v3(median->location, eve->co); + + if (cd_vert_bweight_offset != -1) { + median->bv_weight += BM_ELEM_CD_GET_FLOAT(eve, cd_vert_bweight_offset); + } + + if (has_skinradius) { + MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); + add_v2_v2(median->skin, vs->radius); /* Third val not used currently. */ + } + } + } + } + + if ((cd_edge_bweight_offset != -1) || (cd_edge_crease_offset != -1)) { + if (bm->totedgesel) { + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + if (cd_edge_bweight_offset != -1) { + median->be_weight += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_bweight_offset); + } + + if (cd_edge_crease_offset != -1) { + median->crease += BM_ELEM_CD_GET_FLOAT(eed, cd_edge_crease_offset); + } + + totedgedata++; + } + } + } + } + else { + totedgedata = bm->totedgesel; + } + + has_meshdata = (tot || totedgedata); + } + else if (ob->type == OB_CURVE || ob->type == OB_SURF) { + TransformMedian_Curve *median = &median_basis.curve; + Curve *cu = ob->data; + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + StructRNA *seltype = NULL; + void *selp = NULL; + + nu = nurbs->first; + while (nu) { + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + if (bezt->f2 & SELECT) { + add_v3_v3(median->location, bezt->vec[1]); + tot++; + median->weight += bezt->weight; + median->radius += bezt->radius; + median->tilt += bezt->tilt; + if (!totcurvedata) { /* I.e. first time... */ + selp = bezt; + seltype = &RNA_BezierSplinePoint; + } + totcurvedata++; + } + else { + if (bezt->f1 & SELECT) { + add_v3_v3(median->location, bezt->vec[0]); + tot++; + } + if (bezt->f3 & SELECT) { + add_v3_v3(median->location, bezt->vec[2]); + tot++; + } + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->f1 & SELECT) { + add_v3_v3(median->location, bp->vec); + median->b_weight += bp->vec[3]; + totcurvebweight++; + tot++; + median->weight += bp->weight; + median->radius += bp->radius; + median->tilt += bp->tilt; + if (!totcurvedata) { /* I.e. first time... */ + selp = bp; + seltype = &RNA_SplinePoint; + } + totcurvedata++; + } + bp++; + } + } + nu = nu->next; + } + + if (totcurvedata == 1) { + RNA_pointer_create(&cu->id, seltype, selp, &data_ptr); + } + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; + TransformMedian_Lattice *median = &median_basis.lattice; + BPoint *bp; + int a; + StructRNA *seltype = NULL; + void *selp = NULL; + + a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + bp = lt->editlatt->latt->def; + while (a--) { + if (bp->f1 & SELECT) { + add_v3_v3(median->location, bp->vec); + tot++; + median->weight += bp->weight; + if (!totlattdata) { /* I.e. first time... */ + selp = bp; + seltype = &RNA_LatticePoint; + } + totlattdata++; + } + bp++; + } + + if (totlattdata == 1) { + RNA_pointer_create(<->id, seltype, selp, &data_ptr); + } + } + + if (tot == 0) { + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + IFACE_("Nothing selected"), + 0, + 130, + 200, + 20, + NULL, + 0, + 0, + 0, + 0, + ""); + return; + } + + /* Location, X/Y/Z */ + mul_v3_fl(median_basis.generic.location, 1.0f / (float)tot); + if (v3d->flag & V3D_GLOBAL_STATS) { + mul_m4_v3(ob->obmat, median_basis.generic.location); + } + + if (has_meshdata) { + TransformMedian_Mesh *median = &median_basis.mesh; + if (totedgedata) { + median->crease /= (float)totedgedata; + median->be_weight /= (float)totedgedata; + } + if (tot) { + median->bv_weight /= (float)tot; + if (has_skinradius) { + median->skin[0] /= (float)tot; + median->skin[1] /= (float)tot; + } + } + } + else if (totcurvedata) { + TransformMedian_Curve *median = &median_basis.curve; + if (totcurvebweight) { + median->b_weight /= (float)totcurvebweight; + } + median->weight /= (float)totcurvedata; + median->radius /= (float)totcurvedata; + median->tilt /= (float)totcurvedata; + } + else if (totlattdata) { + TransformMedian_Lattice *median = &median_basis.lattice; + median->weight /= (float)totlattdata; + } + + if (block) { /* buttons */ + uiBut *but; + int yi = 200; + const float tilt_limit = DEG2RADF(21600.0f); + const int butw = 200; + const int buth = 20 * UI_DPI_FAC; + const int but_margin = 2; + const char *c; + + memcpy(&tfp->ve_median, &median_basis, sizeof(tfp->ve_median)); + + UI_block_align_begin(block); + if (tot == 1) { + if (totcurvedata) { + /* Curve */ + c = IFACE_("Control Point:"); + } + else { + /* Mesh or lattice */ + c = IFACE_("Vertex:"); + } + } + else { + c = IFACE_("Median:"); + } + uiDefBut(block, UI_BTYPE_LABEL, 0, c, 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, ""); + + UI_block_align_begin(block); + + /* Should be no need to translate these. */ + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("X:"), + 0, + yi -= buth, + butw, + buth, + &tfp->ve_median.generic.location[0], + -lim, + lim, + 10, + RNA_TRANSLATION_PREC_DEFAULT, + ""); + UI_but_unit_type_set(but, PROP_UNIT_LENGTH); + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Y:"), + 0, + yi -= buth, + butw, + buth, + &tfp->ve_median.generic.location[1], + -lim, + lim, + 10, + RNA_TRANSLATION_PREC_DEFAULT, + ""); + UI_but_unit_type_set(but, PROP_UNIT_LENGTH); + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Z:"), + 0, + yi -= buth, + butw, + buth, + &tfp->ve_median.generic.location[2], + -lim, + lim, + 10, + RNA_TRANSLATION_PREC_DEFAULT, + ""); + UI_but_unit_type_set(but, PROP_UNIT_LENGTH); + + if (totcurvebweight == tot) { + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("W:"), + 0, + yi -= buth, + butw, + buth, + &(tfp->ve_median.curve.b_weight), + 0.01, + 100.0, + 1, + 3, + ""); + } + + UI_block_align_begin(block); + uiDefButBitS(block, + UI_BTYPE_TOGGLE, + V3D_GLOBAL_STATS, + B_REDR, + IFACE_("Global"), + 0, + yi -= buth + but_margin, + 100, + buth, + &v3d->flag, + 0, + 0, + 0, + 0, + TIP_("Displays global values")); + uiDefButBitS(block, + UI_BTYPE_TOGGLE_N, + V3D_GLOBAL_STATS, + B_REDR, + IFACE_("Local"), + 100, + yi, + 100, + buth, + &v3d->flag, + 0, + 0, + 0, + 0, + TIP_("Displays local values")); + UI_block_align_end(block); + + /* Meshes... */ + if (has_meshdata) { + TransformMedian_Mesh *ve_median = &tfp->ve_median.mesh; + if (tot) { + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + tot == 1 ? IFACE_("Vertex Data:") : IFACE_("Vertices Data:"), + 0, + yi -= buth + but_margin, + butw, + buth, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); + /* customdata layer added on demand */ + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + tot == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->bv_weight, + 0.0, + 1.0, + 1, + 2, + TIP_("Vertex weight used by Bevel modifier")); + } + if (has_skinradius) { + UI_block_align_begin(block); + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + tot == 1 ? IFACE_("Radius X:") : IFACE_("Mean Radius X:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->skin[0], + 0.0, + 100.0, + 1, + 3, + TIP_("X radius used by Skin modifier")); + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + tot == 1 ? IFACE_("Radius Y:") : IFACE_("Mean Radius Y:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->skin[1], + 0.0, + 100.0, + 1, + 3, + TIP_("Y radius used by Skin modifier")); + UI_block_align_end(block); + } + if (totedgedata) { + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + totedgedata == 1 ? IFACE_("Edge Data:") : IFACE_("Edges Data:"), + 0, + yi -= buth + but_margin, + butw, + buth, + NULL, + 0.0, + 0.0, + 0, + 0, + ""); + /* customdata layer added on demand */ + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + totedgedata == 1 ? IFACE_("Bevel Weight:") : IFACE_("Mean Bevel Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->be_weight, + 0.0, + 1.0, + 1, + 2, + TIP_("Edge weight used by Bevel modifier")); + /* customdata layer added on demand */ + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + totedgedata == 1 ? IFACE_("Crease:") : IFACE_("Mean Crease:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->crease, + 0.0, + 1.0, + 1, + 2, + TIP_("Weight used by the Subdivision Surface modifier")); + } + } + /* Curve... */ + else if (totcurvedata) { + TransformMedian_Curve *ve_median = &tfp->ve_median.curve; + if (totcurvedata == 1) { + uiDefButR(block, + UI_BTYPE_NUM, + 0, + IFACE_("Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &data_ptr, + "weight_softbody", + 0, + 0.0, + 1.0, + 1, + 3, + NULL); + uiDefButR(block, + UI_BTYPE_NUM, + 0, + IFACE_("Radius:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &data_ptr, + "radius", + 0, + 0.0, + 100.0, + 1, + 3, + NULL); + uiDefButR(block, + UI_BTYPE_NUM, + 0, + IFACE_("Tilt:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &data_ptr, + "tilt", + 0, + -tilt_limit, + tilt_limit, + 1, + 3, + NULL); + } + else if (totcurvedata > 1) { + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Mean Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->weight, + 0.0, + 1.0, + 1, + 3, + TIP_("Weight used for Soft Body Goal")); + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Mean Radius:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->radius, + 0.0, + 100.0, + 1, + 3, + TIP_("Radius of curve control points")); + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Mean Tilt:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->tilt, + -tilt_limit, + tilt_limit, + 1, + 3, + TIP_("Tilt of curve control points")); + UI_but_unit_type_set(but, PROP_UNIT_ROTATION); + } + } + /* Lattice... */ + else if (totlattdata) { + TransformMedian_Lattice *ve_median = &tfp->ve_median.lattice; + if (totlattdata == 1) { + uiDefButR(block, + UI_BTYPE_NUM, + 0, + IFACE_("Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &data_ptr, + "weight_softbody", + 0, + 0.0, + 1.0, + 1, + 3, + NULL); + } + else if (totlattdata > 1) { + uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_MEDIAN, + IFACE_("Mean Weight:"), + 0, + yi -= buth + but_margin, + butw, + buth, + &ve_median->weight, + 0.0, + 1.0, + 1, + 3, + TIP_("Weight used for Soft Body Goal")); + } + } + + UI_block_align_end(block); + } + else { /* apply */ + memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); + + if (v3d->flag & V3D_GLOBAL_STATS) { + invert_m4_m4(ob->imat, ob->obmat); + mul_m4_v3(ob->imat, median_basis.generic.location); + mul_m4_v3(ob->imat, ve_median_basis.generic.location); + } + sub_vn_vnvn((float *)&median_basis, + (float *)&ve_median_basis, + (float *)&median_basis, + TRANSFORM_MEDIAN_ARRAY_LEN); + + /* Note with a single element selected, we always do. */ + const bool apply_vcos = (tot == 1) || (len_squared_v3(median_basis.generic.location) != 0.0f); + + if ((ob->type == OB_MESH) && + (apply_vcos || median_basis.mesh.bv_weight || median_basis.mesh.skin[0] || + median_basis.mesh.skin[1] || median_basis.mesh.be_weight || median_basis.mesh.crease)) { + const TransformMedian_Mesh *median = &median_basis.mesh, *ve_median = &ve_median_basis.mesh; + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + BMesh *bm = em->bm; + BMIter iter; + BMVert *eve; + BMEdge *eed; + + int cd_vert_bweight_offset = -1; + int cd_vert_skin_offset = -1; + int cd_edge_bweight_offset = -1; + int cd_edge_crease_offset = -1; + + float scale_bv_weight = 1.0f; + float scale_skin[2] = {1.0f, 1.0f}; + float scale_be_weight = 1.0f; + float scale_crease = 1.0f; + + /* Vertices */ + + if (apply_vcos || median->bv_weight || median->skin[0] || median->skin[1]) { + if (median->bv_weight) { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + BLI_assert(cd_vert_bweight_offset != -1); + + scale_bv_weight = compute_scale_factor(ve_median->bv_weight, median->bv_weight); + } + + for (int i = 0; i < 2; i++) { + if (median->skin[i]) { + cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN); + BLI_assert(cd_vert_skin_offset != -1); + + if (ve_median->skin[i] != median->skin[i]) { + scale_skin[i] = ve_median->skin[i] / (ve_median->skin[i] - median->skin[i]); + } + } + } + + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (apply_vcos) { + apply_raw_diff_v3(eve->co, tot, ve_median->location, median->location); + } + + if (cd_vert_bweight_offset != -1) { + float *b_weight = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset); + apply_scale_factor_clamp(b_weight, tot, ve_median->bv_weight, scale_bv_weight); + } + + if (cd_vert_skin_offset != -1) { + MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_vert_skin_offset); + + /* That one is not clamped to [0.0, 1.0]. */ + for (int i = 0; i < 2; i++) { + if (median->skin[i] != 0.0f) { + apply_scale_factor( + &vs->radius[i], tot, ve_median->skin[i], median->skin[i], scale_skin[i]); + } + } + } + } + } + } + + if (apply_vcos) { + EDBM_mesh_normals_update(em); + } + + /* Edges */ + + if (median->be_weight || median->crease) { + if (median->be_weight) { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); + BLI_assert(cd_edge_bweight_offset != -1); + + scale_be_weight = compute_scale_factor(ve_median->be_weight, median->be_weight); + } + + if (median->crease) { + BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); + cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + BLI_assert(cd_edge_crease_offset != -1); + + scale_crease = compute_scale_factor(ve_median->crease, median->crease); + } + + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + if (median->be_weight != 0.0f) { + float *b_weight = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_bweight_offset); + apply_scale_factor_clamp(b_weight, tot, ve_median->be_weight, scale_be_weight); + } + + if (median->crease != 0.0f) { + float *crease = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_crease_offset); + apply_scale_factor_clamp(crease, tot, ve_median->crease, scale_crease); + } + } + } + } + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF) && + (apply_vcos || median_basis.curve.b_weight || median_basis.curve.weight || + median_basis.curve.radius || median_basis.curve.tilt)) { + const TransformMedian_Curve *median = &median_basis.curve, + *ve_median = &ve_median_basis.curve; + Curve *cu = ob->data; + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + const float scale_w = compute_scale_factor(ve_median->weight, median->weight); + + nu = nurbs->first; + while (nu) { + if (nu->type == CU_BEZIER) { + for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { + if (bezt->f2 & SELECT) { + if (apply_vcos) { + /* Here we always have to use the diff... :/ + * Cannot avoid some glitches when going e.g. from 3 to 0.0001 (see T37327), + * unless we use doubles. + */ + add_v3_v3(bezt->vec[0], median->location); + add_v3_v3(bezt->vec[1], median->location); + add_v3_v3(bezt->vec[2], median->location); + } + if (median->weight) { + apply_scale_factor_clamp(&bezt->weight, tot, ve_median->weight, scale_w); + } + if (median->radius) { + apply_raw_diff(&bezt->radius, tot, ve_median->radius, median->radius); + } + if (median->tilt) { + apply_raw_diff(&bezt->tilt, tot, ve_median->tilt, median->tilt); + } + } + else if (apply_vcos) { + /* Handles can only have their coordinates changed here. */ + if (bezt->f1 & SELECT) { + apply_raw_diff_v3(bezt->vec[0], tot, ve_median->location, median->location); + } + if (bezt->f3 & SELECT) { + apply_raw_diff_v3(bezt->vec[2], tot, ve_median->location, median->location); + } + } + } + } + else { + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a--; bp++) { + if (bp->f1 & SELECT) { + if (apply_vcos) { + apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location); + } + if (median->b_weight) { + apply_raw_diff(&bp->vec[3], tot, ve_median->b_weight, median->b_weight); + } + if (median->weight) { + apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w); + } + if (median->radius) { + apply_raw_diff(&bp->radius, tot, ve_median->radius, median->radius); + } + if (median->tilt) { + apply_raw_diff(&bp->tilt, tot, ve_median->tilt, median->tilt); + } + } + } + } + BKE_nurb_test_2d(nu); + BKE_nurb_handles_test(nu, true); /* test for bezier too */ + + nu = nu->next; + } + } + else if ((ob->type == OB_LATTICE) && (apply_vcos || median_basis.lattice.weight)) { + const TransformMedian_Lattice *median = &median_basis.lattice, + *ve_median = &ve_median_basis.lattice; + Lattice *lt = ob->data; + BPoint *bp; + int a; + const float scale_w = compute_scale_factor(ve_median->weight, median->weight); + + a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + bp = lt->editlatt->latt->def; + while (a--) { + if (bp->f1 & SELECT) { + if (apply_vcos) { + apply_raw_diff_v3(bp->vec, tot, ve_median->location, median->location); + } + if (median->weight) { + apply_scale_factor_clamp(&bp->weight, tot, ve_median->weight, scale_w); + } + } + bp++; + } + } + + /* ED_undo_push(C, "Transform properties"); */ + } } #undef TRANSFORM_MEDIAN_ARRAY_LEN static void v3d_object_dimension_buts(bContext *C, uiLayout *layout, View3D *v3d, Object *ob) { - uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL; - TransformProperties *tfp = v3d_transform_props_ensure(v3d); - - if (block) { - BLI_assert(C == NULL); - int yi = 200; - const int butw = 200; - const int buth = 20 * UI_DPI_FAC; - - BKE_object_dimensions_get(ob, tfp->ob_dims); - copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims); - - uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Dimensions:"), 0, yi -= buth, butw, buth, NULL, 0, 0, 0, 0, ""); - UI_block_align_begin(block); - const float lim = 10000; - for (int i = 0; i < 3; i++) { - uiBut *but; - char text[3] = {'X' + i, ':', '\0'}; - but = uiDefButF( - block, UI_BTYPE_NUM, B_TRANSFORM_PANEL_DIMS, text, 0, yi -= buth, butw, buth, - &(tfp->ob_dims[i]), 0.0f, lim, 10, 3, ""); - UI_but_unit_type_set(but, PROP_UNIT_LENGTH); - } - UI_block_align_end(block); - } - else { /* apply */ - int axis_mask = 0; - for (int i = 0; i < 3; i++) { - if (tfp->ob_dims[i] == tfp->ob_dims_orig[i]) { - axis_mask |= (1 << i); - } - } - BKE_object_dimensions_set(ob, tfp->ob_dims, axis_mask); - - PointerRNA obptr; - RNA_id_pointer_create(&ob->id, &obptr); - PropertyRNA *prop = RNA_struct_find_property(&obptr, "scale"); - RNA_property_update(C, &obptr, prop); - } + uiBlock *block = (layout) ? uiLayoutAbsoluteBlock(layout) : NULL; + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + + if (block) { + BLI_assert(C == NULL); + int yi = 200; + const int butw = 200; + const int buth = 20 * UI_DPI_FAC; + + BKE_object_dimensions_get(ob, tfp->ob_dims); + copy_v3_v3(tfp->ob_dims_orig, tfp->ob_dims); + + uiDefBut(block, + UI_BTYPE_LABEL, + 0, + IFACE_("Dimensions:"), + 0, + yi -= buth, + butw, + buth, + NULL, + 0, + 0, + 0, + 0, + ""); + UI_block_align_begin(block); + const float lim = 10000; + for (int i = 0; i < 3; i++) { + uiBut *but; + char text[3] = {'X' + i, ':', '\0'}; + but = uiDefButF(block, + UI_BTYPE_NUM, + B_TRANSFORM_PANEL_DIMS, + text, + 0, + yi -= buth, + butw, + buth, + &(tfp->ob_dims[i]), + 0.0f, + lim, + 10, + 3, + ""); + UI_but_unit_type_set(but, PROP_UNIT_LENGTH); + } + UI_block_align_end(block); + } + else { /* apply */ + int axis_mask = 0; + for (int i = 0; i < 3; i++) { + if (tfp->ob_dims[i] == tfp->ob_dims_orig[i]) { + axis_mask |= (1 << i); + } + } + BKE_object_dimensions_set(ob, tfp->ob_dims, axis_mask); + + PointerRNA obptr; + RNA_id_pointer_create(&ob->id, &obptr); + PropertyRNA *prop = RNA_struct_find_property(&obptr, "scale"); + RNA_property_update(C, &obptr, prop); + } } -#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ +#define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) { - if (event < B_VGRP_PNL_EDIT_SINGLE) { - /* not for me */ - return; - } - else { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; - ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); - } + if (event < B_VGRP_PNL_EDIT_SINGLE) { + /* not for me */ + return; + } + else { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = view_layer->basact->object; + ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); + } } static bool view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - if (ob && (BKE_object_is_in_editmode_vgroup(ob) || - BKE_object_is_in_wpaint_select_vert(ob))) - { - MDeformVert *dvert_act = ED_mesh_active_dvert_get_only(ob); - if (dvert_act) { - return (dvert_act->totweight != 0); - } - } - - return false; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + if (ob && (BKE_object_is_in_editmode_vgroup(ob) || BKE_object_is_in_wpaint_select_vert(ob))) { + MDeformVert *dvert_act = ED_mesh_active_dvert_get_only(ob); + if (dvert_act) { + return (dvert_act->totweight != 0); + } + } + + return false; } - static void view3d_panel_vgroup(const bContext *C, Panel *pa) { - uiBlock *block = uiLayoutAbsoluteBlock(pa->layout); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; - - MDeformVert *dv; - - dv = ED_mesh_active_dvert_get_only(ob); - - if (dv && dv->totweight) { - ToolSettings *ts = scene->toolsettings; - - wmOperatorType *ot; - PointerRNA op_ptr, tools_ptr; - PointerRNA *but_ptr; - - uiLayout *col, *bcol; - uiLayout *row; - uiBut *but; - bDeformGroup *dg; - uint i; - int subset_count, vgroup_tot; - const bool *vgroup_validmap; - eVGroupSelect subset_type = ts->vgroupsubset; - int yco = 0; - int lock_count = 0; - - UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL); - - bcol = uiLayoutColumn(pa->layout, true); - row = uiLayoutRow(bcol, true); /* The filter button row */ - - RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr); - uiItemR(row, &tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - - col = uiLayoutColumn(bcol, true); - - vgroup_validmap = BKE_object_defgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); - for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { - bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0; - if (vgroup_validmap[i]) { - MDeformWeight *dw = defvert_find_index(dv, i); - if (dw) { - int x, xco = 0; - int icon; - uiLayout *split = uiLayoutSplit(col, 0.45, true); - row = uiLayoutRow(split, true); - - /* The Weight Group Name */ - - ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); - but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name, - xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, ""); - but_ptr = UI_but_operator_ptr_get(but); - RNA_int_set(but_ptr, "weight_group", i); - UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); - if (ob->actdef != i + 1) { - UI_but_flag_enable(but, UI_BUT_INACTIVE); - } - xco += x; - - row = uiLayoutRow(split, true); - uiLayoutSetEnabled(row, !locked); - - /* The weight group value */ - /* To be reworked still */ - but = uiDefButF(block, UI_BTYPE_NUM, B_VGRP_PNL_EDIT_SINGLE + i, "", - xco, yco, (x = UI_UNIT_X * 4), UI_UNIT_Y, - &dw->weight, 0.0, 1.0, 1, 3, ""); - UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT); - if (locked) { - lock_count++; - } - xco += x; - - /* The weight group paste function */ - icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN; - uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_int_set(&op_ptr, "weight_group", i); - - /* The weight entry delete function */ - icon = (locked) ? ICON_LOCKED : ICON_X; - uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_int_set(&op_ptr, "weight_group", i); - - yco -= UI_UNIT_Y; - } - } - } - MEM_freeN((void *)vgroup_validmap); - - yco -= 2; - - col = uiLayoutColumn(pa->layout, true); - row = uiLayoutRow(col, true); - - ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1); - but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Normalize", - 0, yco, UI_UNIT_X * 5, UI_UNIT_Y, - TIP_("Normalize weights of active vertex (if affected groups are unlocked)")); - if (lock_count) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - - ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1); - but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, "Copy", - UI_UNIT_X * 5, yco, UI_UNIT_X * 5, UI_UNIT_Y, - TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)")); - if (lock_count) { - UI_but_flag_enable(but, UI_BUT_DISABLED); - } - - } + uiBlock *block = uiLayoutAbsoluteBlock(pa->layout); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = view_layer->basact->object; + + MDeformVert *dv; + + dv = ED_mesh_active_dvert_get_only(ob); + + if (dv && dv->totweight) { + ToolSettings *ts = scene->toolsettings; + + wmOperatorType *ot; + PointerRNA op_ptr, tools_ptr; + PointerRNA *but_ptr; + + uiLayout *col, *bcol; + uiLayout *row; + uiBut *but; + bDeformGroup *dg; + uint i; + int subset_count, vgroup_tot; + const bool *vgroup_validmap; + eVGroupSelect subset_type = ts->vgroupsubset; + int yco = 0; + int lock_count = 0; + + UI_block_func_handle_set(block, do_view3d_vgroup_buttons, NULL); + + bcol = uiLayoutColumn(pa->layout, true); + row = uiLayoutRow(bcol, true); /* The filter button row */ + + RNA_pointer_create(NULL, &RNA_ToolSettings, ts, &tools_ptr); + uiItemR(row, &tools_ptr, "vertex_group_subset", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + col = uiLayoutColumn(bcol, true); + + vgroup_validmap = BKE_object_defgroup_subset_from_select_type( + ob, subset_type, &vgroup_tot, &subset_count); + for (i = 0, dg = ob->defbase.first; dg; i++, dg = dg->next) { + bool locked = (dg->flag & DG_LOCK_WEIGHT) != 0; + if (vgroup_validmap[i]) { + MDeformWeight *dw = defvert_find_index(dv, i); + if (dw) { + int x, xco = 0; + int icon; + uiLayout *split = uiLayoutSplit(col, 0.45, true); + row = uiLayoutRow(split, true); + + /* The Weight Group Name */ + + ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true); + but = uiDefButO_ptr(block, + UI_BTYPE_BUT, + ot, + WM_OP_EXEC_DEFAULT, + dg->name, + xco, + yco, + (x = UI_UNIT_X * 5), + UI_UNIT_Y, + ""); + but_ptr = UI_but_operator_ptr_get(but); + RNA_int_set(but_ptr, "weight_group", i); + UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); + if (ob->actdef != i + 1) { + UI_but_flag_enable(but, UI_BUT_INACTIVE); + } + xco += x; + + row = uiLayoutRow(split, true); + uiLayoutSetEnabled(row, !locked); + + /* The weight group value */ + /* To be reworked still */ + but = uiDefButF(block, + UI_BTYPE_NUM, + B_VGRP_PNL_EDIT_SINGLE + i, + "", + xco, + yco, + (x = UI_UNIT_X * 4), + UI_UNIT_Y, + &dw->weight, + 0.0, + 1.0, + 1, + 3, + ""); + UI_but_drawflag_enable(but, UI_BUT_TEXT_LEFT); + if (locked) { + lock_count++; + } + xco += x; + + /* The weight group paste function */ + icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN; + uiItemFullO(row, + "OBJECT_OT_vertex_weight_paste", + "", + icon, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + RNA_int_set(&op_ptr, "weight_group", i); + + /* The weight entry delete function */ + icon = (locked) ? ICON_LOCKED : ICON_X; + uiItemFullO(row, + "OBJECT_OT_vertex_weight_delete", + "", + icon, + NULL, + WM_OP_INVOKE_DEFAULT, + 0, + &op_ptr); + RNA_int_set(&op_ptr, "weight_group", i); + + yco -= UI_UNIT_Y; + } + } + } + MEM_freeN((void *)vgroup_validmap); + + yco -= 2; + + col = uiLayoutColumn(pa->layout, true); + row = uiLayoutRow(col, true); + + ot = WM_operatortype_find("OBJECT_OT_vertex_weight_normalize_active_vertex", 1); + but = uiDefButO_ptr( + block, + UI_BTYPE_BUT, + ot, + WM_OP_EXEC_DEFAULT, + "Normalize", + 0, + yco, + UI_UNIT_X * 5, + UI_UNIT_Y, + TIP_("Normalize weights of active vertex (if affected groups are unlocked)")); + if (lock_count) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + + ot = WM_operatortype_find("OBJECT_OT_vertex_weight_copy", 1); + but = uiDefButO_ptr( + block, + UI_BTYPE_BUT, + ot, + WM_OP_EXEC_DEFAULT, + "Copy", + UI_UNIT_X * 5, + yco, + UI_UNIT_X * 5, + UI_UNIT_Y, + TIP_("Copy active vertex to other selected vertices (if affected groups are unlocked)")); + if (lock_count) { + UI_but_flag_enable(but, UI_BUT_DISABLED); + } + } } static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr) { - uiLayout *split, *colsub; - - split = uiLayoutSplit(layout, 0.8f, false); - - if (ptr->type == &RNA_PoseBone) { - PointerRNA boneptr; - Bone *bone; - - boneptr = RNA_pointer_get(ptr, "bone"); - bone = boneptr.data; - uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED)); - } - colsub = uiLayoutColumn(split, true); - uiItemR(colsub, ptr, "location", 0, NULL, ICON_NONE); - colsub = uiLayoutColumn(split, true); - uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); - uiItemL(colsub, "", ICON_NONE); - uiItemR(colsub, ptr, "lock_location", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - - split = uiLayoutSplit(layout, 0.8f, false); - - switch (RNA_enum_get(ptr, "rotation_mode")) { - case ROT_MODE_QUAT: /* quaternion */ - colsub = uiLayoutColumn(split, true); - uiItemR(colsub, ptr, "rotation_quaternion", 0, IFACE_("Rotation"), ICON_NONE); - colsub = uiLayoutColumn(split, true); - uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); - uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE); - if (RNA_boolean_get(ptr, "lock_rotations_4d")) { - uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE + UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - } - else { - uiItemL(colsub, "", ICON_NONE); - } - uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - break; - case ROT_MODE_AXISANGLE: /* axis angle */ - colsub = uiLayoutColumn(split, true); - uiItemR(colsub, ptr, "rotation_axis_angle", 0, IFACE_("Rotation"), ICON_NONE); - colsub = uiLayoutColumn(split, true); - uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); - uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE); - if (RNA_boolean_get(ptr, "lock_rotations_4d")) { - uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - } - else { - uiItemL(colsub, "", ICON_NONE); - } - uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - break; - default: /* euler rotations */ - colsub = uiLayoutColumn(split, true); - uiItemR(colsub, ptr, "rotation_euler", 0, IFACE_("Rotation"), ICON_NONE); - colsub = uiLayoutColumn(split, true); - uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); - uiItemL(colsub, "", ICON_NONE); - uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); - break; - } - uiItemR(layout, ptr, "rotation_mode", 0, "", ICON_NONE); - - split = uiLayoutSplit(layout, 0.8f, false); - colsub = uiLayoutColumn(split, true); - uiItemR(colsub, ptr, "scale", 0, NULL, ICON_NONE); - colsub = uiLayoutColumn(split, true); - uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); - uiItemL(colsub, "", ICON_NONE); - uiItemR(colsub, ptr, "lock_scale", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_DECORATE_UNLOCKED); + uiLayout *split, *colsub; + + split = uiLayoutSplit(layout, 0.8f, false); + + if (ptr->type == &RNA_PoseBone) { + PointerRNA boneptr; + Bone *bone; + + boneptr = RNA_pointer_get(ptr, "bone"); + bone = boneptr.data; + uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED)); + } + colsub = uiLayoutColumn(split, true); + uiItemR(colsub, ptr, "location", 0, NULL, ICON_NONE); + colsub = uiLayoutColumn(split, true); + uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); + uiItemL(colsub, "", ICON_NONE); + uiItemR(colsub, + ptr, + "lock_location", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + + split = uiLayoutSplit(layout, 0.8f, false); + + switch (RNA_enum_get(ptr, "rotation_mode")) { + case ROT_MODE_QUAT: /* quaternion */ + colsub = uiLayoutColumn(split, true); + uiItemR(colsub, ptr, "rotation_quaternion", 0, IFACE_("Rotation"), ICON_NONE); + colsub = uiLayoutColumn(split, true); + uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); + uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE); + if (RNA_boolean_get(ptr, "lock_rotations_4d")) { + uiItemR(colsub, + ptr, + "lock_rotation_w", + UI_ITEM_R_TOGGLE + UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + } + else { + uiItemL(colsub, "", ICON_NONE); + } + uiItemR(colsub, + ptr, + "lock_rotation", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + break; + case ROT_MODE_AXISANGLE: /* axis angle */ + colsub = uiLayoutColumn(split, true); + uiItemR(colsub, ptr, "rotation_axis_angle", 0, IFACE_("Rotation"), ICON_NONE); + colsub = uiLayoutColumn(split, true); + uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); + uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, IFACE_("4L"), ICON_NONE); + if (RNA_boolean_get(ptr, "lock_rotations_4d")) { + uiItemR(colsub, + ptr, + "lock_rotation_w", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + } + else { + uiItemL(colsub, "", ICON_NONE); + } + uiItemR(colsub, + ptr, + "lock_rotation", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + break; + default: /* euler rotations */ + colsub = uiLayoutColumn(split, true); + uiItemR(colsub, ptr, "rotation_euler", 0, IFACE_("Rotation"), ICON_NONE); + colsub = uiLayoutColumn(split, true); + uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); + uiItemL(colsub, "", ICON_NONE); + uiItemR(colsub, + ptr, + "lock_rotation", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); + break; + } + uiItemR(layout, ptr, "rotation_mode", 0, "", ICON_NONE); + + split = uiLayoutSplit(layout, 0.8f, false); + colsub = uiLayoutColumn(split, true); + uiItemR(colsub, ptr, "scale", 0, NULL, ICON_NONE); + colsub = uiLayoutColumn(split, true); + uiLayoutSetEmboss(colsub, UI_EMBOSS_NONE); + uiItemL(colsub, "", ICON_NONE); + uiItemR(colsub, + ptr, + "lock_scale", + UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, + "", + ICON_DECORATE_UNLOCKED); } static void v3d_posearmature_buts(uiLayout *layout, Object *ob) { - bPoseChannel *pchan; - PointerRNA pchanptr; - uiLayout *col; + bPoseChannel *pchan; + PointerRNA pchanptr; + uiLayout *col; - pchan = BKE_pose_channel_active(ob); + pchan = BKE_pose_channel_active(ob); - if (!pchan) { - uiItemL(layout, IFACE_("No Bone Active"), ICON_NONE); - return; - } + if (!pchan) { + uiItemL(layout, IFACE_("No Bone Active"), ICON_NONE); + return; + } - RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr); + RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr); - col = uiLayoutColumn(layout, false); + col = uiLayoutColumn(layout, false); - /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) - * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? - * Maybe needs RNA/ui options to display rotations as different types... */ - v3d_transform_butsR(col, &pchanptr); + /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) + * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? + * Maybe needs RNA/ui options to display rotations as different types... */ + v3d_transform_butsR(col, &pchanptr); } static void v3d_editarmature_buts(uiLayout *layout, Object *ob) { - bArmature *arm = ob->data; - EditBone *ebone; - uiLayout *col; - PointerRNA eboneptr; - - ebone = arm->act_edbone; - - if (!ebone || (ebone->layer & arm->layer) == 0) { - uiItemL(layout, IFACE_("Nothing selected"), ICON_NONE); - return; - } - - RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr); - - col = uiLayoutColumn(layout, false); - uiItemR(col, &eboneptr, "head", 0, NULL, ICON_NONE); - if (ebone->parent && ebone->flag & BONE_CONNECTED) { - PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent"); - uiItemR(col, &parptr, "tail_radius", 0, IFACE_("Radius (Parent)"), ICON_NONE); - } - else { - uiItemR(col, &eboneptr, "head_radius", 0, IFACE_("Radius"), ICON_NONE); - } - - uiItemR(col, &eboneptr, "tail", 0, NULL, ICON_NONE); - uiItemR(col, &eboneptr, "tail_radius", 0, IFACE_("Radius"), ICON_NONE); - - uiItemR(col, &eboneptr, "roll", 0, NULL, ICON_NONE); - uiItemR(col, &eboneptr, "envelope_distance", 0, IFACE_("Envelope"), ICON_NONE); + bArmature *arm = ob->data; + EditBone *ebone; + uiLayout *col; + PointerRNA eboneptr; + + ebone = arm->act_edbone; + + if (!ebone || (ebone->layer & arm->layer) == 0) { + uiItemL(layout, IFACE_("Nothing selected"), ICON_NONE); + return; + } + + RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr); + + col = uiLayoutColumn(layout, false); + uiItemR(col, &eboneptr, "head", 0, NULL, ICON_NONE); + if (ebone->parent && ebone->flag & BONE_CONNECTED) { + PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent"); + uiItemR(col, &parptr, "tail_radius", 0, IFACE_("Radius (Parent)"), ICON_NONE); + } + else { + uiItemR(col, &eboneptr, "head_radius", 0, IFACE_("Radius"), ICON_NONE); + } + + uiItemR(col, &eboneptr, "tail", 0, NULL, ICON_NONE); + uiItemR(col, &eboneptr, "tail_radius", 0, IFACE_("Radius"), ICON_NONE); + + uiItemR(col, &eboneptr, "roll", 0, NULL, ICON_NONE); + uiItemR(col, &eboneptr, "envelope_distance", 0, IFACE_("Envelope"), ICON_NONE); } static void v3d_editmetaball_buts(uiLayout *layout, Object *ob) { - PointerRNA mbptr, ptr; - MetaBall *mball = ob->data; - uiLayout *col; - - if (!mball || !(mball->lastelem)) { - return; - } - - RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr); - - RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr); - - col = uiLayoutColumn(layout, false); - uiItemR(col, &ptr, "co", 0, NULL, ICON_NONE); - - uiItemR(col, &ptr, "radius", 0, NULL, ICON_NONE); - uiItemR(col, &ptr, "stiffness", 0, NULL, ICON_NONE); - - uiItemR(col, &ptr, "type", 0, NULL, ICON_NONE); - - col = uiLayoutColumn(layout, true); - switch (RNA_enum_get(&ptr, "type")) { - case MB_BALL: - break; - case MB_CUBE: - uiItemL(col, IFACE_("Size:"), ICON_NONE); - uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); - uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); - uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE); - break; - case MB_TUBE: - uiItemL(col, IFACE_("Size:"), ICON_NONE); - uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); - break; - case MB_PLANE: - uiItemL(col, IFACE_("Size:"), ICON_NONE); - uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); - uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); - break; - case MB_ELIPSOID: - uiItemL(col, IFACE_("Size:"), ICON_NONE); - uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); - uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); - uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE); - break; - } + PointerRNA mbptr, ptr; + MetaBall *mball = ob->data; + uiLayout *col; + + if (!mball || !(mball->lastelem)) { + return; + } + + RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr); + + RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr); + + col = uiLayoutColumn(layout, false); + uiItemR(col, &ptr, "co", 0, NULL, ICON_NONE); + + uiItemR(col, &ptr, "radius", 0, NULL, ICON_NONE); + uiItemR(col, &ptr, "stiffness", 0, NULL, ICON_NONE); + + uiItemR(col, &ptr, "type", 0, NULL, ICON_NONE); + + col = uiLayoutColumn(layout, true); + switch (RNA_enum_get(&ptr, "type")) { + case MB_BALL: + break; + case MB_CUBE: + uiItemL(col, IFACE_("Size:"), ICON_NONE); + uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); + uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); + uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE); + break; + case MB_TUBE: + uiItemL(col, IFACE_("Size:"), ICON_NONE); + uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); + break; + case MB_PLANE: + uiItemL(col, IFACE_("Size:"), ICON_NONE); + uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); + uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); + break; + case MB_ELIPSOID: + uiItemL(col, IFACE_("Size:"), ICON_NONE); + uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE); + uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE); + uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE); + break; + } } static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - Object *ob = OBACT(view_layer); - - switch (event) { - - case B_REDR: - ED_area_tag_redraw(CTX_wm_area(C)); - return; /* no notifier! */ - - case B_TRANSFORM_PANEL_MEDIAN: - if (ob) { - v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } - break; - case B_TRANSFORM_PANEL_DIMS: - if (ob) { - v3d_object_dimension_buts(C, NULL, v3d, ob); - } - break; - } - - /* default for now */ - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + Object *ob = OBACT(view_layer); + + switch (event) { + + case B_REDR: + ED_area_tag_redraw(CTX_wm_area(C)); + return; /* no notifier! */ + + case B_TRANSFORM_PANEL_MEDIAN: + if (ob) { + v3d_editvertex_buts(NULL, v3d, ob, 1.0); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + break; + case B_TRANSFORM_PANEL_DIMS: + if (ob) { + v3d_object_dimension_buts(C, NULL, v3d, ob); + } + break; + } + + /* default for now */ + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); } static bool view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - return (view_layer->basact != NULL); + ViewLayer *view_layer = CTX_data_view_layer(C); + return (view_layer->basact != NULL); } static void view3d_panel_transform(const bContext *C, Panel *pa) { - uiBlock *block; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = view_layer->basact->object; - Object *obedit = OBEDIT_FROM_OBACT(ob); - uiLayout *col; - - block = uiLayoutGetBlock(pa->layout); - UI_block_func_handle_set(block, do_view3d_region_buttons, NULL); - - col = uiLayoutColumn(pa->layout, false); - - if (ob == obedit) { - if (ob->type == OB_ARMATURE) { - v3d_editarmature_buts(col, ob); - } - else if (ob->type == OB_MBALL) { - v3d_editmetaball_buts(col, ob); - } - else { - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL)); - v3d_editvertex_buts(col, v3d, ob, lim); - } - } - else if (ob->mode & OB_MODE_POSE) { - v3d_posearmature_buts(col, ob); - } - else { - PointerRNA obptr; - - RNA_id_pointer_create(&ob->id, &obptr); - v3d_transform_butsR(col, &obptr); - - /* dimensions and editmode just happen to be the same checks */ - if (OB_TYPE_SUPPORT_EDITMODE(ob->type)) { - View3D *v3d = CTX_wm_view3d(C); - v3d_object_dimension_buts(NULL, col, v3d, ob); - } - } + uiBlock *block; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = view_layer->basact->object; + Object *obedit = OBEDIT_FROM_OBACT(ob); + uiLayout *col; + + block = uiLayoutGetBlock(pa->layout); + UI_block_func_handle_set(block, do_view3d_region_buttons, NULL); + + col = uiLayoutColumn(pa->layout, false); + + if (ob == obedit) { + if (ob->type == OB_ARMATURE) { + v3d_editarmature_buts(col, ob); + } + else if (ob->type == OB_MBALL) { + v3d_editmetaball_buts(col, ob); + } + else { + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + const float lim = 10000.0f * max_ff(1.0f, ED_view3d_grid_scale(scene, v3d, NULL)); + v3d_editvertex_buts(col, v3d, ob, lim); + } + } + else if (ob->mode & OB_MODE_POSE) { + v3d_posearmature_buts(col, ob); + } + else { + PointerRNA obptr; + + RNA_id_pointer_create(&ob->id, &obptr); + v3d_transform_butsR(col, &obptr); + + /* dimensions and editmode just happen to be the same checks */ + if (OB_TYPE_SUPPORT_EDITMODE(ob->type)) { + View3D *v3d = CTX_wm_view3d(C); + v3d_object_dimension_buts(NULL, col, v3d, ob); + } + } } static void hide_collections_menu_draw(const bContext *C, Menu *menu) { - ED_collection_hide_menu_draw(C, menu->layout); + ED_collection_hide_menu_draw(C, menu->layout); } void view3d_buttons_register(ARegionType *art) { - PanelType *pt; - - pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object"); - strcpy(pt->idname, "VIEW3D_PT_transform"); - strcpy(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */ - strcpy(pt->category, "View"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = view3d_panel_transform; - pt->poll = view3d_panel_transform_poll; - BLI_addtail(&art->paneltypes, pt); - - pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup"); - strcpy(pt->idname, "VIEW3D_PT_vgroup"); - strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */ - strcpy(pt->category, "View"); - strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - pt->draw = view3d_panel_vgroup; - pt->poll = view3d_panel_vgroup_poll; - BLI_addtail(&art->paneltypes, pt); - - MenuType *mt; - - mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections"); - strcpy(mt->idname, "VIEW3D_MT_collection"); - strcpy(mt->label, N_("Collection")); - strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); - mt->draw = hide_collections_menu_draw; - WM_menutype_add(mt); + PanelType *pt; + + pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel object"); + strcpy(pt->idname, "VIEW3D_PT_transform"); + strcpy(pt->label, N_("Transform")); /* XXX C panels unavailable through RNA bpy.types! */ + strcpy(pt->category, "View"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = view3d_panel_transform; + pt->poll = view3d_panel_transform_poll; + BLI_addtail(&art->paneltypes, pt); + + pt = MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup"); + strcpy(pt->idname, "VIEW3D_PT_vgroup"); + strcpy(pt->label, N_("Vertex Weights")); /* XXX C panels unavailable through RNA bpy.types! */ + strcpy(pt->category, "View"); + strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + pt->draw = view3d_panel_vgroup; + pt->poll = view3d_panel_vgroup_poll; + BLI_addtail(&art->paneltypes, pt); + + MenuType *mt; + + mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections"); + strcpy(mt->idname, "VIEW3D_MT_collection"); + strcpy(mt->label, N_("Collection")); + strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); + mt->draw = hide_collections_menu_draw; + WM_menutype_add(mt); } static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = view3d_has_buttons_region(sa); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = view3d_has_buttons_region(sa); - if (ar) { - ED_region_toggle_hidden(C, ar); - } + if (ar) { + ED_region_toggle_hidden(C, ar); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_properties(wmOperatorType *ot) { - ot->name = "Toggle Sidebar"; - ot->description = "Toggle the properties region visibility"; - ot->idname = "VIEW3D_OT_properties"; + ot->name = "Toggle Sidebar"; + ot->description = "Toggle the properties region visibility"; + ot->idname = "VIEW3D_OT_properties"; - ot->exec = view3d_properties_toggle_exec; - ot->poll = ED_operator_view3d_active; + ot->exec = view3d_properties_toggle_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } static int view3d_object_mode_menu(bContext *C, wmOperator *op) { - Object *ob = CTX_data_active_object(C); - if (ob == NULL) { - BKE_report(op->reports, RPT_WARNING, "No active object found"); - return OPERATOR_CANCELLED; - } - else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) { - ED_object_mode_toggle(C, OB_MODE_POSE); - return OPERATOR_CANCELLED; - } - else { - UI_pie_menu_invoke(C, "VIEW3D_MT_object_mode_pie", CTX_wm_window(C)->eventstate); - return OPERATOR_CANCELLED; - } + Object *ob = CTX_data_active_object(C); + if (ob == NULL) { + BKE_report(op->reports, RPT_WARNING, "No active object found"); + return OPERATOR_CANCELLED; + } + else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) { + ED_object_mode_toggle(C, OB_MODE_POSE); + return OPERATOR_CANCELLED; + } + else { + UI_pie_menu_invoke(C, "VIEW3D_MT_object_mode_pie", CTX_wm_window(C)->eventstate); + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_object_mode_pie_or_toggle(wmOperatorType *ot) { - ot->name = "Object Mode Menu"; - ot->idname = "VIEW3D_OT_object_mode_pie_or_toggle"; + ot->name = "Object Mode Menu"; + ot->idname = "VIEW3D_OT_object_mode_pie_or_toggle"; - ot->exec = view3d_object_mode_menu; - ot->poll = ED_operator_view3d_active; + ot->exec = view3d_object_mode_menu; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 3f7356de465..c8059c25e15 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -51,287 +51,277 @@ #include "ED_screen.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ #include "BLI_strict_flags.h" - typedef struct View3DCameraControl { - /* -------------------------------------------------------------------- */ - /* Context (assign these to vars before use) */ - Scene *ctx_scene; - View3D *ctx_v3d; - RegionView3D *ctx_rv3d; - - - /* -------------------------------------------------------------------- */ - /* internal vars */ + /* -------------------------------------------------------------------- */ + /* Context (assign these to vars before use) */ + Scene *ctx_scene; + View3D *ctx_v3d; + RegionView3D *ctx_rv3d; - /* for parenting calculation */ - float view_mat_prev[4][4]; + /* -------------------------------------------------------------------- */ + /* internal vars */ + /* for parenting calculation */ + float view_mat_prev[4][4]; - /* -------------------------------------------------------------------- */ - /* optional capabilities */ + /* -------------------------------------------------------------------- */ + /* optional capabilities */ - bool use_parent_root; + bool use_parent_root; + /* -------------------------------------------------------------------- */ + /* initial values */ - /* -------------------------------------------------------------------- */ - /* initial values */ + /* root most parent */ + Object *root_parent; - /* root most parent */ - Object *root_parent; + /* backup values */ + float dist_backup; + /* backup the views distance since we use a zero dist for fly mode */ + float ofs_backup[3]; + /* backup the views offset in case the user cancels flying in non camera mode */ - /* backup values */ - float dist_backup; - /* backup the views distance since we use a zero dist for fly mode */ - float ofs_backup[3]; - /* backup the views offset in case the user cancels flying in non camera mode */ + /* backup the views quat in case the user cancels flying in non camera mode. + * (quat for view, eul for camera) */ + float rot_backup[4]; + /* remember if were ortho or not, only used for restoring the view if it was a ortho view */ + char persp_backup; - /* backup the views quat in case the user cancels flying in non camera mode. - * (quat for view, eul for camera) */ - float rot_backup[4]; - /* remember if were ortho or not, only used for restoring the view if it was a ortho view */ - char persp_backup; + /* are we flying an ortho camera in perspective view, + * which was originally in ortho view? + * could probably figure it out but better be explicit */ + bool is_ortho_cam; - /* are we flying an ortho camera in perspective view, - * which was originally in ortho view? - * could probably figure it out but better be explicit */ - bool is_ortho_cam; - - /* backup the objects transform */ - void *obtfm; + /* backup the objects transform */ + void *obtfm; } View3DCameraControl; - BLI_INLINE Object *view3d_cameracontrol_object(View3DCameraControl *vctrl) { - return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera; + return vctrl->root_parent ? vctrl->root_parent : vctrl->ctx_v3d->camera; } - /** * Returns the object which is being manipulated or NULL. */ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl) { - RegionView3D *rv3d = vctrl->ctx_rv3d; - - if (rv3d->persp == RV3D_CAMOB) { - return view3d_cameracontrol_object(vctrl); - } - else { - return NULL; - } + RegionView3D *rv3d = vctrl->ctx_rv3d; + + if (rv3d->persp == RV3D_CAMOB) { + return view3d_cameracontrol_object(vctrl); + } + else { + return NULL; + } } - /** * Creates a #View3DCameraControl handle and sets up * the view for first-person style navigation. */ -struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, - const bool use_parent_root) +struct View3DCameraControl *ED_view3d_cameracontrol_acquire(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + const bool use_parent_root) { - View3DCameraControl *vctrl; - - vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__); - - /* Store context */ - vctrl->ctx_scene = scene; - vctrl->ctx_v3d = v3d; - vctrl->ctx_rv3d = rv3d; - - vctrl->use_parent_root = use_parent_root; - - vctrl->persp_backup = rv3d->persp; - vctrl->dist_backup = rv3d->dist; - - /* check for flying ortho camera - which we cant support well - * we _could_ also check for an ortho camera but this is easier */ - if ((rv3d->persp == RV3D_CAMOB) && - (rv3d->is_persp == false)) - { - ((Camera *)v3d->camera->data)->type = CAM_PERSP; - vctrl->is_ortho_cam = true; - } - - if (rv3d->persp == RV3D_CAMOB) { - Object *ob_back; - if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) { - while (vctrl->root_parent->parent) { - vctrl->root_parent = vctrl->root_parent->parent; - } - ob_back = vctrl->root_parent; - } - else { - ob_back = v3d->camera; - } - - /* store the original camera loc and rot */ - vctrl->obtfm = BKE_object_tfm_backup(ob_back); - - BKE_object_where_is_calc(depsgraph, scene, v3d->camera); - negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); - - rv3d->dist = 0.0; - } - else { - /* perspective or ortho */ - if (rv3d->persp == RV3D_ORTHO) { - /* if ortho projection, make perspective */ - rv3d->persp = RV3D_PERSP; - } - - copy_qt_qt(vctrl->rot_backup, rv3d->viewquat); - copy_v3_v3(vctrl->ofs_backup, rv3d->ofs); - - /* the dist defines a vector that is infront of the offset - * to rotate the view about. - * this is no good for fly mode because we - * want to rotate about the viewers center. - * but to correct the dist removal we must - * alter offset so the view doesn't jump. */ - - ED_view3d_distance_set(rv3d, 0.0f); - /* Done with correcting for the dist */ - } - - ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist); - - return vctrl; + View3DCameraControl *vctrl; + + vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__); + + /* Store context */ + vctrl->ctx_scene = scene; + vctrl->ctx_v3d = v3d; + vctrl->ctx_rv3d = rv3d; + + vctrl->use_parent_root = use_parent_root; + + vctrl->persp_backup = rv3d->persp; + vctrl->dist_backup = rv3d->dist; + + /* check for flying ortho camera - which we cant support well + * we _could_ also check for an ortho camera but this is easier */ + if ((rv3d->persp == RV3D_CAMOB) && (rv3d->is_persp == false)) { + ((Camera *)v3d->camera->data)->type = CAM_PERSP; + vctrl->is_ortho_cam = true; + } + + if (rv3d->persp == RV3D_CAMOB) { + Object *ob_back; + if (use_parent_root && (vctrl->root_parent = v3d->camera->parent)) { + while (vctrl->root_parent->parent) { + vctrl->root_parent = vctrl->root_parent->parent; + } + ob_back = vctrl->root_parent; + } + else { + ob_back = v3d->camera; + } + + /* store the original camera loc and rot */ + vctrl->obtfm = BKE_object_tfm_backup(ob_back); + + BKE_object_where_is_calc(depsgraph, scene, v3d->camera); + negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); + + rv3d->dist = 0.0; + } + else { + /* perspective or ortho */ + if (rv3d->persp == RV3D_ORTHO) { + /* if ortho projection, make perspective */ + rv3d->persp = RV3D_PERSP; + } + + copy_qt_qt(vctrl->rot_backup, rv3d->viewquat); + copy_v3_v3(vctrl->ofs_backup, rv3d->ofs); + + /* the dist defines a vector that is infront of the offset + * to rotate the view about. + * this is no good for fly mode because we + * want to rotate about the viewers center. + * but to correct the dist removal we must + * alter offset so the view doesn't jump. */ + + ED_view3d_distance_set(rv3d, 0.0f); + /* Done with correcting for the dist */ + } + + ED_view3d_to_m4(vctrl->view_mat_prev, rv3d->ofs, rv3d->viewquat, rv3d->dist); + + return vctrl; } - /** * Updates cameras from the ``rv3d`` values, optionally auto-keyframing. */ -void ED_view3d_cameracontrol_update( - View3DCameraControl *vctrl, - /* args for keyframing */ - const bool use_autokey, - struct bContext *C, const bool do_rotate, const bool do_translate) +void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl, + /* args for keyframing */ + const bool use_autokey, + struct bContext *C, + const bool do_rotate, + const bool do_translate) { - /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera - * to the view */ + /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera + * to the view */ - Scene *scene = vctrl->ctx_scene; - View3D *v3d = vctrl->ctx_v3d; - RegionView3D *rv3d = vctrl->ctx_rv3d; + Scene *scene = vctrl->ctx_scene; + View3D *v3d = vctrl->ctx_v3d; + RegionView3D *rv3d = vctrl->ctx_rv3d; - ID *id_key; + ID *id_key; - /* transform the parent or the camera? */ - if (vctrl->root_parent) { - Object *ob_update; + /* transform the parent or the camera? */ + if (vctrl->root_parent) { + Object *ob_update; - float view_mat[4][4]; - float prev_view_imat[4][4]; - float diff_mat[4][4]; - float parent_mat[4][4]; + float view_mat[4][4]; + float prev_view_imat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; - invert_m4_m4(prev_view_imat, vctrl->view_mat_prev); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - mul_m4_m4m4(diff_mat, view_mat, prev_view_imat); - mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat); + invert_m4_m4(prev_view_imat, vctrl->view_mat_prev); + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + mul_m4_m4m4(diff_mat, view_mat, prev_view_imat); + mul_m4_m4m4(parent_mat, diff_mat, vctrl->root_parent->obmat); - BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false); + BKE_object_apply_mat4(vctrl->root_parent, parent_mat, true, false); - ob_update = v3d->camera->parent; - while (ob_update) { - DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM); - ob_update = ob_update->parent; - } + ob_update = v3d->camera->parent; + while (ob_update) { + DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM); + ob_update = ob_update->parent; + } - copy_m4_m4(vctrl->view_mat_prev, view_mat); + copy_m4_m4(vctrl->view_mat_prev, view_mat); - id_key = &vctrl->root_parent->id; - } - else { - float view_mat[4][4]; - float scale_mat[4][4]; - float scale_back[3]; + id_key = &vctrl->root_parent->id; + } + else { + float view_mat[4][4]; + float scale_mat[4][4]; + float scale_back[3]; - /* even though we handle the scale matrix, this still changes over time */ - copy_v3_v3(scale_back, v3d->camera->scale); + /* even though we handle the scale matrix, this still changes over time */ + copy_v3_v3(scale_back, v3d->camera->scale); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - size_to_mat4(scale_mat, v3d->camera->scale); - mul_m4_m4m4(view_mat, view_mat, scale_mat); + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + size_to_mat4(scale_mat, v3d->camera->scale); + mul_m4_m4m4(view_mat, view_mat, scale_mat); - BKE_object_apply_mat4(v3d->camera, view_mat, true, true); + BKE_object_apply_mat4(v3d->camera, view_mat, true, true); - DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); + DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); - copy_v3_v3(v3d->camera->scale, scale_back); + copy_v3_v3(v3d->camera->scale, scale_back); - id_key = &v3d->camera->id; - } + id_key = &v3d->camera->id; + } - /* record the motion */ - if (use_autokey) { - ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate); - } + /* record the motion */ + if (use_autokey) { + ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate); + } } - /** * Release view control. * * \param restore: Sets the view state to the values that were set * before #ED_view3d_control_acquire was called. */ -void ED_view3d_cameracontrol_release( - View3DCameraControl *vctrl, - const bool restore) +void ED_view3d_cameracontrol_release(View3DCameraControl *vctrl, const bool restore) { - View3D *v3d = vctrl->ctx_v3d; - RegionView3D *rv3d = vctrl->ctx_rv3d; - - if (restore) { - /* Revert to original view? */ - if (vctrl->persp_backup == RV3D_CAMOB) { /* a camera view */ - Object *ob_back = view3d_cameracontrol_object(vctrl); - - /* store the original camera loc and rot */ - BKE_object_tfm_restore(ob_back, vctrl->obtfm); - - DEG_id_tag_update(&ob_back->id, ID_RECALC_TRANSFORM); - } - else { - /* Non Camera we need to reset the view back - * to the original location because the user canceled. */ - copy_qt_qt(rv3d->viewquat, vctrl->rot_backup); - rv3d->persp = vctrl->persp_backup; - } - /* always, is set to zero otherwise */ - copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); - rv3d->dist = vctrl->dist_backup; - } - else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */ - DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), ID_RECALC_TRANSFORM); - - /* always, is set to zero otherwise */ - copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); - rv3d->dist = vctrl->dist_backup; - } - else { /* not camera */ - /* Apply the fly mode view */ - /* restore the dist */ - ED_view3d_distance_set(rv3d, vctrl->dist_backup); - /* Done with correcting for the dist */ - } - - if (vctrl->is_ortho_cam) { - ((Camera *)v3d->camera->data)->type = CAM_ORTHO; - } - - if (vctrl->obtfm) { - MEM_freeN(vctrl->obtfm); - } - - MEM_freeN(vctrl); + View3D *v3d = vctrl->ctx_v3d; + RegionView3D *rv3d = vctrl->ctx_rv3d; + + if (restore) { + /* Revert to original view? */ + if (vctrl->persp_backup == RV3D_CAMOB) { /* a camera view */ + Object *ob_back = view3d_cameracontrol_object(vctrl); + + /* store the original camera loc and rot */ + BKE_object_tfm_restore(ob_back, vctrl->obtfm); + + DEG_id_tag_update(&ob_back->id, ID_RECALC_TRANSFORM); + } + else { + /* Non Camera we need to reset the view back + * to the original location because the user canceled. */ + copy_qt_qt(rv3d->viewquat, vctrl->rot_backup); + rv3d->persp = vctrl->persp_backup; + } + /* always, is set to zero otherwise */ + copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); + rv3d->dist = vctrl->dist_backup; + } + else if (vctrl->persp_backup == RV3D_CAMOB) { /* camera */ + DEG_id_tag_update((ID *)view3d_cameracontrol_object(vctrl), ID_RECALC_TRANSFORM); + + /* always, is set to zero otherwise */ + copy_v3_v3(rv3d->ofs, vctrl->ofs_backup); + rv3d->dist = vctrl->dist_backup; + } + else { /* not camera */ + /* Apply the fly mode view */ + /* restore the dist */ + ED_view3d_distance_set(rv3d, vctrl->dist_backup); + /* Done with correcting for the dist */ + } + + if (vctrl->is_ortho_cam) { + ((Camera *)v3d->camera->data)->type = CAM_ORTHO; + } + + if (vctrl->obtfm) { + MEM_freeN(vctrl->obtfm); + } + + MEM_freeN(vctrl); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3399bda1cfa..4610111aafa 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -30,7 +30,6 @@ #include "BLI_threads.h" #include "BLI_jitter_2d.h" - #include "BKE_camera.h" #include "BKE_collection.h" #include "BKE_context.h" @@ -91,7 +90,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name General Functions @@ -100,125 +99,131 @@ /** * \note keep this synced with #ED_view3d_mats_rv3d_backup/#ED_view3d_mats_rv3d_restore */ -void ED_view3d_update_viewmat( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, - float viewmat[4][4], float winmat[4][4], const rcti *rect) +void ED_view3d_update_viewmat(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + ARegion *ar, + float viewmat[4][4], + float winmat[4][4], + const rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - - /* setup window matrices */ - if (winmat) { - copy_m4_m4(rv3d->winmat, winmat); - } - else { - view3d_winmatrix_set(depsgraph, ar, v3d, rect); - } - - /* setup view matrix */ - if (viewmat) { - copy_m4_m4(rv3d->viewmat, viewmat); - } - else { - float rect_scale[2]; - if (rect) { - rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx; - rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy; - } - /* note: calls BKE_object_where_is_calc for camera... */ - view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL); - } - /* update utility matrices */ - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(rv3d->persinv, rv3d->persmat); - invert_m4_m4(rv3d->viewinv, rv3d->viewmat); - - /* calculate GLSL view dependent values */ - - /* store window coordinates scaling/offset */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - rctf cameraborder; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false); - rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); - rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); - - rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; - rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; - } - else { - rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; - rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; - } - - /* calculate pixelsize factor once, is used for lights and obcenters */ - { - /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' - * because of float point precision problems at large values [#23908] */ - float v1[3], v2[3]; - float len_px, len_sc; - - v1[0] = rv3d->persmat[0][0]; - v1[1] = rv3d->persmat[1][0]; - v1[2] = rv3d->persmat[2][0]; - - v2[0] = rv3d->persmat[0][1]; - v2[1] = rv3d->persmat[1][1]; - v2[2] = rv3d->persmat[2][1]; - - len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); - len_sc = (float)MAX2(ar->winx, ar->winy); - - rv3d->pixsize = len_px / len_sc; - } + RegionView3D *rv3d = ar->regiondata; + + /* setup window matrices */ + if (winmat) { + copy_m4_m4(rv3d->winmat, winmat); + } + else { + view3d_winmatrix_set(depsgraph, ar, v3d, rect); + } + + /* setup view matrix */ + if (viewmat) { + copy_m4_m4(rv3d->viewmat, viewmat); + } + else { + float rect_scale[2]; + if (rect) { + rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx; + rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy; + } + /* note: calls BKE_object_where_is_calc for camera... */ + view3d_viewmatrix_set(depsgraph, scene, v3d, rv3d, rect ? rect_scale : NULL); + } + /* update utility matrices */ + mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + invert_m4_m4(rv3d->persinv, rv3d->persmat); + invert_m4_m4(rv3d->viewinv, rv3d->viewmat); + + /* calculate GLSL view dependent values */ + + /* store window coordinates scaling/offset */ + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + rctf cameraborder; + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false); + rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder); + rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder); + + rv3d->viewcamtexcofac[2] = -rv3d->viewcamtexcofac[0] * cameraborder.xmin / (float)ar->winx; + rv3d->viewcamtexcofac[3] = -rv3d->viewcamtexcofac[1] * cameraborder.ymin / (float)ar->winy; + } + else { + rv3d->viewcamtexcofac[0] = rv3d->viewcamtexcofac[1] = 1.0f; + rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; + } + + /* calculate pixelsize factor once, is used for lights and obcenters */ + { + /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' + * because of float point precision problems at large values [#23908] */ + float v1[3], v2[3]; + float len_px, len_sc; + + v1[0] = rv3d->persmat[0][0]; + v1[1] = rv3d->persmat[1][0]; + v1[2] = rv3d->persmat[2][0]; + + v2[0] = rv3d->persmat[0][1]; + v2[1] = rv3d->persmat[1][1]; + v2[2] = rv3d->persmat[2][1]; + + len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2))); + len_sc = (float)MAX2(ar->winx, ar->winy); + + rv3d->pixsize = len_px / len_sc; + } } -static void view3d_main_region_setup_view( - Depsgraph *depsgraph, Scene *scene, - View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4], const rcti *rect) +static void view3d_main_region_setup_view(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + ARegion *ar, + float viewmat[4][4], + float winmat[4][4], + const rcti *rect) { - RegionView3D *rv3d = ar->regiondata; + RegionView3D *rv3d = ar->regiondata; - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect); - /* set for opengl */ - GPU_matrix_projection_set(rv3d->winmat); - GPU_matrix_set(rv3d->viewmat); + /* set for opengl */ + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); } static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, RegionView3D *rv3d) { - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - return false; - } - - if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { - return false; - } - - switch (v3d->stereo3d_camera) { - case STEREO_MONO_ID: - return false; - break; - case STEREO_3D_ID: - /* win will be NULL when calling this from the selection or draw loop. */ - if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { - return false; - } - if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && - !BKE_scene_multiview_is_stereo3d(&scene->r)) - { - return false; - } - break; - /* We always need the stereo calculation for left and right cameras. */ - case STEREO_LEFT_ID: - case STEREO_RIGHT_ID: - default: - break; - } - return true; + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + return false; + } + + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) { + return false; + } + + switch (v3d->stereo3d_camera) { + case STEREO_MONO_ID: + return false; + break; + case STEREO_3D_ID: + /* win will be NULL when calling this from the selection or draw loop. */ + if ((win == NULL) || (WM_stereo3d_enabled(win, true) == false)) { + return false; + } + if (((scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) != 0) && + !BKE_scene_multiview_is_stereo3d(&scene->r)) { + return false; + } + break; + /* We always need the stereo calculation for left and right cameras. */ + case STEREO_LEFT_ID: + case STEREO_RIGHT_ID: + default: + break; + } + return true; } - /* setup the view and win matrices for the multiview cameras * * unlike view3d_stereo3d_setup_offscreen, when view3d_stereo3d_setup is called @@ -228,72 +233,77 @@ static bool view3d_stereo3d_active(wmWindow *win, Scene *scene, View3D *v3d, Reg * view3d)main_region_setup_view() code to account for that. */ static void view3d_stereo3d_setup( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) + Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, const rcti *rect) { - bool is_left; - const char *names[2] = { STEREO_LEFT_NAME, STEREO_RIGHT_NAME }; - const char *viewname; + bool is_left; + const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + const char *viewname; - /* show only left or right camera */ - if (v3d->stereo3d_camera != STEREO_3D_ID) { - v3d->multiview_eye = v3d->stereo3d_camera; - } + /* show only left or right camera */ + if (v3d->stereo3d_camera != STEREO_3D_ID) { + v3d->multiview_eye = v3d->stereo3d_camera; + } - is_left = v3d->multiview_eye == STEREO_LEFT_ID; - viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; + is_left = v3d->multiview_eye == STEREO_LEFT_ID; + viewname = names[is_left ? STEREO_LEFT_ID : STEREO_RIGHT_ID]; - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - Camera *data, *data_eval; - float viewmat[4][4]; - float shiftx; + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + Camera *data, *data_eval; + float viewmat[4][4]; + float shiftx; - data = (Camera *)v3d->camera->data; - data_eval = (Camera *)DEG_get_evaluated_id(depsgraph, &data->id); + data = (Camera *)v3d->camera->data; + data_eval = (Camera *)DEG_get_evaluated_id(depsgraph, &data->id); - shiftx = data_eval->shiftx; + shiftx = data_eval->shiftx; - BLI_thread_lock(LOCK_VIEW3D); - data_eval->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); + BLI_thread_lock(LOCK_VIEW3D); + data_eval->shiftx = BKE_camera_multiview_shift_x(&scene->r, v3d->camera, viewname); - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect); + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect); - data_eval->shiftx = shiftx; - BLI_thread_unlock(LOCK_VIEW3D); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *view_ob = v3d->camera; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + data_eval->shiftx = shiftx; + BLI_thread_unlock(LOCK_VIEW3D); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *view_ob = v3d->camera; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - BLI_thread_lock(LOCK_VIEW3D); - v3d->camera = camera; + BLI_thread_lock(LOCK_VIEW3D); + v3d->camera = camera; - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect); + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, NULL, rect); - v3d->camera = view_ob; - BLI_thread_unlock(LOCK_VIEW3D); - } + v3d->camera = view_ob; + BLI_thread_unlock(LOCK_VIEW3D); + } } /** * Set the correct matrices */ -void ED_view3d_draw_setup_view( - wmWindow *win, Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, - float viewmat[4][4], float winmat[4][4], const rcti *rect) +void ED_view3d_draw_setup_view(wmWindow *win, + Depsgraph *depsgraph, + Scene *scene, + ARegion *ar, + View3D *v3d, + float viewmat[4][4], + float winmat[4][4], + const rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - - /* Setup the view matrix. */ - if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { - view3d_stereo3d_setup(depsgraph, scene, v3d, ar, rect); - } - else { - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, rect); - } + RegionView3D *rv3d = ar->regiondata; + + /* Setup the view matrix. */ + if (view3d_stereo3d_active(win, scene, v3d, rv3d)) { + view3d_stereo3d_setup(depsgraph, scene, v3d, ar, rect); + } + else { + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, rect); + } } /** \} */ @@ -302,471 +312,493 @@ void ED_view3d_draw_setup_view( /** \name Draw View Border * \{ */ -static void view3d_camera_border( - const Scene *scene, struct Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift, const bool no_zoom) +static void view3d_camera_border(const Scene *scene, + struct Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const RegionView3D *rv3d, + rctf *r_viewborder, + const bool no_shift, + const bool no_zoom) { - CameraParams params; - rctf rect_view, rect_camera; - Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - - /* get viewport viewplane */ - BKE_camera_params_init(¶ms); - BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); - if (no_zoom) { - params.zoom = 1.0f; - } - BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); - rect_view = params.viewplane; - - /* get camera viewplane */ - BKE_camera_params_init(¶ms); - /* fallback for non camera objects */ - params.clip_start = v3d->clip_start; - params.clip_end = v3d->clip_end; - BKE_camera_params_from_object(¶ms, camera_eval); - if (no_shift) { - params.shiftx = 0.0f; - params.shifty = 0.0f; - } - BKE_camera_params_compute_viewplane(¶ms, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); - rect_camera = params.viewplane; - - /* get camera border within viewport */ - r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; - r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; + CameraParams params; + rctf rect_view, rect_camera; + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + + /* get viewport viewplane */ + BKE_camera_params_init(¶ms); + BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); + if (no_zoom) { + params.zoom = 1.0f; + } + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + rect_view = params.viewplane; + + /* get camera viewplane */ + BKE_camera_params_init(¶ms); + /* fallback for non camera objects */ + params.clip_start = v3d->clip_start; + params.clip_end = v3d->clip_end; + BKE_camera_params_from_object(¶ms, camera_eval); + if (no_shift) { + params.shiftx = 0.0f; + params.shifty = 0.0f; + } + BKE_camera_params_compute_viewplane( + ¶ms, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); + rect_camera = params.viewplane; + + /* get camera border within viewport */ + r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * + ar->winx; + r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * + ar->winx; + r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * + ar->winy; + r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * + ar->winy; } -void ED_view3d_calc_camera_border_size( - const Scene *scene, Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, - float r_size[2]) +void ED_view3d_calc_camera_border_size(const Scene *scene, + Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const RegionView3D *rv3d, + float r_size[2]) { - rctf viewborder; + rctf viewborder; - view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true); - r_size[0] = BLI_rctf_size_x(&viewborder); - r_size[1] = BLI_rctf_size_y(&viewborder); + view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true); + r_size[0] = BLI_rctf_size_x(&viewborder); + r_size[1] = BLI_rctf_size_y(&viewborder); } -void ED_view3d_calc_camera_border( - const Scene *scene, Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d, - rctf *r_viewborder, const bool no_shift) +void ED_view3d_calc_camera_border(const Scene *scene, + Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const RegionView3D *rv3d, + rctf *r_viewborder, + const bool no_shift) { - view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, r_viewborder, no_shift, false); + view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, r_viewborder, no_shift, false); } static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac) { - float x3, y3, x4, y4; + float x3, y3, x4, y4; - x3 = x1 + fac * (x2 - x1); - y3 = y1 + fac * (y2 - y1); - x4 = x1 + (1.0f - fac) * (x2 - x1); - y4 = y1 + (1.0f - fac) * (y2 - y1); + x3 = x1 + fac * (x2 - x1); + y3 = y1 + fac * (y2 - y1); + x4 = x1 + (1.0f - fac) * (x2 - x1); + y4 = y1 + (1.0f - fac) * (y2 - y1); - immBegin(GPU_PRIM_LINES, 8); + immBegin(GPU_PRIM_LINES, 8); - immVertex2f(shdr_pos, x1, y3); - immVertex2f(shdr_pos, x2, y3); + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); - immVertex2f(shdr_pos, x1, y4); - immVertex2f(shdr_pos, x2, y4); + immVertex2f(shdr_pos, x1, y4); + immVertex2f(shdr_pos, x2, y4); - immVertex2f(shdr_pos, x3, y1); - immVertex2f(shdr_pos, x3, y2); + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); - immVertex2f(shdr_pos, x4, y1); - immVertex2f(shdr_pos, x4, y2); + immVertex2f(shdr_pos, x4, y1); + immVertex2f(shdr_pos, x4, y2); - immEnd(); + immEnd(); } /* harmonious triangle */ static void drawviewborder_triangle( - uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir) + uint shdr_pos, float x1, float x2, float y1, float y2, const char golden, const char dir) { - float ofs; - float w = x2 - x1; - float h = y2 - y1; - - immBegin(GPU_PRIM_LINES, 6); - - if (w > h) { - if (golden) { - ofs = w * (1.0f - (1.0f / 1.61803399f)); - } - else { - ofs = h * (h / w); - } - if (dir == 'B') { - SWAP(float, y1, y2); - } - - immVertex2f(shdr_pos, x1, y1); - immVertex2f(shdr_pos, x2, y2); - - immVertex2f(shdr_pos, x2, y1); - immVertex2f(shdr_pos, x1 + (w - ofs), y2); - - immVertex2f(shdr_pos, x1, y2); - immVertex2f(shdr_pos, x1 + ofs, y1); - } - else { - if (golden) { - ofs = h * (1.0f - (1.0f / 1.61803399f)); - } - else { - ofs = w * (w / h); - } - if (dir == 'B') { - SWAP(float, x1, x2); - } - - immVertex2f(shdr_pos, x1, y1); - immVertex2f(shdr_pos, x2, y2); - - immVertex2f(shdr_pos, x2, y1); - immVertex2f(shdr_pos, x1, y1 + ofs); - - immVertex2f(shdr_pos, x1, y2); - immVertex2f(shdr_pos, x2, y1 + (h - ofs)); - } - - immEnd(); + float ofs; + float w = x2 - x1; + float h = y2 - y1; + + immBegin(GPU_PRIM_LINES, 6); + + if (w > h) { + if (golden) { + ofs = w * (1.0f - (1.0f / 1.61803399f)); + } + else { + ofs = h * (h / w); + } + if (dir == 'B') { + SWAP(float, y1, y2); + } + + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); + + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1 + (w - ofs), y2); + + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x1 + ofs, y1); + } + else { + if (golden) { + ofs = h * (1.0f - (1.0f / 1.61803399f)); + } + else { + ofs = w * (w / h); + } + if (dir == 'B') { + SWAP(float, x1, x2); + } + + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); + + immVertex2f(shdr_pos, x2, y1); + immVertex2f(shdr_pos, x1, y1 + ofs); + + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1 + (h - ofs)); + } + + immEnd(); } static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d) { - float x1, x2, y1, y2; - float x1i, x2i, y1i, y2i; - - rctf viewborder; - Camera *ca = NULL; - RegionView3D *rv3d = ar->regiondata; - - if (v3d->camera == NULL) { - return; - } - if (v3d->camera->type == OB_CAMERA) { - ca = v3d->camera->data; - } - - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); - /* the offsets */ - x1 = viewborder.xmin; - y1 = viewborder.ymin; - x2 = viewborder.xmax; - y2 = viewborder.ymax; - - GPU_line_width(1.0f); - - /* apply offsets so the real 3D camera shows through */ - - /* note: quite un-scientific but without this bit extra - * 0.0001 on the lower left the 2D border sometimes - * obscures the 3D camera border */ - /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable - * but keep it here in case we need to remove the workaround */ - x1i = (int)(x1 - 1.0001f); - y1i = (int)(y1 - 1.0001f); - x2i = (int)(x2 + (1.0f - 0.0001f)); - y2i = (int)(y2 + (1.0f - 0.0001f)); - - uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - /* First, solid lines. */ - { - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - /* passepartout, specified in camera edit buttons */ - if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { - const float winx = (ar->winx + 1); - const float winy = (ar->winy + 1); - - float alpha = 1.0f; - - if (ca->passepartalpha != 1.0f) { - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - alpha = ca->passepartalpha; - } - - immUniformColor4f(0.0f, 0.0f, 0.0f, alpha); - - if (x1i > 0.0f) { - immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f); - } - if (x2i < winx) { - immRectf(shdr_pos, x2i, winy, winx, 0.0f); - } - if (y2i < winy) { - immRectf(shdr_pos, x1i, winy, x2i, y2i); - } - if (y2i > 0.0f) { - immRectf(shdr_pos, x1i, y1i, x2i, 0.0f); - } - - GPU_blend(false); - } - - immUniformThemeColor(TH_BACK); - imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); + float x1, x2, y1, y2; + float x1i, x2i, y1i, y2i; + + rctf viewborder; + Camera *ca = NULL; + RegionView3D *rv3d = ar->regiondata; + + if (v3d->camera == NULL) { + return; + } + if (v3d->camera->type == OB_CAMERA) { + ca = v3d->camera->data; + } + + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); + /* the offsets */ + x1 = viewborder.xmin; + y1 = viewborder.ymin; + x2 = viewborder.xmax; + y2 = viewborder.ymax; + + GPU_line_width(1.0f); + + /* apply offsets so the real 3D camera shows through */ + + /* note: quite un-scientific but without this bit extra + * 0.0001 on the lower left the 2D border sometimes + * obscures the 3D camera border */ + /* note: with VIEW3D_CAMERA_BORDER_HACK defined this error isn't noticeable + * but keep it here in case we need to remove the workaround */ + x1i = (int)(x1 - 1.0001f); + y1i = (int)(y1 - 1.0001f); + x2i = (int)(x2 + (1.0f - 0.0001f)); + y2i = (int)(y2 + (1.0f - 0.0001f)); + + uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + /* First, solid lines. */ + { + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + + /* passepartout, specified in camera edit buttons */ + if (ca && (ca->flag & CAM_SHOWPASSEPARTOUT) && ca->passepartalpha > 0.000001f) { + const float winx = (ar->winx + 1); + const float winy = (ar->winy + 1); + + float alpha = 1.0f; + + if (ca->passepartalpha != 1.0f) { + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + alpha = ca->passepartalpha; + } + + immUniformColor4f(0.0f, 0.0f, 0.0f, alpha); + + if (x1i > 0.0f) { + immRectf(shdr_pos, 0.0f, winy, x1i, 0.0f); + } + if (x2i < winx) { + immRectf(shdr_pos, x2i, winy, winx, 0.0f); + } + if (y2i < winy) { + immRectf(shdr_pos, x1i, winy, x2i, y2i); + } + if (y2i > 0.0f) { + immRectf(shdr_pos, x1i, y1i, x2i, 0.0f); + } + + GPU_blend(false); + } + + immUniformThemeColor(TH_BACK); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); #ifdef VIEW3D_CAMERA_BORDER_HACK - if (view3d_camera_border_hack_test == true) { - immUniformColor3ubv(view3d_camera_border_hack_col); - imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1); - view3d_camera_border_hack_test = false; - } + if (view3d_camera_border_hack_test == true) { + immUniformColor3ubv(view3d_camera_border_hack_col); + imm_draw_box_wire_2d(shdr_pos, x1i + 1, y1i + 1, x2i - 1, y2i - 1); + view3d_camera_border_hack_test = false; + } #endif - immUnbindProgram(); - } + immUnbindProgram(); + } - /* When overlays are disabled, only show camera outline & passepartout. */ - if (v3d->flag2 & V3D_HIDE_OVERLAYS) { - return; - } + /* When overlays are disabled, only show camera outline & passepartout. */ + if (v3d->flag2 & V3D_HIDE_OVERLAYS) { + return; + } - /* And now, the dashed lines! */ - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + /* And now, the dashed lines! */ + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - { - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + { + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniform1f("dash_width", 6.0f); - immUniform1f("dash_factor", 0.5f); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - /* outer line not to confuse with object selection */ - if (v3d->flag2 & V3D_LOCK_CAMERA) { - immUniformThemeColor(TH_REDALERT); - imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1); - } + /* outer line not to confuse with object selection */ + if (v3d->flag2 & V3D_LOCK_CAMERA) { + immUniformThemeColor(TH_REDALERT); + imm_draw_box_wire_2d(shdr_pos, x1i - 1, y1i - 1, x2i + 1, y2i + 1); + } - immUniformThemeColor(TH_VIEW_OVERLAY); - imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); - } + immUniformThemeColor(TH_VIEW_OVERLAY); + imm_draw_box_wire_2d(shdr_pos, x1i, y1i, x2i, y2i); + } - /* Render Border. */ - if (scene->r.mode & R_BORDER) { - float x3, y3, x4, y4; + /* Render Border. */ + if (scene->r.mode & R_BORDER) { + float x3, y3, x4, y4; - x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1; - y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1; - x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1); - y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1); - - immUniformColor3f(1.0f, 0.25f, 0.25f); - imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4); - } - - /* safety border */ - if (ca) { - immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); - - if (ca->dtx & CAM_DTX_CENTER) { - float x3, y3; - - x3 = x1 + 0.5f * (x2 - x1); - y3 = y1 + 0.5f * (y2 - y1); - - immBegin(GPU_PRIM_LINES, 4); - - immVertex2f(shdr_pos, x1, y3); - immVertex2f(shdr_pos, x2, y3); - - immVertex2f(shdr_pos, x3, y1); - immVertex2f(shdr_pos, x3, y2); - - immEnd(); - } - - if (ca->dtx & CAM_DTX_CENTER_DIAG) { - immBegin(GPU_PRIM_LINES, 4); - - immVertex2f(shdr_pos, x1, y1); - immVertex2f(shdr_pos, x2, y2); - - immVertex2f(shdr_pos, x1, y2); - immVertex2f(shdr_pos, x2, y1); - - immEnd(); - } - - if (ca->dtx & CAM_DTX_THIRDS) { - drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f); - } - - if (ca->dtx & CAM_DTX_GOLDEN) { - drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); - } - - if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { - drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A'); - } - - if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { - drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B'); - } - - if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { - drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A'); - } - - if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { - drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B'); - } - - if (ca->flag & CAM_SHOW_SAFE_MARGINS) { - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, - scene->safe_areas.title, scene->safe_areas.action); - - if (ca->flag & CAM_SHOW_SAFE_CENTER) { - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, - scene->safe_areas.title_center, scene->safe_areas.action_center); - } - } - - if (ca->flag & CAM_SHOWSENSOR) { - /* determine sensor fit, and get sensor x/y, for auto fit we - * assume and square sensor and only use sensor_x */ - float sizex = scene->r.xsch * scene->r.xasp; - float sizey = scene->r.ysch * scene->r.yasp; - int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey); - float sensor_x = ca->sensor_x; - float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y; - - /* determine sensor plane */ - rctf rect; - - if (sensor_fit == CAMERA_SENSOR_FIT_HOR) { - float sensor_scale = (x2i - x1i) / sensor_x; - float sensor_height = sensor_scale * sensor_y; - - rect.xmin = x1i; - rect.xmax = x2i; - rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f; - rect.ymax = rect.ymin + sensor_height; - } - else { - float sensor_scale = (y2i - y1i) / sensor_y; - float sensor_width = sensor_scale * sensor_x; - - rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f; - rect.xmax = rect.xmin + sensor_width; - rect.ymin = y1i; - rect.ymax = y2i; - } - - /* draw */ - immUniformThemeColorShade(TH_VIEW_OVERLAY, 100); - - /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color). - * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the - * 2.0f round corner effect was nearly not visible anyway... */ - imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - } - } - - immUnbindProgram(); - /* end dashed lines */ - - /* camera name - draw in highlighted text color */ - if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) { - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - BLF_draw_default( - x1i, y1i - (0.7f * U.widget_unit), 0.0f, - v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2); - } + x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1; + y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1; + x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1); + y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1); + + immUniformColor3f(1.0f, 0.25f, 0.25f); + imm_draw_box_wire_2d(shdr_pos, x3, y3, x4, y4); + } + + /* safety border */ + if (ca) { + immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); + + if (ca->dtx & CAM_DTX_CENTER) { + float x3, y3; + + x3 = x1 + 0.5f * (x2 - x1); + y3 = y1 + 0.5f * (y2 - y1); + + immBegin(GPU_PRIM_LINES, 4); + + immVertex2f(shdr_pos, x1, y3); + immVertex2f(shdr_pos, x2, y3); + + immVertex2f(shdr_pos, x3, y1); + immVertex2f(shdr_pos, x3, y2); + + immEnd(); + } + + if (ca->dtx & CAM_DTX_CENTER_DIAG) { + immBegin(GPU_PRIM_LINES, 4); + + immVertex2f(shdr_pos, x1, y1); + immVertex2f(shdr_pos, x2, y2); + + immVertex2f(shdr_pos, x1, y2); + immVertex2f(shdr_pos, x2, y1); + + immEnd(); + } + + if (ca->dtx & CAM_DTX_THIRDS) { + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f / 3.0f); + } + + if (ca->dtx & CAM_DTX_GOLDEN) { + drawviewborder_grid3(shdr_pos, x1, x2, y1, y2, 1.0f - (1.0f / 1.61803399f)); + } + + if (ca->dtx & CAM_DTX_GOLDEN_TRI_A) { + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'A'); + } + + if (ca->dtx & CAM_DTX_GOLDEN_TRI_B) { + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 0, 'B'); + } + + if (ca->dtx & CAM_DTX_HARMONY_TRI_A) { + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'A'); + } + + if (ca->dtx & CAM_DTX_HARMONY_TRI_B) { + drawviewborder_triangle(shdr_pos, x1, x2, y1, y2, 1, 'B'); + } + + if (ca->flag & CAM_SHOW_SAFE_MARGINS) { + UI_draw_safe_areas( + shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); + + if (ca->flag & CAM_SHOW_SAFE_CENTER) { + UI_draw_safe_areas(shdr_pos, + x1, + x2, + y1, + y2, + scene->safe_areas.title_center, + scene->safe_areas.action_center); + } + } + + if (ca->flag & CAM_SHOWSENSOR) { + /* determine sensor fit, and get sensor x/y, for auto fit we + * assume and square sensor and only use sensor_x */ + float sizex = scene->r.xsch * scene->r.xasp; + float sizey = scene->r.ysch * scene->r.yasp; + int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, sizex, sizey); + float sensor_x = ca->sensor_x; + float sensor_y = (ca->sensor_fit == CAMERA_SENSOR_FIT_AUTO) ? ca->sensor_x : ca->sensor_y; + + /* determine sensor plane */ + rctf rect; + + if (sensor_fit == CAMERA_SENSOR_FIT_HOR) { + float sensor_scale = (x2i - x1i) / sensor_x; + float sensor_height = sensor_scale * sensor_y; + + rect.xmin = x1i; + rect.xmax = x2i; + rect.ymin = (y1i + y2i) * 0.5f - sensor_height * 0.5f; + rect.ymax = rect.ymin + sensor_height; + } + else { + float sensor_scale = (y2i - y1i) / sensor_y; + float sensor_width = sensor_scale * sensor_x; + + rect.xmin = (x1i + x2i) * 0.5f - sensor_width * 0.5f; + rect.xmax = rect.xmin + sensor_width; + rect.ymin = y1i; + rect.ymax = y2i; + } + + /* draw */ + immUniformThemeColorShade(TH_VIEW_OVERLAY, 100); + + /* TODO Was using UI_draw_roundbox_4fv(false, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 2.0f, color). + * We'll probably need a new imm_draw_line_roundbox_dashed dor that - though in practice the + * 2.0f round corner effect was nearly not visible anyway... */ + imm_draw_box_wire_2d(shdr_pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + } + } + + immUnbindProgram(); + /* end dashed lines */ + + /* camera name - draw in highlighted text color */ + if (ca && ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) && (ca->flag & CAM_SHOWNAME)) { + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + BLF_draw_default(x1i, + y1i - (0.7f * U.widget_unit), + 0.0f, + v3d->camera->id.name + 2, + sizeof(v3d->camera->id.name) - 2); + } } static void drawrenderborder(ARegion *ar, View3D *v3d) { - /* use the same program for everything */ - uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + /* use the same program for everything */ + uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - GPU_line_width(1.0f); + GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f); - immUniform1f("dash_width", 6.0f); - immUniform1f("dash_factor", 0.5f); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniform4f("color", 1.0f, 0.25f, 0.25f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - imm_draw_box_wire_2d(shdr_pos, - v3d->render_border.xmin * ar->winx, v3d->render_border.ymin * ar->winy, - v3d->render_border.xmax * ar->winx, v3d->render_border.ymax * ar->winy); + imm_draw_box_wire_2d(shdr_pos, + v3d->render_border.xmin * ar->winx, + v3d->render_border.ymin * ar->winy, + v3d->render_border.xmax * ar->winx, + v3d->render_border.ymax * ar->winy); - immUnbindProgram(); + immUnbindProgram(); } -void ED_view3d_draw_depth( - Depsgraph *depsgraph, - ARegion *ar, View3D *v3d, bool alphaoverride) +void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool alphaoverride) { - struct bThemeState theme_state; - Scene *scene = DEG_get_evaluated_scene(depsgraph); - RegionView3D *rv3d = ar->regiondata; + struct bThemeState theme_state; + Scene *scene = DEG_get_evaluated_scene(depsgraph); + RegionView3D *rv3d = ar->regiondata; - short flag = v3d->flag; - float glalphaclip = U.glalphaclip; - int obcenter_dia = U.obcenter_dia; - /* temp set drawtype to solid */ - /* Setting these temporarily is not nice */ - v3d->flag &= ~V3D_SELECT_OUTLINE; + short flag = v3d->flag; + float glalphaclip = U.glalphaclip; + int obcenter_dia = U.obcenter_dia; + /* temp set drawtype to solid */ + /* Setting these temporarily is not nice */ + v3d->flag &= ~V3D_SELECT_OUTLINE; - /* not that nice but means we wont zoom into billboards */ - U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; + /* not that nice but means we wont zoom into billboards */ + U.glalphaclip = alphaoverride ? 0.5f : glalphaclip; - U.obcenter_dia = 0; + U.obcenter_dia = 0; - /* Tools may request depth outside of regular drawing code. */ - UI_Theme_Store(&theme_state); - UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); - ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); + ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); - GPU_clear(GPU_DEPTH_BIT); + GPU_clear(GPU_DEPTH_BIT); - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } - /* get surface depth without bias */ - rv3d->rflag |= RV3D_ZOFFSET_DISABLED; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } + /* get surface depth without bias */ + rv3d->rflag |= RV3D_ZOFFSET_DISABLED; - GPU_depth_test(true); + GPU_depth_test(true); - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_loop(depsgraph, ar, v3d, viewport); + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_loop(depsgraph, ar, v3d, viewport); - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } - rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } + rv3d->rflag &= ~RV3D_ZOFFSET_DISABLED; - /* Reset default for UI */ - GPU_depth_test(false); + /* Reset default for UI */ + GPU_depth_test(false); - U.glalphaclip = glalphaclip; - v3d->flag = flag; - U.obcenter_dia = obcenter_dia; + U.glalphaclip = glalphaclip; + v3d->flag = flag; + U.obcenter_dia = obcenter_dia; - UI_Theme_Restore(&theme_state); + UI_Theme_Restore(&theme_state); } /* ******************** other elements ***************** */ @@ -774,241 +806,244 @@ void ED_view3d_draw_depth( /** could move this elsewhere, but tied into #ED_view3d_grid_scale */ float ED_scene_grid_scale(Scene *scene, const char **grid_unit) { - /* apply units */ - if (scene->unit.system) { - const void *usys; - int len; - - bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); - - if (usys) { - int i = bUnit_GetBaseUnit(usys); - if (grid_unit) { - *grid_unit = bUnit_GetNameDisplay(usys, i); - } - return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; - } - } - - return 1.0f; + /* apply units */ + if (scene->unit.system) { + const void *usys; + int len; + + bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); + + if (usys) { + int i = bUnit_GetBaseUnit(usys); + if (grid_unit) { + *grid_unit = bUnit_GetNameDisplay(usys, i); + } + return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; + } + } + + return 1.0f; } float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) { - return v3d->grid * ED_scene_grid_scale(scene, grid_unit); + return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } /* Simulates the grid scale that is actually viewed. * The actual code is seen in `object_grid_frag.glsl` (see `grid_res`). * Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */ -float ED_view3d_grid_view_scale( - Scene *scene, View3D *v3d, RegionView3D *rv3d, const char **grid_unit) +float ED_view3d_grid_view_scale(Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + const char **grid_unit) { - float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); - if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { - /* Decrease the distance between grid snap points depending on zoom. */ - float grid_subdiv = v3d->gridsubdiv; - if (grid_subdiv > 1) { - /* Allow 3 more subdivisions (see OBJECT_engine_init). */ - grid_scale /= powf(grid_subdiv, 3); - - /* `3.0` was a value obtained by trial and error in order to get - * a nice snap distance.*/ - float grid_res = 3.0 * (rv3d->dist / v3d->lens); - float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv)); - - CLAMP_MIN(lvl, 0.0f); - - grid_scale *= pow(grid_subdiv, (int)lvl); - } - } - - return grid_scale; + float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { + /* Decrease the distance between grid snap points depending on zoom. */ + float grid_subdiv = v3d->gridsubdiv; + if (grid_subdiv > 1) { + /* Allow 3 more subdivisions (see OBJECT_engine_init). */ + grid_scale /= powf(grid_subdiv, 3); + + /* `3.0` was a value obtained by trial and error in order to get + * a nice snap distance.*/ + float grid_res = 3.0 * (rv3d->dist / v3d->lens); + float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv)); + + CLAMP_MIN(lvl, 0.0f); + + grid_scale *= pow(grid_subdiv, (int)lvl); + } + } + + return grid_scale; } static void draw_view_axis(RegionView3D *rv3d, const rcti *rect) { - const float k = U.rvisize * U.pixelsize; /* axis size */ - /* axis alpha offset (rvibright has range 0-10) */ - const int bright = - 20 * (10 - U.rvibright); - - /* Axis center in screen coordinates. - * - * - Unit size offset so small text doesn't draw outside the screen - * - Extra X offset because of the panel expander. - */ - const float startx = rect->xmax - (k + UI_UNIT_X * 1.5); - const float starty = rect->ymax - (k + UI_UNIT_Y); - - float axis_pos[3][2]; - uchar axis_col[3][4]; - - int axis_order[3] = {0, 1, 2}; - axis_sort_v3(rv3d->viewinv[2], axis_order); - - for (int axis_i = 0; axis_i < 3; axis_i++) { - int i = axis_order[axis_i]; - - /* get position of each axis tip on screen */ - float vec[3] = { 0.0f }; - vec[i] = 1.0f; - mul_qt_v3(rv3d->viewquat, vec); - axis_pos[i][0] = startx + vec[0] * k; - axis_pos[i][1] = starty + vec[1] * k; - - /* get color of each axis */ - UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */ - axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */ - } - - /* draw axis lines */ - GPU_line_width(2.0f); - GPU_line_smooth(true); - GPU_blend(true); - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(GPU_PRIM_LINES, 6); - - for (int axis_i = 0; axis_i < 3; axis_i++) { - int i = axis_order[axis_i]; - - immAttr4ubv(col, axis_col[i]); - immVertex2f(pos, startx, starty); - immAttr4ubv(col, axis_col[i]); - immVertex2fv(pos, axis_pos[i]); - } - - immEnd(); - immUnbindProgram(); - GPU_line_smooth(false); - - /* draw axis names */ - for (int axis_i = 0; axis_i < 3; axis_i++) { - int i = axis_order[axis_i]; - - const char axis_text[2] = {'x' + i, '\0'}; - BLF_color4ubv(BLF_default(), axis_col[i]); - BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1); - } + const float k = U.rvisize * U.pixelsize; /* axis size */ + /* axis alpha offset (rvibright has range 0-10) */ + const int bright = -20 * (10 - U.rvibright); + + /* Axis center in screen coordinates. + * + * - Unit size offset so small text doesn't draw outside the screen + * - Extra X offset because of the panel expander. + */ + const float startx = rect->xmax - (k + UI_UNIT_X * 1.5); + const float starty = rect->ymax - (k + UI_UNIT_Y); + + float axis_pos[3][2]; + uchar axis_col[3][4]; + + int axis_order[3] = {0, 1, 2}; + axis_sort_v3(rv3d->viewinv[2], axis_order); + + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; + + /* get position of each axis tip on screen */ + float vec[3] = {0.0f}; + vec[i] = 1.0f; + mul_qt_v3(rv3d->viewquat, vec); + axis_pos[i][0] = startx + vec[0] * k; + axis_pos[i][1] = starty + vec[1] * k; + + /* get color of each axis */ + UI_GetThemeColorShade3ubv(TH_AXIS_X + i, bright, axis_col[i]); /* rgb */ + axis_col[i][3] = 255 * hypotf(vec[0], vec[1]); /* alpha */ + } + + /* draw axis lines */ + GPU_line_width(2.0f); + GPU_line_smooth(true); + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + immBegin(GPU_PRIM_LINES, 6); + + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; + + immAttr4ubv(col, axis_col[i]); + immVertex2f(pos, startx, starty); + immAttr4ubv(col, axis_col[i]); + immVertex2fv(pos, axis_pos[i]); + } + + immEnd(); + immUnbindProgram(); + GPU_line_smooth(false); + + /* draw axis names */ + for (int axis_i = 0; axis_i < 3; axis_i++) { + int i = axis_order[axis_i]; + + const char axis_text[2] = {'x' + i, '\0'}; + BLF_color4ubv(BLF_default(), axis_col[i]); + BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1); + } } #ifdef WITH_INPUT_NDOF /* draw center and axis of rotation for ongoing 3D mouse navigation */ static void draw_rotation_guide(const RegionView3D *rv3d) { - float o[3]; /* center of rotation */ - float end[3]; /* endpoints for drawing */ - - GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ - - negate_v3_v3(o, rv3d->ofs); - - GPU_blend(true); - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - glDepthMask(GL_FALSE); /* don't overwrite zbuf */ - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); - - if (rv3d->rot_angle != 0.0f) { - /* -- draw rotation axis -- */ - float scaled_axis[3]; - const float scale = rv3d->dist; - mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); - - - immBegin(GPU_PRIM_LINE_STRIP, 3); - color[3] = 0; /* more transparent toward the ends */ - immAttr4ubv(col, color); - add_v3_v3v3(end, o, scaled_axis); - immVertex3fv(pos, end); - -#if 0 - color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ - /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ -#endif - - color[3] = 127; /* more opaque toward the center */ - immAttr4ubv(col, color); - immVertex3fv(pos, o); - - color[3] = 0; - immAttr4ubv(col, color); - sub_v3_v3v3(end, o, scaled_axis); - immVertex3fv(pos, end); - immEnd(); - - /* -- draw ring around rotation center -- */ - { -#define ROT_AXIS_DETAIL 13 - - const float s = 0.05f * scale; - const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); - - float q[4]; /* rotate ring so it's perpendicular to axis */ - const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; - if (!upright) { - const float up[3] = {0.0f, 0.0f, 1.0f}; - float vis_angle, vis_axis[3]; - - cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); - vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); - axis_angle_to_quat(q, vis_axis, vis_angle); - } - - immBegin(GPU_PRIM_LINE_LOOP, ROT_AXIS_DETAIL); - color[3] = 63; /* somewhat faint */ - immAttr4ubv(col, color); - float angle = 0.0f; - for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) { - float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; - - if (!upright) { - mul_qt_v3(q, p); - } - - add_v3_v3(p, o); - immVertex3fv(pos, p); - } - immEnd(); - -#undef ROT_AXIS_DETAIL - } - - color[3] = 255; /* solid dot */ - } - else { - color[3] = 127; /* see-through dot */ - } - - immUnbindProgram(); - - /* -- draw rotation center -- */ - immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); - GPU_point_size(5.0f); - immBegin(GPU_PRIM_POINTS, 1); - immAttr4ubv(col, color); - immVertex3fv(pos, o); - immEnd(); - immUnbindProgram(); - -#if 0 - /* find screen coordinates for rotation center, then draw pretty icon */ - mul_m4_v3(rv3d->persinv, rot_center); - UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); - /* ^^ just playing around, does not work */ -#endif - - GPU_blend(false); - glDepthMask(GL_TRUE); + float o[3]; /* center of rotation */ + float end[3]; /* endpoints for drawing */ + + GLubyte color[4] = {0, 108, 255, 255}; /* bright blue so it matches device LEDs */ + + negate_v3_v3(o, rv3d->ofs); + + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + glDepthMask(GL_FALSE); /* don't overwrite zbuf */ + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR); + + if (rv3d->rot_angle != 0.0f) { + /* -- draw rotation axis -- */ + float scaled_axis[3]; + const float scale = rv3d->dist; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); + + immBegin(GPU_PRIM_LINE_STRIP, 3); + color[3] = 0; /* more transparent toward the ends */ + immAttr4ubv(col, color); + add_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); + +# if 0 + color[3] = 0.2f + fabsf(rv3d->rot_angle); /* modulate opacity with angle */ + /* ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 */ +# endif + + color[3] = 127; /* more opaque toward the center */ + immAttr4ubv(col, color); + immVertex3fv(pos, o); + + color[3] = 0; + immAttr4ubv(col, color); + sub_v3_v3v3(end, o, scaled_axis); + immVertex3fv(pos, end); + immEnd(); + + /* -- draw ring around rotation center -- */ + { +# define ROT_AXIS_DETAIL 13 + + const float s = 0.05f * scale; + const float step = 2.0f * (float)(M_PI / ROT_AXIS_DETAIL); + + float q[4]; /* rotate ring so it's perpendicular to axis */ + const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; + if (!upright) { + const float up[3] = {0.0f, 0.0f, 1.0f}; + float vis_angle, vis_axis[3]; + + cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); + vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); + axis_angle_to_quat(q, vis_axis, vis_angle); + } + + immBegin(GPU_PRIM_LINE_LOOP, ROT_AXIS_DETAIL); + color[3] = 63; /* somewhat faint */ + immAttr4ubv(col, color); + float angle = 0.0f; + for (int i = 0; i < ROT_AXIS_DETAIL; ++i, angle += step) { + float p[3] = {s * cosf(angle), s * sinf(angle), 0.0f}; + + if (!upright) { + mul_qt_v3(q, p); + } + + add_v3_v3(p, o); + immVertex3fv(pos, p); + } + immEnd(); + +# undef ROT_AXIS_DETAIL + } + + color[3] = 255; /* solid dot */ + } + else { + color[3] = 127; /* see-through dot */ + } + + immUnbindProgram(); + + /* -- draw rotation center -- */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + GPU_point_size(5.0f); + immBegin(GPU_PRIM_POINTS, 1); + immAttr4ubv(col, color); + immVertex3fv(pos, o); + immEnd(); + immUnbindProgram(); + +# if 0 + /* find screen coordinates for rotation center, then draw pretty icon */ + mul_m4_v3(rv3d->persinv, rot_center); + UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); + /* ^^ just playing around, does not work */ +# endif + + GPU_blend(false); + glDepthMask(GL_TRUE); } #endif /* WITH_INPUT_NDOF */ @@ -1017,17 +1052,17 @@ static void draw_rotation_guide(const RegionView3D *rv3d) */ static void view3d_draw_border(const bContext *C, ARegion *ar) { - Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - RegionView3D *rv3d = ar->regiondata; - View3D *v3d = CTX_wm_view3d(C); - - if (rv3d->persp == RV3D_CAMOB) { - drawviewborder(scene, depsgraph, ar, v3d); - } - else if (v3d->flag2 & V3D_RENDER_BORDER) { - drawrenderborder(ar, v3d); - } + Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + + if (rv3d->persp == RV3D_CAMOB) { + drawviewborder(scene, depsgraph, ar, v3d); + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + drawrenderborder(ar, v3d); + } } /** \} */ @@ -1041,7 +1076,7 @@ static void view3d_draw_border(const bContext *C, ARegion *ar) */ static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) { - /* TODO viewport */ + /* TODO viewport */ } /** @@ -1049,119 +1084,120 @@ static void view3d_draw_grease_pencil(const bContext *UNUSED(C)) */ static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d) { - const char *name = NULL; - - switch (rv3d->view) { - case RV3D_VIEW_FRONT: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Front Orthographic"); - } - else { - name = IFACE_("Front Perspective"); - } - break; - case RV3D_VIEW_BACK: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Back Orthographic"); - } - else { - name = IFACE_("Back Perspective"); - } - break; - case RV3D_VIEW_TOP: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Top Orthographic"); - } - else { - name = IFACE_("Top Perspective"); - } - break; - case RV3D_VIEW_BOTTOM: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Bottom Orthographic"); - } - else { - name = IFACE_("Bottom Perspective"); - } - break; - case RV3D_VIEW_RIGHT: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Right Orthographic"); - } - else { - name = IFACE_("Right Perspective"); - } - break; - case RV3D_VIEW_LEFT: - if (rv3d->persp == RV3D_ORTHO) { - name = IFACE_("Left Orthographic"); - } - else { - name = IFACE_("Left Perspective"); - } - break; - - default: - if (rv3d->persp == RV3D_CAMOB) { - if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { - Camera *cam; - cam = v3d->camera->data; - if (cam->type == CAM_PERSP) { - name = IFACE_("Camera Perspective"); - } - else if (cam->type == CAM_ORTHO) { - name = IFACE_("Camera Orthographic"); - } - else { - BLI_assert(cam->type == CAM_PANO); - name = IFACE_("Camera Panoramic"); - } - } - else { - name = IFACE_("Object as Camera"); - } - } - else { - name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Orthographic") : IFACE_("User Perspective"); - } - } - - return name; + const char *name = NULL; + + switch (rv3d->view) { + case RV3D_VIEW_FRONT: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Front Orthographic"); + } + else { + name = IFACE_("Front Perspective"); + } + break; + case RV3D_VIEW_BACK: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Back Orthographic"); + } + else { + name = IFACE_("Back Perspective"); + } + break; + case RV3D_VIEW_TOP: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Top Orthographic"); + } + else { + name = IFACE_("Top Perspective"); + } + break; + case RV3D_VIEW_BOTTOM: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Bottom Orthographic"); + } + else { + name = IFACE_("Bottom Perspective"); + } + break; + case RV3D_VIEW_RIGHT: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Right Orthographic"); + } + else { + name = IFACE_("Right Perspective"); + } + break; + case RV3D_VIEW_LEFT: + if (rv3d->persp == RV3D_ORTHO) { + name = IFACE_("Left Orthographic"); + } + else { + name = IFACE_("Left Perspective"); + } + break; + + default: + if (rv3d->persp == RV3D_CAMOB) { + if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) { + Camera *cam; + cam = v3d->camera->data; + if (cam->type == CAM_PERSP) { + name = IFACE_("Camera Perspective"); + } + else if (cam->type == CAM_ORTHO) { + name = IFACE_("Camera Orthographic"); + } + else { + BLI_assert(cam->type == CAM_PANO); + name = IFACE_("Camera Panoramic"); + } + } + else { + name = IFACE_("Object as Camera"); + } + } + else { + name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Orthographic") : + IFACE_("User Perspective"); + } + } + + return name; } static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffset) { - RegionView3D *rv3d = ar->regiondata; - const char *name = view3d_get_name(v3d, rv3d); - const int font_id = BLF_default(); + RegionView3D *rv3d = ar->regiondata; + const char *name = view3d_get_name(v3d, rv3d); + const int font_id = BLF_default(); - /* increase size for unicode languages (Chinese in utf-8...) */ + /* increase size for unicode languages (Chinese in utf-8...) */ #ifdef WITH_INTERNATIONAL - char tmpstr[96]; + char tmpstr[96]; #else - char tmpstr[32]; + char tmpstr[32]; #endif - BLF_enable(font_id, BLF_SHADOW); - BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); - BLF_shadow_offset(font_id, 1, -1); + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); - if (v3d->localvd) { - BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); - name = tmpstr; - } + if (v3d->localvd) { + BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name); + name = tmpstr; + } - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - *yoffset -= U.widget_unit; + *yoffset -= U.widget_unit; #ifdef WITH_INTERNATIONAL - BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); + BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); #else - BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); + BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); #endif - BLF_disable(font_id, BLF_SHADOW); + BLF_disable(font_id, BLF_SHADOW); } /** @@ -1169,125 +1205,130 @@ static void draw_viewport_name(ARegion *ar, View3D *v3d, int xoffset, int *yoffs * framenum, collection, object name, bone name (if available), marker name (if available) */ -static void draw_selected_name(Scene *scene, ViewLayer *view_layer, Object *ob, int xoffset, int *yoffset) +static void draw_selected_name( + Scene *scene, ViewLayer *view_layer, Object *ob, int xoffset, int *yoffset) { - const int cfra = CFRA; - const char *msg_pin = " (Pinned)"; - const char *msg_sep = " : "; - - const int font_id = BLF_default(); - - char info[300]; - char *s = info; - - s += sprintf(s, "(%d)", cfra); - - if ((ob == NULL) || (ob->mode == OB_MODE_OBJECT)) { - LayerCollection *layer_collection = view_layer->active_collection; - s += sprintf(s, " %s%s", BKE_collection_ui_name_get(layer_collection->collection), (ob == NULL) ? "" : " |"); - } - - /* - * info can contain: - * - a frame (7 + 2) - * - a collection name (MAX_NAME + 3) - * - 3 object names (MAX_NAME) - * - 2 BREAD_CRUMB_SEPARATORs (6) - * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! - * - a marker name (MAX_NAME + 3) - */ - - /* get name of marker on current frame (if available) */ - const char *markern = BKE_scene_find_marker_name(scene, cfra); - - /* check if there is an object */ - if (ob) { - *s++ = ' '; - s += BLI_strcpy_rlen(s, ob->id.name + 2); - - /* name(s) to display depends on type of object */ - if (ob->type == OB_ARMATURE) { - bArmature *arm = ob->data; - - /* show name of active bone too (if possible) */ - if (arm->edbo) { - if (arm->act_edbone) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_edbone->name); - } - } - else if (ob->mode & OB_MODE_POSE) { - if (arm->act_bone) { - - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } - else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { - /* try to display active bone and active shapekey too (if they exist) */ - - if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { - Object *armobj = BKE_object_pose_armature_get(ob); - if (armobj && armobj->mode & OB_MODE_POSE) { - bArmature *arm = armobj->data; - if (arm->act_bone) { - if (arm->act_bone->layer & arm->layer) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, arm->act_bone->name); - } - } - } - } - - Key *key = BKE_key_from_object(ob); - if (key) { - KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); - if (kb) { - s += BLI_strcpy_rlen(s, msg_sep); - s += BLI_strcpy_rlen(s, kb->name); - if (ob->shapeflag & OB_SHAPE_LOCK) { - s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); - } - } - } - } - - /* color depends on whether there is a keyframe */ - if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { - UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); - } - else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { - UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); - } - else { - UI_FontThemeColor(font_id, TH_TEXT_HI); - } - } - else { - /* no object */ - if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) { - UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); - } - else { - UI_FontThemeColor(font_id, TH_TEXT_HI); - } - } - - if (markern) { - s += sprintf(s, " <%s>", markern); - } - - BLF_enable(font_id, BLF_SHADOW); - BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); - BLF_shadow_offset(font_id, 1, -1); - - *yoffset -= U.widget_unit; - BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); - - BLF_disable(font_id, BLF_SHADOW); + const int cfra = CFRA; + const char *msg_pin = " (Pinned)"; + const char *msg_sep = " : "; + + const int font_id = BLF_default(); + + char info[300]; + char *s = info; + + s += sprintf(s, "(%d)", cfra); + + if ((ob == NULL) || (ob->mode == OB_MODE_OBJECT)) { + LayerCollection *layer_collection = view_layer->active_collection; + s += sprintf(s, + " %s%s", + BKE_collection_ui_name_get(layer_collection->collection), + (ob == NULL) ? "" : " |"); + } + + /* + * info can contain: + * - a frame (7 + 2) + * - a collection name (MAX_NAME + 3) + * - 3 object names (MAX_NAME) + * - 2 BREAD_CRUMB_SEPARATORs (6) + * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room! + * - a marker name (MAX_NAME + 3) + */ + + /* get name of marker on current frame (if available) */ + const char *markern = BKE_scene_find_marker_name(scene, cfra); + + /* check if there is an object */ + if (ob) { + *s++ = ' '; + s += BLI_strcpy_rlen(s, ob->id.name + 2); + + /* name(s) to display depends on type of object */ + if (ob->type == OB_ARMATURE) { + bArmature *arm = ob->data; + + /* show name of active bone too (if possible) */ + if (arm->edbo) { + if (arm->act_edbone) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_edbone->name); + } + } + else if (ob->mode & OB_MODE_POSE) { + if (arm->act_bone) { + + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } + } + } + else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + /* try to display active bone and active shapekey too (if they exist) */ + + if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) { + Object *armobj = BKE_object_pose_armature_get(ob); + if (armobj && armobj->mode & OB_MODE_POSE) { + bArmature *arm = armobj->data; + if (arm->act_bone) { + if (arm->act_bone->layer & arm->layer) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, arm->act_bone->name); + } + } + } + } + + Key *key = BKE_key_from_object(ob); + if (key) { + KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1); + if (kb) { + s += BLI_strcpy_rlen(s, msg_sep); + s += BLI_strcpy_rlen(s, kb->name); + if (ob->shapeflag & OB_SHAPE_LOCK) { + s += BLI_strcpy_rlen(s, IFACE_(msg_pin)); + } + } + } + } + + /* color depends on whether there is a keyframe */ + if (id_frame_has_keyframe( + (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { + UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); + } + else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + } + } + else { + /* no object */ + if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra)) { + UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + } + } + + if (markern) { + s += sprintf(s, " <%s>", markern); + } + + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); + + *yoffset -= U.widget_unit; + BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); + + BLF_disable(font_id, BLF_SHADOW); } /** @@ -1295,83 +1336,77 @@ static void draw_selected_name(Scene *scene, ViewLayer *view_layer, Object *ob, */ void view3d_draw_region_info(const bContext *C, ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; - View3D *v3d = CTX_wm_view3d(C); - Scene *scene = CTX_data_scene(C); - wmWindowManager *wm = CTX_wm_manager(C); + RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + Scene *scene = CTX_data_scene(C); + wmWindowManager *wm = CTX_wm_manager(C); #ifdef WITH_INPUT_NDOF - if ((U.ndof_flag & NDOF_SHOW_GUIDE) && - ((rv3d->viewlock & RV3D_LOCKED) == 0) && - (rv3d->persp != RV3D_CAMOB)) - { - /* TODO: draw something else (but not this) during fly mode */ - draw_rotation_guide(rv3d); - } + if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) && + (rv3d->persp != RV3D_CAMOB)) { + /* TODO: draw something else (but not this) during fly mode */ + draw_rotation_guide(rv3d); + } #endif - /* correct projection matrix */ - ED_region_pixelspace(ar); + /* correct projection matrix */ + ED_region_pixelspace(ar); - /* local coordinate visible rect inside region, to accommodate overlapping ui */ - rcti rect; - ED_region_visible_rect(ar, &rect); + /* local coordinate visible rect inside region, to accommodate overlapping ui */ + rcti rect; + ED_region_visible_rect(ar, &rect); + view3d_draw_border(C, ar); + view3d_draw_grease_pencil(C); - view3d_draw_border(C, ar); - view3d_draw_grease_pencil(C); + BLF_batch_draw_begin(); - BLF_batch_draw_begin(); + if ((U.uiflag & USER_SHOW_GIZMO_AXIS) || + /* No need to display gizmo and this info. */ + (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) { + /* pass */ + } + else { + draw_view_axis(rv3d, &rect); + } - if ((U.uiflag & USER_SHOW_GIZMO_AXIS) || - /* No need to display gizmo and this info. */ - (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) - { - /* pass */ - } - else { - draw_view_axis(rv3d, &rect); - } + int xoffset = rect.xmin + U.widget_unit; + int yoffset = rect.ymax; - int xoffset = rect.xmin + U.widget_unit; - int yoffset = rect.ymax; + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { + if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { + ED_scene_draw_fps(scene, xoffset, &yoffset); + } + else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { + draw_viewport_name(ar, v3d, xoffset, &yoffset); + } - if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && - (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) - { - if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { - ED_scene_draw_fps(scene, xoffset, &yoffset); - } - else if (U.uiflag & USER_SHOW_VIEWPORTNAME) { - draw_viewport_name(ar, v3d, xoffset, &yoffset); - } - - if (U.uiflag & USER_DRAWVIEWINFO) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); - } + if (U.uiflag & USER_DRAWVIEWINFO) { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); + } #if 0 /* TODO */ - if (grid_unit) { /* draw below the viewport name */ - char numstr[32] = ""; + if (grid_unit) { /* draw below the viewport name */ + char numstr[32] = ""; - UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - if (v3d->grid != 1.0f) { - BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); - } + UI_FontThemeColor(BLF_default(), TH_TEXT_HI); + if (v3d->grid != 1.0f) { + BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); + } - *yoffset -= U.widget_unit; - BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr)); - } + *yoffset -= U.widget_unit; + BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr)); + } #endif - } + } - if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { - DRW_draw_region_engine_info(xoffset, yoffset); - } + if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { + DRW_draw_region_engine_info(xoffset, yoffset); + } - BLF_batch_draw_end(); + BLF_batch_draw_end(); } /** \} */ @@ -1382,43 +1417,50 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar) static void view3d_draw_view(const bContext *C, ARegion *ar) { - ED_view3d_draw_setup_view(CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, CTX_wm_view3d(C), NULL, NULL, NULL); - - /* Only 100% compliant on new spec goes below */ - DRW_draw_view(C); + ED_view3d_draw_setup_view(CTX_wm_window(C), + CTX_data_depsgraph(C), + CTX_data_scene(C), + ar, + CTX_wm_view3d(C), + NULL, + NULL, + NULL); + + /* Only 100% compliant on new spec goes below */ + DRW_draw_view(C); } RenderEngineType *ED_view3d_engine_type(Scene *scene, int drawtype) { - /* - * Temporary viewport draw modes until we have a proper system. - * all modes are done in the draw manager, except - * cycles material as it is an external render engine. - */ - if (strcmp(scene->r.engine, RE_engine_id_CYCLES) == 0 && drawtype == OB_MATERIAL) { - return RE_engines_find(RE_engine_id_BLENDER_EEVEE); - } - return RE_engines_find(scene->r.engine); + /* + * Temporary viewport draw modes until we have a proper system. + * all modes are done in the draw manager, except + * cycles material as it is an external render engine. + */ + if (strcmp(scene->r.engine, RE_engine_id_CYCLES) == 0 && drawtype == OB_MATERIAL) { + return RE_engines_find(RE_engine_id_BLENDER_EEVEE); + } + return RE_engines_find(scene->r.engine); } void view3d_main_region_draw(const bContext *C, ARegion *ar) { - Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); + Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); - view3d_draw_view(C, ar); + view3d_draw_view(C, ar); - GPU_free_images_old(bmain); - GPU_pass_cache_garbage_collect(); + GPU_free_images_old(bmain); + GPU_pass_cache_garbage_collect(); - /* XXX This is in order to draw UI batches with the DRW - * olg context since we now use it for drawing the entire area */ - gpu_batch_presets_reset(); + /* XXX This is in order to draw UI batches with the DRW + * olg context since we now use it for drawing the entire area */ + gpu_batch_presets_reset(); - /* No depth test for drawing action zones afterwards. */ - GPU_depth_test(false); + /* No depth test for drawing action zones afterwards. */ + GPU_depth_test(false); - v3d->flag |= V3D_INVALID_BACKBUF; + v3d->flag |= V3D_INVALID_BACKBUF; } /** \} */ @@ -1427,92 +1469,103 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) /** \name Offscreen Drawing * \{ */ -static void view3d_stereo3d_setup_offscreen( - Depsgraph *depsgraph, Scene *scene, View3D *v3d, ARegion *ar, - float winmat[4][4], const char *viewname) +static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + ARegion *ar, + float winmat[4][4], + const char *viewname) { - /* update the viewport matrices with the new camera */ - if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { - float viewmat[4][4]; - const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); - - BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); - } - else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ - float viewmat[4][4]; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - - BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); - } + /* update the viewport matrices with the new camera */ + if (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D) { + float viewmat[4][4]; + const bool is_left = STREQ(viewname, STEREO_LEFT_NAME); + + BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat); + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + } + else { /* SCE_VIEWS_FORMAT_MULTIVIEW */ + float viewmat[4][4]; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + + BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat); + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + } } -void ED_view3d_draw_offscreen( - Depsgraph *depsgraph, Scene *scene, - int drawtype, - View3D *v3d, ARegion *ar, int winx, int winy, - float viewmat[4][4], float winmat[4][4], - bool do_sky, bool UNUSED(is_persp), const char *viewname, - GPUFXSettings *UNUSED(fx_settings), const bool do_color_management, - GPUOffScreen *ofs, GPUViewport *viewport) +void ED_view3d_draw_offscreen(Depsgraph *depsgraph, + Scene *scene, + int drawtype, + View3D *v3d, + ARegion *ar, + int winx, + int winy, + float viewmat[4][4], + float winmat[4][4], + bool do_sky, + bool UNUSED(is_persp), + const char *viewname, + GPUFXSettings *UNUSED(fx_settings), + const bool do_color_management, + GPUOffScreen *ofs, + GPUViewport *viewport) { - RegionView3D *rv3d = ar->regiondata; - RenderEngineType *engine_type = ED_view3d_engine_type(scene, drawtype); - - /* set temporary new size */ - int bwinx = ar->winx; - int bwiny = ar->winy; - rcti brect = ar->winrct; - - ar->winx = winx; - ar->winy = winy; - ar->winrct.xmin = 0; - ar->winrct.ymin = 0; - ar->winrct.xmax = winx; - ar->winrct.ymax = winy; - - struct bThemeState theme_state; - UI_Theme_Store(&theme_state); - UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); - - /* set flags */ - G.f |= G_FLAG_RENDER_VIEWPORT; - - { - /* free images which can have changed on frame-change - * warning! can be slow so only free animated images - campbell */ - GPU_free_images_anim(G.main); /* XXX :((( */ - } - - GPU_matrix_push_projection(); - GPU_matrix_identity_set(); - GPU_matrix_push(); - GPU_matrix_identity_set(); - - if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) { - view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname); - } - else { - view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); - } - - /* main drawing call */ - DRW_draw_render_loop_offscreen( - depsgraph, engine_type, ar, v3d, - do_sky, do_color_management, ofs, viewport); - - /* restore size */ - ar->winx = bwinx; - ar->winy = bwiny; - ar->winrct = brect; - - GPU_matrix_pop_projection(); - GPU_matrix_pop(); - - UI_Theme_Restore(&theme_state); - - G.f &= ~G_FLAG_RENDER_VIEWPORT; + RegionView3D *rv3d = ar->regiondata; + RenderEngineType *engine_type = ED_view3d_engine_type(scene, drawtype); + + /* set temporary new size */ + int bwinx = ar->winx; + int bwiny = ar->winy; + rcti brect = ar->winrct; + + ar->winx = winx; + ar->winy = winy; + ar->winrct.xmin = 0; + ar->winrct.ymin = 0; + ar->winrct.xmax = winx; + ar->winrct.ymax = winy; + + struct bThemeState theme_state; + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + + /* set flags */ + G.f |= G_FLAG_RENDER_VIEWPORT; + + { + /* free images which can have changed on frame-change + * warning! can be slow so only free animated images - campbell */ + GPU_free_images_anim(G.main); /* XXX :((( */ + } + + GPU_matrix_push_projection(); + GPU_matrix_identity_set(); + GPU_matrix_push(); + GPU_matrix_identity_set(); + + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && + rv3d->persp == RV3D_CAMOB && v3d->camera) { + view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname); + } + else { + view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL); + } + + /* main drawing call */ + DRW_draw_render_loop_offscreen( + depsgraph, engine_type, ar, v3d, do_sky, do_color_management, ofs, viewport); + + /* restore size */ + ar->winx = bwinx; + ar->winy = bwiny; + ar->winrct = brect; + + GPU_matrix_pop_projection(); + GPU_matrix_pop(); + + UI_Theme_Restore(&theme_state); + + G.f &= ~G_FLAG_RENDER_VIEWPORT; } /** @@ -1521,189 +1574,242 @@ void ED_view3d_draw_offscreen( * \param ofs: Optional off-screen buffer, can be NULL. * (avoids re-creating when doing multiple GL renders). */ -ImBuf *ED_view3d_draw_offscreen_imbuf( - Depsgraph *depsgraph, Scene *scene, - int drawtype, - View3D *v3d, ARegion *ar, int sizex, int sizey, - uint flag, uint draw_flags, - int alpha_mode, int samples, const char *viewname, - /* output vars */ - GPUOffScreen *ofs, char err_out[256]) +ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, + Scene *scene, + int drawtype, + View3D *v3d, + ARegion *ar, + int sizex, + int sizey, + uint flag, + uint draw_flags, + int alpha_mode, + int samples, + const char *viewname, + /* output vars */ + GPUOffScreen *ofs, + char err_out[256]) { - RegionView3D *rv3d = ar->regiondata; - const bool draw_sky = (alpha_mode == R_ADDSKY); - const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE); - - /* view state */ - GPUFXSettings fx_settings = v3d->fx_settings; - bool is_ortho = false; - float winmat[4][4]; - - if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) { - /* sizes differ, can't reuse */ - ofs = NULL; - } - - GPUFrameBuffer *old_fb = GPU_framebuffer_active_get(); - - if (old_fb) { - GPU_framebuffer_restore(); - } - - const bool own_ofs = (ofs == NULL); - DRW_opengl_context_enable(); - - if (own_ofs) { - /* bind */ - ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out); - if (ofs == NULL) { - DRW_opengl_context_disable(); - return NULL; - } - } - - GPU_offscreen_bind(ofs, true); - - /* read in pixels & stamp */ - ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); - - /* render 3d view */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - CameraParams params; - Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); - const Object *camera_eval = DEG_get_evaluated_object( - depsgraph, - camera); - - BKE_camera_params_init(¶ms); - /* fallback for non camera objects */ - params.clip_start = v3d->clip_start; - params.clip_end = v3d->clip_end; - BKE_camera_params_from_object(¶ms, camera_eval); - BKE_camera_multiview_params(&scene->r, ¶ms, camera_eval, viewname); - BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); - BKE_camera_params_compute_matrix(¶ms); - - BKE_camera_to_gpu_dof(camera, &fx_settings); - - is_ortho = params.is_ortho; - copy_m4_m4(winmat, params.winmat); - } - else { - rctf viewplane; - float clip_start, clipend; - - is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clip_start, &clipend, NULL); - if (is_ortho) { - orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); - } - else { - perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clip_start, clipend); - } - } - - if ((samples && use_full_sample) == 0) { - const bool do_color_management = (ibuf->rect_float == NULL); - /* Single-pass render, common case */ - ED_view3d_draw_offscreen( - depsgraph, scene, drawtype, - v3d, ar, sizex, sizey, NULL, winmat, - draw_sky, !is_ortho, viewname, - &fx_settings, do_color_management, ofs, NULL); - - if (ibuf->rect_float) { - GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); - } - else if (ibuf->rect) { - GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); - } - } - else { - /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling. - * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */ - static float jit_ofs[32][2]; - float winmat_jitter[4][4]; - float *rect_temp = (ibuf->rect_float) ? ibuf->rect_float : MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp"); - float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer"); - GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs); - - BLI_jitter_init(jit_ofs, samples); - - /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen( - depsgraph, scene, drawtype, - v3d, ar, sizex, sizey, NULL, winmat, - draw_sky, !is_ortho, viewname, - &fx_settings, false, ofs, viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer); - - /* skip the first sample */ - for (int j = 1; j < samples; j++) { - copy_m4_m4(winmat_jitter, winmat); - window_translate_m4( - winmat_jitter, rv3d->persmat, - (jit_ofs[j][0] * 2.0f) / sizex, - (jit_ofs[j][1] * 2.0f) / sizey); - - ED_view3d_draw_offscreen( - depsgraph, scene, drawtype, - v3d, ar, sizex, sizey, NULL, winmat_jitter, - draw_sky, !is_ortho, viewname, - &fx_settings, false, ofs, viewport); - GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp); - - uint i = sizex * sizey * 4; - while (i--) { - accum_buffer[i] += rect_temp[i]; - } - } - - { - /* don't free data owned by 'ofs' */ - GPU_viewport_clear_from_offscreen(viewport); - GPU_viewport_free(viewport); - } - - if (ibuf->rect_float == NULL) { - MEM_freeN(rect_temp); - } - - if (ibuf->rect_float) { - float *rect_float = ibuf->rect_float; - uint i = sizex * sizey * 4; - while (i--) { - rect_float[i] = accum_buffer[i] / samples; - } - } - else { - uchar *rect_ub = (uchar *)ibuf->rect; - uint i = sizex * sizey * 4; - while (i--) { - rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples); - } - } - - MEM_freeN(accum_buffer); - } - - /* unbind */ - GPU_offscreen_unbind(ofs, true); - - if (own_ofs) { - GPU_offscreen_free(ofs); - } - - DRW_opengl_context_disable(); - - if (old_fb) { - GPU_framebuffer_bind(old_fb); - } - - if (ibuf->rect_float && ibuf->rect) { - IMB_rect_from_float(ibuf); - } - - return ibuf; + RegionView3D *rv3d = ar->regiondata; + const bool draw_sky = (alpha_mode == R_ADDSKY); + const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE); + + /* view state */ + GPUFXSettings fx_settings = v3d->fx_settings; + bool is_ortho = false; + float winmat[4][4]; + + if (ofs && ((GPU_offscreen_width(ofs) != sizex) || (GPU_offscreen_height(ofs) != sizey))) { + /* sizes differ, can't reuse */ + ofs = NULL; + } + + GPUFrameBuffer *old_fb = GPU_framebuffer_active_get(); + + if (old_fb) { + GPU_framebuffer_restore(); + } + + const bool own_ofs = (ofs == NULL); + DRW_opengl_context_enable(); + + if (own_ofs) { + /* bind */ + ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out); + if (ofs == NULL) { + DRW_opengl_context_disable(); + return NULL; + } + } + + GPU_offscreen_bind(ofs, true); + + /* read in pixels & stamp */ + ImBuf *ibuf = IMB_allocImBuf(sizex, sizey, 32, flag); + + /* render 3d view */ + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + CameraParams params; + Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname); + const Object *camera_eval = DEG_get_evaluated_object(depsgraph, camera); + + BKE_camera_params_init(¶ms); + /* fallback for non camera objects */ + params.clip_start = v3d->clip_start; + params.clip_end = v3d->clip_end; + BKE_camera_params_from_object(¶ms, camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, camera_eval, viewname); + BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); + BKE_camera_params_compute_matrix(¶ms); + + BKE_camera_to_gpu_dof(camera, &fx_settings); + + is_ortho = params.is_ortho; + copy_m4_m4(winmat, params.winmat); + } + else { + rctf viewplane; + float clip_start, clipend; + + is_ortho = ED_view3d_viewplane_get( + depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clip_start, &clipend, NULL); + if (is_ortho) { + orthographic_m4(winmat, + viewplane.xmin, + viewplane.xmax, + viewplane.ymin, + viewplane.ymax, + -clipend, + clipend); + } + else { + perspective_m4(winmat, + viewplane.xmin, + viewplane.xmax, + viewplane.ymin, + viewplane.ymax, + clip_start, + clipend); + } + } + + if ((samples && use_full_sample) == 0) { + const bool do_color_management = (ibuf->rect_float == NULL); + /* Single-pass render, common case */ + ED_view3d_draw_offscreen(depsgraph, + scene, + drawtype, + v3d, + ar, + sizex, + sizey, + NULL, + winmat, + draw_sky, + !is_ortho, + viewname, + &fx_settings, + do_color_management, + ofs, + NULL); + + if (ibuf->rect_float) { + GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); + } + else if (ibuf->rect) { + GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); + } + } + else { + /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling. + * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */ + static float jit_ofs[32][2]; + float winmat_jitter[4][4]; + float *rect_temp = (ibuf->rect_float) ? + ibuf->rect_float : + MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp"); + float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer"); + GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs); + + BLI_jitter_init(jit_ofs, samples); + + /* first sample buffer, also initializes 'rv3d->persmat' */ + ED_view3d_draw_offscreen(depsgraph, + scene, + drawtype, + v3d, + ar, + sizex, + sizey, + NULL, + winmat, + draw_sky, + !is_ortho, + viewname, + &fx_settings, + false, + ofs, + viewport); + GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer); + + /* skip the first sample */ + for (int j = 1; j < samples; j++) { + copy_m4_m4(winmat_jitter, winmat); + window_translate_m4(winmat_jitter, + rv3d->persmat, + (jit_ofs[j][0] * 2.0f) / sizex, + (jit_ofs[j][1] * 2.0f) / sizey); + + ED_view3d_draw_offscreen(depsgraph, + scene, + drawtype, + v3d, + ar, + sizex, + sizey, + NULL, + winmat_jitter, + draw_sky, + !is_ortho, + viewname, + &fx_settings, + false, + ofs, + viewport); + GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp); + + uint i = sizex * sizey * 4; + while (i--) { + accum_buffer[i] += rect_temp[i]; + } + } + + { + /* don't free data owned by 'ofs' */ + GPU_viewport_clear_from_offscreen(viewport); + GPU_viewport_free(viewport); + } + + if (ibuf->rect_float == NULL) { + MEM_freeN(rect_temp); + } + + if (ibuf->rect_float) { + float *rect_float = ibuf->rect_float; + uint i = sizex * sizey * 4; + while (i--) { + rect_float[i] = accum_buffer[i] / samples; + } + } + else { + uchar *rect_ub = (uchar *)ibuf->rect; + uint i = sizex * sizey * 4; + while (i--) { + rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples); + } + } + + MEM_freeN(accum_buffer); + } + + /* unbind */ + GPU_offscreen_unbind(ofs, true); + + if (own_ofs) { + GPU_offscreen_free(ofs); + } + + DRW_opengl_context_disable(); + + if (old_fb) { + GPU_framebuffer_bind(old_fb); + } + + if (ibuf->rect_float && ibuf->rect) { + IMB_rect_from_float(ibuf); + } + + return ibuf; } /** @@ -1714,71 +1820,86 @@ ImBuf *ED_view3d_draw_offscreen_imbuf( * * \note used by the sequencer */ -ImBuf *ED_view3d_draw_offscreen_imbuf_simple( - Depsgraph *depsgraph, Scene *scene, - int drawtype, - Object *camera, int width, int height, - uint flag, uint draw_flags, - int alpha_mode, int samples, const char *viewname, - GPUOffScreen *ofs, char err_out[256]) +ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, + Scene *scene, + int drawtype, + Object *camera, + int width, + int height, + uint flag, + uint draw_flags, + int alpha_mode, + int samples, + const char *viewname, + GPUOffScreen *ofs, + char err_out[256]) { - View3D v3d = {NULL}; - ARegion ar = {NULL}; - RegionView3D rv3d = {{{0}}}; - - /* connect data */ - v3d.regionbase.first = v3d.regionbase.last = &ar; - ar.regiondata = &rv3d; - ar.regiontype = RGN_TYPE_WINDOW; - - v3d.camera = camera; - v3d.shading.type = drawtype; - v3d.flag2 = V3D_HIDE_OVERLAYS; - - if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) { - v3d.flag2 |= V3D_SHOW_ANNOTATION; - } - - v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD; - - if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) { - if (camera->type == OB_CAMERA) { - v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof; - v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF; - } - } - - rv3d.persp = RV3D_CAMOB; - - copy_m4_m4(rv3d.viewinv, v3d.camera->obmat); - normalize_m4(rv3d.viewinv); - invert_m4_m4(rv3d.viewmat, rv3d.viewinv); - - { - CameraParams params; - const Object *view_camera_eval = DEG_get_evaluated_object( - depsgraph, - BKE_camera_multiview_render(scene, v3d.camera, viewname)); - - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, view_camera_eval); - BKE_camera_multiview_params(&scene->r, ¶ms, view_camera_eval, viewname); - BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); - BKE_camera_params_compute_matrix(¶ms); - - copy_m4_m4(rv3d.winmat, params.winmat); - v3d.clip_start = params.clip_start; - v3d.clip_end = params.clip_end; - v3d.lens = params.lens; - } - - mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); - invert_m4_m4(rv3d.persinv, rv3d.viewinv); - - return ED_view3d_draw_offscreen_imbuf( - depsgraph, scene, drawtype, - &v3d, &ar, width, height, flag, - draw_flags, alpha_mode, samples, viewname, ofs, err_out); + View3D v3d = {NULL}; + ARegion ar = {NULL}; + RegionView3D rv3d = {{{0}}}; + + /* connect data */ + v3d.regionbase.first = v3d.regionbase.last = &ar; + ar.regiondata = &rv3d; + ar.regiontype = RGN_TYPE_WINDOW; + + v3d.camera = camera; + v3d.shading.type = drawtype; + v3d.flag2 = V3D_HIDE_OVERLAYS; + + if (draw_flags & V3D_OFSDRAW_USE_GPENCIL) { + v3d.flag2 |= V3D_SHOW_ANNOTATION; + } + + v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD; + + if (draw_flags & V3D_OFSDRAW_USE_CAMERA_DOF) { + if (camera->type == OB_CAMERA) { + v3d.fx_settings.dof = &((Camera *)camera->data)->gpu_dof; + v3d.fx_settings.fx_flag |= GPU_FX_FLAG_DOF; + } + } + + rv3d.persp = RV3D_CAMOB; + + copy_m4_m4(rv3d.viewinv, v3d.camera->obmat); + normalize_m4(rv3d.viewinv); + invert_m4_m4(rv3d.viewmat, rv3d.viewinv); + + { + CameraParams params; + const Object *view_camera_eval = DEG_get_evaluated_object( + depsgraph, BKE_camera_multiview_render(scene, v3d.camera, viewname)); + + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, view_camera_eval); + BKE_camera_multiview_params(&scene->r, ¶ms, view_camera_eval, viewname); + BKE_camera_params_compute_viewplane(¶ms, width, height, scene->r.xasp, scene->r.yasp); + BKE_camera_params_compute_matrix(¶ms); + + copy_m4_m4(rv3d.winmat, params.winmat); + v3d.clip_start = params.clip_start; + v3d.clip_end = params.clip_end; + v3d.lens = params.lens; + } + + mul_m4_m4m4(rv3d.persmat, rv3d.winmat, rv3d.viewmat); + invert_m4_m4(rv3d.persinv, rv3d.viewinv); + + return ED_view3d_draw_offscreen_imbuf(depsgraph, + scene, + drawtype, + &v3d, + &ar, + width, + height, + flag, + draw_flags, + alpha_mode, + samples, + viewname, + ofs, + err_out); } /** \} */ @@ -1789,24 +1910,24 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple( static bool view3d_clipping_test(const float co[3], const float clip[6][4]) { - if (plane_point_side_v3(clip[0], co) > 0.0f) { - if (plane_point_side_v3(clip[1], co) > 0.0f) { - if (plane_point_side_v3(clip[2], co) > 0.0f) { - if (plane_point_side_v3(clip[3], co) > 0.0f) { - return false; - } - } - } - } - - return true; + if (plane_point_side_v3(clip[0], co) > 0.0f) { + if (plane_point_side_v3(clip[1], co) > 0.0f) { + if (plane_point_side_v3(clip[2], co) > 0.0f) { + if (plane_point_side_v3(clip[3], co) > 0.0f) { + return false; + } + } + } + } + + return true; } /* for 'local' ED_view3d_clipping_local must run first * then all comparisons can be done in localspace */ bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], const bool is_local) { - return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); + return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index f7fcd5cb11f..85bc0fba36b 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -102,7 +102,7 @@ #include "DRW_engine.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* ********* custom clipping *********** */ @@ -113,206 +113,207 @@ void ED_view3d_clipping_set(RegionView3D *rv3d) { #ifdef USE_CLIP_PLANES - double plane[4]; - const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; - - for (unsigned a = 0; a < tot; a++) { - copy_v4db_v4fl(plane, rv3d->clip[a]); - glClipPlane(GL_CLIP_PLANE0 + a, plane); - glEnable(GL_CLIP_PLANE0 + a); - glEnable(GL_CLIP_DISTANCE0 + a); - } + double plane[4]; + const uint tot = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6; + + for (unsigned a = 0; a < tot; a++) { + copy_v4db_v4fl(plane, rv3d->clip[a]); + glClipPlane(GL_CLIP_PLANE0 + a, plane); + glEnable(GL_CLIP_PLANE0 + a); + glEnable(GL_CLIP_DISTANCE0 + a); + } #else - for (unsigned a = 0; a < 6; a++) { - glEnable(GL_CLIP_DISTANCE0 + a); - } + for (unsigned a = 0; a < 6; a++) { + glEnable(GL_CLIP_DISTANCE0 + a); + } #endif } /* use these to temp disable/enable clipping when 'rv3d->rflag & RV3D_CLIPPING' is set */ void ED_view3d_clipping_disable(void) { - for (unsigned a = 0; a < 6; a++) { + for (unsigned a = 0; a < 6; a++) { #ifdef USE_CLIP_PLANES - glDisable(GL_CLIP_PLANE0 + a); + glDisable(GL_CLIP_PLANE0 + a); #endif - glDisable(GL_CLIP_DISTANCE0 + a); - } + glDisable(GL_CLIP_DISTANCE0 + a); + } } void ED_view3d_clipping_enable(void) { - for (unsigned a = 0; a < 6; a++) { + for (unsigned a = 0; a < 6; a++) { #ifdef USE_CLIP_PLANES - glEnable(GL_CLIP_PLANE0 + a); + glEnable(GL_CLIP_PLANE0 + a); #endif - glEnable(GL_CLIP_DISTANCE0 + a); - } + glEnable(GL_CLIP_DISTANCE0 + a); + } } /* *********************** backdraw for selection *************** */ -static void validate_object_select_id( - struct Depsgraph *depsgraph, Scene *scene, - ARegion *ar, View3D *v3d, - Object *obact, Object *obedit, - short select_mode) +static void validate_object_select_id(struct Depsgraph *depsgraph, + Scene *scene, + ARegion *ar, + View3D *v3d, + Object *obact, + Object *obedit, + short select_mode) { - RegionView3D *rv3d = ar->regiondata; - Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); - Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); - - BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); - - if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || - BKE_paint_select_face_test(obact_eval))) - { - /* do nothing */ - } - /* texture paint mode sampling */ - else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && - (v3d->shading.type > OB_WIRE)) - { - /* do nothing */ - } - else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && - !XRAY_ENABLED(v3d)) - { - /* do nothing */ - } - else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && - !XRAY_FLAG_ENABLED(v3d)) - { - /* do nothing */ - } - else { - v3d->flag &= ~V3D_INVALID_BACKBUF; - return; - } - - if (!(v3d->flag & V3D_INVALID_BACKBUF)) { - return; - } + RegionView3D *rv3d = ar->regiondata; + Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id); + Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); + + BLI_assert(ar->regiontype == RGN_TYPE_WINDOW); + + if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) || + BKE_paint_select_face_test(obact_eval))) { + /* do nothing */ + } + /* texture paint mode sampling */ + else if (obact_eval && (obact_eval->mode & OB_MODE_TEXTURE_PAINT) && + (v3d->shading.type > OB_WIRE)) { + /* do nothing */ + } + else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) { + /* do nothing */ + } + else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) { + /* do nothing */ + } + else { + v3d->flag &= ~V3D_INVALID_BACKBUF; + return; + } + + if (!(v3d->flag & V3D_INVALID_BACKBUF)) { + return; + } #if 0 - if (test) { - if (qtest()) { - addafterqueue(ar->win, BACKBUFDRAW, 1); - return; - } - } + if (test) { + if (qtest()) { + addafterqueue(ar->win, BACKBUFDRAW, 1); + return; + } + } #endif #if 0 /* v3d->zbuf deprecated */ - if (v3d->shading.type > OB_WIRE) { - v3d->zbuf = true; - } + if (v3d->shading.type > OB_WIRE) { + v3d->zbuf = true; + } #endif - G.f |= G_FLAG_BACKBUFSEL; + G.f |= G_FLAG_BACKBUFSEL; - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - DRW_framebuffer_select_id_setup(ar, true); - draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); - DRW_framebuffer_select_id_release(ar); - } + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { + DRW_framebuffer_select_id_setup(ar, true); + draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode); + DRW_framebuffer_select_id_release(ar); + } - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - v3d->flag &= ~V3D_INVALID_BACKBUF; + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + v3d->flag &= ~V3D_INVALID_BACKBUF; - G.f &= ~G_FLAG_BACKBUFSEL; + G.f &= ~G_FLAG_BACKBUFSEL; } -void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +void view3d_opengl_read_pixels( + ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) { - glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } /* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. * Calling this function should be avoided during interactive drawing. */ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) { - DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); + DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); - GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); - GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); - GPU_framebuffer_bind(tmp_fb); - glDisable(GL_SCISSOR_TEST); + GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); + GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); + GPU_framebuffer_bind(tmp_fb); + glDisable(GL_SCISSOR_TEST); - glReadPixels(rect->xmin, rect->ymin, - BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - GL_DEPTH_COMPONENT, GL_FLOAT, data); + glReadPixels(rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + GL_DEPTH_COMPONENT, + GL_FLOAT, + data); - glEnable(GL_SCISSOR_TEST); - GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); + GPU_framebuffer_restore(); - GPU_framebuffer_free(tmp_fb); + GPU_framebuffer_free(tmp_fb); } void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode) { - /* TODO: Create a flag in `DRW_manager` because the drawing is no longer - * made on the backbuffer in this case. */ - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - validate_object_select_id( - vc->depsgraph, vc->scene, vc->ar, vc->v3d, - vc->obact, vc->obedit, select_mode); - } + /* TODO: Create a flag in `DRW_manager` because the drawing is no longer + * made on the backbuffer in this case. */ + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + validate_object_select_id( + vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode); + } } void ED_view3d_select_id_validate(ViewContext *vc) { - ED_view3d_select_id_validate_with_select_mode(vc, -1); + ED_view3d_select_id_validate_with_select_mode(vc, -1); } void ED_view3d_backbuf_depth_validate(ViewContext *vc) { - if (vc->v3d->flag & V3D_INVALID_BACKBUF) { - ARegion *ar = vc->ar; - RegionView3D *rv3d = ar->regiondata; - Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + if (vc->v3d->flag & V3D_INVALID_BACKBUF) { + ARegion *ar = vc->ar; + RegionView3D *rv3d = ar->regiondata; + Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { - GPU_scissor(ar->winrct.xmin, ar->winrct.ymin, - BLI_rcti_size_x(&ar->winrct), - BLI_rcti_size_y(&ar->winrct)); + if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) { + GPU_scissor(ar->winrct.xmin, + ar->winrct.ymin, + BLI_rcti_size_x(&ar->winrct), + BLI_rcti_size_y(&ar->winrct)); - GPU_depth_test(true); - GPU_clear(GPU_DEPTH_BIT); + GPU_depth_test(true); + GPU_clear(GPU_DEPTH_BIT); - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(rv3d); - } + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(rv3d); + } - draw_object_depth(rv3d, obact_eval); + draw_object_depth(rv3d, obact_eval); - if (rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } + if (rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } - GPU_depth_test(false); - } + GPU_depth_test(false); + } - vc->v3d->flag &= ~V3D_INVALID_BACKBUF; - } + vc->v3d->flag &= ~V3D_INVALID_BACKBUF; + } } uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len) { - ED_view3d_select_id_validate(vc); + ED_view3d_select_id_validate(vc); - uint width = BLI_rcti_size_x(clip); - uint height = BLI_rcti_size_y(clip); - uint buf_len = width * height; - uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__); + uint width = BLI_rcti_size_x(clip); + uint height = BLI_rcti_size_y(clip); + uint buf_len = width * height; + uint *buf = MEM_mallocN(buf_len * sizeof(*buf), __func__); - DRW_framebuffer_select_id_read(clip, buf); + DRW_framebuffer_select_id_read(clip, buf); - if (r_buf_len) { - *r_buf_len = buf_len; - } + if (r_buf_len) { + *r_buf_len = buf_len; + } - return buf; + return buf; } /** @@ -321,611 +322,623 @@ uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_b */ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) { - return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); } /* samples a single pixel (copied from vpaint) */ -uint ED_view3d_select_id_sample( - ViewContext *vc, int x, int y) +uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y) { - if (x >= vc->ar->winx || y >= vc->ar->winy) { - return 0; - } + if (x >= vc->ar->winx || y >= vc->ar->winy) { + return 0; + } - uint buf_len; - uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len); - BLI_assert(0 != buf_len); - uint ret = buf[0]; - MEM_freeN(buf); + uint buf_len; + uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len); + BLI_assert(0 != buf_len); + uint ret = buf[0]; + MEM_freeN(buf); - return ret; + return ret; } /* reads full rect, converts indices */ uint *ED_view3d_select_id_read( - ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) + ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len) { - if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { - return NULL; - } + if (UNLIKELY((xmin > xmax) || (ymin > ymax))) { + return NULL; + } - const rcti rect = { - .xmin = xmin, .xmax = xmax + 1, - .ymin = ymin, .ymax = ymax + 1, - }; + const rcti rect = { + .xmin = xmin, + .xmax = xmax + 1, + .ymin = ymin, + .ymax = ymax + 1, + }; - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len); + uint buf_len; + uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len); - if (r_buf_len) { - *r_buf_len = buf_len; - } + if (r_buf_len) { + *r_buf_len = buf_len; + } - return buf; + return buf; } /* smart function to sample a rect spiralling outside, nice for backbuf selection */ -uint ED_view3d_select_id_read_nearest( - struct ViewContext *UNUSED(vc), const int mval[2], - const uint id_min, const uint id_max, uint *r_dist) +uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc), + const int mval[2], + const uint id_min, + const uint id_max, + uint *r_dist) { - /* Create region around mouse cursor. This must be square and have an odd - * width, the spiralling algorithm does not work with arbitrary rectangles. */ - rcti rect; - BLI_rcti_init_pt_radius(&rect, mval, *r_dist); - rect.xmax += 1; - rect.ymax += 1; - - int width = BLI_rcti_size_x(&rect); - int height = width; - BLI_assert(width == height); - - /* Read from selection framebuffer. */ - uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__); - DRW_framebuffer_select_id_read(&rect, buf); - - /* Spiral, starting from center of buffer. */ - int spiral_offset = height * (int)(width / 2) + (height / 2); - int spiral_direction = 0; - - uint index = 0; - - for (int nr = 1; nr <= height; nr++) { - for (int a = 0; a < 2; a++) { - for (int b = 0; b < nr; b++) { - /* Find hit within the specified range. */ - uint hit_id = buf[spiral_offset]; - - if (hit_id && hit_id >= id_min && hit_id < id_max) { - /* Get x/y from spiral offset. */ - int hit_x = spiral_offset % width; - int hit_y = spiral_offset / width; - - int center_x = width / 2; - int center_y = height / 2; - - /* Manhatten distance in keeping with other screen-based selection. */ - *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); - - /* Indices start at 1 here. */ - index = (hit_id - id_min) + 1; - goto exit; - } - - /* Next spiral step. */ - if (spiral_direction == 0) { - spiral_offset += 1; /* right */ - } - else if (spiral_direction == 1) { - spiral_offset -= width; /* down */ - } - else if (spiral_direction == 2) { - spiral_offset -= 1; /* left */ - } - else { - spiral_offset += width; /* up */ - } - - /* Stop if we are outside the buffer. */ - if (spiral_offset < 0 || spiral_offset >= width * height) { - goto exit; - } - } - - spiral_direction = (spiral_direction + 1) % 4; - } - } + /* Create region around mouse cursor. This must be square and have an odd + * width, the spiralling algorithm does not work with arbitrary rectangles. */ + rcti rect; + BLI_rcti_init_pt_radius(&rect, mval, *r_dist); + rect.xmax += 1; + rect.ymax += 1; + + int width = BLI_rcti_size_x(&rect); + int height = width; + BLI_assert(width == height); + + /* Read from selection framebuffer. */ + uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__); + DRW_framebuffer_select_id_read(&rect, buf); + + /* Spiral, starting from center of buffer. */ + int spiral_offset = height * (int)(width / 2) + (height / 2); + int spiral_direction = 0; + + uint index = 0; + + for (int nr = 1; nr <= height; nr++) { + for (int a = 0; a < 2; a++) { + for (int b = 0; b < nr; b++) { + /* Find hit within the specified range. */ + uint hit_id = buf[spiral_offset]; + + if (hit_id && hit_id >= id_min && hit_id < id_max) { + /* Get x/y from spiral offset. */ + int hit_x = spiral_offset % width; + int hit_y = spiral_offset / width; + + int center_x = width / 2; + int center_y = height / 2; + + /* Manhatten distance in keeping with other screen-based selection. */ + *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); + + /* Indices start at 1 here. */ + index = (hit_id - id_min) + 1; + goto exit; + } + + /* Next spiral step. */ + if (spiral_direction == 0) { + spiral_offset += 1; /* right */ + } + else if (spiral_direction == 1) { + spiral_offset -= width; /* down */ + } + else if (spiral_direction == 2) { + spiral_offset -= 1; /* left */ + } + else { + spiral_offset += width; /* up */ + } + + /* Stop if we are outside the buffer. */ + if (spiral_offset < 0 || spiral_offset >= width * height) { + goto exit; + } + } + + spiral_direction = (spiral_direction + 1) % 4; + } + } exit: - MEM_freeN(buf); - return index; + MEM_freeN(buf); + return index; } - /* ************************************************************* */ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser) { - if (BKE_image_is_stereo(ima)) { - iuser->flag |= IMA_SHOW_STEREO; - - if ((scene->r.scemode & R_MULTIVIEW) == 0) { - iuser->multiview_eye = STEREO_LEFT_ID; - } - else if (v3d->stereo3d_camera != STEREO_3D_ID) { - /* show only left or right camera */ - iuser->multiview_eye = v3d->stereo3d_camera; - } - - BKE_image_multiview_index(ima, iuser); - } - else { - iuser->flag &= ~IMA_SHOW_STEREO; - } + if (BKE_image_is_stereo(ima)) { + iuser->flag |= IMA_SHOW_STEREO; + + if ((scene->r.scemode & R_MULTIVIEW) == 0) { + iuser->multiview_eye = STEREO_LEFT_ID; + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ + iuser->multiview_eye = v3d->stereo3d_camera; + } + + BKE_image_multiview_index(ima, iuser); + } + else { + iuser->flag &= ~IMA_SHOW_STEREO; + } } -static void view3d_draw_bgpic(Scene *scene, Depsgraph *depsgraph, - ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) +static void view3d_draw_bgpic(Scene *scene, + Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + const bool do_foreground, + const bool do_camera_frame) { - RegionView3D *rv3d = ar->regiondata; - int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0; - if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) { - return; - } - Camera *cam = v3d->camera->data; - - for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { - if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) { - continue; - } - - { - float image_aspect[2]; - float x1, y1, x2, y2, centx, centy; - - void *lock; - - Image *ima = NULL; - - /* disable individual images */ - if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) { - continue; - } - - ImBuf *ibuf = NULL; - ImBuf *freeibuf = NULL; - ImBuf *releaseibuf = NULL; - if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { - ima = bgpic->ima; - if (ima == NULL) { - continue; - } - - ImageUser iuser = bgpic->iuser; - iuser.scene = scene; /* Needed for render results. */ - BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph)); - if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) { - ibuf = NULL; /* frame is out of range, dont show */ - } - else { - view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser); - ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); - releaseibuf = ibuf; - } - - image_aspect[0] = ima->aspx; - image_aspect[1] = ima->aspy; - } - else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { - /* TODO: skip drawing when out of frame range (as image sequences do above) */ - MovieClip *clip = NULL; - - if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { - if (scene->camera) { - clip = BKE_object_movieclip_get(scene, scene->camera, true); - } - } - else { - clip = bgpic->clip; - } - - if (clip == NULL) { - continue; - } - - BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph)); - ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); - - image_aspect[0] = clip->aspx; - image_aspect[1] = clip->aspy; - - /* working with ibuf from image and clip has got different workflow now. - * ibuf acquired from clip is referenced by cache system and should - * be dereferenced after usage. */ - freeibuf = ibuf; - } - else { - /* perhaps when loading future files... */ - BLI_assert(0); - copy_v2_fl(image_aspect, 1.0f); - } - - if (ibuf == NULL) { - continue; - } - - if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { - /* invalid image format */ - if (freeibuf) { - IMB_freeImBuf(freeibuf); - } - if (releaseibuf) { - BKE_image_release_ibuf(ima, releaseibuf, lock); - } - - continue; - } - - if (ibuf->rect == NULL) { - IMB_rect_from_float(ibuf); - } - - BLI_assert(rv3d->persp == RV3D_CAMOB); - { - if (do_camera_frame) { - rctf vb; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false); - x1 = vb.xmin; - y1 = vb.ymin; - x2 = vb.xmax; - y2 = vb.ymax; - } - else { - x1 = ar->winrct.xmin; - y1 = ar->winrct.ymin; - x2 = ar->winrct.xmax; - y2 = ar->winrct.ymax; - } - - /* apply offset last - camera offset is different to offset in blender units */ - /* so this has some sane way of working - this matches camera's shift _exactly_ */ - { - const float max_dim = max_ff(x2 - x1, y2 - y1); - const float xof_scale = bgpic->offset[0] * max_dim; - const float yof_scale = bgpic->offset[1] * max_dim; - - x1 += xof_scale; - y1 += yof_scale; - x2 += xof_scale; - y2 += yof_scale; - } - - centx = (x1 + x2) * 0.5f; - centy = (y1 + y2) * 0.5f; - - /* aspect correction */ - if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) { - /* apply aspect from clip */ - const float w_src = ibuf->x * image_aspect[0]; - const float h_src = ibuf->y * image_aspect[1]; - - /* destination aspect is already applied from the camera frame */ - const float w_dst = x1 - x2; - const float h_dst = y1 - y2; - - const float asp_src = w_src / h_src; - const float asp_dst = w_dst / h_dst; - - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) { - /* fit X */ - const float div = asp_src / asp_dst; - x1 = ((x1 - centx) * div) + centx; - x2 = ((x2 - centx) * div) + centx; - } - else { - /* fit Y */ - const float div = asp_dst / asp_src; - y1 = ((y1 - centy) * div) + centy; - y2 = ((y2 - centy) * div) + centy; - } - } - } - } - - /* complete clip? */ - rctf clip_rect; - BLI_rctf_init(&clip_rect, x1, x2, y1, y2); - if (bgpic->rotation) { - BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); - } - - if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || clip_rect.ymin > ar->winy) { - if (freeibuf) { - IMB_freeImBuf(freeibuf); - } - if (releaseibuf) { - BKE_image_release_ibuf(ima, releaseibuf, lock); - } - - continue; - } - - float zoomx = (x2 - x1) / ibuf->x; - float zoomy = (y2 - y1) / ibuf->y; - - /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */ - if (zoomx < 1.0f || zoomy < 1.0f) { - float tzoom = min_ff(zoomx, zoomy); - int mip = 0; - - if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { - IMB_remakemipmap(ibuf, 0); - ibuf->userflags &= ~IB_MIPMAP_INVALID; - } - else if (ibuf->mipmap[0] == NULL) { - IMB_makemipmap(ibuf, 0); - } - - while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { - tzoom *= 2.0f; - zoomx *= 2.0f; - zoomy *= 2.0f; - mip++; - } - if (mip > 0) { - ibuf = ibuf->mipmap[mip - 1]; - } - } - - GPU_depth_test(!do_foreground); - glDepthMask(GL_FALSE); - - GPU_blend(true); - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - - GPU_matrix_push_projection(); - GPU_matrix_push(); - ED_region_pixelspace(ar); - - GPU_matrix_translate_2f(centx, centy); - GPU_matrix_scale_1f(bgpic->scale); - GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation)); - - if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) { - zoomx *= -1.0f; - x1 = x2; - } - if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) { - zoomy *= -1.0f; - y1 = y2; - } - - float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; - IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); - immDrawPixelsTex(&state, x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect, - zoomx, zoomy, col); - - GPU_matrix_pop_projection(); - GPU_matrix_pop(); - - GPU_blend(false); - - glDepthMask(GL_TRUE); - GPU_depth_test(true); - - if (freeibuf) { - IMB_freeImBuf(freeibuf); - } - if (releaseibuf) { - BKE_image_release_ibuf(ima, releaseibuf, lock); - } - } - } + RegionView3D *rv3d = ar->regiondata; + int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0; + if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) { + return; + } + Camera *cam = v3d->camera->data; + + for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { + if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) { + continue; + } + + { + float image_aspect[2]; + float x1, y1, x2, y2, centx, centy; + + void *lock; + + Image *ima = NULL; + + /* disable individual images */ + if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) { + continue; + } + + ImBuf *ibuf = NULL; + ImBuf *freeibuf = NULL; + ImBuf *releaseibuf = NULL; + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + ima = bgpic->ima; + if (ima == NULL) { + continue; + } + + ImageUser iuser = bgpic->iuser; + iuser.scene = scene; /* Needed for render results. */ + BKE_image_user_frame_calc(&iuser, (int)DEG_get_ctime(depsgraph)); + if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) { + ibuf = NULL; /* frame is out of range, dont show */ + } + else { + view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock); + releaseibuf = ibuf; + } + + image_aspect[0] = ima->aspx; + image_aspect[1] = ima->aspy; + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + /* TODO: skip drawing when out of frame range (as image sequences do above) */ + MovieClip *clip = NULL; + + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { + if (scene->camera) { + clip = BKE_object_movieclip_get(scene, scene->camera, true); + } + } + else { + clip = bgpic->clip; + } + + if (clip == NULL) { + continue; + } + + BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph)); + ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser); + + image_aspect[0] = clip->aspx; + image_aspect[1] = clip->aspy; + + /* working with ibuf from image and clip has got different workflow now. + * ibuf acquired from clip is referenced by cache system and should + * be dereferenced after usage. */ + freeibuf = ibuf; + } + else { + /* perhaps when loading future files... */ + BLI_assert(0); + copy_v2_fl(image_aspect, 1.0f); + } + + if (ibuf == NULL) { + continue; + } + + if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { + /* invalid image format */ + if (freeibuf) { + IMB_freeImBuf(freeibuf); + } + if (releaseibuf) { + BKE_image_release_ibuf(ima, releaseibuf, lock); + } + + continue; + } + + if (ibuf->rect == NULL) { + IMB_rect_from_float(ibuf); + } + + BLI_assert(rv3d->persp == RV3D_CAMOB); + { + if (do_camera_frame) { + rctf vb; + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false); + x1 = vb.xmin; + y1 = vb.ymin; + x2 = vb.xmax; + y2 = vb.ymax; + } + else { + x1 = ar->winrct.xmin; + y1 = ar->winrct.ymin; + x2 = ar->winrct.xmax; + y2 = ar->winrct.ymax; + } + + /* apply offset last - camera offset is different to offset in blender units */ + /* so this has some sane way of working - this matches camera's shift _exactly_ */ + { + const float max_dim = max_ff(x2 - x1, y2 - y1); + const float xof_scale = bgpic->offset[0] * max_dim; + const float yof_scale = bgpic->offset[1] * max_dim; + + x1 += xof_scale; + y1 += yof_scale; + x2 += xof_scale; + y2 += yof_scale; + } + + centx = (x1 + x2) * 0.5f; + centy = (y1 + y2) * 0.5f; + + /* aspect correction */ + if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) { + /* apply aspect from clip */ + const float w_src = ibuf->x * image_aspect[0]; + const float h_src = ibuf->y * image_aspect[1]; + + /* destination aspect is already applied from the camera frame */ + const float w_dst = x1 - x2; + const float h_dst = y1 - y2; + + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { + if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) { + /* fit X */ + const float div = asp_src / asp_dst; + x1 = ((x1 - centx) * div) + centx; + x2 = ((x2 - centx) * div) + centx; + } + else { + /* fit Y */ + const float div = asp_dst / asp_src; + y1 = ((y1 - centy) * div) + centy; + y2 = ((y2 - centy) * div) + centy; + } + } + } + } + + /* complete clip? */ + rctf clip_rect; + BLI_rctf_init(&clip_rect, x1, x2, y1, y2); + if (bgpic->rotation) { + BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation); + } + + if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx || + clip_rect.ymin > ar->winy) { + if (freeibuf) { + IMB_freeImBuf(freeibuf); + } + if (releaseibuf) { + BKE_image_release_ibuf(ima, releaseibuf, lock); + } + + continue; + } + + float zoomx = (x2 - x1) / ibuf->x; + float zoomy = (y2 - y1) / ibuf->y; + + /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */ + if (zoomx < 1.0f || zoomy < 1.0f) { + float tzoom = min_ff(zoomx, zoomy); + int mip = 0; + + if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) { + IMB_remakemipmap(ibuf, 0); + ibuf->userflags &= ~IB_MIPMAP_INVALID; + } + else if (ibuf->mipmap[0] == NULL) { + IMB_makemipmap(ibuf, 0); + } + + while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) { + tzoom *= 2.0f; + zoomx *= 2.0f; + zoomy *= 2.0f; + mip++; + } + if (mip > 0) { + ibuf = ibuf->mipmap[mip - 1]; + } + } + + GPU_depth_test(!do_foreground); + glDepthMask(GL_FALSE); + + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + + GPU_matrix_push_projection(); + GPU_matrix_push(); + ED_region_pixelspace(ar); + + GPU_matrix_translate_2f(centx, centy); + GPU_matrix_scale_1f(bgpic->scale); + GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation)); + + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) { + zoomx *= -1.0f; + x1 = x2; + } + if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) { + zoomy *= -1.0f; + y1 = y2; + } + + float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha}; + IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); + immDrawPixelsTex(&state, + x1 - centx, + y1 - centy, + ibuf->x, + ibuf->y, + GL_RGBA, + GL_UNSIGNED_BYTE, + GL_LINEAR, + ibuf->rect, + zoomx, + zoomy, + col); + + GPU_matrix_pop_projection(); + GPU_matrix_pop(); + + GPU_blend(false); + + glDepthMask(GL_TRUE); + GPU_depth_test(true); + + if (freeibuf) { + IMB_freeImBuf(freeibuf); + } + if (releaseibuf) { + BKE_image_release_ibuf(ima, releaseibuf, lock); + } + } + } } -void ED_view3d_draw_bgpic_test( - Scene *scene, Depsgraph *depsgraph, - ARegion *ar, View3D *v3d, - const bool do_foreground, const bool do_camera_frame) +void ED_view3d_draw_bgpic_test(Scene *scene, + Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + const bool do_foreground, + const bool do_camera_frame) { - RegionView3D *rv3d = ar->regiondata; - - if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { - Camera *cam = v3d->camera->data; - if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) { - return; - } - } - else { - return; - } - - /* disabled - mango request, since footage /w only render is quite useful - * and this option is easy to disable all background images at once */ + RegionView3D *rv3d = ar->regiondata; + + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { + Camera *cam = v3d->camera->data; + if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) { + return; + } + } + else { + return; + } + + /* disabled - mango request, since footage /w only render is quite useful + * and this option is easy to disable all background images at once */ #if 0 - if (v3d->flag2 & V3D_HIDE_OVERLAYS) { - return; - } + if (v3d->flag2 & V3D_HIDE_OVERLAYS) { + return; + } #endif - if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { - if (rv3d->persp == RV3D_CAMOB) { - view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame); - } - } - else { - view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame); - } + if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) { + if (rv3d->persp == RV3D_CAMOB) { + view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame); + } + } + else { + view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame); + } } /* *********************** */ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) { - /* clamp rect by region */ - rcti r = { - .xmin = 0, - .xmax = ar->winx - 1, - .ymin = 0, - .ymax = ar->winy - 1, - }; - - /* Constrain rect to depth bounds */ - BLI_rcti_isect(&r, rect, rect); - - /* assign values to compare with the ViewDepths */ - int x = rect->xmin; - int y = rect->ymin; - - int w = BLI_rcti_size_x(rect); - int h = BLI_rcti_size_y(rect); - - if (w <= 0 || h <= 0) { - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = NULL; - - d->damaged = false; - } - else if (d->w != w || - d->h != h || - d->x != x || - d->y != y || - d->depths == NULL - ) - { - d->x = x; - d->y = y; - d->w = w; - d->h = h; - - if (d->depths) { - MEM_freeN(d->depths); - } - - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); - - d->damaged = true; - } - - if (d->damaged) { - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - view3d_opengl_read_Z_pixels(viewport, rect, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - d->damaged = false; - } + /* clamp rect by region */ + rcti r = { + .xmin = 0, + .xmax = ar->winx - 1, + .ymin = 0, + .ymax = ar->winy - 1, + }; + + /* Constrain rect to depth bounds */ + BLI_rcti_isect(&r, rect, rect); + + /* assign values to compare with the ViewDepths */ + int x = rect->xmin; + int y = rect->ymin; + + int w = BLI_rcti_size_x(rect); + int h = BLI_rcti_size_y(rect); + + if (w <= 0 || h <= 0) { + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = NULL; + + d->damaged = false; + } + else if (d->w != w || d->h != h || d->x != x || d->y != y || d->depths == NULL) { + d->x = x; + d->y = y; + d->w = w; + d->h = h; + + if (d->depths) { + MEM_freeN(d->depths); + } + + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths Subset"); + + d->damaged = true; + } + + if (d->damaged) { + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + view3d_opengl_read_Z_pixels(viewport, rect, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + d->damaged = false; + } } /* note, with nouveau drivers the glReadPixels() is very slow. [#24339] */ void ED_view3d_depth_update(ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; - - /* Create storage for, and, if necessary, copy depth buffer */ - if (!rv3d->depths) { - rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); - } - if (rv3d->depths) { - ViewDepths *d = rv3d->depths; - if (d->w != ar->winx || - d->h != ar->winy || - !d->depths) - { - d->w = ar->winx; - d->h = ar->winy; - if (d->depths) { - MEM_freeN(d->depths); - } - d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); - d->damaged = true; - } - - if (d->damaged) { - view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - glGetDoublev(GL_DEPTH_RANGE, d->depth_range); - - d->damaged = false; - } - } + RegionView3D *rv3d = ar->regiondata; + + /* Create storage for, and, if necessary, copy depth buffer */ + if (!rv3d->depths) { + rv3d->depths = MEM_callocN(sizeof(ViewDepths), "ViewDepths"); + } + if (rv3d->depths) { + ViewDepths *d = rv3d->depths; + if (d->w != ar->winx || d->h != ar->winy || !d->depths) { + d->w = ar->winx; + d->h = ar->winy; + if (d->depths) { + MEM_freeN(d->depths); + } + d->depths = MEM_mallocN(sizeof(float) * d->w * d->h, "View depths"); + d->damaged = true; + } + + if (d->damaged) { + view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + glGetDoublev(GL_DEPTH_RANGE, d->depth_range); + + d->damaged = false; + } + } } /* utility function to find the closest Z value, use for autodepth */ float view3d_depth_near(ViewDepths *d) { - /* convert to float for comparisons */ - const float near = (float)d->depth_range[0]; - const float far_real = (float)d->depth_range[1]; - float far = far_real; - - const float *depths = d->depths; - float depth = FLT_MAX; - int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ - - /* far is both the starting 'far' value - * and the closest value found. */ - while (i--) { - depth = *depths++; - if ((depth < far) && (depth > near)) { - far = depth; - } - } - - return far == far_real ? FLT_MAX : far; + /* convert to float for comparisons */ + const float near = (float)d->depth_range[0]; + const float far_real = (float)d->depth_range[1]; + float far = far_real; + + const float *depths = d->depths; + float depth = FLT_MAX; + int i = (int)d->w * (int)d->h; /* cast to avoid short overflow */ + + /* far is both the starting 'far' value + * and the closest value found. */ + while (i--) { + depth = *depths++; + if ((depth < far) && (depth > near)) { + far = depth; + } + } + + return far == far_real ? FLT_MAX : far; } -void ED_view3d_draw_depth_gpencil( - Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) +void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d) { - /* Setup view matrix. */ - ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); + /* Setup view matrix. */ + ED_view3d_draw_setup_view(NULL, depsgraph, scene, ar, v3d, NULL, NULL, NULL); - GPU_clear(GPU_DEPTH_BIT); + GPU_clear(GPU_DEPTH_BIT); - GPU_depth_test(true); + GPU_depth_test(true); - GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); - DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); + GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0); + DRW_draw_depth_loop_gpencil(depsgraph, ar, v3d, viewport); - GPU_depth_test(false); + GPU_depth_test(false); } /* *********************** customdata **************** */ -void ED_view3d_datamask( - const bContext *C, const Scene *UNUSED(scene), const View3D *v3d, CustomData_MeshMasks *r_cddata_masks) +void ED_view3d_datamask(const bContext *C, + const Scene *UNUSED(scene), + const View3D *v3d, + CustomData_MeshMasks *r_cddata_masks) { - const int drawtype = view3d_effective_drawtype(v3d); + const int drawtype = view3d_effective_drawtype(v3d); - if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL)) { - r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; + if (ELEM(drawtype, OB_TEXTURE, OB_MATERIAL)) { + r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; - if (drawtype == OB_MATERIAL) { - r_cddata_masks->vmask |= CD_MASK_ORCO; - } - } + if (drawtype == OB_MATERIAL) { + r_cddata_masks->vmask |= CD_MASK_ORCO; + } + } - if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && - (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) - { - r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; - } + if ((CTX_data_mode_enum(C) == CTX_MODE_EDIT_MESH) && + (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT)) { + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; + } } /* goes over all modes and view3d settings */ -void ED_view3d_screen_datamask( - const bContext *C, const Scene *scene, const bScreen *screen, CustomData_MeshMasks *r_cddata_masks) +void ED_view3d_screen_datamask(const bContext *C, + const Scene *scene, + const bScreen *screen, + CustomData_MeshMasks *r_cddata_masks) { - CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); - - /* check if we need tfaces & mcols due to view mode */ - for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); - } - } + CustomData_MeshMasks_update(r_cddata_masks, &CD_MASK_BAREMESH); + + /* check if we need tfaces & mcols due to view mode */ + for (const ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_VIEW3D) { + ED_view3d_datamask(C, scene, sa->spacedata.first, r_cddata_masks); + } + } } /** @@ -935,38 +948,38 @@ void ED_view3d_screen_datamask( * Values set by #ED_view3d_update_viewmat should be handled here. */ struct RV3DMatrixStore { - float winmat[4][4]; - float viewmat[4][4]; - float viewinv[4][4]; - float persmat[4][4]; - float persinv[4][4]; - float viewcamtexcofac[4]; - float pixsize; + float winmat[4][4]; + float viewmat[4][4]; + float viewinv[4][4]; + float persmat[4][4]; + float persinv[4][4]; + float viewcamtexcofac[4]; + float pixsize; }; struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d) { - struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); - copy_m4_m4(rv3dmat->winmat, rv3d->winmat); - copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); - copy_m4_m4(rv3dmat->persmat, rv3d->persmat); - copy_m4_m4(rv3dmat->persinv, rv3d->persinv); - copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); - copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); - rv3dmat->pixsize = rv3d->pixsize; - return (void *)rv3dmat; + struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__); + copy_m4_m4(rv3dmat->winmat, rv3d->winmat); + copy_m4_m4(rv3dmat->viewmat, rv3d->viewmat); + copy_m4_m4(rv3dmat->persmat, rv3d->persmat); + copy_m4_m4(rv3dmat->persinv, rv3d->persinv); + copy_m4_m4(rv3dmat->viewinv, rv3d->viewinv); + copy_v4_v4(rv3dmat->viewcamtexcofac, rv3d->viewcamtexcofac); + rv3dmat->pixsize = rv3d->pixsize; + return (void *)rv3dmat; } void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt) { - struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; - copy_m4_m4(rv3d->winmat, rv3dmat->winmat); - copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); - copy_m4_m4(rv3d->persmat, rv3dmat->persmat); - copy_m4_m4(rv3d->persinv, rv3dmat->persinv); - copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); - copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); - rv3d->pixsize = rv3dmat->pixsize; + struct RV3DMatrixStore *rv3dmat = rv3dmat_pt; + copy_m4_m4(rv3d->winmat, rv3dmat->winmat); + copy_m4_m4(rv3d->viewmat, rv3dmat->viewmat); + copy_m4_m4(rv3d->persmat, rv3dmat->persmat); + copy_m4_m4(rv3d->persinv, rv3dmat->persinv); + copy_m4_m4(rv3d->viewinv, rv3dmat->viewinv); + copy_v4_v4(rv3d->viewcamtexcofac, rv3dmat->viewcamtexcofac); + rv3d->pixsize = rv3dmat->pixsize; } /** @@ -975,115 +988,117 @@ void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixSto */ void ED_scene_draw_fps(Scene *scene, int xoffset, int *yoffset) { - ScreenFrameRateInfo *fpsi = scene->fps_info; - char printable[16]; + ScreenFrameRateInfo *fpsi = scene->fps_info; + char printable[16]; - if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { - return; - } + if (!fpsi || !fpsi->lredrawtime || !fpsi->redrawtime) { + return; + } - printable[0] = '\0'; + printable[0] = '\0'; #if 0 - /* this is too simple, better do an average */ - fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) + /* this is too simple, better do an average */ + fps = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)) #else - fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / (fpsi->lredrawtime - fpsi->redrawtime)); - - float fps = 0.0f; - int tot = 0; - for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { - if (fpsi->redrawtimes_fps[i]) { - fps += fpsi->redrawtimes_fps[i]; - tot++; - } - } - if (tot) { - fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; - - //fpsi->redrawtime_index++; - //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) { - // fpsi->redrawtime = 0; - //} - - fps = fps / tot; - } + fpsi->redrawtimes_fps[fpsi->redrawtime_index] = (float)(1.0 / + (fpsi->lredrawtime - fpsi->redrawtime)); + + float fps = 0.0f; + int tot = 0; + for (int i = 0; i < REDRAW_FRAME_AVERAGE; i++) { + if (fpsi->redrawtimes_fps[i]) { + fps += fpsi->redrawtimes_fps[i]; + tot++; + } + } + if (tot) { + fpsi->redrawtime_index = (fpsi->redrawtime_index + 1) % REDRAW_FRAME_AVERAGE; + + //fpsi->redrawtime_index++; + //if (fpsi->redrawtime >= REDRAW_FRAME_AVERAGE) { + // fpsi->redrawtime = 0; + //} + + fps = fps / tot; + } #endif - const int font_id = BLF_default(); + const int font_id = BLF_default(); - /* is this more than half a frame behind? */ - if (fps + 0.5f < (float)(FPS)) { - UI_FontThemeColor(font_id, TH_REDALERT); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); - } - else { - UI_FontThemeColor(font_id, TH_TEXT_HI); - BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); - } + /* is this more than half a frame behind? */ + if (fps + 0.5f < (float)(FPS)) { + UI_FontThemeColor(font_id, TH_REDALERT); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %.2f"), fps); + } + else { + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLI_snprintf(printable, sizeof(printable), IFACE_("fps: %i"), (int)(fps + 0.5f)); + } - BLF_enable(font_id, BLF_SHADOW); - BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); - BLF_shadow_offset(font_id, 1, -1); + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); - *yoffset -= U.widget_unit; + *yoffset -= U.widget_unit; #ifdef WITH_INTERNATIONAL - BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); + BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); #else - BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); + BLF_draw_default_ascii(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); #endif - BLF_disable(font_id, BLF_SHADOW); + BLF_disable(font_id, BLF_SHADOW); } static bool view3d_main_region_do_render_draw(const Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->view_update && type->view_draw); + RenderEngineType *type = RE_engines_find(scene->r.engine); + return (type && type->view_update && type->view_draw); } -bool ED_view3d_calc_render_border(const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) +bool ED_view3d_calc_render_border( + const Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - bool use_border; - - /* test if there is a 3d view rendering */ - if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { - return false; - } - - /* test if there is a border render */ - if (rv3d->persp == RV3D_CAMOB) { - use_border = (scene->r.mode & R_BORDER) != 0; - } - else { - use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; - } - - if (!use_border) { - return false; - } - - /* compute border */ - if (rv3d->persp == RV3D_CAMOB) { - rctf viewborder; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); - - rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); - rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); - rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); - rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); - } - else { - rect->xmin = v3d->render_border.xmin * ar->winx; - rect->xmax = v3d->render_border.xmax * ar->winx; - rect->ymin = v3d->render_border.ymin * ar->winy; - rect->ymax = v3d->render_border.ymax * ar->winy; - } - - BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); - BLI_rcti_isect(&ar->winrct, rect, rect); - - return true; + RegionView3D *rv3d = ar->regiondata; + bool use_border; + + /* test if there is a 3d view rendering */ + if (v3d->shading.type != OB_RENDER || !view3d_main_region_do_render_draw(scene)) { + return false; + } + + /* test if there is a border render */ + if (rv3d->persp == RV3D_CAMOB) { + use_border = (scene->r.mode & R_BORDER) != 0; + } + else { + use_border = (v3d->flag2 & V3D_RENDER_BORDER) != 0; + } + + if (!use_border) { + return false; + } + + /* compute border */ + if (rv3d->persp == RV3D_CAMOB) { + rctf viewborder; + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false); + + rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder); + rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder); + rect->xmax = viewborder.xmin + scene->r.border.xmax * BLI_rctf_size_x(&viewborder); + rect->ymax = viewborder.ymin + scene->r.border.ymax * BLI_rctf_size_y(&viewborder); + } + else { + rect->xmin = v3d->render_border.xmin * ar->winx; + rect->xmax = v3d->render_border.xmax * ar->winx; + rect->ymin = v3d->render_border.ymin * ar->winy; + rect->ymax = v3d->render_border.ymax * ar->winy; + } + + BLI_rcti_translate(rect, ar->winrct.xmin, ar->winrct.ymin); + BLI_rcti_isect(&ar->winrct, rect, rect); + + return true; } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index e74703baf2d..1d2d361d868 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -78,12 +78,11 @@ #include "PIL_time.h" -#include "view3d_intern.h" /* own include */ - +#include "view3d_intern.h" /* own include */ enum { - HAS_TRANSLATE = (1 << 0), - HAS_ROTATE = (1 << 0), + HAS_TRANSLATE = (1 << 0), + HAS_ROTATE = (1 << 0), }; /* -------------------------------------------------------------------- */ @@ -91,35 +90,37 @@ enum { * \{ */ enum eV3D_OpPropFlag { - V3D_OP_PROP_MOUSE_CO = (1 << 0), - 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_MOUSE_CO = (1 << 0), + V3D_OP_PROP_DELTA = (1 << 1), + V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2), + V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3), }; static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag) { - if (flag & V3D_OP_PROP_MOUSE_CO) { - PropertyRNA *prop; - prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); - prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); - } - if (flag & V3D_OP_PROP_DELTA) { - RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); - } - if (flag & V3D_OP_PROP_USE_ALL_REGIONS) { - PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - } - if (flag & V3D_OP_PROP_USE_MOUSE_INIT) { - /* Disable when view operators are initialized from buttons. */ - PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); - } + if (flag & V3D_OP_PROP_MOUSE_CO) { + PropertyRNA *prop; + prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + } + if (flag & V3D_OP_PROP_DELTA) { + RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); + } + if (flag & V3D_OP_PROP_USE_ALL_REGIONS) { + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + } + if (flag & V3D_OP_PROP_USE_MOUSE_INIT) { + /* Disable when view operators are initialized from buttons. */ + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); + } } /** \} */ @@ -129,87 +130,87 @@ static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3 * \{ */ typedef struct ViewOpsData { - /** Context pointers (assigned by #viewops_data_alloc). */ - Main *bmain; - Scene *scene; - ScrArea *sa; - ARegion *ar; - View3D *v3d; - RegionView3D *rv3d; - Depsgraph *depsgraph; - - /** Needed for continuous zoom. */ - wmTimer *timer; - - /** Viewport state on initialization, don't change afterwards. */ - struct { - float dist; - float camzoom; - float quat[4]; - /** #wmEvent.x, y. */ - int event_xy[2]; - /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set. - * so we can simulate pressing in the middle of the screen. */ - int event_xy_offset[2]; - /** #wmEvent.type that triggered the operator. */ - int event_type; - float ofs[3]; - /** Initial distance to 'ofs'. */ - float zfac; - - /** Trackball rotation only. */ - float trackvec[3]; - /** Dolly only. */ - float mousevec[3]; - } init; - - /** Previous state (previous modal event handled). */ - struct { - int event_xy[2]; - /** For operators that use time-steps (continuous zoom). */ - double time; - } prev; - - /** Current state. */ - struct { - /** Working copy of #RegionView3D.viewquat, needed for rotation calculation - * so we can apply snap to the view-port while keeping the unsnapped rotation - * here to use when snap is disabled and for continued calculation. */ - float viewquat[4]; - } curr; - - float reverse; - bool axis_snap; /* view rotate only */ - - /** Use for orbit selection and auto-dist. */ - float dyn_ofs[3]; - bool use_dyn_ofs; + /** Context pointers (assigned by #viewops_data_alloc). */ + Main *bmain; + Scene *scene; + ScrArea *sa; + ARegion *ar; + View3D *v3d; + RegionView3D *rv3d; + Depsgraph *depsgraph; + + /** Needed for continuous zoom. */ + wmTimer *timer; + + /** Viewport state on initialization, don't change afterwards. */ + struct { + float dist; + float camzoom; + float quat[4]; + /** #wmEvent.x, y. */ + int event_xy[2]; + /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set. + * so we can simulate pressing in the middle of the screen. */ + int event_xy_offset[2]; + /** #wmEvent.type that triggered the operator. */ + int event_type; + float ofs[3]; + /** Initial distance to 'ofs'. */ + float zfac; + + /** Trackball rotation only. */ + float trackvec[3]; + /** Dolly only. */ + float mousevec[3]; + } init; + + /** Previous state (previous modal event handled). */ + struct { + int event_xy[2]; + /** For operators that use time-steps (continuous zoom). */ + double time; + } prev; + + /** Current state. */ + struct { + /** Working copy of #RegionView3D.viewquat, needed for rotation calculation + * so we can apply snap to the view-port while keeping the unsnapped rotation + * here to use when snap is disabled and for continued calculation. */ + float viewquat[4]; + } curr; + + float reverse; + bool axis_snap; /* view rotate only */ + + /** Use for orbit selection and auto-dist. */ + float dyn_ofs[3]; + bool use_dyn_ofs; } ViewOpsData; -#define TRACKBALLSIZE (1.1f) +#define TRACKBALLSIZE (1.1f) static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[3]) { - const float radius = TRACKBALLSIZE; - const float t = radius / (float)M_SQRT2; - float x, y, z, d; + const float radius = TRACKBALLSIZE; + const float t = radius / (float)M_SQRT2; + float x, y, z, d; - /* normalize x and y */ - x = BLI_rcti_cent_x(rect) - event_xy[0]; - x /= (float)(BLI_rcti_size_x(rect) / 4); - y = BLI_rcti_cent_y(rect) - event_xy[1]; - y /= (float)(BLI_rcti_size_y(rect) / 2); - d = sqrtf(x * x + y * y); - if (d < t) { /* Inside sphere */ - z = sqrtf(radius * radius - d * d); - } - else { /* On hyperbola */ - z = t * t / d; - } + /* normalize x and y */ + x = BLI_rcti_cent_x(rect) - event_xy[0]; + x /= (float)(BLI_rcti_size_x(rect) / 4); + y = BLI_rcti_cent_y(rect) - event_xy[1]; + y /= (float)(BLI_rcti_size_y(rect) / 2); + d = sqrtf(x * x + y * y); + if (d < t) { /* Inside sphere */ + z = sqrtf(radius * radius - d * d); + } + else { /* On hyperbola */ + z = t * t / d; + } - vec[0] = x; - vec[1] = y; - vec[2] = -z; /* yah yah! */ + vec[0] = x; + vec[1] = y; + vec[2] = -z; /* yah yah! */ } /** @@ -217,331 +218,330 @@ static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[ */ static void viewops_data_alloc(bContext *C, wmOperator *op) { - ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data"); + ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data"); - /* store data */ - op->customdata = vod; - vod->bmain = CTX_data_main(C); - vod->depsgraph = CTX_data_depsgraph(C); - vod->scene = CTX_data_scene(C); - vod->sa = CTX_wm_area(C); - vod->ar = CTX_wm_region(C); - vod->v3d = vod->sa->spacedata.first; - vod->rv3d = vod->ar->regiondata; + /* store data */ + op->customdata = vod; + vod->bmain = CTX_data_main(C); + vod->depsgraph = CTX_data_depsgraph(C); + vod->scene = CTX_data_scene(C); + vod->sa = CTX_wm_area(C); + vod->ar = CTX_wm_region(C); + vod->v3d = vod->sa->spacedata.first; + vod->rv3d = vod->ar->regiondata; } -void view3d_orbit_apply_dyn_ofs( - float r_ofs[3], const float ofs_init[3], const float viewquat_old[4], - const float viewquat_new[4], const float dyn_ofs[3]) +void view3d_orbit_apply_dyn_ofs(float r_ofs[3], + const float ofs_init[3], + const float viewquat_old[4], + const float viewquat_new[4], + const float dyn_ofs[3]) { - float q[4]; - invert_qt_qt_normalized(q, viewquat_old); - mul_qt_qtqt(q, q, viewquat_new); + float q[4]; + invert_qt_qt_normalized(q, viewquat_old); + mul_qt_qtqt(q, q, viewquat_new); - invert_qt_normalized(q); + invert_qt_normalized(q); - sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs); - mul_qt_v3(q, r_ofs); - add_v3_v3(r_ofs, dyn_ofs); + sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs); + mul_qt_v3(q, r_ofs); + add_v3_v3(r_ofs, dyn_ofs); } static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3]) { - static float lastofs[3] = {0, 0, 0}; - bool is_set = false; - - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - View3D *v3d = CTX_wm_view3d(C); - Object *ob_act_eval = OBACT(view_layer_eval); - Object *ob_act = DEG_get_original_object(ob_act_eval); - - if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) && - /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */ - ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0) - { - /* in case of sculpting use last average stroke position as a rotation - * center, in other cases it's not clear what rotation center shall be - * so just rotate around object origin - */ - if (ob_act->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { - float stroke[3]; - BKE_paint_stroke_get_average(scene, ob_act_eval, stroke); - copy_v3_v3(lastofs, stroke); - } - else { - copy_v3_v3(lastofs, ob_act_eval->obmat[3]); - } - is_set = true; - } - else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) { - Curve *cu = ob_act_eval->data; - EditFont *ef = cu->editfont; - int i; - - zero_v3(lastofs); - for (i = 0; i < 4; i++) { - add_v2_v2(lastofs, ef->textcurs[i]); - } - mul_v2_fl(lastofs, 1.0f / 4.0f); - - mul_m4_v3(ob_act_eval->obmat, lastofs); - - is_set = true; - } - else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { - /* object mode use boundbox centers */ - Base *base_eval; - uint tot = 0; - float select_center[3]; - - zero_v3(select_center); - for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { - if (BASE_SELECTED(v3d, base_eval)) { - /* use the boundbox if we can */ - Object *ob_eval = base_eval->object; - - if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) { - float cent[3]; - - BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent); - - mul_m4_v3(ob_eval->obmat, cent); - add_v3_v3(select_center, cent); - } - else { - add_v3_v3(select_center, ob_eval->obmat[3]); - } - tot++; - } - } - if (tot) { - mul_v3_fl(select_center, 1.0f / (float)tot); - copy_v3_v3(lastofs, select_center); - is_set = true; - } - } - else { - /* If there's no selection, lastofs is unmodified and last value since static */ - is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL); - } - - copy_v3_v3(r_dyn_ofs, lastofs); - - return is_set; + static float lastofs[3] = {0, 0, 0}; + bool is_set = false; + + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); + View3D *v3d = CTX_wm_view3d(C); + Object *ob_act_eval = OBACT(view_layer_eval); + Object *ob_act = DEG_get_original_object(ob_act_eval); + + if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) && + /* with weight-paint + pose-mode, fall through to using calculateTransformCenter */ + ((ob_act->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(ob_act)) == 0) { + /* in case of sculpting use last average stroke position as a rotation + * center, in other cases it's not clear what rotation center shall be + * so just rotate around object origin + */ + if (ob_act->mode & + (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { + float stroke[3]; + BKE_paint_stroke_get_average(scene, ob_act_eval, stroke); + copy_v3_v3(lastofs, stroke); + } + else { + copy_v3_v3(lastofs, ob_act_eval->obmat[3]); + } + is_set = true; + } + else if (ob_act && (ob_act->mode & OB_MODE_EDIT) && (ob_act->type == OB_FONT)) { + Curve *cu = ob_act_eval->data; + EditFont *ef = cu->editfont; + int i; + + zero_v3(lastofs); + for (i = 0; i < 4; i++) { + add_v2_v2(lastofs, ef->textcurs[i]); + } + mul_v2_fl(lastofs, 1.0f / 4.0f); + + mul_m4_v3(ob_act_eval->obmat, lastofs); + + is_set = true; + } + else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) { + /* object mode use boundbox centers */ + Base *base_eval; + uint tot = 0; + float select_center[3]; + + zero_v3(select_center); + for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { + if (BASE_SELECTED(v3d, base_eval)) { + /* use the boundbox if we can */ + Object *ob_eval = base_eval->object; + + if (ob_eval->runtime.bb && !(ob_eval->runtime.bb->flag & BOUNDBOX_DIRTY)) { + float cent[3]; + + BKE_boundbox_calc_center_aabb(ob_eval->runtime.bb, cent); + + mul_m4_v3(ob_eval->obmat, cent); + add_v3_v3(select_center, cent); + } + else { + add_v3_v3(select_center, ob_eval->obmat[3]); + } + tot++; + } + } + if (tot) { + mul_v3_fl(select_center, 1.0f / (float)tot); + copy_v3_v3(lastofs, select_center); + is_set = true; + } + } + else { + /* If there's no selection, lastofs is unmodified and last value since static */ + is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, NULL); + } + + copy_v3_v3(r_dyn_ofs, lastofs); + + return is_set; } enum eViewOpsFlag { - /** When enabled, rotate around the selection. */ - VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0), - /** When enabled, use the depth under the cursor for navigation. */ - VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1), - /** - * When enabled run #ED_view3d_persp_ensure this may switch out of - * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled. - * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common - * so we don't want it to trigger auto-perspective). */ - VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2), - /** When set, ignore any options that depend on initial cursor location. */ - VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3), + /** When enabled, rotate around the selection. */ + VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0), + /** When enabled, use the depth under the cursor for navigation. */ + VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1), + /** + * When enabled run #ED_view3d_persp_ensure this may switch out of + * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled. + * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common + * so we don't want it to trigger auto-perspective). */ + VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2), + /** When set, ignore any options that depend on initial cursor location. */ + VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3), }; static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth) { - enum eViewOpsFlag flag = 0; - if (use_select) { - flag |= VIEWOPS_FLAG_ORBIT_SELECT; - } - if (use_depth) { - flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE; - } + enum eViewOpsFlag flag = 0; + if (use_select) { + flag |= VIEWOPS_FLAG_ORBIT_SELECT; + } + if (use_depth) { + flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE; + } - return flag; + return flag; } static enum eViewOpsFlag viewops_flag_from_prefs(void) { - return viewops_flag_from_args( - (U.uiflag & USER_ORBIT_SELECTION) != 0, - (U.uiflag & USER_DEPTH_NAVIGATE) != 0); + return viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, + (U.uiflag & USER_DEPTH_NAVIGATE) != 0); } /** * Calculate the values for #ViewOpsData */ -static void viewops_data_create( - bContext *C, wmOperator *op, const wmEvent *event, - enum eViewOpsFlag viewops_flag) -{ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewOpsData *vod = op->customdata; - RegionView3D *rv3d = vod->rv3d; - - /* Could do this more nicely. */ - if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) { - viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE; - } - - /* we need the depth info before changing any viewport options */ - if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) { - float fallback_depth_pt[3]; - - view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ - - negate_v3_v3(fallback_depth_pt, rv3d->ofs); - - vod->use_dyn_ofs = ED_view3d_autodist( - depsgraph, vod->ar, vod->v3d, - event->mval, vod->dyn_ofs, true, fallback_depth_pt); - } - else { - vod->use_dyn_ofs = false; - } - - if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) { - if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) { - /* If we're switching from camera view to the perspective one, - * need to tag viewport update, so camera vuew and borders - * are properly updated. - */ - ED_region_tag_redraw(vod->ar); - } - } - - /* set the view from the camera, if view locking is enabled. - * we may want to make this optional but for now its needed always */ - ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d); - - vod->init.dist = rv3d->dist; - vod->init.camzoom = rv3d->camzoom; - copy_qt_qt(vod->init.quat, rv3d->viewquat); - vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; - vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y; - - if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) { - vod->init.event_xy_offset[0] = 0; - vod->init.event_xy_offset[1] = 0; - } - else { - /* Simulate the event starting in the middle of the region. */ - vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->ar->winrct) - event->x; - vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->ar->winrct) - event->y; - } - - vod->init.event_type = event->type; - copy_v3_v3(vod->init.ofs, rv3d->ofs); - - copy_qt_qt(vod->curr.viewquat, rv3d->viewquat); - - if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) { - float ofs[3]; - if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) { - vod->use_dyn_ofs = true; - negate_v3_v3(vod->dyn_ofs, ofs); - viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE; - } - } - - if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) { - if (vod->use_dyn_ofs) { - if (rv3d->is_persp) { - float my_origin[3]; /* original G.vd->ofs */ - float my_pivot[3]; /* view */ - float dvec[3]; - - /* locals for dist correction */ - float mat[3][3]; - float upvec[3]; - - negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */ - - /* Set the dist value to be the distance from this 3d point this means youll - * always be able to zoom into it and panning wont go bad when dist was zero */ - - /* remove dist value */ - upvec[0] = upvec[1] = 0; - upvec[2] = rv3d->dist; - copy_m3_m4(mat, rv3d->viewinv); - - mul_m3_v3(mat, upvec); - sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); - negate_v3(my_pivot); /* ofs is flipped */ - - /* find a new ofs value that is along the view axis - * (rather than the mouse location) */ - closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); - vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec); - - negate_v3_v3(rv3d->ofs, dvec); - } - else { - const float mval_ar_mid[2] = { - (float)vod->ar->winx / 2.0f, - (float)vod->ar->winy / 2.0f}; - - ED_view3d_win_to_3d(vod->v3d, vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs); - negate_v3(rv3d->ofs); - } - negate_v3(vod->dyn_ofs); - copy_v3_v3(vod->init.ofs, rv3d->ofs); - } - } - - /* For dolly */ - ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec); - - { - const int event_xy_offset[2] = { - event->x + vod->init.event_xy_offset[0], - event->y + vod->init.event_xy_offset[1], - }; - /* For rotation with trackball rotation. */ - calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec); - } - - { - float tvec[3]; - negate_v3_v3(tvec, rv3d->ofs); - vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); - } - - vod->reverse = 1.0f; - if (rv3d->persmat[2][1] < 0.0f) { - vod->reverse = -1.0f; - } - - rv3d->rflag |= RV3D_NAVIGATING; +static void viewops_data_create(bContext *C, + wmOperator *op, + const wmEvent *event, + enum eViewOpsFlag viewops_flag) +{ + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewOpsData *vod = op->customdata; + RegionView3D *rv3d = vod->rv3d; + + /* Could do this more nicely. */ + if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) { + viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE; + } + + /* we need the depth info before changing any viewport options */ + if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) { + float fallback_depth_pt[3]; + + view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ + + negate_v3_v3(fallback_depth_pt, rv3d->ofs); + + vod->use_dyn_ofs = ED_view3d_autodist( + depsgraph, vod->ar, vod->v3d, event->mval, vod->dyn_ofs, true, fallback_depth_pt); + } + else { + vod->use_dyn_ofs = false; + } + + if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) { + if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) { + /* If we're switching from camera view to the perspective one, + * need to tag viewport update, so camera vuew and borders + * are properly updated. + */ + ED_region_tag_redraw(vod->ar); + } + } + + /* set the view from the camera, if view locking is enabled. + * we may want to make this optional but for now its needed always */ + ED_view3d_camera_lock_init(depsgraph, vod->v3d, vod->rv3d); + + vod->init.dist = rv3d->dist; + vod->init.camzoom = rv3d->camzoom; + copy_qt_qt(vod->init.quat, rv3d->viewquat); + vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; + vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y; + + if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) { + vod->init.event_xy_offset[0] = 0; + vod->init.event_xy_offset[1] = 0; + } + else { + /* Simulate the event starting in the middle of the region. */ + vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->ar->winrct) - event->x; + vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->ar->winrct) - event->y; + } + + vod->init.event_type = event->type; + copy_v3_v3(vod->init.ofs, rv3d->ofs); + + copy_qt_qt(vod->curr.viewquat, rv3d->viewquat); + + if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) { + float ofs[3]; + if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) { + vod->use_dyn_ofs = true; + negate_v3_v3(vod->dyn_ofs, ofs); + viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE; + } + } + + if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) { + if (vod->use_dyn_ofs) { + if (rv3d->is_persp) { + float my_origin[3]; /* original G.vd->ofs */ + float my_pivot[3]; /* view */ + float dvec[3]; + + /* locals for dist correction */ + float mat[3][3]; + float upvec[3]; + + negate_v3_v3(my_origin, rv3d->ofs); /* ofs is flipped */ + + /* Set the dist value to be the distance from this 3d point this means youll + * always be able to zoom into it and panning wont go bad when dist was zero */ + + /* remove dist value */ + upvec[0] = upvec[1] = 0; + upvec[2] = rv3d->dist; + copy_m3_m4(mat, rv3d->viewinv); + + mul_m3_v3(mat, upvec); + sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); + negate_v3(my_pivot); /* ofs is flipped */ + + /* find a new ofs value that is along the view axis + * (rather than the mouse location) */ + closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); + vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec); + + negate_v3_v3(rv3d->ofs, dvec); + } + else { + const float mval_ar_mid[2] = {(float)vod->ar->winx / 2.0f, (float)vod->ar->winy / 2.0f}; + + ED_view3d_win_to_3d(vod->v3d, vod->ar, vod->dyn_ofs, mval_ar_mid, rv3d->ofs); + negate_v3(rv3d->ofs); + } + negate_v3(vod->dyn_ofs); + copy_v3_v3(vod->init.ofs, rv3d->ofs); + } + } + + /* For dolly */ + ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec); + + { + const int event_xy_offset[2] = { + event->x + vod->init.event_xy_offset[0], + event->y + vod->init.event_xy_offset[1], + }; + /* For rotation with trackball rotation. */ + calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec); + } + + { + float tvec[3]; + negate_v3_v3(tvec, rv3d->ofs); + vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + } + + vod->reverse = 1.0f; + if (rv3d->persmat[2][1] < 0.0f) { + vod->reverse = -1.0f; + } + + rv3d->rflag |= RV3D_NAVIGATING; } static void viewops_data_free(bContext *C, wmOperator *op) { - ARegion *ar; + ARegion *ar; #if 0 - Paint *p = BKE_paint_get_active_from_context(C); + Paint *p = BKE_paint_get_active_from_context(C); #endif - if (op->customdata) { - ViewOpsData *vod = op->customdata; - ar = vod->ar; - vod->rv3d->rflag &= ~RV3D_NAVIGATING; - - if (vod->timer) { - WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer); - } - - MEM_freeN(vod); - op->customdata = NULL; - } - else { - ar = CTX_wm_region(C); - } + if (op->customdata) { + ViewOpsData *vod = op->customdata; + ar = vod->ar; + vod->rv3d->rflag &= ~RV3D_NAVIGATING; + + if (vod->timer) { + WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win, vod->timer); + } + + MEM_freeN(vod); + op->customdata = NULL; + } + else { + ar = CTX_wm_region(C); + } #if 0 - if (p && (p->flags & PAINT_FAST_NAVIGATE)) + if (p && (p->flags & PAINT_FAST_NAVIGATE)) #endif - { - ED_region_tag_redraw(ar); - } + { + ED_region_tag_redraw(ar); + } } /** \} */ @@ -551,444 +551,445 @@ static void viewops_data_free(bContext *C, wmOperator *op) * \{ */ enum { - VIEW_PASS = 0, - VIEW_APPLY, - VIEW_CONFIRM, + VIEW_PASS = 0, + VIEW_APPLY, + VIEW_CONFIRM, }; /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ enum { - VIEW_MODAL_CONFIRM = 1, /* used for all view operations */ - VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2, - VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3, - VIEWROT_MODAL_SWITCH_ZOOM = 4, - VIEWROT_MODAL_SWITCH_MOVE = 5, - VIEWROT_MODAL_SWITCH_ROTATE = 6, + VIEW_MODAL_CONFIRM = 1, /* used for all view operations */ + VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2, + VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3, + VIEWROT_MODAL_SWITCH_ZOOM = 4, + VIEWROT_MODAL_SWITCH_MOVE = 5, + VIEWROT_MODAL_SWITCH_ROTATE = 6, }; /* called in transform_ops.c, on each regeneration of keymaps */ void viewrotate_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + static const EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""}, - {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""}, + {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Axis Snap", ""}, + {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Axis Snap (Off)", ""}, - {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, - {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, + {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, + {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items); - /* disabled mode switching for now, can re-implement better, later on */ + /* disabled mode switching for now, can re-implement better, later on */ #if 0 - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); - WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); #endif - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); } static void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4]) { - if (vod->use_dyn_ofs) { - RegionView3D *rv3d = vod->rv3d; - view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs); - } + if (vod->use_dyn_ofs) { + RegionView3D *rv3d = vod->rv3d; + view3d_orbit_apply_dyn_ofs( + rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs); + } } static void viewrotate_apply_snap(ViewOpsData *vod) { - const float axis_limit = DEG2RADF(45 / 3); - - RegionView3D *rv3d = vod->rv3d; - - float viewquat_inv[4]; - float zaxis[3] = {0, 0, 1}; - float zaxis_best[3]; - int x, y, z; - bool found = false; - - invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat); - - mul_qt_v3(viewquat_inv, zaxis); - normalize_v3(zaxis); - - - for (x = -1; x < 2; x++) { - for (y = -1; y < 2; y++) { - for (z = -1; z < 2; z++) { - if (x || y || z) { - float zaxis_test[3] = {x, y, z}; - - normalize_v3(zaxis_test); - - if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) { - copy_v3_v3(zaxis_best, zaxis_test); - found = true; - } - } - } - } - } - - if (found) { - - /* find the best roll */ - float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4]; - float viewquat_align[4]; /* viewquat aligned to zaxis_best */ - float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */ - float best_angle = axis_limit; - int j; - - /* viewquat_align is the original viewquat aligned to the snapped axis - * for testing roll */ - rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis); - normalize_qt(viewquat_align); - mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align); - normalize_qt(viewquat_align); - invert_qt_qt_normalized(viewquat_align_inv, viewquat_align); - - vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY); - normalize_qt(quat_snap); - invert_qt_normalized(quat_snap); - - /* check if we can find the roll */ - found = false; - - /* find best roll */ - for (j = 0; j < 8; j++) { - float angle; - float xaxis1[3] = {1, 0, 0}; - float xaxis2[3] = {1, 0, 0}; - float quat_final_inv[4]; - - axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f)); - normalize_qt(quat_roll); - - mul_qt_qtqt(quat_final, quat_snap, quat_roll); - normalize_qt(quat_final); - - /* compare 2 vector angles to find the least roll */ - invert_qt_qt_normalized(quat_final_inv, quat_final); - mul_qt_v3(viewquat_align_inv, xaxis1); - mul_qt_v3(quat_final_inv, xaxis2); - angle = angle_v3v3(xaxis1, xaxis2); - - if (angle <= best_angle) { - found = true; - best_angle = angle; - copy_qt_qt(quat_best, quat_final); - } - } - - if (found) { - /* lock 'quat_best' to an axis view if we can */ - rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f); - if (rv3d->view != RV3D_VIEW_USER) { - ED_view3d_quat_from_axis_view(rv3d->view, quat_best); - } - } - else { - copy_qt_qt(quat_best, viewquat_align); - } - - copy_qt_qt(rv3d->viewquat, quat_best); - - viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); - } + const float axis_limit = DEG2RADF(45 / 3); + + RegionView3D *rv3d = vod->rv3d; + + float viewquat_inv[4]; + float zaxis[3] = {0, 0, 1}; + float zaxis_best[3]; + int x, y, z; + bool found = false; + + invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat); + + mul_qt_v3(viewquat_inv, zaxis); + normalize_v3(zaxis); + + for (x = -1; x < 2; x++) { + for (y = -1; y < 2; y++) { + for (z = -1; z < 2; z++) { + if (x || y || z) { + float zaxis_test[3] = {x, y, z}; + + normalize_v3(zaxis_test); + + if (angle_normalized_v3v3(zaxis_test, zaxis) < axis_limit) { + copy_v3_v3(zaxis_best, zaxis_test); + found = true; + } + } + } + } + } + + if (found) { + + /* find the best roll */ + float quat_roll[4], quat_final[4], quat_best[4], quat_snap[4]; + float viewquat_align[4]; /* viewquat aligned to zaxis_best */ + float viewquat_align_inv[4]; /* viewquat aligned to zaxis_best */ + float best_angle = axis_limit; + int j; + + /* viewquat_align is the original viewquat aligned to the snapped axis + * for testing roll */ + rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis); + normalize_qt(viewquat_align); + mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align); + normalize_qt(viewquat_align); + invert_qt_qt_normalized(viewquat_align_inv, viewquat_align); + + vec_to_quat(quat_snap, zaxis_best, OB_NEGZ, OB_POSY); + normalize_qt(quat_snap); + invert_qt_normalized(quat_snap); + + /* check if we can find the roll */ + found = false; + + /* find best roll */ + for (j = 0; j < 8; j++) { + float angle; + float xaxis1[3] = {1, 0, 0}; + float xaxis2[3] = {1, 0, 0}; + float quat_final_inv[4]; + + axis_angle_to_quat(quat_roll, zaxis_best, (float)j * DEG2RADF(45.0f)); + normalize_qt(quat_roll); + + mul_qt_qtqt(quat_final, quat_snap, quat_roll); + normalize_qt(quat_final); + + /* compare 2 vector angles to find the least roll */ + invert_qt_qt_normalized(quat_final_inv, quat_final); + mul_qt_v3(viewquat_align_inv, xaxis1); + mul_qt_v3(quat_final_inv, xaxis2); + angle = angle_v3v3(xaxis1, xaxis2); + + if (angle <= best_angle) { + found = true; + best_angle = angle; + copy_qt_qt(quat_best, quat_final); + } + } + + if (found) { + /* lock 'quat_best' to an axis view if we can */ + rv3d->view = ED_view3d_quat_to_axis_view(quat_best, 0.01f); + if (rv3d->view != RV3D_VIEW_USER) { + ED_view3d_quat_from_axis_view(rv3d->view, quat_best); + } + } + else { + copy_qt_qt(quat_best, viewquat_align); + } + + copy_qt_qt(rv3d->viewquat, quat_best); + + viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); + } } static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2]) { - RegionView3D *rv3d = vod->rv3d; + RegionView3D *rv3d = vod->rv3d; - rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */ + rv3d->view = RV3D_VIEW_USER; /* need to reset every time because of view snapping */ - if (U.flag & USER_TRACKBALL) { - float axis[3], q1[4], dvec[3], newvec[3]; - float angle; + if (U.flag & USER_TRACKBALL) { + float axis[3], q1[4], dvec[3], newvec[3]; + float angle; - { - const int event_xy_offset[2] = { - event_xy[0] + vod->init.event_xy_offset[0], - event_xy[1] + vod->init.event_xy_offset[1], - }; - calctrackballvec(&vod->ar->winrct, event_xy_offset, newvec); - } + { + const int event_xy_offset[2] = { + event_xy[0] + vod->init.event_xy_offset[0], + event_xy[1] + vod->init.event_xy_offset[1], + }; + calctrackballvec(&vod->ar->winrct, event_xy_offset, newvec); + } - sub_v3_v3v3(dvec, newvec, vod->init.trackvec); + sub_v3_v3v3(dvec, newvec, vod->init.trackvec); - angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI; + angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI; - /* Allow for rotation beyond the interval [-pi, pi] */ - angle = angle_wrap_rad(angle); + /* Allow for rotation beyond the interval [-pi, pi] */ + angle = angle_wrap_rad(angle); - /* This relation is used instead of the actual angle between vectors - * so that the angle of rotation is linearly proportional to - * the distance that the mouse is dragged. */ + /* This relation is used instead of the actual angle between vectors + * so that the angle of rotation is linearly proportional to + * the distance that the mouse is dragged. */ - cross_v3_v3v3(axis, vod->init.trackvec, newvec); - axis_angle_to_quat(q1, axis, angle); + cross_v3_v3v3(axis, vod->init.trackvec, newvec); + axis_angle_to_quat(q1, axis, angle); - mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat); + mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat); - viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); - } - else { - /* New turntable view code by John Aughey */ - float quat_local_x[4], quat_global_z[4]; - float m[3][3]; - float m_inv[3][3]; - const float zvec_global[3] = {0.0f, 0.0f, 1.0f}; - float xaxis[3]; + viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); + } + else { + /* New turntable view code by John Aughey */ + float quat_local_x[4], quat_global_z[4]; + float m[3][3]; + float m_inv[3][3]; + const float zvec_global[3] = {0.0f, 0.0f, 1.0f}; + float xaxis[3]; - /* Sensitivity will control how fast the viewport rotates. 0.007 was - * obtained experimentally by looking at viewport rotation sensitivities - * on other modeling programs. */ - /* Perhaps this should be a configurable user parameter. */ - const float sensitivity = 0.007f; + /* Sensitivity will control how fast the viewport rotates. 0.007 was + * obtained experimentally by looking at viewport rotation sensitivities + * on other modeling programs. */ + /* Perhaps this should be a configurable user parameter. */ + const float sensitivity = 0.007f; - /* Get the 3x3 matrix and its inverse from the quaternion */ - quat_to_mat3(m, vod->curr.viewquat); - invert_m3_m3(m_inv, m); + /* Get the 3x3 matrix and its inverse from the quaternion */ + quat_to_mat3(m, vod->curr.viewquat); + invert_m3_m3(m_inv, m); - /* avoid gimble lock */ + /* avoid gimble lock */ #if 1 - if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) { - float fac; - cross_v3_v3v3(xaxis, zvec_global, m_inv[2]); - if (dot_v3v3(xaxis, m_inv[0]) < 0) { - negate_v3(xaxis); - } - fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI; - fac = fabsf(fac - 0.5f) * 2; - fac = fac * fac; - interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac); - } - else { - copy_v3_v3(xaxis, m_inv[0]); - } + if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) { + float fac; + cross_v3_v3v3(xaxis, zvec_global, m_inv[2]); + if (dot_v3v3(xaxis, m_inv[0]) < 0) { + negate_v3(xaxis); + } + fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (float)M_PI; + fac = fabsf(fac - 0.5f) * 2; + fac = fac * fac; + interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac); + } + else { + copy_v3_v3(xaxis, m_inv[0]); + } #else - copy_v3_v3(xaxis, m_inv[0]); + copy_v3_v3(xaxis, m_inv[0]); #endif - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be computed directly from the quaternion. */ + /* Determine the direction of the x vector (for rotating up and down) */ + /* This can likely be computed directly from the quaternion. */ - /* Perform the up/down rotation */ - axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1])); - mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x); + /* Perform the up/down rotation */ + axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1])); + mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x); - /* Perform the orbital rotation */ - axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0])); - mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z); + /* Perform the orbital rotation */ + axis_angle_to_quat_single( + quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0])); + mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z); - viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); - } + viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat); + } - /* avoid precision loss over time */ - normalize_qt(vod->curr.viewquat); + /* avoid precision loss over time */ + normalize_qt(vod->curr.viewquat); - /* use a working copy so view rotation locking doesn't overwrite the locked - * rotation back into the view we calculate with */ - copy_qt_qt(rv3d->viewquat, vod->curr.viewquat); + /* use a working copy so view rotation locking doesn't overwrite the locked + * rotation back into the view we calculate with */ + copy_qt_qt(rv3d->viewquat, vod->curr.viewquat); - /* check for view snap, - * note: don't apply snap to vod->viewquat so the view wont jam up */ - if (vod->axis_snap) { - viewrotate_apply_snap(vod); - } - vod->prev.event_xy[0] = event_xy[0]; - vod->prev.event_xy[1] = event_xy[1]; + /* check for view snap, + * note: don't apply snap to vod->viewquat so the view wont jam up */ + if (vod->axis_snap) { + viewrotate_apply_snap(vod); + } + vod->prev.event_xy[0] = event_xy[0]; + vod->prev.event_xy[1] = event_xy[1]; - ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d); + ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, rv3d); - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); } static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod = op->customdata; - short event_code = VIEW_PASS; - bool use_autokey = false; - int ret = OPERATOR_RUNNING_MODAL; - - /* execute the events */ - if (event->type == MOUSEMOVE) { - event_code = VIEW_APPLY; - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case VIEW_MODAL_CONFIRM: - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_AXIS_SNAP_ENABLE: - vod->axis_snap = true; - event_code = VIEW_APPLY; - break; - case VIEWROT_MODAL_AXIS_SNAP_DISABLE: - vod->axis_snap = false; - event_code = VIEW_APPLY; - break; - case VIEWROT_MODAL_SWITCH_ZOOM: - WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - } - } - else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { - event_code = VIEW_CONFIRM; - } - - if (event_code == VIEW_APPLY) { - viewrotate_apply(vod, &event->x); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - use_autokey = true; - } - } - else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); - use_autokey = true; - ret = OPERATOR_FINISHED; - } - - if (use_autokey) { - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true); - } - - if (ret & OPERATOR_FINISHED) { - viewops_data_free(C, op); - } - - return ret; + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + bool use_autokey = false; + int ret = OPERATOR_RUNNING_MODAL; + + /* execute the events */ + if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_AXIS_SNAP_ENABLE: + vod->axis_snap = true; + event_code = VIEW_APPLY; + break; + case VIEWROT_MODAL_AXIS_SNAP_DISABLE: + vod->axis_snap = false; + event_code = VIEW_APPLY; + break; + case VIEWROT_MODAL_SWITCH_ZOOM: + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + viewrotate_apply(vod, &event->x); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + use_autokey = true; + } + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + use_autokey = true; + ret = OPERATOR_FINISHED; + } + + if (use_autokey) { + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, true); + } + + if (ret & OPERATOR_FINISHED) { + viewops_data_free(C, op); + } + + return ret; } static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod; + ViewOpsData *vod; - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - /* makes op->customdata */ - viewops_data_alloc(C, op); - vod = op->customdata; + /* makes op->customdata */ + viewops_data_alloc(C, op); + vod = op->customdata; - /* poll should check but in some cases fails, see poll func for details */ - if (vod->rv3d->viewlock & RV3D_LOCKED) { - viewops_data_free(C, op); - return OPERATOR_PASS_THROUGH; - } + /* poll should check but in some cases fails, see poll func for details */ + if (vod->rv3d->viewlock & RV3D_LOCKED) { + viewops_data_free(C, op); + return OPERATOR_PASS_THROUGH; + } - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - viewops_data_create( - C, op, event, - viewops_flag_from_prefs() | - VIEWOPS_FLAG_PERSP_ENSURE | - (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); + viewops_data_create(C, + op, + event, + viewops_flag_from_prefs() | VIEWOPS_FLAG_PERSP_ENSURE | + (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); - if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) { - /* Rotate direction we keep always same */ - int event_xy[2]; + if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) { + /* Rotate direction we keep always same */ + int event_xy[2]; - if (event->type == MOUSEPAN) { - if (U.uiflag2 & USER_TRACKPAD_NATURAL) { - event_xy[0] = 2 * event->x - event->prevx; - event_xy[1] = 2 * event->y - event->prevy; - } - else { - event_xy[0] = event->prevx; - event_xy[1] = event->prevy; - } - } - else { - /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */ - event_xy[0] = event->prevx; - event_xy[1] = event->y; - } + if (event->type == MOUSEPAN) { + if (U.uiflag2 & USER_TRACKPAD_NATURAL) { + event_xy[0] = 2 * event->x - event->prevx; + event_xy[1] = 2 * event->y - event->prevy; + } + else { + event_xy[0] = event->prevx; + event_xy[1] = event->prevy; + } + } + else { + /* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */ + event_xy[0] = event->prevx; + event_xy[1] = event->y; + } - viewrotate_apply(vod, event_xy); - ED_view3d_depth_tag_update(vod->rv3d); + viewrotate_apply(vod, event_xy); + ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); + viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - /* add temp handler */ - WM_event_add_modal_handler(C, op); + return OPERATOR_FINISHED; + } + else { + /* add temp handler */ + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; - } + return OPERATOR_RUNNING_MODAL; + } } /* test for unlocked camera view in quad view */ static bool view3d_camera_user_poll(bContext *C) { - View3D *v3d; - ARegion *ar; + View3D *v3d; + ARegion *ar; - if (ED_view3d_context_user_region(C, &v3d, &ar)) { - RegionView3D *rv3d = ar->regiondata; - if (rv3d->persp == RV3D_CAMOB) { - return 1; - } - } + if (ED_view3d_context_user_region(C, &v3d, &ar)) { + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + return 1; + } + } - return 0; + return 0; } static bool view3d_lock_poll(bContext *C) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (rv3d) { - return ED_view3d_offset_lock_check(v3d, rv3d); - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + if (v3d) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (rv3d) { + return ED_view3d_offset_lock_check(v3d, rv3d); + } + } + return false; } static void viewrotate_cancel(bContext *C, wmOperator *op) { - viewops_data_free(C, op); + viewops_data_free(C, op); } void VIEW3D_OT_rotate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Rotate View"; - ot->description = "Rotate the view"; - ot->idname = "VIEW3D_OT_rotate"; + /* identifiers */ + ot->name = "Rotate View"; + ot->description = "Rotate the view"; + ot->idname = "VIEW3D_OT_rotate"; - /* api callbacks */ - ot->invoke = viewrotate_invoke; - ot->modal = viewrotate_modal; - ot->poll = ED_operator_region_view3d_active; - ot->cancel = viewrotate_cancel; + /* api callbacks */ + ot->invoke = viewrotate_invoke; + ot->modal = viewrotate_modal; + ot->poll = ED_operator_region_view3d_active; + ot->cancel = viewrotate_cancel; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; - view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT); + view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT); } /** \} */ @@ -998,48 +999,48 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) * \{ */ #ifdef WITH_INPUT_NDOF -#define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec)) -#define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec)) +# define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec)) +# define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec)) /** * \param depth_pt: A point to calculate the depth (in perspective mode) */ static float view3d_ndof_pan_speed_calc_ex(RegionView3D *rv3d, const float depth_pt[3]) { - float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND; + float speed = rv3d->pixsize * NDOF_PIXELS_PER_SECOND; - if (rv3d->is_persp) { - speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL); - } + if (rv3d->is_persp) { + speed *= ED_view3d_calc_zfac(rv3d, depth_pt, NULL); + } - return speed; + return speed; } static float view3d_ndof_pan_speed_calc_from_dist(RegionView3D *rv3d, const float dist) { - float viewinv[4]; - float tvec[3]; + float viewinv[4]; + float tvec[3]; - BLI_assert(dist >= 0.0f); + BLI_assert(dist >= 0.0f); - copy_v3_fl3(tvec, 0.0f, 0.0f, dist); - /* rv3d->viewinv isn't always valid */ -#if 0 - mul_mat3_m4_v3(rv3d->viewinv, tvec); -#else - invert_qt_qt_normalized(viewinv, rv3d->viewquat); - mul_qt_v3(viewinv, tvec); -#endif + copy_v3_fl3(tvec, 0.0f, 0.0f, dist); + /* rv3d->viewinv isn't always valid */ +# if 0 + mul_mat3_m4_v3(rv3d->viewinv, tvec); +# else + invert_qt_qt_normalized(viewinv, rv3d->viewquat); + mul_qt_v3(viewinv, tvec); +# endif - return view3d_ndof_pan_speed_calc_ex(rv3d, tvec); + return view3d_ndof_pan_speed_calc_ex(rv3d, tvec); } static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d) { - float tvec[3]; - negate_v3_v3(tvec, rv3d->ofs); + float tvec[3]; + negate_v3_v3(tvec, rv3d->ofs); - return view3d_ndof_pan_speed_calc_ex(rv3d, tvec); + return view3d_ndof_pan_speed_calc_ex(rv3d, tvec); } /** @@ -1047,261 +1048,265 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d) * * \param has_zoom: zoom, otherwise dolly, often `!rv3d->is_persp` since it doesn't make sense to dolly in ortho. */ -static void view3d_ndof_pan_zoom( - const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, - const bool has_translate, const bool has_zoom) +static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, + ScrArea *sa, + ARegion *ar, + const bool has_translate, + const bool has_zoom) { - RegionView3D *rv3d = ar->regiondata; - float view_inv[4]; - float pan_vec[3]; + RegionView3D *rv3d = ar->regiondata; + float view_inv[4]; + float pan_vec[3]; - if (has_translate == false && has_zoom == false) { - return; - } + if (has_translate == false && has_zoom == false) { + return; + } - WM_event_ndof_pan_get(ndof, pan_vec, false); + WM_event_ndof_pan_get(ndof, pan_vec, false); - if (has_zoom) { - /* zoom with Z */ + if (has_zoom) { + /* zoom with Z */ - /* Zoom! - * velocity should be proportional to the linear velocity attained by rotational motion of same strength - * [got that?] - * proportional to arclength = radius * angle - */ + /* Zoom! + * velocity should be proportional to the linear velocity attained by rotational motion of same strength + * [got that?] + * proportional to arclength = radius * angle + */ - pan_vec[2] = 0.0f; + pan_vec[2] = 0.0f; - /* "zoom in" or "translate"? depends on zoom mode in user settings? */ - if (ndof->tvec[2]) { - float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2]; + /* "zoom in" or "translate"? depends on zoom mode in user settings? */ + if (ndof->tvec[2]) { + float zoom_distance = rv3d->dist * ndof->dt * ndof->tvec[2]; - if (U.ndof_flag & NDOF_ZOOM_INVERT) { - zoom_distance = -zoom_distance; - } + if (U.ndof_flag & NDOF_ZOOM_INVERT) { + zoom_distance = -zoom_distance; + } - rv3d->dist += zoom_distance; - } - } - else { - /* dolly with Z */ + rv3d->dist += zoom_distance; + } + } + else { + /* dolly with Z */ - /* all callers must check */ - if (has_translate) { - BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false); - } - } + /* all callers must check */ + if (has_translate) { + BLI_assert(ED_view3d_offset_lock_check((View3D *)sa->spacedata.first, rv3d) == false); + } + } - if (has_translate) { - const float speed = view3d_ndof_pan_speed_calc(rv3d); + if (has_translate) { + const float speed = view3d_ndof_pan_speed_calc(rv3d); - mul_v3_fl(pan_vec, speed * ndof->dt); + mul_v3_fl(pan_vec, speed * ndof->dt); - /* transform motion from view to world coordinates */ - invert_qt_qt_normalized(view_inv, rv3d->viewquat); - mul_qt_v3(view_inv, pan_vec); + /* transform motion from view to world coordinates */ + invert_qt_qt_normalized(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); - /* move center of view opposite of hand motion (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, pan_vec); + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(sa, ar); - } - } + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(sa, ar); + } + } } - -static void view3d_ndof_orbit( - const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, - ViewOpsData *vod, const bool apply_dyn_ofs) +static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, + ScrArea *sa, + ARegion *ar, + ViewOpsData *vod, + const bool apply_dyn_ofs) { - View3D *v3d = sa->spacedata.first; - RegionView3D *rv3d = ar->regiondata; + View3D *v3d = sa->spacedata.first; + RegionView3D *rv3d = ar->regiondata; - float view_inv[4]; + float view_inv[4]; - BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); + BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); - ED_view3d_persp_ensure(vod->depsgraph, v3d, ar); + ED_view3d_persp_ensure(vod->depsgraph, v3d, ar); - rv3d->view = RV3D_VIEW_USER; + rv3d->view = RV3D_VIEW_USER; - invert_qt_qt_normalized(view_inv, rv3d->viewquat); + invert_qt_qt_normalized(view_inv, rv3d->viewquat); - if (U.ndof_flag & NDOF_TURNTABLE) { - float rot[3]; + if (U.ndof_flag & NDOF_TURNTABLE) { + float rot[3]; - /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ - float angle, quat[4]; - float xvec[3] = {1, 0, 0}; + /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + float angle, quat[4]; + float xvec[3] = {1, 0, 0}; - /* only use XY, ignore Z */ - WM_event_ndof_rotate_get(ndof, rot); + /* only use XY, ignore Z */ + WM_event_ndof_rotate_get(ndof, rot); - /* Determine the direction of the x vector (for rotating up and down) */ - mul_qt_v3(view_inv, xvec); + /* Determine the direction of the x vector (for rotating up and down) */ + mul_qt_v3(view_inv, xvec); - /* Perform the up/down rotation */ - angle = ndof->dt * rot[0]; - axis_angle_to_quat(quat, xvec, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); + /* Perform the up/down rotation */ + angle = ndof->dt * rot[0]; + axis_angle_to_quat(quat, xvec, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); - /* Perform the orbital rotation */ - angle = ndof->dt * rot[1]; + /* Perform the orbital rotation */ + angle = ndof->dt * rot[1]; - /* update the onscreen doo-dad */ - rv3d->rot_angle = angle; - rv3d->rot_axis[0] = 0; - rv3d->rot_axis[1] = 0; - rv3d->rot_axis[2] = 1; + /* update the onscreen doo-dad */ + rv3d->rot_angle = angle; + rv3d->rot_axis[0] = 0; + rv3d->rot_axis[1] = 0; + rv3d->rot_axis[2] = 1; - axis_angle_to_quat_single(quat, 'Z', angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); - } - else { - float quat[4]; - float axis[3]; - float angle = WM_event_ndof_to_axis_angle(ndof, axis); + axis_angle_to_quat_single(quat, 'Z', angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); + } + else { + float quat[4]; + float axis[3]; + float angle = WM_event_ndof_to_axis_angle(ndof, axis); - /* transform rotation axis from view to world coordinates */ - mul_qt_v3(view_inv, axis); + /* transform rotation axis from view to world coordinates */ + mul_qt_v3(view_inv, axis); - /* update the onscreen doo-dad */ - rv3d->rot_angle = angle; - copy_v3_v3(rv3d->rot_axis, axis); + /* update the onscreen doo-dad */ + rv3d->rot_angle = angle; + copy_v3_v3(rv3d->rot_axis, axis); - axis_angle_to_quat(quat, axis, angle); + axis_angle_to_quat(quat, axis, angle); - /* apply rotation */ - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); - } + /* apply rotation */ + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat); + } - if (apply_dyn_ofs) { - viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); - } + if (apply_dyn_ofs) { + viewrotate_apply_dyn_ofs(vod, rv3d->viewquat); + } } /** * Called from both fly mode and walk mode, */ -void view3d_ndof_fly( - const wmNDOFMotionData *ndof, - View3D *v3d, RegionView3D *rv3d, - const bool use_precision, const short protectflag, - bool *r_has_translate, bool *r_has_rotate) -{ - bool has_translate = NDOF_HAS_TRANSLATE; - bool has_rotate = NDOF_HAS_ROTATE; - - float view_inv[4]; - invert_qt_qt_normalized(view_inv, rv3d->viewquat); - - rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */ - - if (has_translate) { - /* ignore real 'dist' since fly has its own speed settings, - * also its overwritten at this point. */ - float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f); - float trans[3], trans_orig_y; - - if (use_precision) { - speed *= 0.2f; - } - - WM_event_ndof_pan_get(ndof, trans, false); - mul_v3_fl(trans, speed * ndof->dt); - trans_orig_y = trans[1]; - - if (U.ndof_flag & NDOF_FLY_HELICOPTER) { - trans[1] = 0.0f; - } - - /* transform motion from view to world coordinates */ - mul_qt_v3(view_inv, trans); - - if (U.ndof_flag & NDOF_FLY_HELICOPTER) { - /* replace world z component with device y (yes it makes sense) */ - trans[2] = trans_orig_y; - } - - if (rv3d->persp == RV3D_CAMOB) { - /* respect camera position locks */ - if (protectflag & OB_LOCK_LOCX) { - trans[0] = 0.0f; - } - if (protectflag & OB_LOCK_LOCY) { - trans[1] = 0.0f; - } - if (protectflag & OB_LOCK_LOCZ) { - trans[2] = 0.0f; - } - } - - if (!is_zero_v3(trans)) { - /* move center of view opposite of hand motion - * (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, trans); - has_translate = true; - } - else { - has_translate = false; - } - } - - if (has_rotate) { - const float turn_sensitivity = 1.0f; - - float rotation[4]; - float axis[3]; - float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis); - - if (fabsf(angle) > 0.0001f) { - has_rotate = true; - - if (use_precision) { - angle *= 0.2f; - } - - /* transform rotation axis from view to world coordinates */ - mul_qt_v3(view_inv, axis); - - /* apply rotation to view */ - axis_angle_to_quat(rotation, axis, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - - if (U.ndof_flag & NDOF_LOCK_HORIZON) { - /* force an upright viewpoint - * TODO: make this less... sudden */ - float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */ - float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */ - - /* find new inverse since viewquat has changed */ - invert_qt_qt_normalized(view_inv, rv3d->viewquat); - /* could apply reverse rotation to existing view_inv to save a few cycles */ - - /* transform view vectors to world coordinates */ - mul_qt_v3(view_inv, view_horizon); - mul_qt_v3(view_inv, view_direction); - - - /* find difference between view & world horizons - * true horizon lives in world xy plane, so look only at difference in z */ - angle = -asinf(view_horizon[2]); - - /* rotate view so view horizon = world horizon */ - axis_angle_to_quat(rotation, view_direction, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - } - - rv3d->view = RV3D_VIEW_USER; - } - else { - has_rotate = false; - } - } - - *r_has_translate = has_translate; - *r_has_rotate = has_rotate; +void view3d_ndof_fly(const wmNDOFMotionData *ndof, + View3D *v3d, + RegionView3D *rv3d, + const bool use_precision, + const short protectflag, + bool *r_has_translate, + bool *r_has_rotate) +{ + bool has_translate = NDOF_HAS_TRANSLATE; + bool has_rotate = NDOF_HAS_ROTATE; + + float view_inv[4]; + invert_qt_qt_normalized(view_inv, rv3d->viewquat); + + rv3d->rot_angle = 0.0f; /* disable onscreen rotation doo-dad */ + + if (has_translate) { + /* ignore real 'dist' since fly has its own speed settings, + * also its overwritten at this point. */ + float speed = view3d_ndof_pan_speed_calc_from_dist(rv3d, 1.0f); + float trans[3], trans_orig_y; + + if (use_precision) { + speed *= 0.2f; + } + + WM_event_ndof_pan_get(ndof, trans, false); + mul_v3_fl(trans, speed * ndof->dt); + trans_orig_y = trans[1]; + + if (U.ndof_flag & NDOF_FLY_HELICOPTER) { + trans[1] = 0.0f; + } + + /* transform motion from view to world coordinates */ + mul_qt_v3(view_inv, trans); + + if (U.ndof_flag & NDOF_FLY_HELICOPTER) { + /* replace world z component with device y (yes it makes sense) */ + trans[2] = trans_orig_y; + } + + if (rv3d->persp == RV3D_CAMOB) { + /* respect camera position locks */ + if (protectflag & OB_LOCK_LOCX) { + trans[0] = 0.0f; + } + if (protectflag & OB_LOCK_LOCY) { + trans[1] = 0.0f; + } + if (protectflag & OB_LOCK_LOCZ) { + trans[2] = 0.0f; + } + } + + if (!is_zero_v3(trans)) { + /* move center of view opposite of hand motion + * (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, trans); + has_translate = true; + } + else { + has_translate = false; + } + } + + if (has_rotate) { + const float turn_sensitivity = 1.0f; + + float rotation[4]; + float axis[3]; + float angle = turn_sensitivity * WM_event_ndof_to_axis_angle(ndof, axis); + + if (fabsf(angle) > 0.0001f) { + has_rotate = true; + + if (use_precision) { + angle *= 0.2f; + } + + /* transform rotation axis from view to world coordinates */ + mul_qt_v3(view_inv, axis); + + /* apply rotation to view */ + axis_angle_to_quat(rotation, axis, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + + if (U.ndof_flag & NDOF_LOCK_HORIZON) { + /* force an upright viewpoint + * TODO: make this less... sudden */ + float view_horizon[3] = {1.0f, 0.0f, 0.0f}; /* view +x */ + float view_direction[3] = {0.0f, 0.0f, -1.0f}; /* view -z (into screen) */ + + /* find new inverse since viewquat has changed */ + invert_qt_qt_normalized(view_inv, rv3d->viewquat); + /* could apply reverse rotation to existing view_inv to save a few cycles */ + + /* transform view vectors to world coordinates */ + mul_qt_v3(view_inv, view_horizon); + mul_qt_v3(view_inv, view_direction); + + /* find difference between view & world horizons + * true horizon lives in world xy plane, so look only at difference in z */ + angle = -asinf(view_horizon[2]); + + /* rotate view so view horizon = world horizon */ + axis_angle_to_quat(rotation, view_direction, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + } + + rv3d->view = RV3D_VIEW_USER; + } + else { + has_rotate = false; + } + } + + *r_has_translate = has_translate; + *r_has_rotate = has_rotate; } /** \} */ @@ -1312,76 +1317,76 @@ void view3d_ndof_fly( static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (event->type != NDOF_MOTION) { - return OPERATOR_CANCELLED; - } + if (event->type != NDOF_MOTION) { + return OPERATOR_CANCELLED; + } - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewOpsData *vod; - View3D *v3d; - RegionView3D *rv3d; - char xform_flag = 0; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewOpsData *vod; + View3D *v3d; + RegionView3D *rv3d; + char xform_flag = 0; - const wmNDOFMotionData *ndof = event->customdata; + const wmNDOFMotionData *ndof = event->customdata; - viewops_data_alloc(C, op); - viewops_data_create( - C, op, event, - viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false)); - vod = op->customdata; + viewops_data_alloc(C, op); + viewops_data_create( + C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false)); + vod = op->customdata; - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - v3d = vod->v3d; - rv3d = vod->rv3d; + v3d = vod->v3d; + rv3d = vod->rv3d; - /* off by default, until changed later this function */ - rv3d->rot_angle = 0.0f; + /* off by default, until changed later this function */ + rv3d->rot_angle = 0.0f; - ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); + ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); - if (ndof->progress != P_FINISHING) { - const bool has_rotation = NDOF_HAS_ROTATE; - /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED); - const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; + if (ndof->progress != P_FINISHING) { + const bool has_rotation = NDOF_HAS_ROTATE; + /* if we can't rotate, fallback to translate (locked axis views) */ + const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED); + const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; - if (has_translate || has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); - xform_flag |= HAS_TRANSLATE; - } + if (has_translate || has_zoom) { + view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); + xform_flag |= HAS_TRANSLATE; + } - if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); - xform_flag |= HAS_ROTATE; - } - } + if (has_rotation) { + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); + xform_flag |= HAS_ROTATE; + } + } - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - if (xform_flag) { - ED_view3d_camera_lock_autokey(v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE); - } + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + if (xform_flag) { + ED_view3d_camera_lock_autokey( + v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE); + } - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); - viewops_data_free(C, op); + viewops_data_free(C, op); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "NDOF Orbit View"; - ot->description = "Orbit the view using the 3D mouse"; - ot->idname = "VIEW3D_OT_ndof_orbit"; + /* identifiers */ + ot->name = "NDOF Orbit View"; + ot->description = "Orbit the view using the 3D mouse"; + ot->idname = "VIEW3D_OT_ndof_orbit"; - /* api callbacks */ - ot->invoke = ndof_orbit_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = ndof_orbit_invoke; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -1392,112 +1397,110 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (event->type != NDOF_MOTION) { - return OPERATOR_CANCELLED; - } + if (event->type != NDOF_MOTION) { + return OPERATOR_CANCELLED; + } - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewOpsData *vod; - View3D *v3d; - RegionView3D *rv3d; - char xform_flag = 0; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewOpsData *vod; + View3D *v3d; + RegionView3D *rv3d; + char xform_flag = 0; - const wmNDOFMotionData *ndof = event->customdata; + const wmNDOFMotionData *ndof = event->customdata; - viewops_data_alloc(C, op); - viewops_data_create( - C, op, event, - viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false)); + viewops_data_alloc(C, op); + viewops_data_create( + C, op, event, viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false)); - vod = op->customdata; + vod = op->customdata; - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - v3d = vod->v3d; - rv3d = vod->rv3d; + v3d = vod->v3d; + rv3d = vod->rv3d; - /* off by default, until changed later this function */ - rv3d->rot_angle = 0.0f; + /* off by default, until changed later this function */ + rv3d->rot_angle = 0.0f; - ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); + ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); - if (ndof->progress == P_FINISHING) { - /* pass */ - } - else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) { - /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d); + if (ndof->progress == P_FINISHING) { + /* pass */ + } + else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) { + /* if we can't rotate, fallback to translate (locked axis views) */ + const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d); - if (has_translate || has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, true); - xform_flag |= HAS_TRANSLATE; - } - } - else if ((U.ndof_flag & NDOF_MODE_ORBIT) || - ED_view3d_offset_lock_check(v3d, rv3d)) - { - const bool has_rotation = NDOF_HAS_ROTATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f); + if (has_translate || has_zoom) { + view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, true); + xform_flag |= HAS_TRANSLATE; + } + } + else if ((U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d)) { + const bool has_rotation = NDOF_HAS_ROTATE; + const bool has_zoom = (ndof->tvec[2] != 0.0f); - if (has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom); - xform_flag |= HAS_TRANSLATE; - } + if (has_zoom) { + view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom); + xform_flag |= HAS_TRANSLATE; + } - if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); - xform_flag |= HAS_ROTATE; - } - } - else { /* free/explore (like fly mode) */ - const bool has_rotation = NDOF_HAS_ROTATE; - const bool has_translate = NDOF_HAS_TRANSLATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; + if (has_rotation) { + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); + xform_flag |= HAS_ROTATE; + } + } + else { /* free/explore (like fly mode) */ + const bool has_rotation = NDOF_HAS_ROTATE; + const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; - float dist_backup; + float dist_backup; - if (has_translate || has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); - xform_flag |= HAS_TRANSLATE; - } + if (has_translate || has_zoom) { + view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); + xform_flag |= HAS_TRANSLATE; + } - dist_backup = rv3d->dist; - ED_view3d_distance_set(rv3d, 0.0f); + dist_backup = rv3d->dist; + ED_view3d_distance_set(rv3d, 0.0f); - if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); - xform_flag |= HAS_ROTATE; - } + if (has_rotation) { + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); + xform_flag |= HAS_ROTATE; + } - ED_view3d_distance_set(rv3d, dist_backup); - } + ED_view3d_distance_set(rv3d, dist_backup); + } - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - if (xform_flag) { - ED_view3d_camera_lock_autokey(v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE); - } + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + if (xform_flag) { + ED_view3d_camera_lock_autokey( + v3d, rv3d, C, xform_flag & HAS_ROTATE, xform_flag & HAS_TRANSLATE); + } - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); - viewops_data_free(C, op); + viewops_data_free(C, op); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "NDOF Orbit View with Zoom"; - ot->description = "Orbit and zoom the view using the 3D mouse"; - ot->idname = "VIEW3D_OT_ndof_orbit_zoom"; + /* identifiers */ + ot->name = "NDOF Orbit View with Zoom"; + ot->description = "Orbit and zoom the view using the 3D mouse"; + ot->idname = "VIEW3D_OT_ndof_orbit_zoom"; - /* api callbacks */ - ot->invoke = ndof_orbit_zoom_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = ndof_orbit_zoom_invoke; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -1508,61 +1511,61 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot) static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - if (event->type != NDOF_MOTION) { - return OPERATOR_CANCELLED; - } + if (event->type != NDOF_MOTION) { + return OPERATOR_CANCELLED; + } - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - const wmNDOFMotionData *ndof = event->customdata; - char xform_flag = 0; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + const wmNDOFMotionData *ndof = event->customdata; + char xform_flag = 0; - const bool has_translate = NDOF_HAS_TRANSLATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; + const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; - /* we're panning here! so erase any leftover rotation from other operators */ - rv3d->rot_angle = 0.0f; + /* we're panning here! so erase any leftover rotation from other operators */ + rv3d->rot_angle = 0.0f; - if (!(has_translate || has_zoom)) { - return OPERATOR_CANCELLED; - } + if (!(has_translate || has_zoom)) { + return OPERATOR_CANCELLED; + } - ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); + ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); - if (ndof->progress != P_FINISHING) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); + if (ndof->progress != P_FINISHING) { + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); - if (has_translate || has_zoom) { - view3d_ndof_pan_zoom(ndof, sa, ar, has_translate, has_zoom); - xform_flag |= HAS_TRANSLATE; - } - } + if (has_translate || has_zoom) { + view3d_ndof_pan_zoom(ndof, sa, ar, has_translate, has_zoom); + xform_flag |= HAS_TRANSLATE; + } + } - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - if (xform_flag) { - ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE); - } + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + if (xform_flag) { + ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, xform_flag & HAS_TRANSLATE); + } - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(CTX_wm_region(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "NDOF Pan View"; - ot->description = "Pan the view with the 3D mouse"; - ot->idname = "VIEW3D_OT_ndof_pan"; + /* identifiers */ + ot->name = "NDOF Pan View"; + ot->description = "Pan the view with the 3D mouse"; + ot->idname = "VIEW3D_OT_ndof_pan"; - /* api callbacks */ - ot->invoke = ndof_pan_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = ndof_pan_invoke; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -1576,32 +1579,32 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) */ static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - /* weak!, but it works */ - const int ndof_flag = U.ndof_flag; - int ret; + /* weak!, but it works */ + const int ndof_flag = U.ndof_flag; + int ret; - U.ndof_flag &= ~NDOF_MODE_ORBIT; + U.ndof_flag &= ~NDOF_MODE_ORBIT; - ret = ndof_orbit_zoom_invoke(C, op, event); + ret = ndof_orbit_zoom_invoke(C, op, event); - U.ndof_flag = ndof_flag; + U.ndof_flag = ndof_flag; - return ret; + return ret; } void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) { - /* identifiers */ - ot->name = "NDOF Transform View"; - ot->description = "Pan and rotate the view with the 3D mouse"; - ot->idname = "VIEW3D_OT_ndof_all"; + /* identifiers */ + ot->name = "NDOF Transform View"; + ot->description = "Pan and rotate the view with the 3D mouse"; + ot->idname = "VIEW3D_OT_ndof_all"; - /* api callbacks */ - ot->invoke = ndof_all_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = ndof_all_invoke; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } #endif /* WITH_INPUT_NDOF */ @@ -1617,188 +1620,187 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) /* called in transform_ops.c, on each regeneration of keymaps */ void viewmove_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + static const EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, - {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, + {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"}, + {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items); - /* items for modal map */ - WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); + /* items for modal map */ + WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); + WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM); - /* disabled mode switching for now, can re-implement better, later on */ + /* disabled mode switching for now, can re-implement better, later on */ #if 0 - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); - WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); #endif - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); } - static void viewmove_apply(ViewOpsData *vod, int x, int y) { - if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) { - vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->ar->winx; - vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->ar->winy; - } - else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { - const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; - vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->ar->winx * zoomfac); - vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->ar->winy * zoomfac); - CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); - CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); - } - else { - float dvec[3]; - float mval_f[2]; + if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) { + vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->ar->winx; + vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->ar->winy; + } + else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { + const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; + vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->ar->winx * zoomfac); + vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->ar->winy * zoomfac); + CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); + CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); + } + else { + float dvec[3]; + float mval_f[2]; - mval_f[0] = x - vod->prev.event_xy[0]; - mval_f[1] = y - vod->prev.event_xy[1]; - ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->init.zfac); + mval_f[0] = x - vod->prev.event_xy[0]; + mval_f[1] = y - vod->prev.event_xy[1]; + ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->init.zfac); - add_v3_v3(vod->rv3d->ofs, dvec); + add_v3_v3(vod->rv3d->ofs, dvec); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(vod->sa, vod->ar); - } - } + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(vod->sa, vod->ar); + } + } - vod->prev.event_xy[0] = x; - vod->prev.event_xy[1] = y; + vod->prev.event_xy[0] = x; + vod->prev.event_xy[1] = y; - ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); + ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); } - static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod = op->customdata; - short event_code = VIEW_PASS; - bool use_autokey = false; - int ret = OPERATOR_RUNNING_MODAL; - - /* execute the events */ - if (event->type == MOUSEMOVE) { - event_code = VIEW_APPLY; - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case VIEW_MODAL_CONFIRM: - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_ZOOM: - WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - } - } - else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { - event_code = VIEW_CONFIRM; - } - - if (event_code == VIEW_APPLY) { - viewmove_apply(vod, event->x, event->y); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - use_autokey = true; - } - } - else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); - use_autokey = true; - ret = OPERATOR_FINISHED; - } - - if (use_autokey) { - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); - } - - if (ret & OPERATOR_FINISHED) { - viewops_data_free(C, op); - } - - return ret; + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + bool use_autokey = false; + int ret = OPERATOR_RUNNING_MODAL; + + /* execute the events */ + if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ZOOM: + WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + viewmove_apply(vod, event->x, event->y); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + use_autokey = true; + } + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + use_autokey = true; + ret = OPERATOR_FINISHED; + } + + if (use_autokey) { + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); + } + + if (ret & OPERATOR_FINISHED) { + viewops_data_free(C, op); + } + + return ret; } static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod; + ViewOpsData *vod; - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - /* makes op->customdata */ - viewops_data_alloc(C, op); - viewops_data_create( - C, op, event, - (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | - (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); - vod = op->customdata; + /* makes op->customdata */ + viewops_data_alloc(C, op); + viewops_data_create(C, + op, + event, + (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | + (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); + vod = op->customdata; - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - if (event->type == MOUSEPAN) { - /* invert it, trackpad scroll follows same principle as 2d windows this way */ - viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy); - ED_view3d_depth_tag_update(vod->rv3d); + if (event->type == MOUSEPAN) { + /* invert it, trackpad scroll follows same principle as 2d windows this way */ + viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy); + ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); + viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - /* add temp handler */ - WM_event_add_modal_handler(C, op); + return OPERATOR_FINISHED; + } + else { + /* add temp handler */ + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; - } + return OPERATOR_RUNNING_MODAL; + } } static void viewmove_cancel(bContext *C, wmOperator *op) { - viewops_data_free(C, op); + viewops_data_free(C, op); } void VIEW3D_OT_move(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Pan View"; - ot->description = "Move the view"; - ot->idname = "VIEW3D_OT_move"; + /* identifiers */ + ot->name = "Pan View"; + ot->description = "Move the view"; + ot->idname = "VIEW3D_OT_move"; - /* api callbacks */ - ot->invoke = viewmove_invoke; - ot->modal = viewmove_modal; - ot->poll = ED_operator_view3d_active; - ot->cancel = viewmove_cancel; + /* api callbacks */ + ot->invoke = viewmove_invoke; + ot->modal = viewmove_modal; + ot->poll = ED_operator_view3d_active; + ot->cancel = viewmove_cancel; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; - /* properties */ - view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT); + /* properties */ + view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT); } /** \} */ @@ -1811,82 +1813,81 @@ void VIEW3D_OT_move(wmOperatorType *ot) /* called in transform_ops.c, on each regeneration of keymaps */ void viewzoom_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + static const EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, - {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, + {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, + {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items); - /* disabled mode switching for now, can re-implement better, later on */ + /* disabled mode switching for now, can re-implement better, later on */ #if 0 - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); #endif - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); } /** * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL. */ static void view_zoom_to_window_xy_camera( - Scene *scene, Depsgraph *depsgraph, View3D *v3d, - ARegion *ar, float dfac, const int zoom_xy[2]) + Scene *scene, Depsgraph *depsgraph, View3D *v3d, ARegion *ar, float dfac, const int zoom_xy[2]) { - RegionView3D *rv3d = ar->regiondata; - const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); - const float zoomfac_new = clamp_f(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); - const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); - + RegionView3D *rv3d = ar->regiondata; + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); + const float zoomfac_new = clamp_f( + zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); - if (zoom_xy != NULL) { - float zoomfac_px; - rctf camera_frame_old; - rctf camera_frame_new; + if (zoom_xy != NULL) { + float zoomfac_px; + rctf camera_frame_old; + rctf camera_frame_new; - const float pt_src[2] = {zoom_xy[0], zoom_xy[1]}; - float pt_dst[2]; - float delta_px[2]; + const float pt_src[2] = {zoom_xy[0], zoom_xy[1]}; + float pt_dst[2]; + float delta_px[2]; - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false); - BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin); + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false); + BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin); - rv3d->camzoom = camzoom_new; - CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false); - BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin); + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false); + BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin); - BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src); - sub_v2_v2v2(delta_px, pt_dst, pt_src); + BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src); + sub_v2_v2v2(delta_px, pt_dst, pt_src); - /* translate the camera offset using pixel space delta - * mapped back to the camera (same logic as panning in camera view) */ - zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; + /* translate the camera offset using pixel space delta + * mapped back to the camera (same logic as panning in camera view) */ + zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; - rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px); - rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px); - CLAMP(rv3d->camdx, -1.0f, 1.0f); - CLAMP(rv3d->camdy, -1.0f, 1.0f); - } - else { - rv3d->camzoom = camzoom_new; - CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - } + rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px); + rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px); + CLAMP(rv3d->camdx, -1.0f, 1.0f); + CLAMP(rv3d->camdy, -1.0f, 1.0f); + } + else { + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + } } /** @@ -1894,441 +1895,472 @@ static void view_zoom_to_window_xy_camera( */ static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy[2]) { - RegionView3D *rv3d = ar->regiondata; - const float dist_new = rv3d->dist * dfac; - - if (zoom_xy != NULL) { - float dvec[3]; - float tvec[3]; - float tpos[3]; - float mval_f[2]; - - float zfac; - - negate_v3_v3(tpos, rv3d->ofs); - - mval_f[0] = (float)(((zoom_xy[0] - ar->winrct.xmin) * 2) - ar->winx) / 2.0f; - mval_f[1] = (float)(((zoom_xy[1] - ar->winrct.ymin) * 2) - ar->winy) / 2.0f; - - /* Project cursor position into 3D space */ - zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - - /* Calculate view target position for dolly */ - add_v3_v3v3(tvec, tpos, dvec); - negate_v3(tvec); - - /* Offset to target position and dolly */ - copy_v3_v3(rv3d->ofs, tvec); - rv3d->dist = dist_new; - - /* Calculate final offset */ - madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); - } - else { - rv3d->dist = dist_new; - } -} - -static float viewzoom_scale_value( - const rcti *winrct, - const short viewzoom, - const bool zoom_invert, const bool zoom_invert_force, - const int xy_curr[2], const int xy_init[2], - const float val, const float val_orig, - double *r_timer_lastdraw) -{ - float zfac; - - if (viewzoom == USER_ZOOM_CONT) { - double time = PIL_check_seconds_timer(); - float time_step = (float)(time - *r_timer_lastdraw); - float fac; - - if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(xy_init[0] - xy_curr[0]); - } - else { - fac = (float)(xy_init[1] - xy_curr[1]); - } - - if (zoom_invert != zoom_invert_force) { - fac = -fac; - } - - /* oldstyle zoom */ - zfac = 1.0f + ((fac / 20.0f) * time_step); - *r_timer_lastdraw = time; - } - else if (viewzoom == USER_ZOOM_SCALE) { - /* method which zooms based on how far you move the mouse */ - - const int ctr[2] = { - BLI_rcti_cent_x(winrct), - BLI_rcti_cent_y(winrct), - }; - float len_new = 5 + len_v2v2_int(ctr, xy_curr); - float len_old = 5 + len_v2v2_int(ctr, xy_init); - - /* intentionally ignore 'zoom_invert' for scale */ - if (zoom_invert_force) { - SWAP(float, len_new, len_old); - } - - zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; - } - else { /* USER_ZOOM_DOLLY */ - float len_new = 5; - float len_old = 5; - - if (U.uiflag & USER_ZOOM_HORIZ) { - len_new += (winrct->xmax - (xy_curr[0])); - len_old += (winrct->xmax - (xy_init[0])); - } - else { - len_new += (winrct->ymax - (xy_curr[1])); - len_old += (winrct->ymax - (xy_init[1])); - } - - if (zoom_invert != zoom_invert_force) { - SWAP(float, len_new, len_old); - } - - zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val; - } - - - return zfac; -} - -static float viewzoom_scale_value_offset( - const rcti *winrct, - const short viewzoom, - const bool zoom_invert, const bool zoom_invert_force, - const int xy_curr[2], const int xy_init[2], const int xy_offset[2], - const float val, const float val_orig, - double *r_timer_lastdraw) -{ - const int xy_curr_offset[2] = { - xy_curr[0] + xy_offset[0], - xy_curr[1] + xy_offset[1], - }; - const int xy_init_offset[2] = { - xy_init[0] + xy_offset[0], - xy_init[1] + xy_offset[1], - }; - return viewzoom_scale_value( - winrct, viewzoom, zoom_invert, zoom_invert_force, - xy_curr_offset, xy_init_offset, - val, val_orig, r_timer_lastdraw); -} - -static void viewzoom_apply_camera( - ViewOpsData *vod, const int xy[2], - const short viewzoom, const bool zoom_invert, const bool zoom_to_pos) -{ - float zfac; - float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f; - float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; - - zfac = viewzoom_scale_value_offset( - &vod->ar->winrct, viewzoom, zoom_invert, true, - xy, vod->init.event_xy, vod->init.event_xy_offset, - zoomfac, zoomfac_prev, - &vod->prev.time); - - if (zfac != 1.0f && zfac != 0.0f) { - /* calculate inverted, then invert again (needed because of camera zoom scaling) */ - zfac = 1.0f / zfac; - view_zoom_to_window_xy_camera( - vod->scene, vod->depsgraph, vod->v3d, - vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL); - } - - ED_region_tag_redraw(vod->ar); -} - -static void viewzoom_apply_3d( - ViewOpsData *vod, const int xy[2], - const short viewzoom, const bool zoom_invert, const bool zoom_to_pos) -{ - float zfac; - float dist_range[2]; - - ED_view3d_dist_range_get(vod->v3d, dist_range); - - zfac = viewzoom_scale_value_offset( - &vod->ar->winrct, viewzoom, zoom_invert, false, - xy, vod->init.event_xy, vod->init.event_xy_offset, - vod->rv3d->dist, vod->init.dist, - &vod->prev.time); - - if (zfac != 1.0f) { - const float zfac_min = dist_range[0] / vod->rv3d->dist; - const float zfac_max = dist_range[1] / vod->rv3d->dist; - CLAMP(zfac, zfac_min, zfac_max); - - view_zoom_to_window_xy_3d( - vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL); - } - - /* these limits were in old code too */ - CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]); - - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(vod->sa, vod->ar); - } - - ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); - - ED_region_tag_redraw(vod->ar); -} - -static void viewzoom_apply( - ViewOpsData *vod, const int xy[2], - const short viewzoom, const bool zoom_invert, const bool zoom_to_pos) -{ - if ((vod->rv3d->persp == RV3D_CAMOB) && - (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) - { - viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos); - } - else { - viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos); - } + RegionView3D *rv3d = ar->regiondata; + const float dist_new = rv3d->dist * dfac; + + if (zoom_xy != NULL) { + float dvec[3]; + float tvec[3]; + float tpos[3]; + float mval_f[2]; + + float zfac; + + negate_v3_v3(tpos, rv3d->ofs); + + mval_f[0] = (float)(((zoom_xy[0] - ar->winrct.xmin) * 2) - ar->winx) / 2.0f; + mval_f[1] = (float)(((zoom_xy[1] - ar->winrct.ymin) * 2) - ar->winy) / 2.0f; + + /* Project cursor position into 3D space */ + zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); + + /* Calculate view target position for dolly */ + add_v3_v3v3(tvec, tpos, dvec); + negate_v3(tvec); + + /* Offset to target position and dolly */ + copy_v3_v3(rv3d->ofs, tvec); + rv3d->dist = dist_new; + + /* Calculate final offset */ + madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); + } + else { + rv3d->dist = dist_new; + } +} + +static float viewzoom_scale_value(const rcti *winrct, + const short viewzoom, + const bool zoom_invert, + const bool zoom_invert_force, + const int xy_curr[2], + const int xy_init[2], + const float val, + const float val_orig, + double *r_timer_lastdraw) +{ + float zfac; + + if (viewzoom == USER_ZOOM_CONT) { + double time = PIL_check_seconds_timer(); + float time_step = (float)(time - *r_timer_lastdraw); + float fac; + + if (U.uiflag & USER_ZOOM_HORIZ) { + fac = (float)(xy_init[0] - xy_curr[0]); + } + else { + fac = (float)(xy_init[1] - xy_curr[1]); + } + + if (zoom_invert != zoom_invert_force) { + fac = -fac; + } + + /* oldstyle zoom */ + zfac = 1.0f + ((fac / 20.0f) * time_step); + *r_timer_lastdraw = time; + } + else if (viewzoom == USER_ZOOM_SCALE) { + /* method which zooms based on how far you move the mouse */ + + const int ctr[2] = { + BLI_rcti_cent_x(winrct), + BLI_rcti_cent_y(winrct), + }; + float len_new = 5 + len_v2v2_int(ctr, xy_curr); + float len_old = 5 + len_v2v2_int(ctr, xy_init); + + /* intentionally ignore 'zoom_invert' for scale */ + if (zoom_invert_force) { + SWAP(float, len_new, len_old); + } + + zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; + } + else { /* USER_ZOOM_DOLLY */ + float len_new = 5; + float len_old = 5; + + if (U.uiflag & USER_ZOOM_HORIZ) { + len_new += (winrct->xmax - (xy_curr[0])); + len_old += (winrct->xmax - (xy_init[0])); + } + else { + len_new += (winrct->ymax - (xy_curr[1])); + len_old += (winrct->ymax - (xy_init[1])); + } + + if (zoom_invert != zoom_invert_force) { + SWAP(float, len_new, len_old); + } + + zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val; + } + + return zfac; +} + +static float viewzoom_scale_value_offset(const rcti *winrct, + const short viewzoom, + const bool zoom_invert, + const bool zoom_invert_force, + const int xy_curr[2], + const int xy_init[2], + const int xy_offset[2], + const float val, + const float val_orig, + double *r_timer_lastdraw) +{ + const int xy_curr_offset[2] = { + xy_curr[0] + xy_offset[0], + xy_curr[1] + xy_offset[1], + }; + const int xy_init_offset[2] = { + xy_init[0] + xy_offset[0], + xy_init[1] + xy_offset[1], + }; + return viewzoom_scale_value(winrct, + viewzoom, + zoom_invert, + zoom_invert_force, + xy_curr_offset, + xy_init_offset, + val, + val_orig, + r_timer_lastdraw); +} + +static void viewzoom_apply_camera(ViewOpsData *vod, + const int xy[2], + const short viewzoom, + const bool zoom_invert, + const bool zoom_to_pos) +{ + float zfac; + float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f; + float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; + + zfac = viewzoom_scale_value_offset(&vod->ar->winrct, + viewzoom, + zoom_invert, + true, + xy, + vod->init.event_xy, + vod->init.event_xy_offset, + zoomfac, + zoomfac_prev, + &vod->prev.time); + + if (zfac != 1.0f && zfac != 0.0f) { + /* calculate inverted, then invert again (needed because of camera zoom scaling) */ + zfac = 1.0f / zfac; + view_zoom_to_window_xy_camera(vod->scene, + vod->depsgraph, + vod->v3d, + vod->ar, + zfac, + zoom_to_pos ? vod->prev.event_xy : NULL); + } + + ED_region_tag_redraw(vod->ar); +} + +static void viewzoom_apply_3d(ViewOpsData *vod, + const int xy[2], + const short viewzoom, + const bool zoom_invert, + const bool zoom_to_pos) +{ + float zfac; + float dist_range[2]; + + ED_view3d_dist_range_get(vod->v3d, dist_range); + + zfac = viewzoom_scale_value_offset(&vod->ar->winrct, + viewzoom, + zoom_invert, + false, + xy, + vod->init.event_xy, + vod->init.event_xy_offset, + vod->rv3d->dist, + vod->init.dist, + &vod->prev.time); + + if (zfac != 1.0f) { + const float zfac_min = dist_range[0] / vod->rv3d->dist; + const float zfac_max = dist_range[1] / vod->rv3d->dist; + CLAMP(zfac, zfac_min, zfac_max); + + view_zoom_to_window_xy_3d(vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL); + } + + /* these limits were in old code too */ + CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]); + + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(vod->sa, vod->ar); + } + + ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); + + ED_region_tag_redraw(vod->ar); +} + +static void viewzoom_apply(ViewOpsData *vod, + const int xy[2], + const short viewzoom, + const bool zoom_invert, + const bool zoom_to_pos) +{ + if ((vod->rv3d->persp == RV3D_CAMOB) && + (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) { + viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos); + } + else { + viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos); + } } static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod = op->customdata; - short event_code = VIEW_PASS; - bool use_autokey = false; - int ret = OPERATOR_RUNNING_MODAL; - - /* execute the events */ - if (event->type == TIMER && event->customdata == vod->timer) { - /* continuous zoom */ - event_code = VIEW_APPLY; - } - else if (event->type == MOUSEMOVE) { - event_code = VIEW_APPLY; - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case VIEW_MODAL_CONFIRM: - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - } - } - else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { - event_code = VIEW_CONFIRM; - } - - if (event_code == VIEW_APPLY) { - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - viewzoom_apply( - vod, &event->x, U.viewzoom, - (U.uiflag & USER_ZOOM_INVERT) != 0, - (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - use_autokey = true; - } - } - else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); - use_autokey = true; - ret = OPERATOR_FINISHED; - } - - if (use_autokey) { - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); - } - - if (ret & OPERATOR_FINISHED) { - viewops_data_free(C, op); - } - - return ret; + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + bool use_autokey = false; + int ret = OPERATOR_RUNNING_MODAL; + + /* execute the events */ + if (event->type == TIMER && event->customdata == vod->timer) { + /* continuous zoom */ + event_code = VIEW_APPLY; + } + else if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + viewzoom_apply(vod, + &event->x, + U.viewzoom, + (U.uiflag & USER_ZOOM_INVERT) != 0, + (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + use_autokey = true; + } + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + use_autokey = true; + ret = OPERATOR_FINISHED; + } + + if (use_autokey) { + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); + } + + if (ret & OPERATOR_FINISHED) { + viewops_data_free(C, op); + } + + return ret; } static int viewzoom_exec(bContext *C, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d; - RegionView3D *rv3d; - ScrArea *sa; - ARegion *ar; - bool use_cam_zoom; - float dist_range[2]; - - const int delta = RNA_int_get(op->ptr, "delta"); - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - - if (op->customdata) { - ViewOpsData *vod = op->customdata; - - sa = vod->sa; - ar = vod->ar; - } - else { - sa = CTX_wm_area(C); - ar = CTX_wm_region(C); - } - - v3d = sa->spacedata.first; - rv3d = ar->regiondata; - - - use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d)); - - int zoom_xy_buf[2]; - const int *zoom_xy = NULL; - if (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) { - zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2; - zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2; - zoom_xy = zoom_xy_buf; - } - - ED_view3d_dist_range_get(v3d, dist_range); - - if (delta < 0) { - const float step = 1.2f; - /* this min and max is also in viewmove() */ - if (use_cam_zoom) { - view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy); - } - else { - if (rv3d->dist < dist_range[1]) { - view_zoom_to_window_xy_3d(ar, step, zoom_xy); - } - } - } - else { - const float step = 1.0f / 1.2f; - if (use_cam_zoom) { - view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy); - } - else { - if (rv3d->dist > dist_range[0]) { - view_zoom_to_window_xy_3d(ar, step, zoom_xy); - } - } - } - - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(sa, ar); - } - - ED_view3d_depth_tag_update(rv3d); - - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true); - - ED_region_tag_redraw(ar); - - viewops_data_free(C, op); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + View3D *v3d; + RegionView3D *rv3d; + ScrArea *sa; + ARegion *ar; + bool use_cam_zoom; + float dist_range[2]; + + const int delta = RNA_int_get(op->ptr, "delta"); + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + + if (op->customdata) { + ViewOpsData *vod = op->customdata; + + sa = vod->sa; + ar = vod->ar; + } + else { + sa = CTX_wm_area(C); + ar = CTX_wm_region(C); + } + + v3d = sa->spacedata.first; + rv3d = ar->regiondata; + + use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && + !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d)); + + int zoom_xy_buf[2]; + const int *zoom_xy = NULL; + if (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) { + zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : + ar->winx / 2; + zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : + ar->winy / 2; + zoom_xy = zoom_xy_buf; + } + + ED_view3d_dist_range_get(v3d, dist_range); + + if (delta < 0) { + const float step = 1.2f; + /* this min and max is also in viewmove() */ + if (use_cam_zoom) { + view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy); + } + else { + if (rv3d->dist < dist_range[1]) { + view_zoom_to_window_xy_3d(ar, step, zoom_xy); + } + } + } + else { + const float step = 1.0f / 1.2f; + if (use_cam_zoom) { + view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy); + } + else { + if (rv3d->dist > dist_range[0]) { + view_zoom_to_window_xy_3d(ar, step, zoom_xy); + } + } + } + + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(sa, ar); + } + + ED_view3d_depth_tag_update(rv3d); + + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + ED_view3d_camera_lock_autokey(v3d, rv3d, C, false, true); + + ED_region_tag_redraw(ar); + + viewops_data_free(C, op); + + return OPERATOR_FINISHED; } /* viewdolly_invoke() copied this function, changes here may apply there */ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod; - - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - - /* makes op->customdata */ - viewops_data_alloc(C, op); - viewops_data_create( - C, op, event, - (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | - (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); - vod = op->customdata; - - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - - /* if one or the other zoom position aren't set, set from event */ - if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) { - RNA_int_set(op->ptr, "mx", event->x); - RNA_int_set(op->ptr, "my", event->y); - } - - if (RNA_struct_property_is_set(op->ptr, "delta")) { - viewzoom_exec(C, op); - } - else { - if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { - - if (U.uiflag & USER_ZOOM_HORIZ) { - vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; - } - else { - /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ - vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx; - } - viewzoom_apply( - vod, &event->prevx, USER_ZOOM_DOLLY, - (U.uiflag & USER_ZOOM_INVERT) != 0, - (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); - - ED_view3d_depth_tag_update(vod->rv3d); - - viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - if (U.viewzoom == USER_ZOOM_CONT) { - /* needs a timer to continue redrawing */ - vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); - vod->prev.time = PIL_check_seconds_timer(); - } - - /* add temp handler */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; - } - } - return OPERATOR_FINISHED; + ViewOpsData *vod; + + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + + /* makes op->customdata */ + viewops_data_alloc(C, op); + viewops_data_create(C, + op, + event, + (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | + (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); + vod = op->customdata; + + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + + /* if one or the other zoom position aren't set, set from event */ + if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) { + RNA_int_set(op->ptr, "mx", event->x); + RNA_int_set(op->ptr, "my", event->y); + } + + if (RNA_struct_property_is_set(op->ptr, "delta")) { + viewzoom_exec(C, op); + } + else { + if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { + + if (U.uiflag & USER_ZOOM_HORIZ) { + vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; + } + else { + /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ + vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - + event->prevx; + } + viewzoom_apply(vod, + &event->prevx, + USER_ZOOM_DOLLY, + (U.uiflag & USER_ZOOM_INVERT) != 0, + (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); + + ED_view3d_depth_tag_update(vod->rv3d); + + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + if (U.viewzoom == USER_ZOOM_CONT) { + /* needs a timer to continue redrawing */ + vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); + vod->prev.time = PIL_check_seconds_timer(); + } + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } + } + return OPERATOR_FINISHED; } static void viewzoom_cancel(bContext *C, wmOperator *op) { - viewops_data_free(C, op); + viewops_data_free(C, op); } void VIEW3D_OT_zoom(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Zoom View"; - ot->description = "Zoom in/out in the view"; - ot->idname = "VIEW3D_OT_zoom"; + /* identifiers */ + ot->name = "Zoom View"; + ot->description = "Zoom in/out in the view"; + ot->idname = "VIEW3D_OT_zoom"; - /* api callbacks */ - ot->invoke = viewzoom_invoke; - ot->exec = viewzoom_exec; - ot->modal = viewzoom_modal; - ot->poll = ED_operator_region_view3d_active; - ot->cancel = viewzoom_cancel; + /* api callbacks */ + ot->invoke = viewzoom_invoke; + ot->exec = viewzoom_exec; + ot->modal = viewzoom_modal; + ot->poll = ED_operator_region_view3d_active; + ot->cancel = viewzoom_cancel; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; - /* properties */ - view3d_operator_properties_common( - ot, - V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT); + /* properties */ + view3d_operator_properties_common( + ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT); } /** \} */ @@ -2344,304 +2376,304 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) /* called in transform_ops.c, on each regeneration of keymaps */ void viewdolly_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + static const EnumPropertyItem modal_items[] = { + {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, - {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, + {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"}, + {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); - /* disabled mode switching for now, can re-implement better, later on */ + /* disabled mode switching for now, can re-implement better, later on */ #if 0 - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); - WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); + WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE); + WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE); #endif - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); } static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - if (ED_view3d_offset_lock_check(v3d, rv3d)) { - BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked"); - return true; - } - else { - return false; - } + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (ED_view3d_offset_lock_check(v3d, rv3d)) { + BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked"); + return true; + } + else { + return false; + } } static void view_dolly_to_vector_3d(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac) { - RegionView3D *rv3d = ar->regiondata; - madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac)); + RegionView3D *rv3d = ar->regiondata; + madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac)); } static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_invert) { - float zfac = 1.0; + float zfac = 1.0; - { - float len1, len2; + { + float len1, len2; - if (U.uiflag & USER_ZOOM_HORIZ) { - len1 = (vod->ar->winrct.xmax - xy[0]) + 5; - len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) + 5; - } - else { - len1 = (vod->ar->winrct.ymax - xy[1]) + 5; - len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5; - } - if (zoom_invert) { - SWAP(float, len1, len2); - } + if (U.uiflag & USER_ZOOM_HORIZ) { + len1 = (vod->ar->winrct.xmax - xy[0]) + 5; + len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) + 5; + } + else { + len1 = (vod->ar->winrct.ymax - xy[1]) + 5; + len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5; + } + if (zoom_invert) { + SWAP(float, len1, len2); + } - zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist); - } + zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist); + } - if (zfac != 1.0f) { - view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac); - } + if (zfac != 1.0f) { + view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac); + } - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(vod->sa, vod->ar); - } + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(vod->sa, vod->ar); + } - ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); + ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); } - static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod = op->customdata; - short event_code = VIEW_PASS; - bool use_autokey = false; - int ret = OPERATOR_RUNNING_MODAL; - - /* execute the events */ - if (event->type == MOUSEMOVE) { - event_code = VIEW_APPLY; - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case VIEW_MODAL_CONFIRM: - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - } - } - else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { - event_code = VIEW_CONFIRM; - } - - if (event_code == VIEW_APPLY) { - viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - use_autokey = true; - } - } - else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); - use_autokey = true; - ret = OPERATOR_FINISHED; - } - - if (use_autokey) { - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); - } - - if (ret & OPERATOR_FINISHED) { - viewops_data_free(C, op); - } - - return ret; + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + bool use_autokey = false; + int ret = OPERATOR_RUNNING_MODAL; + + /* execute the events */ + if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + use_autokey = true; + } + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + use_autokey = true; + ret = OPERATOR_FINISHED; + } + + if (use_autokey) { + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true); + } + + if (ret & OPERATOR_FINISHED) { + viewops_data_free(C, op); + } + + return ret; } static int viewdolly_exec(bContext *C, wmOperator *op) { - View3D *v3d; - RegionView3D *rv3d; - ScrArea *sa; - ARegion *ar; - float mousevec[3]; + View3D *v3d; + RegionView3D *rv3d; + ScrArea *sa; + ARegion *ar; + float mousevec[3]; - const int delta = RNA_int_get(op->ptr, "delta"); + const int delta = RNA_int_get(op->ptr, "delta"); - if (op->customdata) { - ViewOpsData *vod = op->customdata; + if (op->customdata) { + ViewOpsData *vod = op->customdata; - sa = vod->sa; - ar = vod->ar; - copy_v3_v3(mousevec, vod->init.mousevec); - } - else { - sa = CTX_wm_area(C); - ar = CTX_wm_region(C); - negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); - normalize_v3(mousevec); - } + sa = vod->sa; + ar = vod->ar; + copy_v3_v3(mousevec, vod->init.mousevec); + } + else { + sa = CTX_wm_area(C); + ar = CTX_wm_region(C); + negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); + normalize_v3(mousevec); + } - v3d = sa->spacedata.first; - rv3d = ar->regiondata; + v3d = sa->spacedata.first; + rv3d = ar->regiondata; - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - /* overwrite the mouse vector with the view direction (zoom into the center) */ - if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) { - normalize_v3_v3(mousevec, rv3d->viewinv[2]); - } + /* overwrite the mouse vector with the view direction (zoom into the center) */ + if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) { + normalize_v3_v3(mousevec, rv3d->viewinv[2]); + } - view_dolly_to_vector_3d(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f); + view_dolly_to_vector_3d(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f); - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(sa, ar); - } + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(sa, ar); + } - ED_view3d_depth_tag_update(rv3d); + ED_view3d_depth_tag_update(rv3d); - ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d); + ED_view3d_camera_lock_sync(CTX_data_depsgraph(C), v3d, rv3d); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(ar); - viewops_data_free(C, op); + viewops_data_free(C, op); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } /* copied from viewzoom_invoke(), changes here may apply there */ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod; - - if (viewdolly_offset_lock_check(C, op)) { - return OPERATOR_CANCELLED; - } - - /* makes op->customdata */ - viewops_data_alloc(C, op); - vod = op->customdata; - - /* poll should check but in some cases fails, see poll func for details */ - if (vod->rv3d->viewlock & RV3D_LOCKED) { - viewops_data_free(C, op); - return OPERATOR_PASS_THROUGH; - } - - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - - /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */ - /* switch from camera view when: */ - if (vod->rv3d->persp != RV3D_PERSP) { - if (vod->rv3d->persp == RV3D_CAMOB) { - /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */ - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP); - } - else { - vod->rv3d->persp = RV3D_PERSP; - } - ED_region_tag_redraw(vod->ar); - } - - const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); - - viewops_data_create( - C, op, event, - (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | - (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); - - - /* if one or the other zoom position aren't set, set from event */ - if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) { - RNA_int_set(op->ptr, "mx", event->x); - RNA_int_set(op->ptr, "my", event->y); - } - - if (RNA_struct_property_is_set(op->ptr, "delta")) { - viewdolly_exec(C, op); - } - else { - /* overwrite the mouse vector with the view direction (zoom into the center) */ - if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) { - negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]); - normalize_v3(vod->init.mousevec); - } - - if (event->type == MOUSEZOOM) { - /* Bypass Zoom invert flag for track pads (pass false always) */ - - if (U.uiflag & USER_ZOOM_HORIZ) { - vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; - } - else { - /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ - vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx; - } - viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0); - ED_view3d_depth_tag_update(vod->rv3d); - - viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - /* add temp handler */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; - } - } - return OPERATOR_FINISHED; + ViewOpsData *vod; + + if (viewdolly_offset_lock_check(C, op)) { + return OPERATOR_CANCELLED; + } + + /* makes op->customdata */ + viewops_data_alloc(C, op); + vod = op->customdata; + + /* poll should check but in some cases fails, see poll func for details */ + if (vod->rv3d->viewlock & RV3D_LOCKED) { + viewops_data_free(C, op); + return OPERATOR_PASS_THROUGH; + } + + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + + /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */ + /* switch from camera view when: */ + if (vod->rv3d->persp != RV3D_PERSP) { + if (vod->rv3d->persp == RV3D_CAMOB) { + /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */ + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_view3d_persp_switch_from_camera(depsgraph, vod->v3d, vod->rv3d, RV3D_PERSP); + } + else { + vod->rv3d->persp = RV3D_PERSP; + } + ED_region_tag_redraw(vod->ar); + } + + const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init"); + + viewops_data_create(C, + op, + event, + (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) | + (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0)); + + /* if one or the other zoom position aren't set, set from event */ + if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) { + RNA_int_set(op->ptr, "mx", event->x); + RNA_int_set(op->ptr, "my", event->y); + } + + if (RNA_struct_property_is_set(op->ptr, "delta")) { + viewdolly_exec(C, op); + } + else { + /* overwrite the mouse vector with the view direction (zoom into the center) */ + if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) { + negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]); + normalize_v3(vod->init.mousevec); + } + + if (event->type == MOUSEZOOM) { + /* Bypass Zoom invert flag for track pads (pass false always) */ + + if (U.uiflag & USER_ZOOM_HORIZ) { + vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; + } + else { + /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */ + vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - + event->prevx; + } + viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0); + ED_view3d_depth_tag_update(vod->rv3d); + + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } + } + return OPERATOR_FINISHED; } static void viewdolly_cancel(bContext *C, wmOperator *op) { - viewops_data_free(C, op); + viewops_data_free(C, op); } void VIEW3D_OT_dolly(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Dolly View"; - ot->description = "Dolly in/out in the view"; - ot->idname = "VIEW3D_OT_dolly"; + /* identifiers */ + ot->name = "Dolly View"; + ot->description = "Dolly in/out in the view"; + ot->idname = "VIEW3D_OT_dolly"; - /* api callbacks */ - ot->invoke = viewdolly_invoke; - ot->exec = viewdolly_exec; - ot->modal = viewdolly_modal; - ot->poll = ED_operator_region_view3d_active; - ot->cancel = viewdolly_cancel; + /* api callbacks */ + ot->invoke = viewdolly_invoke; + ot->exec = viewdolly_exec; + ot->modal = viewdolly_modal; + ot->poll = ED_operator_region_view3d_active; + ot->cancel = viewdolly_cancel; - /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; + /* flags */ + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; - /* properties */ - view3d_operator_properties_common( - ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT); + /* properties */ + view3d_operator_properties_common( + ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT); } /** \} */ @@ -2652,215 +2684,228 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) * Move & Zoom the view to fit all of it's contents. * \{ */ -static bool view3d_object_skip_minmax( - const View3D *v3d, const RegionView3D *rv3d, const Object *ob, const bool skip_camera, - bool *r_only_center) -{ - BLI_assert(ob->id.orig_id == NULL); - *r_only_center = false; - - if (skip_camera && (ob == v3d->camera)) { - return true; - } - - if ((ob->type == OB_EMPTY) && - (ob->empty_drawtype == OB_EMPTY_IMAGE) && - !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) - { - *r_only_center = true; - return false; - } - - return false; -} - -static void view3d_from_minmax( - bContext *C, View3D *v3d, ARegion *ar, - const float min[3], const float max[3], - bool ok_dist, const int smooth_viewtx) -{ - RegionView3D *rv3d = ar->regiondata; - float afm[3]; - float size; - - ED_view3d_smooth_view_force_finish(C, v3d, ar); - - /* SMOOTHVIEW */ - float new_ofs[3]; - float new_dist; - - sub_v3_v3v3(afm, max, min); - size = max_fff(afm[0], afm[1], afm[2]); - - if (ok_dist) { - char persp; - - if (rv3d->is_persp) { - if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { - persp = RV3D_CAMOB; - } - else { - persp = RV3D_PERSP; - } - } - else { /* ortho */ - if (size < 0.0001f) { - /* bounding box was a single point so do not zoom */ - ok_dist = false; - } - else { - /* adjust zoom so it looks nicer */ - persp = RV3D_ORTHO; - } - } - - if (ok_dist) { - new_dist = ED_view3d_radius_to_dist(v3d, ar, CTX_data_depsgraph(C), 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); - } - } - } - - mid_v3_v3v3(new_ofs, min, max); - negate_v3(new_ofs); - - if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { - rv3d->persp = RV3D_PERSP; - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = v3d->camera, .ofs = new_ofs, - .dist = ok_dist ? &new_dist : NULL, - }); - } - else { - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .ofs = new_ofs, .dist = ok_dist ? &new_dist : NULL, }); - } - - /* smooth view does viewlock RV3D_BOXVIEW copy */ +static bool view3d_object_skip_minmax(const View3D *v3d, + const RegionView3D *rv3d, + const Object *ob, + const bool skip_camera, + bool *r_only_center) +{ + BLI_assert(ob->id.orig_id == NULL); + *r_only_center = false; + + if (skip_camera && (ob == v3d->camera)) { + return true; + } + + if ((ob->type == OB_EMPTY) && (ob->empty_drawtype == OB_EMPTY_IMAGE) && + !BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) { + *r_only_center = true; + return false; + } + + return false; +} + +static void view3d_from_minmax(bContext *C, + View3D *v3d, + ARegion *ar, + const float min[3], + const float max[3], + bool ok_dist, + const int smooth_viewtx) +{ + RegionView3D *rv3d = ar->regiondata; + float afm[3]; + float size; + + ED_view3d_smooth_view_force_finish(C, v3d, ar); + + /* SMOOTHVIEW */ + float new_ofs[3]; + float new_dist; + + sub_v3_v3v3(afm, max, min); + size = max_fff(afm[0], afm[1], afm[2]); + + if (ok_dist) { + char persp; + + if (rv3d->is_persp) { + if (rv3d->persp == RV3D_CAMOB && ED_view3d_camera_lock_check(v3d, rv3d)) { + persp = RV3D_CAMOB; + } + else { + persp = RV3D_PERSP; + } + } + else { /* ortho */ + if (size < 0.0001f) { + /* bounding box was a single point so do not zoom */ + ok_dist = false; + } + else { + /* adjust zoom so it looks nicer */ + persp = RV3D_ORTHO; + } + } + + if (ok_dist) { + new_dist = ED_view3d_radius_to_dist( + v3d, ar, CTX_data_depsgraph(C), 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); + } + } + } + + mid_v3_v3v3(new_ofs, min, max); + negate_v3(new_ofs); + + if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)) { + rv3d->persp = RV3D_PERSP; + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = v3d->camera, + .ofs = new_ofs, + .dist = ok_dist ? &new_dist : NULL, + }); + } + else { + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .ofs = new_ofs, + .dist = ok_dist ? &new_dist : NULL, + }); + } + + /* smooth view does viewlock RV3D_BOXVIEW copy */ } /** * Same as #view3d_from_minmax but for all regions (except cameras). */ -static void view3d_from_minmax_multi( - bContext *C, View3D *v3d, - const float min[3], const float max[3], - const bool ok_dist, const int smooth_viewtx) -{ - ScrArea *sa = CTX_wm_area(C); - ARegion *ar; - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - /* 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, ar, min, max, ok_dist, smooth_viewtx); - } - } - } +static void view3d_from_minmax_multi(bContext *C, + View3D *v3d, + const float min[3], + const float max[3], + const bool ok_dist, + const int smooth_viewtx) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + /* 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, ar, min, max, ok_dist, smooth_viewtx); + } + } + } } static int view3d_all_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - Base *base_eval; - const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); - const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || - /* any one of the regions may be locked */ - (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA)); - const bool center = RNA_boolean_get(op->ptr, "center"); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - - float min[3], max[3]; - bool changed = false; - - if (center) { - /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */ - View3DCursor *cursor = &scene->cursor; - zero_v3(min); - zero_v3(max); - zero_v3(cursor->location); - float mat3[3][3]; - unit_m3(mat3); - BKE_scene_cursor_mat3_to_rot(cursor, mat3, false); - } - else { - INIT_MINMAX(min, max); - } - - for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { - if (BASE_VISIBLE(v3d, base_eval)) { - bool only_center = false; - Object *ob = DEG_get_original_object(base_eval->object); - if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) { - continue; - } - - if (only_center) { - minmax_v3v3_v3(min, max, base_eval->object->obmat[3]); - } - else { - BKE_object_minmax(base_eval->object, min, max, false); - } - changed = true; - } - } - - if (center) { - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - } - - if (!changed) { - ED_region_tag_redraw(ar); - /* TODO - should this be cancel? - * I think no, because we always move the cursor, with or without - * object, but in this case there is no change in the scene, - * only the cursor so I choice a ED_region_tag like - * view3d_smooth_view do for the center_cursor. - * See bug #22640 - */ - return OPERATOR_FINISHED; - } - - if (use_all_regions) { - view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx); - } - else { - view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx); - } - - return OPERATOR_FINISHED; + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + Scene *scene = CTX_data_scene(C); + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); + Base *base_eval; + const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); + const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || + /* any one of the regions may be locked */ + (use_all_regions && v3d->flag2 & V3D_LOCK_CAMERA)); + const bool center = RNA_boolean_get(op->ptr, "center"); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + + float min[3], max[3]; + bool changed = false; + + if (center) { + /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c). */ + View3DCursor *cursor = &scene->cursor; + zero_v3(min); + zero_v3(max); + zero_v3(cursor->location); + float mat3[3][3]; + unit_m3(mat3); + BKE_scene_cursor_mat3_to_rot(cursor, mat3, false); + } + else { + INIT_MINMAX(min, max); + } + + for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { + if (BASE_VISIBLE(v3d, base_eval)) { + bool only_center = false; + Object *ob = DEG_get_original_object(base_eval->object); + if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) { + continue; + } + + if (only_center) { + minmax_v3v3_v3(min, max, base_eval->object->obmat[3]); + } + else { + BKE_object_minmax(base_eval->object, min, max, false); + } + changed = true; + } + } + + if (center) { + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + } + + if (!changed) { + ED_region_tag_redraw(ar); + /* TODO - should this be cancel? + * I think no, because we always move the cursor, with or without + * object, but in this case there is no change in the scene, + * only the cursor so I choice a ED_region_tag like + * view3d_smooth_view do for the center_cursor. + * See bug #22640 + */ + return OPERATOR_FINISHED; + } + + if (use_all_regions) { + view3d_from_minmax_multi(C, v3d, min, max, true, smooth_viewtx); + } + else { + view3d_from_minmax(C, v3d, ar, min, max, true, smooth_viewtx); + } + + return OPERATOR_FINISHED; } - void VIEW3D_OT_view_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View All"; - ot->description = "View all objects in scene"; - ot->idname = "VIEW3D_OT_view_all"; + /* identifiers */ + ot->name = "View All"; + ot->description = "View all objects in scene"; + ot->idname = "VIEW3D_OT_view_all"; - /* api callbacks */ - ot->exec = view3d_all_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = view3d_all_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS); - RNA_def_boolean(ot->srna, "center", 0, "Center", ""); + /* properties */ + view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS); + RNA_def_boolean(ot->srna, "center", 0, "Center", ""); } /** \} */ @@ -2874,151 +2919,150 @@ void VIEW3D_OT_view_all(wmOperatorType *ot) /* like a localview without local!, was centerview() in 2.4x */ static int viewselected_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - bGPdata *gpd = CTX_data_gpencil_data(C); - const bool is_gp_edit = GPENCIL_ANY_MODE(gpd); - const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map && - WM_gizmomap_is_any_selected(ar->gizmo_map)); - Object *ob_eval = OBACT(view_layer_eval); - Object *obedit = CTX_data_edit_object(C); - float min[3], max[3]; - bool ok = false, ok_dist = true; - const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); - const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || - /* 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); - - INIT_MINMAX(min, max); - if (is_face_map) { - ob_eval = NULL; - } - - if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) { - /* hard-coded exception, we look for the one selected armature */ - /* this is weak code this way, we should make a generic - * active/selection callback interface once... */ - Base *base_eval; - for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { - if (BASE_SELECTED_EDITABLE(v3d, base_eval)) { - if (base_eval->object->type == OB_ARMATURE) { - if (base_eval->object->mode & OB_MODE_POSE) { - break; - } - } - } - } - if (base_eval) { - ob_eval = base_eval->object; - } - } - - if (is_gp_edit) { - CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) - { - /* we're only interested in selected points here... */ - if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) { - ok |= BKE_gpencil_stroke_minmax(gps, true, min, max); - } - } - CTX_DATA_END; - - if ((ob_eval) && (ok)) { - mul_m4_v3(ob_eval->obmat, min); - mul_m4_v3(ob_eval->obmat, max); - } - } - else if (is_face_map) { - ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max); - } - else if (obedit) { - /* only selected */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) { - ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max); - } - FOREACH_OBJECT_IN_MODE_END; - } - else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) { - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) { - ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true); - } - FOREACH_OBJECT_IN_MODE_END; - } - else if (BKE_paint_select_face_test(ob_eval)) { - ok = paintface_minmax(ob_eval, min, max); - } - else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) { - ok = PE_minmax(scene, view_layer_eval, min, max); - } - else if (ob_eval && - (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) - { - BKE_paint_stroke_get_average(scene, ob_eval, min); - copy_v3_v3(max, min); - ok = true; - ok_dist = 0; /* don't zoom */ - } - else { - Base *base_eval; - for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { - if (BASE_SELECTED(v3d, base_eval)) { - bool only_center = false; - Object *ob = DEG_get_original_object(base_eval->object); - if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) { - continue; - } - - /* account for duplis */ - if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0) { - /* use if duplis not found */ - if (only_center) { - minmax_v3v3_v3(min, max, base_eval->object->obmat[3]); - } - else { - BKE_object_minmax(base_eval->object, min, max, false); - } - } - - ok = 1; - } - } - } - - if (ok == 0) { - return OPERATOR_FINISHED; - } - - if (use_all_regions) { - view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx); - } - else { - view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx); - } - - return OPERATOR_FINISHED; + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); + bGPdata *gpd = CTX_data_gpencil_data(C); + const bool is_gp_edit = GPENCIL_ANY_MODE(gpd); + const bool is_face_map = ((is_gp_edit == false) && ar->gizmo_map && + WM_gizmomap_is_any_selected(ar->gizmo_map)); + Object *ob_eval = OBACT(view_layer_eval); + Object *obedit = CTX_data_edit_object(C); + float min[3], max[3]; + bool ok = false, ok_dist = true; + const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions"); + const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) || + /* 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); + + INIT_MINMAX(min, max); + if (is_face_map) { + ob_eval = NULL; + } + + if (ob_eval && (ob_eval->mode & OB_MODE_WEIGHT_PAINT)) { + /* hard-coded exception, we look for the one selected armature */ + /* this is weak code this way, we should make a generic + * active/selection callback interface once... */ + Base *base_eval; + for (base_eval = view_layer_eval->object_bases.first; base_eval; base_eval = base_eval->next) { + if (BASE_SELECTED_EDITABLE(v3d, base_eval)) { + if (base_eval->object->type == OB_ARMATURE) { + if (base_eval->object->mode & OB_MODE_POSE) { + break; + } + } + } + } + if (base_eval) { + ob_eval = base_eval->object; + } + } + + if (is_gp_edit) { + CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { + /* we're only interested in selected points here... */ + if ((gps->flag & GP_STROKE_SELECT) && (gps->flag & GP_STROKE_3DSPACE)) { + ok |= BKE_gpencil_stroke_minmax(gps, true, min, max); + } + } + CTX_DATA_END; + + if ((ob_eval) && (ok)) { + mul_m4_v3(ob_eval->obmat, min); + mul_m4_v3(ob_eval->obmat, max); + } + } + else if (is_face_map) { + ok = WM_gizmomap_minmax(ar->gizmo_map, true, true, min, max); + } + else if (obedit) { + /* only selected */ + FOREACH_OBJECT_IN_MODE_BEGIN (view_layer_eval, v3d, obedit->type, obedit->mode, ob_eval_iter) { + ok |= ED_view3d_minmax_verts(ob_eval_iter, min, max); + } + FOREACH_OBJECT_IN_MODE_END; + } + else if (ob_eval && (ob_eval->mode & OB_MODE_POSE)) { + FOREACH_OBJECT_IN_MODE_BEGIN ( + view_layer_eval, v3d, ob_eval->type, ob_eval->mode, ob_eval_iter) { + ok |= BKE_pose_minmax(ob_eval_iter, min, max, true, true); + } + FOREACH_OBJECT_IN_MODE_END; + } + else if (BKE_paint_select_face_test(ob_eval)) { + ok = paintface_minmax(ob_eval, min, max); + } + else if (ob_eval && (ob_eval->mode & OB_MODE_PARTICLE_EDIT)) { + ok = PE_minmax(scene, view_layer_eval, min, max); + } + else if (ob_eval && (ob_eval->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | + OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { + BKE_paint_stroke_get_average(scene, ob_eval, min); + copy_v3_v3(max, min); + ok = true; + ok_dist = 0; /* don't zoom */ + } + else { + Base *base_eval; + for (base_eval = FIRSTBASE(view_layer_eval); base_eval; base_eval = base_eval->next) { + if (BASE_SELECTED(v3d, base_eval)) { + bool only_center = false; + Object *ob = DEG_get_original_object(base_eval->object); + if (view3d_object_skip_minmax(v3d, rv3d, ob, skip_camera, &only_center)) { + continue; + } + + /* account for duplis */ + if (BKE_object_minmax_dupli(depsgraph, scene, base_eval->object, min, max, false) == 0) { + /* use if duplis not found */ + if (only_center) { + minmax_v3v3_v3(min, max, base_eval->object->obmat[3]); + } + else { + BKE_object_minmax(base_eval->object, min, max, false); + } + } + + ok = 1; + } + } + } + + if (ok == 0) { + return OPERATOR_FINISHED; + } + + if (use_all_regions) { + view3d_from_minmax_multi(C, v3d, min, max, ok_dist, smooth_viewtx); + } + else { + view3d_from_minmax(C, v3d, ar, min, max, ok_dist, smooth_viewtx); + } + + return OPERATOR_FINISHED; } void VIEW3D_OT_view_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Selected"; - ot->description = "Move the view to the selection center"; - ot->idname = "VIEW3D_OT_view_selected"; + /* identifiers */ + ot->name = "View Selected"; + ot->description = "Move the view to the selection center"; + ot->idname = "VIEW3D_OT_view_selected"; - /* api callbacks */ - ot->exec = viewselected_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = viewselected_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS); + /* properties */ + view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS); } /** \} */ @@ -3029,34 +3073,34 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot) static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d = CTX_wm_view3d(C); + View3D *v3d = CTX_wm_view3d(C); - if (v3d) { - ED_view3d_lock_clear(v3d); + if (v3d) { + ED_view3d_lock_clear(v3d); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_view_lock_clear(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Lock Clear"; - ot->description = "Clear all view locking"; - ot->idname = "VIEW3D_OT_view_lock_clear"; + /* identifiers */ + ot->name = "View Lock Clear"; + ot->description = "Clear all view locking"; + ot->idname = "VIEW3D_OT_view_lock_clear"; - /* api callbacks */ - ot->exec = view_lock_clear_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = view_lock_clear_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3067,53 +3111,53 @@ void VIEW3D_OT_view_lock_clear(wmOperatorType *ot) static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d = CTX_wm_view3d(C); - Object *obact = CTX_data_active_object(C); + View3D *v3d = CTX_wm_view3d(C); + Object *obact = CTX_data_active_object(C); - if (v3d) { - ED_view3d_lock_clear(v3d); + if (v3d) { + ED_view3d_lock_clear(v3d); - v3d->ob_centre = obact; /* can be NULL */ + v3d->ob_centre = obact; /* can be NULL */ - if (obact && obact->type == OB_ARMATURE) { - if (obact->mode & OB_MODE_POSE) { - Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), obact); - bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval); - if (pcham_act) { - BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone)); - } - } - else { - EditBone *ebone_act = ((bArmature *)obact->data)->act_edbone; - if (ebone_act) { - BLI_strncpy(v3d->ob_centre_bone, ebone_act->name, sizeof(v3d->ob_centre_bone)); - } - } - } + if (obact && obact->type == OB_ARMATURE) { + if (obact->mode & OB_MODE_POSE) { + Object *obact_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), obact); + bPoseChannel *pcham_act = BKE_pose_channel_active(obact_eval); + if (pcham_act) { + BLI_strncpy(v3d->ob_centre_bone, pcham_act->name, sizeof(v3d->ob_centre_bone)); + } + } + else { + EditBone *ebone_act = ((bArmature *)obact->data)->act_edbone; + if (ebone_act) { + BLI_strncpy(v3d->ob_centre_bone, ebone_act->name, sizeof(v3d->ob_centre_bone)); + } + } + } - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Lock to Active"; - ot->description = "Lock the view to the active object/bone"; - ot->idname = "VIEW3D_OT_view_lock_to_active"; + /* identifiers */ + ot->name = "View Lock to Active"; + ot->description = "Lock the view to the active object/bone"; + ot->idname = "VIEW3D_OT_view_lock_to_active"; - /* api callbacks */ - ot->exec = view_lock_to_active_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = view_lock_to_active_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3124,42 +3168,40 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot) static int viewcenter_cursor_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + Scene *scene = CTX_data_scene(C); - if (rv3d) { - ARegion *ar = CTX_wm_region(C); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + if (rv3d) { + ARegion *ar = CTX_wm_region(C); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - ED_view3d_smooth_view_force_finish(C, v3d, ar); + ED_view3d_smooth_view_force_finish(C, v3d, ar); - /* non camera center */ - float new_ofs[3]; - negate_v3_v3(new_ofs, scene->cursor.location); - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) {.ofs = new_ofs}); + /* non camera center */ + float new_ofs[3]; + negate_v3_v3(new_ofs, scene->cursor.location); + ED_view3d_smooth_view(C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs}); - /* smooth view does viewlock RV3D_BOXVIEW copy */ - } + /* smooth view does viewlock RV3D_BOXVIEW copy */ + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Center View to Cursor"; - ot->description = "Center the view so that the cursor is in the middle of the view"; - ot->idname = "VIEW3D_OT_view_center_cursor"; + /* identifiers */ + ot->name = "Center View to Cursor"; + ot->description = "Center the view so that the cursor is in the middle of the view"; + ot->idname = "VIEW3D_OT_view_center_cursor"; - /* api callbacks */ - ot->exec = viewcenter_cursor_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = viewcenter_cursor_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3170,49 +3212,47 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + ARegion *ar = CTX_wm_region(C); - if (rv3d) { - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); - float new_ofs[3]; - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + if (rv3d) { + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + float new_ofs[3]; + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - ED_view3d_smooth_view_force_finish(C, v3d, ar); + ED_view3d_smooth_view_force_finish(C, v3d, ar); - view3d_operator_needs_opengl(C); + view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) { - /* pass */ - } - else { - /* fallback to simple pan */ - negate_v3_v3(new_ofs, rv3d->ofs); - ED_view3d_win_to_3d_int(v3d, ar, new_ofs, event->mval, new_ofs); - } - negate_v3(new_ofs); - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) {.ofs = new_ofs}); - } + if (ED_view3d_autodist(depsgraph, ar, v3d, event->mval, new_ofs, false, NULL)) { + /* pass */ + } + else { + /* fallback to simple pan */ + negate_v3_v3(new_ofs, rv3d->ofs); + ED_view3d_win_to_3d_int(v3d, ar, new_ofs, event->mval, new_ofs); + } + negate_v3(new_ofs); + ED_view3d_smooth_view(C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs}); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_center_pick(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Center View to Mouse"; - ot->description = "Center the view to the Z-depth position under the mouse cursor"; - ot->idname = "VIEW3D_OT_view_center_pick"; + /* identifiers */ + ot->name = "Center View to Mouse"; + ot->description = "Center the view to the Z-depth position under the mouse cursor"; + ot->idname = "VIEW3D_OT_view_center_pick"; - /* api callbacks */ - ot->invoke = viewcenter_pick_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = viewcenter_pick_invoke; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3223,48 +3263,48 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot) static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - float xfac, yfac; - float size[2]; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + float xfac, yfac; + float size[2]; - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; - rv3d->camdx = rv3d->camdy = 0.0f; + rv3d->camdx = rv3d->camdy = 0.0f; - ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size); + ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size); - /* 4px is just a little room from the edge of the area */ - xfac = (float)ar->winx / (float)(size[0] + 4); - yfac = (float)ar->winy / (float)(size[1] + 4); + /* 4px is just a little room from the edge of the area */ + xfac = (float)ar->winx / (float)(size[0] + 4); + yfac = (float)ar->winy / (float)(size[1] + 4); - rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac)); - CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(min_ff(xfac, yfac)); + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_center_camera(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Camera Center"; - ot->description = "Center the camera view"; - ot->idname = "VIEW3D_OT_view_center_camera"; + /* identifiers */ + ot->name = "View Camera Center"; + ot->description = "Center the camera view"; + ot->idname = "VIEW3D_OT_view_center_camera"; - /* api callbacks */ - ot->exec = view3d_center_camera_exec; - ot->poll = view3d_camera_user_poll; + /* api callbacks */ + ot->exec = view3d_center_camera_exec; + ot->poll = view3d_camera_user_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3275,28 +3315,28 @@ void VIEW3D_OT_view_center_camera(wmOperatorType *ot) static int view3d_center_lock_exec(bContext *C, wmOperator *UNUSED(op)) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); - zero_v2(rv3d->ofs_lock); + zero_v2(rv3d->ofs_lock); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_center_lock(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Lock Center"; - ot->description = "Center the view lock offset"; - ot->idname = "VIEW3D_OT_view_center_lock"; + /* identifiers */ + ot->name = "View Lock Center"; + ot->description = "Center the view lock offset"; + ot->idname = "VIEW3D_OT_view_center_lock"; - /* api callbacks */ - ot->exec = view3d_center_lock_exec; - ot->poll = view3d_lock_poll; + /* api callbacks */ + ot->exec = view3d_center_lock_exec; + ot->poll = view3d_lock_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3307,97 +3347,97 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot) static int render_border_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - - Scene *scene = CTX_data_scene(C); - - rcti rect; - rctf vb, border; - - /* get box select values using rna */ - WM_operator_properties_border_to_rcti(op, &rect); - - /* calculate range */ - - if (rv3d->persp == RV3D_CAMOB) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false); - } - else { - vb.xmin = 0; - vb.ymin = 0; - vb.xmax = ar->winx; - vb.ymax = ar->winy; - } - - border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb); - border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb); - border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb); - border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb); - - /* actually set border */ - CLAMP(border.xmin, 0.0f, 1.0f); - CLAMP(border.ymin, 0.0f, 1.0f); - CLAMP(border.xmax, 0.0f, 1.0f); - CLAMP(border.ymax, 0.0f, 1.0f); - - if (rv3d->persp == RV3D_CAMOB) { - scene->r.border = border; - - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); - } - else { - v3d->render_border = border; - - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - } - - /* drawing a border outside the camera view switches off border rendering */ - if ((border.xmin == border.xmax || border.ymin == border.ymax)) { - if (rv3d->persp == RV3D_CAMOB) { - scene->r.mode &= ~R_BORDER; - } - else { - v3d->flag2 &= ~V3D_RENDER_BORDER; - } - } - else { - if (rv3d->persp == RV3D_CAMOB) { - scene->r.mode |= R_BORDER; - } - else { - v3d->flag2 |= V3D_RENDER_BORDER; - } - } - - if (rv3d->persp == RV3D_CAMOB) { - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - } - return OPERATOR_FINISHED; + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + + Scene *scene = CTX_data_scene(C); + + rcti rect; + rctf vb, border; + + /* get box select values using rna */ + WM_operator_properties_border_to_rcti(op, &rect); + + /* calculate range */ + + if (rv3d->persp == RV3D_CAMOB) { + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false); + } + else { + vb.xmin = 0; + vb.ymin = 0; + vb.xmax = ar->winx; + vb.ymax = ar->winy; + } + + border.xmin = ((float)rect.xmin - vb.xmin) / BLI_rctf_size_x(&vb); + border.ymin = ((float)rect.ymin - vb.ymin) / BLI_rctf_size_y(&vb); + border.xmax = ((float)rect.xmax - vb.xmin) / BLI_rctf_size_x(&vb); + border.ymax = ((float)rect.ymax - vb.ymin) / BLI_rctf_size_y(&vb); + + /* actually set border */ + CLAMP(border.xmin, 0.0f, 1.0f); + CLAMP(border.ymin, 0.0f, 1.0f); + CLAMP(border.xmax, 0.0f, 1.0f); + CLAMP(border.ymax, 0.0f, 1.0f); + + if (rv3d->persp == RV3D_CAMOB) { + scene->r.border = border; + + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); + } + else { + v3d->render_border = border; + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } + + /* drawing a border outside the camera view switches off border rendering */ + if ((border.xmin == border.xmax || border.ymin == border.ymax)) { + if (rv3d->persp == RV3D_CAMOB) { + scene->r.mode &= ~R_BORDER; + } + else { + v3d->flag2 &= ~V3D_RENDER_BORDER; + } + } + else { + if (rv3d->persp == RV3D_CAMOB) { + scene->r.mode |= R_BORDER; + } + else { + v3d->flag2 |= V3D_RENDER_BORDER; + } + } + + if (rv3d->persp == RV3D_CAMOB) { + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + } + return OPERATOR_FINISHED; } void VIEW3D_OT_render_border(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Render Region"; - ot->description = "Set the boundaries of the border render and enable border render"; - ot->idname = "VIEW3D_OT_render_border"; + /* identifiers */ + ot->name = "Set Render Region"; + ot->description = "Set the boundaries of the border render and enable border render"; + ot->idname = "VIEW3D_OT_render_border"; - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = render_border_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = render_border_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - WM_operator_properties_border(ot); + /* properties */ + WM_operator_properties_border(ot); } /** \} */ @@ -3408,49 +3448,49 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); - Scene *scene = CTX_data_scene(C); - rctf *border = NULL; + Scene *scene = CTX_data_scene(C); + rctf *border = NULL; - if (rv3d->persp == RV3D_CAMOB) { - scene->r.mode &= ~R_BORDER; - border = &scene->r.border; + if (rv3d->persp == RV3D_CAMOB) { + scene->r.mode &= ~R_BORDER; + border = &scene->r.border; - WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); - } - else { - v3d->flag2 &= ~V3D_RENDER_BORDER; - border = &v3d->render_border; + WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); + } + else { + v3d->flag2 &= ~V3D_RENDER_BORDER; + border = &v3d->render_border; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - } + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } - border->xmin = 0.0f; - border->ymin = 0.0f; - border->xmax = 1.0f; - border->ymax = 1.0f; + border->xmin = 0.0f; + border->ymin = 0.0f; + border->xmax = 1.0f; + border->ymax = 1.0f; - if (rv3d->persp == RV3D_CAMOB) { - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - } - return OPERATOR_FINISHED; + if (rv3d->persp == RV3D_CAMOB) { + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + } + return OPERATOR_FINISHED; } void VIEW3D_OT_clear_render_border(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clear Render Region"; - ot->description = "Clear the boundaries of the border render and disable border render"; - ot->idname = "VIEW3D_OT_clear_render_border"; + /* identifiers */ + ot->name = "Clear Render Region"; + ot->description = "Clear the boundaries of the border render and disable border render"; + ot->idname = "VIEW3D_OT_clear_render_border"; - /* api callbacks */ - ot->exec = clear_render_border_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = clear_render_border_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -3461,161 +3501,165 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot) static int view3d_zoom_border_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - - /* Zooms in on a border drawn by the user */ - rcti rect; - float dvec[3], vb[2], xscale, yscale; - float dist_range[2]; - - /* SMOOTHVIEW */ - float new_dist; - float new_ofs[3]; - - /* ZBuffer depth vars */ - float depth_close = FLT_MAX; - float cent[2], p[3]; - - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - /* get box select values using rna */ - WM_operator_properties_border_to_rcti(op, &rect); - - /* check if zooming in/out view */ - const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out"); - - ED_view3d_dist_range_get(v3d, dist_range); - - /* Get Z Depths, needed for perspective, nice for ortho */ - ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, v3d, true); - - { - /* avoid allocating the whole depth buffer */ - ViewDepths depth_temp = {0}; - - /* avoid view3d_update_depths() for speed. */ - view3d_update_depths_rect(ar, &depth_temp, &rect); - - /* find the closest Z pixel */ - depth_close = view3d_depth_near(&depth_temp); - - MEM_SAFE_FREE(depth_temp.depths); - } - - cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2; - cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2; - - if (rv3d->is_persp) { - float p_corner[3]; - - /* no depths to use, we cant do anything! */ - if (depth_close == FLT_MAX) { - BKE_report(op->reports, RPT_ERROR, "Depth too large"); - return OPERATOR_CANCELLED; - } - /* convert border to 3d coordinates */ - if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) || - (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner))) - { - return OPERATOR_CANCELLED; - } - - sub_v3_v3v3(dvec, p, p_corner); - negate_v3_v3(new_ofs, p); - - new_dist = len_v3(dvec); - - /* ignore dist_range min */ - dist_range[0] = v3d->clip_start * 1.5f; - } - else { /* othographic */ - /* find the current window width and height */ - vb[0] = ar->winx; - vb[1] = ar->winy; - - new_dist = rv3d->dist; - - /* convert the drawn rectangle into 3d space */ - if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) { - negate_v3_v3(new_ofs, p); - } - else { - float mval_f[2]; - float zfac; - - /* We cant use the depth, fallback to the old way that dosnt set the center depth */ - copy_v3_v3(new_ofs, rv3d->ofs); - - { - float tvec[3]; - negate_v3_v3(tvec, new_ofs); - zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); - } - - mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; - mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - /* center the view to the center of the rectangle */ - sub_v3_v3(new_ofs, dvec); - } - - /* work out the ratios, so that everything selected fits when we zoom */ - xscale = (BLI_rcti_size_x(&rect) / vb[0]); - yscale = (BLI_rcti_size_y(&rect) / vb[1]); - new_dist *= max_ff(xscale, yscale); - } - - if (!zoom_in) { - sub_v3_v3v3(dvec, new_ofs, rv3d->ofs); - new_dist = rv3d->dist * (rv3d->dist / new_dist); - add_v3_v3v3(new_ofs, rv3d->ofs, dvec); - } - - /* clamp after because we may have been zooming out */ - CLAMP(new_dist, dist_range[0], dist_range[1]); - - /* TODO(campbell): 'is_camera_lock' not currently working well. */ - const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d); - if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP); - } - - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .ofs = new_ofs, .dist = &new_dist, }); - - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(CTX_wm_area(C), ar); - } - - return OPERATOR_FINISHED; + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + + /* Zooms in on a border drawn by the user */ + rcti rect; + float dvec[3], vb[2], xscale, yscale; + float dist_range[2]; + + /* SMOOTHVIEW */ + float new_dist; + float new_ofs[3]; + + /* ZBuffer depth vars */ + float depth_close = FLT_MAX; + float cent[2], p[3]; + + /* note; otherwise opengl won't work */ + view3d_operator_needs_opengl(C); + + /* get box select values using rna */ + WM_operator_properties_border_to_rcti(op, &rect); + + /* check if zooming in/out view */ + const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out"); + + ED_view3d_dist_range_get(v3d, dist_range); + + /* Get Z Depths, needed for perspective, nice for ortho */ + ED_view3d_draw_depth(CTX_data_depsgraph(C), ar, v3d, true); + + { + /* avoid allocating the whole depth buffer */ + ViewDepths depth_temp = {0}; + + /* avoid view3d_update_depths() for speed. */ + view3d_update_depths_rect(ar, &depth_temp, &rect); + + /* find the closest Z pixel */ + depth_close = view3d_depth_near(&depth_temp); + + MEM_SAFE_FREE(depth_temp.depths); + } + + cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2; + cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2; + + if (rv3d->is_persp) { + float p_corner[3]; + + /* no depths to use, we cant do anything! */ + if (depth_close == FLT_MAX) { + BKE_report(op->reports, RPT_ERROR, "Depth too large"); + return OPERATOR_CANCELLED; + } + /* convert border to 3d coordinates */ + if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) || + (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner))) { + return OPERATOR_CANCELLED; + } + + sub_v3_v3v3(dvec, p, p_corner); + negate_v3_v3(new_ofs, p); + + new_dist = len_v3(dvec); + + /* ignore dist_range min */ + dist_range[0] = v3d->clip_start * 1.5f; + } + else { /* othographic */ + /* find the current window width and height */ + vb[0] = ar->winx; + vb[1] = ar->winy; + + new_dist = rv3d->dist; + + /* convert the drawn rectangle into 3d space */ + if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) { + negate_v3_v3(new_ofs, p); + } + else { + float mval_f[2]; + float zfac; + + /* We cant use the depth, fallback to the old way that dosnt set the center depth */ + copy_v3_v3(new_ofs, rv3d->ofs); + + { + float tvec[3]; + negate_v3_v3(tvec, new_ofs); + zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + } + + mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; + mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); + /* center the view to the center of the rectangle */ + sub_v3_v3(new_ofs, dvec); + } + + /* work out the ratios, so that everything selected fits when we zoom */ + xscale = (BLI_rcti_size_x(&rect) / vb[0]); + yscale = (BLI_rcti_size_y(&rect) / vb[1]); + new_dist *= max_ff(xscale, yscale); + } + + if (!zoom_in) { + sub_v3_v3v3(dvec, new_ofs, rv3d->ofs); + new_dist = rv3d->dist * (rv3d->dist / new_dist); + add_v3_v3v3(new_ofs, rv3d->ofs, dvec); + } + + /* clamp after because we may have been zooming out */ + CLAMP(new_dist, dist_range[0], dist_range[1]); + + /* TODO(campbell): 'is_camera_lock' not currently working well. */ + const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d); + if ((rv3d->persp == RV3D_CAMOB) && (is_camera_lock == false)) { + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, RV3D_PERSP); + } + + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .ofs = new_ofs, + .dist = &new_dist, + }); + + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(CTX_wm_area(C), ar); + } + + return OPERATOR_FINISHED; } void VIEW3D_OT_zoom_border(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Zoom to Border"; - ot->description = "Zoom in the view to the nearest object contained in the border"; - ot->idname = "VIEW3D_OT_zoom_border"; + /* identifiers */ + ot->name = "Zoom to Border"; + ot->description = "Zoom in the view to the nearest object contained in the border"; + ot->idname = "VIEW3D_OT_zoom_border"; - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = view3d_zoom_border_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = view3d_zoom_border_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; - ot->poll = ED_operator_region_view3d_active; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - WM_operator_properties_gesture_box_zoom(ot); + /* properties */ + WM_operator_properties_gesture_box_zoom(ot); } /** \} */ @@ -3626,49 +3670,52 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) * Sets the view to 1:1 camera/render-pixel. * \{ */ -static void view3d_set_1_to_1_viewborder(Scene *scene, Depsgraph *depsgraph, ARegion *ar, View3D *v3d) +static void view3d_set_1_to_1_viewborder(Scene *scene, + Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d) { - RegionView3D *rv3d = ar->regiondata; - float size[2]; - int im_width = (scene->r.size * scene->r.xsch) / 100; + RegionView3D *rv3d = ar->regiondata; + float size[2]; + int im_width = (scene->r.size * scene->r.xsch) / 100; - ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size); + ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size); - rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]); - CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]); + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); } static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op)) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); - View3D *v3d; - ARegion *ar; + View3D *v3d; + ARegion *ar; - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); - view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d); + view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Zoom Camera 1:1"; - ot->description = "Match the camera to 1:1 to the render output"; - ot->idname = "VIEW3D_OT_zoom_camera_1_to_1"; + /* identifiers */ + ot->name = "Zoom Camera 1:1"; + ot->description = "Match the camera to 1:1 to the render output"; + ot->idname = "VIEW3D_OT_zoom_camera_1_to_1"; - /* api callbacks */ - ot->exec = view3d_zoom_1_to_1_camera_exec; - ot->poll = view3d_camera_user_poll; + /* api callbacks */ + ot->exec = view3d_zoom_1_to_1_camera_exec; + ot->poll = view3d_camera_user_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -3678,211 +3725,229 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot) * \{ */ static const EnumPropertyItem prop_view_items[] = { - {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"}, - {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"}, - {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"}, - {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"}, - {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"}, - {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"}, - {0, NULL, 0, NULL, NULL}, + {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"}, + {RV3D_VIEW_RIGHT, "RIGHT", ICON_TRIA_RIGHT, "Right", "View From the Right"}, + {RV3D_VIEW_BOTTOM, "BOTTOM", ICON_TRIA_DOWN, "Bottom", "View From the Bottom"}, + {RV3D_VIEW_TOP, "TOP", ICON_TRIA_UP, "Top", "View From the Top"}, + {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"}, + {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"}, + {0, NULL, 0, NULL, NULL}, }; - /* would like to make this a generic function - outside of transform */ /** * \param align_to_quat: When not NULL, set the axis relative to this rotation. */ -static void axis_set_view( - bContext *C, View3D *v3d, ARegion *ar, - const float quat_[4], - short view, int perspo, - const float *align_to_quat, - const int smooth_viewtx) -{ - RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */ - float quat[4]; - const short orig_persp = rv3d->persp; - - - normalize_qt_qt(quat, quat_); - - if (align_to_quat) { - mul_qt_qtqt(quat, quat, align_to_quat); - rv3d->view = view = RV3D_VIEW_USER; - } - - if (align_to_quat == NULL) { - rv3d->view = view; - } - - if (rv3d->viewlock & RV3D_LOCKED) { - ED_region_tag_redraw(ar); - return; - } - - if (U.uiflag & USER_AUTOPERSP) { - rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo; - } - else if (rv3d->persp == RV3D_CAMOB) { - rv3d->persp = perspo; - } - - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - /* to camera */ - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .camera_old = v3d->camera, .ofs = rv3d->ofs, .quat = quat, }); - } - else if (orig_persp == RV3D_CAMOB && v3d->camera) { - /* from camera */ - float ofs[3], dist; - - copy_v3_v3(ofs, rv3d->ofs); - dist = rv3d->dist; - - /* so we animate _from_ the camera location */ - Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera); - ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL); - - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .ofs = ofs, .quat = quat, .dist = &dist, }); - } - else { - /* rotate around selection */ - const float *dyn_ofs_pt = NULL; - float dyn_ofs[3]; - - if (U.uiflag & USER_ORBIT_SELECTION) { - if (view3d_orbit_calc_center(C, dyn_ofs)) { - negate_v3(dyn_ofs); - dyn_ofs_pt = dyn_ofs; - } - } - - /* no camera involved */ - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .quat = quat, .dyn_ofs = dyn_ofs_pt, }); - } +static void axis_set_view(bContext *C, + View3D *v3d, + ARegion *ar, + const float quat_[4], + short view, + int perspo, + const float *align_to_quat, + const int smooth_viewtx) +{ + RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */ + float quat[4]; + const short orig_persp = rv3d->persp; + + normalize_qt_qt(quat, quat_); + + if (align_to_quat) { + mul_qt_qtqt(quat, quat, align_to_quat); + rv3d->view = view = RV3D_VIEW_USER; + } + + if (align_to_quat == NULL) { + rv3d->view = view; + } + + if (rv3d->viewlock & RV3D_LOCKED) { + ED_region_tag_redraw(ar); + return; + } + + if (U.uiflag & USER_AUTOPERSP) { + rv3d->persp = RV3D_VIEW_IS_AXIS(view) ? RV3D_ORTHO : perspo; + } + else if (rv3d->persp == RV3D_CAMOB) { + rv3d->persp = perspo; + } + + if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + /* to camera */ + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = v3d->camera, + .ofs = rv3d->ofs, + .quat = quat, + }); + } + else if (orig_persp == RV3D_CAMOB && v3d->camera) { + /* from camera */ + float ofs[3], dist; + + copy_v3_v3(ofs, rv3d->ofs); + dist = rv3d->dist; + + /* so we animate _from_ the camera location */ + Object *camera_eval = DEG_get_evaluated_object(CTX_data_depsgraph(C), v3d->camera); + ED_view3d_from_object(camera_eval, rv3d->ofs, NULL, &rv3d->dist, NULL); + + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .ofs = ofs, + .quat = quat, + .dist = &dist, + }); + } + else { + /* rotate around selection */ + const float *dyn_ofs_pt = NULL; + float dyn_ofs[3]; + + if (U.uiflag & USER_ORBIT_SELECTION) { + if (view3d_orbit_calc_center(C, dyn_ofs)) { + negate_v3(dyn_ofs); + dyn_ofs_pt = dyn_ofs; + } + } + + /* no camera involved */ + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .quat = quat, + .dyn_ofs = dyn_ofs_pt, + }); + } } static int view_axis_exec(bContext *C, wmOperator *op) { - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; - static int perspo = RV3D_PERSP; - int viewnum; - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; - - ED_view3d_smooth_view_force_finish(C, v3d, ar); - - viewnum = RNA_enum_get(op->ptr, "type"); - - float align_quat_buf[4]; - float *align_quat = NULL; - - if (RNA_boolean_get(op->ptr, "align_active")) { - /* align to active object */ - Object *obact = CTX_data_active_object(C); - if (obact != NULL) { - float twmat[3][3]; - /* same as transform gizmo when normal is set */ - ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE); - align_quat = align_quat_buf; - mat3_to_quat(align_quat, twmat); - invert_qt_normalized(align_quat); - } - } - - if (RNA_boolean_get(op->ptr, "relative")) { - float z_rel[3]; - - if (viewnum == RV3D_VIEW_RIGHT) { - negate_v3_v3(z_rel, rv3d->viewinv[0]); - } - else if (viewnum == RV3D_VIEW_LEFT) { - copy_v3_v3(z_rel, rv3d->viewinv[0]); - } - else if (viewnum == RV3D_VIEW_TOP) { - negate_v3_v3(z_rel, rv3d->viewinv[1]); - } - else if (viewnum == RV3D_VIEW_BOTTOM) { - copy_v3_v3(z_rel, rv3d->viewinv[1]); - } - else if (viewnum == RV3D_VIEW_FRONT) { - negate_v3_v3(z_rel, rv3d->viewinv[2]); - } - else if (viewnum == RV3D_VIEW_BACK) { - copy_v3_v3(z_rel, rv3d->viewinv[2]); - } - else { - BLI_assert(0); - } - - float angle_max = FLT_MAX; - int view_closest = -1; - for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) { - float quat[4]; - float mat[3][3]; - ED_view3d_quat_from_axis_view(i, quat); - quat[0] *= -1.0f; - quat_to_mat3(mat, quat); - if (align_quat) { - mul_qt_qtqt(quat, quat, align_quat); - } - const float angle_test = angle_normalized_v3v3(z_rel, mat[2]); - if (angle_max > angle_test) { - angle_max = angle_test; - view_closest = i; - } - } - if (view_closest == -1) { - view_closest = RV3D_VIEW_FRONT; - } - viewnum = view_closest; - } - - /* Use this to test if we started out with a camera */ - const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo; - float quat[4]; - ED_view3d_quat_from_axis_view(viewnum, quat); - axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx); - - perspo = rv3d->persp; - - return OPERATOR_FINISHED; + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; + static int perspo = RV3D_PERSP; + int viewnum; + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; + + ED_view3d_smooth_view_force_finish(C, v3d, ar); + + viewnum = RNA_enum_get(op->ptr, "type"); + + float align_quat_buf[4]; + float *align_quat = NULL; + + if (RNA_boolean_get(op->ptr, "align_active")) { + /* align to active object */ + Object *obact = CTX_data_active_object(C); + if (obact != NULL) { + float twmat[3][3]; + /* same as transform gizmo when normal is set */ + ED_getTransformOrientationMatrix(C, twmat, V3D_AROUND_ACTIVE); + align_quat = align_quat_buf; + mat3_to_quat(align_quat, twmat); + invert_qt_normalized(align_quat); + } + } + + if (RNA_boolean_get(op->ptr, "relative")) { + float z_rel[3]; + + if (viewnum == RV3D_VIEW_RIGHT) { + negate_v3_v3(z_rel, rv3d->viewinv[0]); + } + else if (viewnum == RV3D_VIEW_LEFT) { + copy_v3_v3(z_rel, rv3d->viewinv[0]); + } + else if (viewnum == RV3D_VIEW_TOP) { + negate_v3_v3(z_rel, rv3d->viewinv[1]); + } + else if (viewnum == RV3D_VIEW_BOTTOM) { + copy_v3_v3(z_rel, rv3d->viewinv[1]); + } + else if (viewnum == RV3D_VIEW_FRONT) { + negate_v3_v3(z_rel, rv3d->viewinv[2]); + } + else if (viewnum == RV3D_VIEW_BACK) { + copy_v3_v3(z_rel, rv3d->viewinv[2]); + } + else { + BLI_assert(0); + } + + float angle_max = FLT_MAX; + int view_closest = -1; + for (int i = RV3D_VIEW_FRONT; i <= RV3D_VIEW_BOTTOM; i++) { + float quat[4]; + float mat[3][3]; + ED_view3d_quat_from_axis_view(i, quat); + quat[0] *= -1.0f; + quat_to_mat3(mat, quat); + if (align_quat) { + mul_qt_qtqt(quat, quat, align_quat); + } + const float angle_test = angle_normalized_v3v3(z_rel, mat[2]); + if (angle_max > angle_test) { + angle_max = angle_test; + view_closest = i; + } + } + if (view_closest == -1) { + view_closest = RV3D_VIEW_FRONT; + } + viewnum = view_closest; + } + + /* Use this to test if we started out with a camera */ + const int nextperspo = (rv3d->persp == RV3D_CAMOB) ? rv3d->lpersp : perspo; + float quat[4]; + ED_view3d_quat_from_axis_view(viewnum, quat); + axis_set_view(C, v3d, ar, quat, viewnum, nextperspo, align_quat, smooth_viewtx); + + perspo = rv3d->persp; + + return OPERATOR_FINISHED; } - void VIEW3D_OT_view_axis(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "View Axis"; - ot->description = "Use a preset viewpoint"; - ot->idname = "VIEW3D_OT_view_axis"; + /* identifiers */ + ot->name = "View Axis"; + ot->description = "Use a preset viewpoint"; + ot->idname = "VIEW3D_OT_view_axis"; - /* api callbacks */ - ot->exec = view_axis_exec; - ot->poll = ED_operator_rv3d_user_region_poll; + /* api callbacks */ + ot->exec = view_axis_exec; + ot->poll = ED_operator_rv3d_user_region_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use"); - RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "Preset viewpoint to use"); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "align_active", 0, "Align Active", "Align to the active object's axis"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "relative", 0, "Relative", "Rotate relative to the current orientation"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ @@ -3893,106 +3958,111 @@ void VIEW3D_OT_view_axis(wmOperatorType *ot) static int view_camera_exec(bContext *C, wmOperator *op) { - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; - ED_view3d_smooth_view_force_finish(C, v3d, ar); + ED_view3d_smooth_view_force_finish(C, v3d, ar); - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - /* lastview - */ + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + /* lastview - */ - ViewLayer *view_layer = CTX_data_view_layer(C); - Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Scene *scene = CTX_data_scene(C); - if (rv3d->persp != RV3D_CAMOB) { - Object *ob = OBACT(view_layer); + if (rv3d->persp != RV3D_CAMOB) { + Object *ob = OBACT(view_layer); - if (!rv3d->smooth_timer) { - /* store settings of current view before allowing overwriting with camera view - * only if we're not currently in a view transition */ + if (!rv3d->smooth_timer) { + /* store settings of current view before allowing overwriting with camera view + * only if we're not currently in a view transition */ - ED_view3d_lastview_store(rv3d); - } + ED_view3d_lastview_store(rv3d); + } #if 0 - if (G.qual == LR_ALTKEY) { - if (oldcamera && is_an_active_object(oldcamera)) { - v3d->camera = oldcamera; - } - handle_view3d_lock(); - } + if (G.qual == LR_ALTKEY) { + if (oldcamera && is_an_active_object(oldcamera)) { + v3d->camera = oldcamera; + } + handle_view3d_lock(); + } #endif - /* first get the default camera for the view lock type */ - if (v3d->scenelock) { - /* sets the camera view if available */ - v3d->camera = scene->camera; - } - else { - /* use scene camera if one is not set (even though we're unlocked) */ - if (v3d->camera == NULL) { - v3d->camera = scene->camera; - } - } - - /* if the camera isn't found, check a number of options */ - if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) { - v3d->camera = ob; - } - - if (v3d->camera == NULL) { - v3d->camera = BKE_view_layer_camera_find(view_layer); - } - - /* couldn't find any useful camera, bail out */ - if (v3d->camera == NULL) { - return OPERATOR_CANCELLED; - } - - /* important these don't get out of sync for locked scenes */ - if (v3d->scenelock && scene->camera != v3d->camera) { - scene->camera = v3d->camera; - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - } - - /* finally do snazzy view zooming */ - rv3d->persp = RV3D_CAMOB; - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat, - .dist = &rv3d->dist, .lens = &v3d->lens, - }); - } - else { - /* return to settings of last view */ - /* does view3d_smooth_view too */ - axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx); - } - } - - return OPERATOR_FINISHED; + /* first get the default camera for the view lock type */ + if (v3d->scenelock) { + /* sets the camera view if available */ + v3d->camera = scene->camera; + } + else { + /* use scene camera if one is not set (even though we're unlocked) */ + if (v3d->camera == NULL) { + v3d->camera = scene->camera; + } + } + + /* if the camera isn't found, check a number of options */ + if (v3d->camera == NULL && ob && ob->type == OB_CAMERA) { + v3d->camera = ob; + } + + if (v3d->camera == NULL) { + v3d->camera = BKE_view_layer_camera_find(view_layer); + } + + /* couldn't find any useful camera, bail out */ + if (v3d->camera == NULL) { + return OPERATOR_CANCELLED; + } + + /* important these don't get out of sync for locked scenes */ + if (v3d->scenelock && scene->camera != v3d->camera) { + scene->camera = v3d->camera; + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + } + + /* finally do snazzy view zooming */ + rv3d->persp = RV3D_CAMOB; + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera = v3d->camera, + .ofs = rv3d->ofs, + .quat = rv3d->viewquat, + .dist = &rv3d->dist, + .lens = &v3d->lens, + }); + } + else { + /* return to settings of last view */ + /* does view3d_smooth_view too */ + axis_set_view(C, v3d, ar, rv3d->lviewquat, rv3d->lview, rv3d->lpersp, NULL, smooth_viewtx); + } + } + + return OPERATOR_FINISHED; } void VIEW3D_OT_view_camera(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Camera"; - ot->description = "Toggle the camera view"; - ot->idname = "VIEW3D_OT_view_camera"; + /* identifiers */ + ot->name = "View Camera"; + ot->description = "Toggle the camera view"; + ot->idname = "VIEW3D_OT_view_camera"; - /* api callbacks */ - ot->exec = view_camera_exec; - ot->poll = ED_operator_rv3d_user_region_poll; + /* api callbacks */ + ot->exec = view_camera_exec; + ot->poll = ED_operator_rv3d_user_region_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -4004,133 +4074,140 @@ void VIEW3D_OT_view_camera(wmOperatorType *ot) * \{ */ enum { - V3D_VIEW_STEPLEFT = 1, - V3D_VIEW_STEPRIGHT, - V3D_VIEW_STEPDOWN, - V3D_VIEW_STEPUP, + V3D_VIEW_STEPLEFT = 1, + V3D_VIEW_STEPRIGHT, + V3D_VIEW_STEPDOWN, + V3D_VIEW_STEPUP, }; static const EnumPropertyItem prop_view_orbit_items[] = { - {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"}, - {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"}, - {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"}, - {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"}, - {0, NULL, 0, NULL, NULL}, + {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"}, + {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"}, + {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"}, + {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"}, + {0, NULL, 0, NULL, NULL}, }; static int vieworbit_exec(bContext *C, wmOperator *op) { - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; - int orbitdir; - char view_opposite; - PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle"); - float angle = RNA_property_is_set(op->ptr, prop_angle) ? - RNA_property_float_get(op->ptr, prop_angle) : DEG2RADF(U.pad_rot_angle); - - /* no NULL check is needed, poll checks */ - v3d = CTX_wm_view3d(C); - ar = CTX_wm_region(C); - rv3d = ar->regiondata; - - /* support for switching to the opposite view (even when in locked views) */ - view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) : RV3D_VIEW_USER; - orbitdir = RNA_enum_get(op->ptr, "type"); - - if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) { - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; - } - - ED_view3d_smooth_view_force_finish(C, v3d, ar); - - if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) { - if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { - int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - float quat_mul[4]; - float quat_new[4]; - - if (view_opposite == RV3D_VIEW_USER) { - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - ED_view3d_persp_ensure(depsgraph, v3d, ar); - } - - if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) { - if (orbitdir == V3D_VIEW_STEPRIGHT) { - angle = -angle; - } - - /* z-axis */ - axis_angle_to_quat_single(quat_mul, 'Z', angle); - } - else { - - if (orbitdir == V3D_VIEW_STEPDOWN) { - angle = -angle; - } - - /* horizontal axis */ - axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle); - } - - mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul); - - /* avoid precision loss over time */ - normalize_qt(quat_new); - - if (view_opposite != RV3D_VIEW_USER) { - rv3d->view = view_opposite; - /* avoid float in-precision, just get a new orientation */ - ED_view3d_quat_from_axis_view(view_opposite, quat_new); - } - else { - rv3d->view = RV3D_VIEW_USER; - } - - - float dyn_ofs[3], *dyn_ofs_pt = NULL; - - if (U.uiflag & USER_ORBIT_SELECTION) { - if (view3d_orbit_calc_center(C, dyn_ofs)) { - negate_v3(dyn_ofs); - dyn_ofs_pt = dyn_ofs; - } - } - - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .quat = quat_new, .dyn_ofs = dyn_ofs_pt, }); - - return OPERATOR_FINISHED; - } - } - - return OPERATOR_CANCELLED; + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; + int orbitdir; + char view_opposite; + PropertyRNA *prop_angle = RNA_struct_find_property(op->ptr, "angle"); + float angle = RNA_property_is_set(op->ptr, prop_angle) ? + RNA_property_float_get(op->ptr, prop_angle) : + DEG2RADF(U.pad_rot_angle); + + /* no NULL check is needed, poll checks */ + v3d = CTX_wm_view3d(C); + ar = CTX_wm_region(C); + rv3d = ar->regiondata; + + /* support for switching to the opposite view (even when in locked views) */ + view_opposite = (fabsf(angle) == (float)M_PI) ? ED_view3d_axis_view_opposite(rv3d->view) : + RV3D_VIEW_USER; + orbitdir = RNA_enum_get(op->ptr, "type"); + + if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) { + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; + } + + ED_view3d_smooth_view_force_finish(C, v3d, ar); + + if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) { + if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { + int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + float quat_mul[4]; + float quat_new[4]; + + if (view_opposite == RV3D_VIEW_USER) { + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + ED_view3d_persp_ensure(depsgraph, v3d, ar); + } + + if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) { + if (orbitdir == V3D_VIEW_STEPRIGHT) { + angle = -angle; + } + + /* z-axis */ + axis_angle_to_quat_single(quat_mul, 'Z', angle); + } + else { + + if (orbitdir == V3D_VIEW_STEPDOWN) { + angle = -angle; + } + + /* horizontal axis */ + axis_angle_to_quat(quat_mul, rv3d->viewinv[0], angle); + } + + mul_qt_qtqt(quat_new, rv3d->viewquat, quat_mul); + + /* avoid precision loss over time */ + normalize_qt(quat_new); + + if (view_opposite != RV3D_VIEW_USER) { + rv3d->view = view_opposite; + /* avoid float in-precision, just get a new orientation */ + ED_view3d_quat_from_axis_view(view_opposite, quat_new); + } + else { + rv3d->view = RV3D_VIEW_USER; + } + + float dyn_ofs[3], *dyn_ofs_pt = NULL; + + if (U.uiflag & USER_ORBIT_SELECTION) { + if (view3d_orbit_calc_center(C, dyn_ofs)) { + negate_v3(dyn_ofs); + dyn_ofs_pt = dyn_ofs; + } + } + + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .quat = quat_new, + .dyn_ofs = dyn_ofs_pt, + }); + + return OPERATOR_FINISHED; + } + } + + return OPERATOR_CANCELLED; } void VIEW3D_OT_view_orbit(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "View Orbit"; - ot->description = "Orbit the view"; - ot->idname = "VIEW3D_OT_view_orbit"; + /* identifiers */ + ot->name = "View Orbit"; + ot->description = "Orbit the view"; + ot->idname = "VIEW3D_OT_view_orbit"; - /* api callbacks */ - ot->exec = vieworbit_exec; - ot->poll = ED_operator_rv3d_user_region_poll; + /* api callbacks */ + ot->exec = vieworbit_exec; + ot->poll = ED_operator_rv3d_user_region_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* properties */ + prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); - ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); + ot->prop = RNA_def_enum( + ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); } /** \} */ @@ -4139,253 +4216,265 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot) /** \name View Roll Operator * \{ */ -static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle) +static void view_roll_angle( + ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle) { - RegionView3D *rv3d = ar->regiondata; - float quat_mul[4]; + RegionView3D *rv3d = ar->regiondata; + float quat_mul[4]; - /* camera axis */ - axis_angle_normalized_to_quat(quat_mul, dvec, angle); + /* camera axis */ + axis_angle_normalized_to_quat(quat_mul, dvec, angle); - mul_qt_qtqt(quat, orig_quat, quat_mul); + mul_qt_qtqt(quat, orig_quat, quat_mul); - /* avoid precision loss over time */ - normalize_qt(quat); + /* avoid precision loss over time */ + normalize_qt(quat); - rv3d->view = RV3D_VIEW_USER; + rv3d->view = RV3D_VIEW_USER; } static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y)) { - float angle = 0.0; + float angle = 0.0; - { - float len1, len2, tot; + { + float len1, len2, tot; - tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin; - len1 = (vod->ar->winrct.xmax - x) / tot; - len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) / tot; - angle = (len1 - len2) * (float)M_PI * 4.0f; - } + tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin; + len1 = (vod->ar->winrct.xmax - x) / tot; + len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) / tot; + angle = (len1 - len2) * (float)M_PI * 4.0f; + } - if (angle != 0.0f) { - view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle); - } + if (angle != 0.0f) { + view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle); + } - if (vod->use_dyn_ofs) { - view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs); - } + if (vod->use_dyn_ofs) { + view3d_orbit_apply_dyn_ofs( + vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs); + } - if (vod->rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(vod->sa, vod->ar); - } + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(vod->sa, vod->ar); + } - ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); + ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d); - ED_region_tag_redraw(vod->ar); + ED_region_tag_redraw(vod->ar); } static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod = op->customdata; - short event_code = VIEW_PASS; - bool use_autokey = false; - int ret = OPERATOR_RUNNING_MODAL; - - /* execute the events */ - if (event->type == MOUSEMOVE) { - event_code = VIEW_APPLY; - } - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case VIEW_MODAL_CONFIRM: - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_MOVE: - WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - case VIEWROT_MODAL_SWITCH_ROTATE: - WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); - event_code = VIEW_CONFIRM; - break; - } - } - else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { - event_code = VIEW_CONFIRM; - } - - if (event_code == VIEW_APPLY) { - viewroll_apply(vod, event->x, event->y); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - use_autokey = true; - } - } - else if (event_code == VIEW_CONFIRM) { - ED_view3d_depth_tag_update(vod->rv3d); - use_autokey = true; - ret = OPERATOR_FINISHED; - } - - if (use_autokey) { - ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false); - } - - if (ret & OPERATOR_FINISHED) { - viewops_data_free(C, op); - } - - return ret; + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + bool use_autokey = false; + int ret = OPERATOR_RUNNING_MODAL; + + /* execute the events */ + if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->init.event_type && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + viewroll_apply(vod, event->x, event->y); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + use_autokey = true; + } + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + use_autokey = true; + ret = OPERATOR_FINISHED; + } + + if (use_autokey) { + ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, true, false); + } + + if (ret & OPERATOR_FINISHED) { + viewops_data_free(C, op); + } + + return ret; } static const EnumPropertyItem prop_view_roll_items[] = { - {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"}, - {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the Left"}, - {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the Right"}, - {0, NULL, 0, NULL, NULL}, + {0, "ANGLE", 0, "Roll Angle", "Roll the view using an angle value"}, + {V3D_VIEW_STEPLEFT, "LEFT", 0, "Roll Left", "Roll the view around to the Left"}, + {V3D_VIEW_STEPRIGHT, "RIGHT", 0, "Roll Right", "Roll the view around to the Right"}, + {0, NULL, 0, NULL, NULL}, }; - static int viewroll_exec(bContext *C, wmOperator *op) { - View3D *v3d; - RegionView3D *rv3d; - ARegion *ar; - - if (op->customdata) { - ViewOpsData *vod = op->customdata; - ar = vod->ar; - v3d = vod->v3d; - } - else { - ED_view3d_context_user_region(C, &v3d, &ar); - } - - rv3d = ar->regiondata; - if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { - - ED_view3d_smooth_view_force_finish(C, v3d, ar); - - int type = RNA_enum_get(op->ptr, "type"); - float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle); - float mousevec[3]; - float quat_new[4]; - - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - - if (type == V3D_VIEW_STEPLEFT) { - angle = -angle; - } - - normalize_v3_v3(mousevec, rv3d->viewinv[2]); - negate_v3(mousevec); - view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle); - - const float *dyn_ofs_pt = NULL; - float dyn_ofs[3]; - if (U.uiflag & USER_ORBIT_SELECTION) { - if (view3d_orbit_calc_center(C, dyn_ofs)) { - negate_v3(dyn_ofs); - dyn_ofs_pt = dyn_ofs; - } - } - - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { .quat = quat_new, .dyn_ofs = dyn_ofs_pt, }); - - viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - viewops_data_free(C, op); - return OPERATOR_CANCELLED; - } + View3D *v3d; + RegionView3D *rv3d; + ARegion *ar; + + if (op->customdata) { + ViewOpsData *vod = op->customdata; + ar = vod->ar; + v3d = vod->v3d; + } + else { + ED_view3d_context_user_region(C, &v3d, &ar); + } + + rv3d = ar->regiondata; + if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { + + ED_view3d_smooth_view_force_finish(C, v3d, ar); + + int type = RNA_enum_get(op->ptr, "type"); + float angle = (type == 0) ? RNA_float_get(op->ptr, "angle") : DEG2RADF(U.pad_rot_angle); + float mousevec[3]; + float quat_new[4]; + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + + if (type == V3D_VIEW_STEPLEFT) { + angle = -angle; + } + + normalize_v3_v3(mousevec, rv3d->viewinv[2]); + negate_v3(mousevec); + view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle); + + const float *dyn_ofs_pt = NULL; + float dyn_ofs[3]; + if (U.uiflag & USER_ORBIT_SELECTION) { + if (view3d_orbit_calc_center(C, dyn_ofs)) { + negate_v3(dyn_ofs); + dyn_ofs_pt = dyn_ofs; + } + } + + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .quat = quat_new, + .dyn_ofs = dyn_ofs_pt, + }); + + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + viewops_data_free(C, op); + return OPERATOR_CANCELLED; + } } static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewOpsData *vod; + ViewOpsData *vod; - bool use_angle = RNA_enum_get(op->ptr, "type") != 0; + bool use_angle = RNA_enum_get(op->ptr, "type") != 0; - if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) { - viewroll_exec(C, op); - } - else { - /* makes op->customdata */ - viewops_data_alloc(C, op); - viewops_data_create(C, op, event, viewops_flag_from_prefs()); - vod = op->customdata; + if (use_angle || RNA_struct_property_is_set(op->ptr, "angle")) { + viewroll_exec(C, op); + } + else { + /* makes op->customdata */ + viewops_data_alloc(C, op); + viewops_data_create(C, op, event, viewops_flag_from_prefs()); + vod = op->customdata; - ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); + ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar); - /* overwrite the mouse vector with the view direction */ - normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]); - negate_v3(vod->init.mousevec); + /* overwrite the mouse vector with the view direction */ + normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]); + negate_v3(vod->init.mousevec); - if (event->type == MOUSEROTATE) { - vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; - viewroll_apply(vod, event->prevx, event->prevy); - ED_view3d_depth_tag_update(vod->rv3d); + if (event->type == MOUSEROTATE) { + vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x; + viewroll_apply(vod, event->prevx, event->prevy); + ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); - return OPERATOR_FINISHED; - } - else { - /* add temp handler */ - WM_event_add_modal_handler(C, op); + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + /* add temp handler */ + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; - } - } - return OPERATOR_FINISHED; + return OPERATOR_RUNNING_MODAL; + } + } + return OPERATOR_FINISHED; } static void viewroll_cancel(bContext *C, wmOperator *op) { - viewops_data_free(C, op); + viewops_data_free(C, op); } void VIEW3D_OT_view_roll(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "View Roll"; - ot->description = "Roll the view"; - ot->idname = "VIEW3D_OT_view_roll"; + /* identifiers */ + ot->name = "View Roll"; + ot->description = "Roll the view"; + ot->idname = "VIEW3D_OT_view_roll"; - /* api callbacks */ - ot->invoke = viewroll_invoke; - ot->exec = viewroll_exec; - ot->modal = viewroll_modal; - ot->poll = ED_operator_rv3d_user_region_poll; - ot->cancel = viewroll_cancel; + /* api callbacks */ + ot->invoke = viewroll_invoke; + ot->exec = viewroll_exec; + ot->modal = viewroll_modal; + ot->poll = ED_operator_rv3d_user_region_poll; + ot->cancel = viewroll_cancel; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - ot->prop = prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_enum(ot->srna, "type", prop_view_roll_items, 0, "Roll Angle Source", "How roll angle is calculated"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + /* properties */ + ot->prop = prop = RNA_def_float( + ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, + "type", + prop_view_roll_items, + 0, + "Roll Angle Source", + "How roll angle is calculated"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } enum { - V3D_VIEW_PANLEFT = 1, - V3D_VIEW_PANRIGHT, - V3D_VIEW_PANDOWN, - V3D_VIEW_PANUP, + V3D_VIEW_PANLEFT = 1, + V3D_VIEW_PANRIGHT, + V3D_VIEW_PANDOWN, + V3D_VIEW_PANUP, }; static const EnumPropertyItem prop_view_pan_items[] = { - {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"}, - {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"}, - {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"}, - {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"}, - {0, NULL, 0, NULL, NULL}, + {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"}, + {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"}, + {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"}, + {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"}, + {0, NULL, 0, NULL, NULL}, }; /** \} */ @@ -4398,42 +4487,51 @@ static const EnumPropertyItem prop_view_pan_items[] = { static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - int x = 0, y = 0; - int pandir = RNA_enum_get(op->ptr, "type"); + int x = 0, y = 0; + int pandir = RNA_enum_get(op->ptr, "type"); - if (pandir == V3D_VIEW_PANRIGHT) { x = -32; } - else if (pandir == V3D_VIEW_PANLEFT) { x = 32; } - else if (pandir == V3D_VIEW_PANUP) { y = -25; } - else if (pandir == V3D_VIEW_PANDOWN) { y = 25; } + if (pandir == V3D_VIEW_PANRIGHT) { + x = -32; + } + else if (pandir == V3D_VIEW_PANLEFT) { + x = 32; + } + else if (pandir == V3D_VIEW_PANUP) { + y = -25; + } + else if (pandir == V3D_VIEW_PANDOWN) { + y = 25; + } - viewops_data_alloc(C, op); - viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT)); - ViewOpsData *vod = op->customdata; + viewops_data_alloc(C, op); + viewops_data_create(C, op, event, (viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT)); + ViewOpsData *vod = op->customdata; - viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y); + viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y); - ED_view3d_depth_tag_update(vod->rv3d); - viewops_data_free(C, op); + ED_view3d_depth_tag_update(vod->rv3d); + viewops_data_free(C, op); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_pan(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Pan View Direction"; - ot->description = "Pan the view in a given direction"; - ot->idname = "VIEW3D_OT_view_pan"; + /* identifiers */ + ot->name = "Pan View Direction"; + ot->description = "Pan the view in a given direction"; + ot->idname = "VIEW3D_OT_view_pan"; - /* api callbacks */ - ot->invoke = viewpan_invoke; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->invoke = viewpan_invoke; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* Properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); + /* Properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); } /** \} */ @@ -4444,40 +4542,40 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot) static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d_dummy; - ARegion *ar; - RegionView3D *rv3d; + View3D *v3d_dummy; + ARegion *ar; + RegionView3D *rv3d; - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d_dummy, &ar); - rv3d = ar->regiondata; + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d_dummy, &ar); + rv3d = ar->regiondata; - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - if (rv3d->persp != RV3D_ORTHO) { - rv3d->persp = RV3D_ORTHO; - } - else { - rv3d->persp = RV3D_PERSP; - } - ED_region_tag_redraw(ar); - } + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + if (rv3d->persp != RV3D_ORTHO) { + rv3d->persp = RV3D_ORTHO; + } + else { + rv3d->persp = RV3D_PERSP; + } + ED_region_tag_redraw(ar); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_view_persportho(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Persp/Ortho"; - ot->description = "Switch the current view from perspective/orthographic projection"; - ot->idname = "VIEW3D_OT_view_persportho"; + /* identifiers */ + ot->name = "View Persp/Ortho"; + ot->description = "Switch the current view from perspective/orthographic projection"; + ot->idname = "VIEW3D_OT_view_persportho"; - /* api callbacks */ - ot->exec = viewpersportho_exec; - ot->poll = ED_operator_rv3d_user_region_poll; + /* api callbacks */ + ot->exec = viewpersportho_exec; + ot->poll = ED_operator_rv3d_user_region_poll; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } /** \} */ @@ -4488,33 +4586,36 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot) * Wraps walk/fly modes. * \{ */ -static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +static int view3d_navigate_invoke(bContext *C, + wmOperator *UNUSED(op), + const wmEvent *UNUSED(event)) { - eViewNavigation_Method mode = U.navigation_mode; + eViewNavigation_Method mode = U.navigation_mode; - switch (mode) { - case VIEW_NAVIGATION_FLY: - WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL); - break; - case VIEW_NAVIGATION_WALK: - default: - WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL); - break; - } + switch (mode) { + case VIEW_NAVIGATION_FLY: + WM_operator_name_call(C, "VIEW3D_OT_fly", WM_OP_INVOKE_DEFAULT, NULL); + break; + case VIEW_NAVIGATION_WALK: + default: + WM_operator_name_call(C, "VIEW3D_OT_walk", WM_OP_INVOKE_DEFAULT, NULL); + break; + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_navigate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "View Navigation"; - ot->description = "Interactively navigate around the scene (uses the mode (walk/fly) preference)"; - ot->idname = "VIEW3D_OT_navigate"; + /* identifiers */ + ot->name = "View Navigation"; + ot->description = + "Interactively navigate around the scene (uses the mode (walk/fly) preference)"; + ot->idname = "VIEW3D_OT_navigate"; - /* api callbacks */ - ot->invoke = view3d_navigate_invoke; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->invoke = view3d_navigate_invoke; + ot->poll = ED_operator_view3d_active; } /** \} */ @@ -4523,76 +4624,79 @@ void VIEW3D_OT_navigate(wmOperatorType *ot) /** \name Background Image Add Operator * \{ */ - static Camera *background_image_camera_from_context(bContext *C) { - /* Needed to support drag-and-drop & camera buttons context. */ - View3D *v3d = CTX_wm_view3d(C); - if (v3d != NULL) { - if (v3d->camera && v3d->camera->data && v3d->camera->type == OB_CAMERA) { - return v3d->camera->data; - } - return NULL; - } - else { - return CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; - } + /* Needed to support drag-and-drop & camera buttons context. */ + View3D *v3d = CTX_wm_view3d(C); + if (v3d != NULL) { + if (v3d->camera && v3d->camera->data && v3d->camera->type == OB_CAMERA) { + return v3d->camera->data; + } + return NULL; + } + else { + return CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; + } } static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Camera *cam = background_image_camera_from_context(C); - BKE_camera_background_image_new(cam); + Camera *cam = background_image_camera_from_context(C); + BKE_camera_background_image_new(cam); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Camera *cam = background_image_camera_from_context(C); - Image *ima; - CameraBGImage *bgpic; + Camera *cam = background_image_camera_from_context(C); + Image *ima; + CameraBGImage *bgpic; - ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); - /* may be NULL, continue anyway */ + ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); + /* may be NULL, continue anyway */ - bgpic = BKE_camera_background_image_new(cam); - bgpic->ima = ima; + bgpic = BKE_camera_background_image_new(cam); + bgpic->ima = ima; - cam->flag |= CAM_SHOW_BG_IMAGE; + cam->flag |= CAM_SHOW_BG_IMAGE; - WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static bool background_image_add_poll(bContext *C) { - return background_image_camera_from_context(C) != NULL; + return background_image_camera_from_context(C) != NULL; } void VIEW3D_OT_background_image_add(wmOperatorType *ot) { - /* identifiers */ - /* note: having key shortcut here is bad practice, - * but for now keep because this displays when dragging an image over the 3D viewport */ - ot->name = "Add Background Image"; - ot->description = "Add a new background image"; - ot->idname = "VIEW3D_OT_background_image_add"; + /* identifiers */ + /* note: having key shortcut here is bad practice, + * but for now keep because this displays when dragging an image over the 3D viewport */ + ot->name = "Add Background Image"; + ot->description = "Add a new background image"; + ot->idname = "VIEW3D_OT_background_image_add"; - /* api callbacks */ - ot->invoke = background_image_add_invoke; - ot->exec = background_image_add_exec; - ot->poll = background_image_add_poll; + /* api callbacks */ + ot->invoke = background_image_add_invoke; + ot->exec = background_image_add_exec; + ot->poll = background_image_add_poll; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign"); - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + /* properties */ + RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign"); + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); } /** \} */ @@ -4603,44 +4707,45 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) static int background_image_remove_exec(bContext *C, wmOperator *op) { - Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; - const int index = RNA_int_get(op->ptr, "index"); - CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index); + Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; + const int index = RNA_int_get(op->ptr, "index"); + CameraBGImage *bgpic_rem = BLI_findlink(&cam->bg_images, index); - if (bgpic_rem) { - if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) { - id_us_min((ID *)bgpic_rem->ima); - } - else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) { - id_us_min((ID *)bgpic_rem->clip); - } + if (bgpic_rem) { + if (bgpic_rem->source == CAM_BGIMG_SOURCE_IMAGE) { + id_us_min((ID *)bgpic_rem->ima); + } + else if (bgpic_rem->source == CAM_BGIMG_SOURCE_MOVIE) { + id_us_min((ID *)bgpic_rem->clip); + } - BKE_camera_background_image_remove(cam, bgpic_rem); + BKE_camera_background_image_remove(cam, bgpic_rem); - WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_background_image_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Background Image"; - ot->description = "Remove a background image from the 3D view"; - ot->idname = "VIEW3D_OT_background_image_remove"; + /* identifiers */ + ot->name = "Remove Background Image"; + ot->description = "Remove a background image from the 3D view"; + ot->idname = "VIEW3D_OT_background_image_remove"; - /* api callbacks */ - ot->exec = background_image_remove_exec; - ot->poll = ED_operator_camera; + /* api callbacks */ + ot->exec = background_image_remove_exec; + ot->poll = ED_operator_camera; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX); + /* properties */ + RNA_def_int( + ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX); } /** \} */ @@ -4653,83 +4758,83 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4]) { - BoundBox clipbb_local; - float imat[4][4]; - int i; + BoundBox clipbb_local; + float imat[4][4]; + int i; - invert_m4_m4(imat, mat); + invert_m4_m4(imat, mat); - for (i = 0; i < 8; i++) { - mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]); - } + for (i = 0; i < 8; i++) { + mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]); + } - ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat)); + ED_view3d_clipping_calc_from_boundbox(clip_local, &clipbb_local, is_negative_m4(mat)); } void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4]) { - if (rv3d->rflag & RV3D_CLIPPING) { - calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat); - } + if (rv3d->rflag & RV3D_CLIPPING) { + calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat); + } } static int view3d_clipping_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - rcti rect; + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + rcti rect; - WM_operator_properties_border_to_rcti(op, &rect); + WM_operator_properties_border_to_rcti(op, &rect); - rv3d->rflag |= RV3D_CLIPPING; - rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb"); + rv3d->rflag |= RV3D_CLIPPING; + rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb"); - /* NULL object because we don't want it in object space */ - ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect); + /* NULL object because we don't want it in object space */ + ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + ARegion *ar = CTX_wm_region(C); - if (rv3d->rflag & RV3D_CLIPPING) { - rv3d->rflag &= ~RV3D_CLIPPING; - ED_region_tag_redraw(ar); - if (rv3d->clipbb) { - MEM_freeN(rv3d->clipbb); - } - rv3d->clipbb = NULL; - return OPERATOR_FINISHED; - } - else { - return WM_gesture_box_invoke(C, op, event); - } + if (rv3d->rflag & RV3D_CLIPPING) { + rv3d->rflag &= ~RV3D_CLIPPING; + ED_region_tag_redraw(ar); + if (rv3d->clipbb) { + MEM_freeN(rv3d->clipbb); + } + rv3d->clipbb = NULL; + return OPERATOR_FINISHED; + } + else { + return WM_gesture_box_invoke(C, op, event); + } } void VIEW3D_OT_clip_border(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clipping Region"; - ot->description = "Set the view clipping region"; - ot->idname = "VIEW3D_OT_clip_border"; + /* identifiers */ + ot->name = "Clipping Region"; + ot->description = "Set the view clipping region"; + ot->idname = "VIEW3D_OT_clip_border"; - /* api callbacks */ - ot->invoke = view3d_clipping_invoke; - ot->exec = view3d_clipping_exec; - ot->modal = WM_gesture_box_modal; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = view3d_clipping_invoke; + ot->exec = view3d_clipping_exec; + ot->modal = WM_gesture_box_modal; + ot->cancel = WM_gesture_box_cancel; - ot->poll = ED_operator_region_view3d_active; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; - /* properties */ - WM_operator_properties_border(ot); + /* properties */ + WM_operator_properties_border(ot); } /** \} */ @@ -4740,263 +4845,273 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) /* cursor position in vec, result in vec, mval in region coords */ /* note: cannot use event->mval here (called by object_add() */ -void ED_view3d_cursor3d_position(bContext *C, const int mval[2], const bool use_depth, float cursor_co[3]) -{ - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = ar->regiondata; - bool flip; - bool depth_used = false; - - /* normally the caller should ensure this, - * but this is called from areas that aren't already dealing with the viewport */ - if (rv3d == NULL) { - return; - } - - ED_view3d_calc_zfac(rv3d, cursor_co, &flip); - - /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ - if (flip) { - negate_v3_v3(cursor_co, rv3d->ofs); - /* re initialize, no need to check flip again */ - ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */ ); - } - - if (use_depth) { /* maybe this should be accessed some other way */ - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); - - view3d_operator_needs_opengl(C); - if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) { - depth_used = true; - } - } - - if (depth_used == false) { - float depth_pt[3]; - copy_v3_v3(depth_pt, cursor_co); - ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, cursor_co); - } -} - -void ED_view3d_cursor3d_position_rotation( - bContext *C, const int mval[2], - const bool use_depth, enum eV3DCursorOrient orientation, - float cursor_co[3], float cursor_quat[4]) -{ - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - - /* XXX, caller should check. */ - if (rv3d == NULL) { - return; - } - - ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co); - - if (orientation == V3D_CURSOR_ORIENT_NONE) { - /* pass */ - } - else if (orientation == V3D_CURSOR_ORIENT_VIEW) { - copy_qt_qt(cursor_quat, rv3d->viewquat); - cursor_quat[0] *= -1.0f; - } - else if (orientation == V3D_CURSOR_ORIENT_XFORM) { - float mat[3][3]; - ED_transform_calc_orientation_from_type(C, mat); - mat3_to_quat(cursor_quat, mat); - } - else if (orientation == V3D_CURSOR_ORIENT_GEOM) { - copy_qt_qt(cursor_quat, rv3d->viewquat); - cursor_quat[0] *= -1.0f; - - const float mval_fl[2] = {UNPACK2(mval)}; - float ray_no[3]; - float ray_co[3]; - - struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d); - - float obmat[4][4]; - Object *ob_dummy = NULL; - float dist_px = 0; - if (ED_transform_snap_object_project_view3d_ex( - snap_context, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - .use_object_edit_cage = false, - }, - mval_fl, &dist_px, - ray_co, ray_no, NULL, - &ob_dummy, obmat)) - { - if (use_depth) { - copy_v3_v3(cursor_co, ray_co); - } - - float tquat[4]; - - /* Math normal (Z). */ - { - float z_src[3] = {0, 0, 1}; - mul_qt_v3(cursor_quat, z_src); - rotation_between_vecs_to_quat(tquat, z_src, ray_no); - mul_qt_qtqt(cursor_quat, tquat, cursor_quat); - } - - /* Match object matrix (X). */ - { - const float ortho_axis_dot[3] = { - dot_v3v3(ray_no, obmat[0]), - dot_v3v3(ray_no, obmat[1]), - dot_v3v3(ray_no, obmat[2]), - }; - const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot); - float x_src[3] = {1, 0, 0}; - float x_dst[3]; - mul_qt_v3(cursor_quat, x_src); - project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no); - normalize_v3(x_dst); - rotation_between_vecs_to_quat(tquat, x_src, x_dst); - mul_qt_qtqt(cursor_quat, tquat, cursor_quat); - } - } - ED_transform_snap_object_context_destroy(snap_context); - } -} - -void ED_view3d_cursor3d_update( - bContext *C, const int mval[2], - const bool use_depth, enum eV3DCursorOrient orientation) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - - View3DCursor *cursor_curr = &scene->cursor; - View3DCursor cursor_prev = *cursor_curr; - - { - float quat[4], quat_prev[4]; - BKE_scene_cursor_rot_to_quat(cursor_curr, quat); - copy_qt_qt(quat_prev, quat); - ED_view3d_cursor3d_position_rotation( - C, mval, - use_depth, orientation, - cursor_curr->location, quat); - - if (!equals_v4v4(quat_prev, quat)) { - if ((cursor_curr->rotation_mode == ROT_MODE_AXISANGLE) && - RV3D_VIEW_IS_AXIS(rv3d->view)) - { - float tmat[3][3], cmat[3][3]; - quat_to_mat3(tmat, quat); - negate_v3_v3(cursor_curr->rotation_axis, tmat[2]); - axis_angle_to_mat3(cmat, cursor_curr->rotation_axis, 0.0f); - cursor_curr->rotation_angle = angle_signed_on_axis_v3v3_v3(cmat[0], tmat[0], cursor_curr->rotation_axis); - } - else { - BKE_scene_cursor_quat_to_rot(cursor_curr, quat, true); - } - } - } - - /* offset the cursor lock to avoid jumping to new offset */ - if (v3d->ob_centre_cursor) { - if (U.uiflag & USER_LOCK_CURSOR_ADJUST) { - - float co_2d_curr[2], co_2d_prev[2]; - - if ((ED_view3d_project_float_global( - ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_float_global( - ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) - { - rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f); - rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f); - } - } - else { - /* Cursor may be outside of the view, - * prevent it getting 'lost', see: T40353 & T45301 */ - zero_v2(rv3d->ofs_lock); - } - } - - if (v3d->localvd) { - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - } - else { - WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); - } - - { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - wmMsgParams_RNA msg_key_params = {{{0}}}; - RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr); - WM_msg_publish_rna_params(mbus, &msg_key_params); - } - - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); +void ED_view3d_cursor3d_position(bContext *C, + const int mval[2], + const bool use_depth, + float cursor_co[3]) +{ + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + bool flip; + bool depth_used = false; + + /* normally the caller should ensure this, + * but this is called from areas that aren't already dealing with the viewport */ + if (rv3d == NULL) { + return; + } + + ED_view3d_calc_zfac(rv3d, cursor_co, &flip); + + /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ + if (flip) { + negate_v3_v3(cursor_co, rv3d->ofs); + /* re initialize, no need to check flip again */ + ED_view3d_calc_zfac(rv3d, cursor_co, NULL /* &flip */); + } + + if (use_depth) { /* maybe this should be accessed some other way */ + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + + view3d_operator_needs_opengl(C); + if (ED_view3d_autodist(depsgraph, ar, v3d, mval, cursor_co, true, NULL)) { + depth_used = true; + } + } + + if (depth_used == false) { + float depth_pt[3]; + copy_v3_v3(depth_pt, cursor_co); + ED_view3d_win_to_3d_int(v3d, ar, depth_pt, mval, cursor_co); + } +} + +void ED_view3d_cursor3d_position_rotation(bContext *C, + const int mval[2], + const bool use_depth, + enum eV3DCursorOrient orientation, + float cursor_co[3], + float cursor_quat[4]) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + /* XXX, caller should check. */ + if (rv3d == NULL) { + return; + } + + ED_view3d_cursor3d_position(C, mval, use_depth, cursor_co); + + if (orientation == V3D_CURSOR_ORIENT_NONE) { + /* pass */ + } + else if (orientation == V3D_CURSOR_ORIENT_VIEW) { + copy_qt_qt(cursor_quat, rv3d->viewquat); + cursor_quat[0] *= -1.0f; + } + else if (orientation == V3D_CURSOR_ORIENT_XFORM) { + float mat[3][3]; + ED_transform_calc_orientation_from_type(C, mat); + mat3_to_quat(cursor_quat, mat); + } + else if (orientation == V3D_CURSOR_ORIENT_GEOM) { + copy_qt_qt(cursor_quat, rv3d->viewquat); + cursor_quat[0] *= -1.0f; + + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_no[3]; + float ray_co[3]; + + struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( + bmain, scene, CTX_data_depsgraph(C), 0, ar, v3d); + + float obmat[4][4]; + Object *ob_dummy = NULL; + float dist_px = 0; + if (ED_transform_snap_object_project_view3d_ex(snap_context, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = false, + }, + mval_fl, + &dist_px, + ray_co, + ray_no, + NULL, + &ob_dummy, + obmat)) { + if (use_depth) { + copy_v3_v3(cursor_co, ray_co); + } + + float tquat[4]; + + /* Math normal (Z). */ + { + float z_src[3] = {0, 0, 1}; + mul_qt_v3(cursor_quat, z_src); + rotation_between_vecs_to_quat(tquat, z_src, ray_no); + mul_qt_qtqt(cursor_quat, tquat, cursor_quat); + } + + /* Match object matrix (X). */ + { + const float ortho_axis_dot[3] = { + dot_v3v3(ray_no, obmat[0]), + dot_v3v3(ray_no, obmat[1]), + dot_v3v3(ray_no, obmat[2]), + }; + const int ortho_axis = axis_dominant_v3_ortho_single(ortho_axis_dot); + float x_src[3] = {1, 0, 0}; + float x_dst[3]; + mul_qt_v3(cursor_quat, x_src); + project_plane_v3_v3v3(x_dst, obmat[ortho_axis], ray_no); + normalize_v3(x_dst); + rotation_between_vecs_to_quat(tquat, x_src, x_dst); + mul_qt_qtqt(cursor_quat, tquat, cursor_quat); + } + } + ED_transform_snap_object_context_destroy(snap_context); + } +} + +void ED_view3d_cursor3d_update(bContext *C, + const int mval[2], + const bool use_depth, + enum eV3DCursorOrient orientation) +{ + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + View3DCursor *cursor_curr = &scene->cursor; + View3DCursor cursor_prev = *cursor_curr; + + { + float quat[4], quat_prev[4]; + BKE_scene_cursor_rot_to_quat(cursor_curr, quat); + copy_qt_qt(quat_prev, quat); + ED_view3d_cursor3d_position_rotation( + C, mval, use_depth, orientation, cursor_curr->location, quat); + + if (!equals_v4v4(quat_prev, quat)) { + if ((cursor_curr->rotation_mode == ROT_MODE_AXISANGLE) && RV3D_VIEW_IS_AXIS(rv3d->view)) { + float tmat[3][3], cmat[3][3]; + quat_to_mat3(tmat, quat); + negate_v3_v3(cursor_curr->rotation_axis, tmat[2]); + axis_angle_to_mat3(cmat, cursor_curr->rotation_axis, 0.0f); + cursor_curr->rotation_angle = angle_signed_on_axis_v3v3_v3( + cmat[0], tmat[0], cursor_curr->rotation_axis); + } + else { + BKE_scene_cursor_quat_to_rot(cursor_curr, quat, true); + } + } + } + + /* offset the cursor lock to avoid jumping to new offset */ + if (v3d->ob_centre_cursor) { + if (U.uiflag & USER_LOCK_CURSOR_ADJUST) { + + float co_2d_curr[2], co_2d_prev[2]; + + if ((ED_view3d_project_float_global( + ar, cursor_prev.location, co_2d_prev, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && + (ED_view3d_project_float_global( + ar, cursor_curr->location, co_2d_curr, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) { + rv3d->ofs_lock[0] += (co_2d_curr[0] - co_2d_prev[0]) / (ar->winx * 0.5f); + rv3d->ofs_lock[1] += (co_2d_curr[1] - co_2d_prev[1]) / (ar->winy * 0.5f); + } + } + else { + /* Cursor may be outside of the view, + * prevent it getting 'lost', see: T40353 & T45301 */ + zero_v2(rv3d->ofs_lock); + } + } + + if (v3d->localvd) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + } + else { + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); + } + + { + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + wmMsgParams_RNA msg_key_params = {{{0}}}; + RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr); + WM_msg_publish_rna_params(mbus, &msg_key_params); + } + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); } static int view3d_cursor3d_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - bool use_depth = (U.uiflag & USER_DEPTH_CURSOR); - { - PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth"); - if (RNA_property_is_set(op->ptr, prop)) { - use_depth = RNA_property_boolean_get(op->ptr, prop); - } - else { - RNA_property_boolean_set(op->ptr, prop, use_depth); - } - } - const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation"); - ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation); + bool use_depth = (U.uiflag & USER_DEPTH_CURSOR); + { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_depth"); + if (RNA_property_is_set(op->ptr, prop)) { + use_depth = RNA_property_boolean_get(op->ptr, prop); + } + else { + RNA_property_boolean_set(op->ptr, prop, use_depth); + } + } + const enum eV3DCursorOrient orientation = RNA_enum_get(op->ptr, "orientation"); + ED_view3d_cursor3d_update(C, event->mval, use_depth, orientation); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_cursor3d(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set 3D Cursor"; - ot->description = "Set the location of the 3D cursor"; - ot->idname = "VIEW3D_OT_cursor3d"; + /* identifiers */ + ot->name = "Set 3D Cursor"; + ot->description = "Set the location of the 3D cursor"; + ot->idname = "VIEW3D_OT_cursor3d"; - /* api callbacks */ - ot->invoke = view3d_cursor3d_invoke; + /* api callbacks */ + ot->invoke = view3d_cursor3d_invoke; - ot->poll = ED_operator_region_view3d_active; + ot->poll = ED_operator_region_view3d_active; - /* flags */ -// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + /* flags */ + // ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; - PropertyRNA *prop; - static const EnumPropertyItem orientation_items[] = { - {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"}, - {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"}, - {V3D_CURSOR_ORIENT_XFORM, "XFORM", 0, "Transform", "Orient to the current transform setting"}, - {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"}, - {0, NULL, 0, NULL, NULL}, - }; + PropertyRNA *prop; + static const EnumPropertyItem orientation_items[] = { + {V3D_CURSOR_ORIENT_NONE, "NONE", 0, "None", "Leave orientation unchanged"}, + {V3D_CURSOR_ORIENT_VIEW, "VIEW", 0, "View", "Orient to the viewport"}, + {V3D_CURSOR_ORIENT_XFORM, + "XFORM", + 0, + "Transform", + "Orient to the current transform setting"}, + {V3D_CURSOR_ORIENT_GEOM, "GEOM", 0, "Geometry", "Match the surface normal"}, + {0, NULL, 0, NULL, NULL}, + }; - prop = RNA_def_boolean( - ot->srna, "use_depth", true, "Surface Project", - "Project onto the surface"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "use_depth", true, "Surface Project", "Project onto the surface"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_enum( - ot->srna, "orientation", orientation_items, V3D_CURSOR_ORIENT_VIEW, - "Orientation", "Preset viewpoint to use"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum(ot->srna, + "orientation", + orientation_items, + V3D_CURSOR_ORIENT_VIEW, + "Orientation", + "Preset viewpoint to use"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ @@ -5006,120 +5121,114 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) * \{ */ static const EnumPropertyItem prop_shading_type_items[] = { - {OB_WIRE, "WIREFRAME", 0, "Wireframe", "Toggle wireframe shading"}, - {OB_SOLID, "SOLID", 0, "Solid", "Toggle solid shading"}, - {OB_MATERIAL, "MATERIAL", 0, "LookDev", "Toggle lookdev shading"}, - {OB_RENDER, "RENDERED", 0, "Rendered", "Toggle rendered shading"}, - {0, NULL, 0, NULL, NULL}, + {OB_WIRE, "WIREFRAME", 0, "Wireframe", "Toggle wireframe shading"}, + {OB_SOLID, "SOLID", 0, "Solid", "Toggle solid shading"}, + {OB_MATERIAL, "MATERIAL", 0, "LookDev", "Toggle lookdev shading"}, + {OB_RENDER, "RENDERED", 0, "Rendered", "Toggle rendered shading"}, + {0, NULL, 0, NULL, NULL}, }; static int toggle_shading_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); - ScrArea *sa = CTX_wm_area(C); - int type = RNA_enum_get(op->ptr, "type"); - - if (type == OB_SOLID) { - if (v3d->shading.type != type) { - v3d->shading.type = type; - } - else if (v3d->shading.type == OB_WIRE) { - v3d->shading.type = OB_SOLID; - } - else { - v3d->shading.type = OB_WIRE; - } - } - else { - char *prev_type = ( - (type == OB_WIRE) ? - &v3d->shading.prev_type_wire : - &v3d->shading.prev_type); - if (v3d->shading.type == type) { - if (*prev_type == type || !ELEM(*prev_type, OB_WIRE, OB_SOLID, OB_MATERIAL, OB_RENDER)) { - *prev_type = OB_SOLID; - } - v3d->shading.type = *prev_type; - } - else { - *prev_type = v3d->shading.type; - v3d->shading.type = type; - } - } - - ED_view3d_shade_update(bmain, v3d, sa); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); + ScrArea *sa = CTX_wm_area(C); + int type = RNA_enum_get(op->ptr, "type"); + + if (type == OB_SOLID) { + if (v3d->shading.type != type) { + v3d->shading.type = type; + } + else if (v3d->shading.type == OB_WIRE) { + v3d->shading.type = OB_SOLID; + } + else { + v3d->shading.type = OB_WIRE; + } + } + else { + char *prev_type = ((type == OB_WIRE) ? &v3d->shading.prev_type_wire : &v3d->shading.prev_type); + if (v3d->shading.type == type) { + if (*prev_type == type || !ELEM(*prev_type, OB_WIRE, OB_SOLID, OB_MATERIAL, OB_RENDER)) { + *prev_type = OB_SOLID; + } + v3d->shading.type = *prev_type; + } + else { + *prev_type = v3d->shading.type; + v3d->shading.type = type; + } + } + + ED_view3d_shade_update(bmain, v3d, sa); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + + return OPERATOR_FINISHED; } void VIEW3D_OT_toggle_shading(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Toggle Shading Type"; - ot->description = "Toggle shading type in 3D viewport"; - ot->idname = "VIEW3D_OT_toggle_shading"; + /* identifiers */ + ot->name = "Toggle Shading Type"; + ot->description = "Toggle shading type in 3D viewport"; + ot->idname = "VIEW3D_OT_toggle_shading"; - /* api callbacks */ - ot->exec = toggle_shading_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = toggle_shading_exec; + ot->poll = ED_operator_view3d_active; - prop = RNA_def_enum(ot->srna, "type", prop_shading_type_items, 0, "Type", "Shading type to toggle"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_enum( + ot->srna, "type", prop_shading_type_items, 0, "Type", "Shading type to toggle"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Toggle XRay * \{ */ static int toggle_xray_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - ScrArea *sa = CTX_wm_area(C); - Object *obact = CTX_data_active_object(C); - - if (obact && - ((obact->mode & OB_MODE_POSE) || - ((obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact)))) - { - v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECT; - } - else { - const bool xray_active = ( - (obact && (obact->mode & OB_MODE_EDIT)) || - ELEM(v3d->shading.type, OB_WIRE, OB_SOLID)); - - if (v3d->shading.type == OB_WIRE) { - v3d->shading.flag ^= V3D_SHADING_XRAY_BONE; - } - else { - v3d->shading.flag ^= V3D_SHADING_XRAY; - } - if (!xray_active) { - BKE_report(op->reports, RPT_INFO, "X-Ray not available in current mode"); - } - } - - ED_area_tag_redraw(sa); - - return OPERATOR_FINISHED; + View3D *v3d = CTX_wm_view3d(C); + ScrArea *sa = CTX_wm_area(C); + Object *obact = CTX_data_active_object(C); + + if (obact && ((obact->mode & OB_MODE_POSE) || + ((obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact)))) { + v3d->overlay.flag ^= V3D_OVERLAY_BONE_SELECT; + } + else { + const bool xray_active = ((obact && (obact->mode & OB_MODE_EDIT)) || + ELEM(v3d->shading.type, OB_WIRE, OB_SOLID)); + + if (v3d->shading.type == OB_WIRE) { + v3d->shading.flag ^= V3D_SHADING_XRAY_BONE; + } + else { + v3d->shading.flag ^= V3D_SHADING_XRAY; + } + if (!xray_active) { + BKE_report(op->reports, RPT_INFO, "X-Ray not available in current mode"); + } + } + + ED_area_tag_redraw(sa); + + return OPERATOR_FINISHED; } void VIEW3D_OT_toggle_xray(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Toggle X-Ray"; - ot->idname = "VIEW3D_OT_toggle_xray"; + /* identifiers */ + ot->name = "Toggle X-Ray"; + ot->idname = "VIEW3D_OT_toggle_xray"; - /* api callbacks */ - ot->exec = toggle_xray_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = toggle_xray_exec; + ot->poll = ED_operator_view3d_active; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index b80ce2c49b0..8dc3abe6af5 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -38,7 +38,6 @@ #include "BLT_translation.h" - #include "WM_api.h" #include "WM_types.h" @@ -54,1068 +53,1085 @@ #include "DEG_depsgraph.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* NOTE: these defines are saved in keymap files, * do not change values but just add new ones */ enum { - FLY_MODAL_CANCEL = 1, - FLY_MODAL_CONFIRM, - FLY_MODAL_ACCELERATE, - FLY_MODAL_DECELERATE, - FLY_MODAL_PAN_ENABLE, - FLY_MODAL_PAN_DISABLE, - FLY_MODAL_DIR_FORWARD, - FLY_MODAL_DIR_BACKWARD, - FLY_MODAL_DIR_LEFT, - FLY_MODAL_DIR_RIGHT, - FLY_MODAL_DIR_UP, - FLY_MODAL_DIR_DOWN, - FLY_MODAL_AXIS_LOCK_X, - FLY_MODAL_AXIS_LOCK_Z, - FLY_MODAL_PRECISION_ENABLE, - FLY_MODAL_PRECISION_DISABLE, - FLY_MODAL_FREELOOK_ENABLE, - FLY_MODAL_FREELOOK_DISABLE, - FLY_MODAL_SPEED, /* mousepan typically */ + FLY_MODAL_CANCEL = 1, + FLY_MODAL_CONFIRM, + FLY_MODAL_ACCELERATE, + FLY_MODAL_DECELERATE, + FLY_MODAL_PAN_ENABLE, + FLY_MODAL_PAN_DISABLE, + FLY_MODAL_DIR_FORWARD, + FLY_MODAL_DIR_BACKWARD, + FLY_MODAL_DIR_LEFT, + FLY_MODAL_DIR_RIGHT, + FLY_MODAL_DIR_UP, + FLY_MODAL_DIR_DOWN, + FLY_MODAL_AXIS_LOCK_X, + FLY_MODAL_AXIS_LOCK_Z, + FLY_MODAL_PRECISION_ENABLE, + FLY_MODAL_PRECISION_DISABLE, + FLY_MODAL_FREELOOK_ENABLE, + FLY_MODAL_FREELOOK_DISABLE, + FLY_MODAL_SPEED, /* mousepan typically */ }; /* relative view axis locking - xlock, zlock */ typedef enum eFlyPanState { - /* disabled */ - FLY_AXISLOCK_STATE_OFF = 0, + /* disabled */ + FLY_AXISLOCK_STATE_OFF = 0, - /* enabled but not checking because mouse hasn't moved outside the margin since locking was - * checked an not needed when the mouse moves, locking is set to 2 so checks are done. */ - FLY_AXISLOCK_STATE_IDLE = 1, + /* enabled but not checking because mouse hasn't moved outside the margin since locking was + * checked an not needed when the mouse moves, locking is set to 2 so checks are done. */ + FLY_AXISLOCK_STATE_IDLE = 1, - /* mouse moved and checking needed, - * if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */ - FLY_AXISLOCK_STATE_ACTIVE = 2, + /* mouse moved and checking needed, + * if no view altering is done its changed back to #FLY_AXISLOCK_STATE_IDLE */ + FLY_AXISLOCK_STATE_ACTIVE = 2, } eFlyPanState; /* called in transform_ops.c, on each regeneration of keymaps */ void fly_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + static const EnumPropertyItem modal_items[] = { + {FLY_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {FLY_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, - {FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, - {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""}, - {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""}, - {FLY_MODAL_DIR_UP, "UP", 0, "Up", ""}, - {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, + {FLY_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, + {FLY_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, + {FLY_MODAL_DIR_LEFT, "LEFT", 0, "Left", ""}, + {FLY_MODAL_DIR_RIGHT, "RIGHT", 0, "Right", ""}, + {FLY_MODAL_DIR_UP, "UP", 0, "Up", ""}, + {FLY_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, - {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""}, - {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""}, + {FLY_MODAL_PAN_ENABLE, "PAN_ENABLE", 0, "Pan", ""}, + {FLY_MODAL_PAN_DISABLE, "PAN_DISABLE", 0, "Pan (Off)", ""}, - {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, - {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, + {FLY_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, + {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, - {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, - {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, - {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, - {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, + {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, + {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, - {FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""}, - {FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""}, + {FLY_MODAL_FREELOOK_ENABLE, "FREELOOK_ENABLE", 0, "Rotation", ""}, + {FLY_MODAL_FREELOOK_DISABLE, "FREELOOK_DISABLE", 0, "Rotation (Off)", ""}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); } typedef struct FlyInfo { - /* context stuff */ - RegionView3D *rv3d; - View3D *v3d; - ARegion *ar; - struct Depsgraph *depsgraph; - Scene *scene; - - wmTimer *timer; /* needed for redraws */ - - short state; - bool redraw; - bool use_precision; - /* if the user presses shift they can look about - * without moving the direction there looking */ - bool use_freelook; - - int mval[2]; /* latest 2D mouse values */ - int center_mval[2]; /* center mouse values */ - float width, height; /* camera viewport dimensions */ + /* context stuff */ + RegionView3D *rv3d; + View3D *v3d; + ARegion *ar; + struct Depsgraph *depsgraph; + Scene *scene; + + wmTimer *timer; /* needed for redraws */ + + short state; + bool redraw; + bool use_precision; + /* if the user presses shift they can look about + * without moving the direction there looking */ + bool use_freelook; + + int mval[2]; /* latest 2D mouse values */ + int center_mval[2]; /* center mouse values */ + float width, height; /* camera viewport dimensions */ #ifdef WITH_INPUT_NDOF - wmNDOFMotionData *ndof; /* latest 3D mouse values */ + wmNDOFMotionData *ndof; /* latest 3D mouse values */ #endif - /* fly state state */ - float speed; /* the speed the view is moving per redraw */ - short axis; /* Axis index to move along by default Z to move along the view */ - bool pan_view; /* when true, pan the view instead of rotating */ + /* fly state state */ + float speed; /* the speed the view is moving per redraw */ + short axis; /* Axis index to move along by default Z to move along the view */ + bool pan_view; /* when true, pan the view instead of rotating */ - eFlyPanState xlock, zlock; - float xlock_momentum, zlock_momentum; /* nicer dynamics */ - float grid; /* world scale 1.0 default */ + eFlyPanState xlock, zlock; + float xlock_momentum, zlock_momentum; /* nicer dynamics */ + float grid; /* world scale 1.0 default */ - /* compare between last state */ - double time_lastwheel; /* used to accelerate when using the mousewheel a lot */ - double time_lastdraw; /* time between draws */ + /* compare between last state */ + double time_lastwheel; /* used to accelerate when using the mousewheel a lot */ + double time_lastdraw; /* time between draws */ - void *draw_handle_pixel; + void *draw_handle_pixel; - /* use for some lag */ - float dvec_prev[3]; /* old for some lag */ + /* use for some lag */ + float dvec_prev[3]; /* old for some lag */ - struct View3DCameraControl *v3d_camera_control; + struct View3DCameraControl *v3d_camera_control; } FlyInfo; static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg) { - FlyInfo *fly = arg; - rctf viewborder; - int xoff, yoff; - float x1, x2, y1, y2; + FlyInfo *fly = arg; + rctf viewborder; + int xoff, yoff; + float x1, x2, y1, y2; - if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) { - ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); - xoff = viewborder.xmin; - yoff = viewborder.ymin; - } - else { - xoff = 0; - yoff = 0; - } + if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) { + ED_view3d_calc_camera_border( + fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); + xoff = viewborder.xmin; + yoff = viewborder.ymin; + } + else { + xoff = 0; + yoff = 0; + } - /* draws 4 edge brackets that frame the safe area where the - * mouse can move during fly mode without spinning the view */ + /* draws 4 edge brackets that frame the safe area where the + * mouse can move during fly mode without spinning the view */ - x1 = xoff + 0.45f * fly->width; - y1 = yoff + 0.45f * fly->height; - x2 = xoff + 0.55f * fly->width; - y2 = yoff + 0.55f * fly->height; + x1 = xoff + 0.45f * fly->width; + y1 = yoff + 0.45f * fly->height; + x2 = xoff + 0.55f * fly->width; + y2 = yoff + 0.55f * fly->height; - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - immBegin(GPU_PRIM_LINES, 16); + immBegin(GPU_PRIM_LINES, 16); - /* bottom left */ - immVertex2f(pos, x1, y1); - immVertex2f(pos, x1, y1 + 5); + /* bottom left */ + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y1 + 5); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x1 + 5, y1); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1 + 5, y1); - /* top right */ - immVertex2f(pos, x2, y2); - immVertex2f(pos, x2, y2 - 5); + /* top right */ + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y2 - 5); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x2 - 5, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2 - 5, y2); - /* top left */ - immVertex2f(pos, x1, y2); - immVertex2f(pos, x1, y2 - 5); + /* top left */ + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1, y2 - 5); - immVertex2f(pos, x1, y2); - immVertex2f(pos, x1 + 5, y2); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x1 + 5, y2); - /* bottom right */ - immVertex2f(pos, x2, y1); - immVertex2f(pos, x2, y1 + 5); + /* bottom right */ + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y1 + 5); - immVertex2f(pos, x2, y1); - immVertex2f(pos, x2 - 5, y1); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2 - 5, y1); - immEnd(); - immUnbindProgram(); + immEnd(); + immUnbindProgram(); } static void fly_update_header(bContext *C, wmOperator *op, FlyInfo *fly) { - char header[UI_MAX_DRAW_STR]; - char buf[UI_MAX_DRAW_STR]; + char header[UI_MAX_DRAW_STR]; + char buf[UI_MAX_DRAW_STR]; - char *p = buf; - int available_len = sizeof(buf); + char *p = buf; + int available_len = sizeof(buf); #define WM_MODALKEY(_id) \ - WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) - - BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, " - "%s: pan enable, " - "%s|%s|%s|%s|%s|%s: direction, " - "%s: slow, %s: free look, " - "%s: Upright x axis (%s), " - "%s: Upright z axis (%s), " - "%s: increase speed, %s: decrease speed"), - WM_MODALKEY(FLY_MODAL_CONFIRM), WM_MODALKEY(FLY_MODAL_CANCEL), - WM_MODALKEY(FLY_MODAL_PAN_ENABLE), - WM_MODALKEY(FLY_MODAL_DIR_FORWARD), WM_MODALKEY(FLY_MODAL_DIR_LEFT), - WM_MODALKEY(FLY_MODAL_DIR_BACKWARD), WM_MODALKEY(FLY_MODAL_DIR_RIGHT), - WM_MODALKEY(FLY_MODAL_DIR_UP), WM_MODALKEY(FLY_MODAL_DIR_DOWN), - WM_MODALKEY(FLY_MODAL_PRECISION_ENABLE), WM_MODALKEY(FLY_MODAL_FREELOOK_ENABLE), - WM_MODALKEY(FLY_MODAL_AXIS_LOCK_X), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF), - WM_MODALKEY(FLY_MODAL_AXIS_LOCK_Z), WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF), - WM_MODALKEY(FLY_MODAL_ACCELERATE), WM_MODALKEY(FLY_MODAL_DECELERATE)); + WM_modalkeymap_operator_items_to_string_buf( \ + op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) + + BLI_snprintf(header, + sizeof(header), + IFACE_("%s: confirm, %s: cancel, " + "%s: pan enable, " + "%s|%s|%s|%s|%s|%s: direction, " + "%s: slow, %s: free look, " + "%s: Upright x axis (%s), " + "%s: Upright z axis (%s), " + "%s: increase speed, %s: decrease speed"), + WM_MODALKEY(FLY_MODAL_CONFIRM), + WM_MODALKEY(FLY_MODAL_CANCEL), + WM_MODALKEY(FLY_MODAL_PAN_ENABLE), + WM_MODALKEY(FLY_MODAL_DIR_FORWARD), + WM_MODALKEY(FLY_MODAL_DIR_LEFT), + WM_MODALKEY(FLY_MODAL_DIR_BACKWARD), + WM_MODALKEY(FLY_MODAL_DIR_RIGHT), + WM_MODALKEY(FLY_MODAL_DIR_UP), + WM_MODALKEY(FLY_MODAL_DIR_DOWN), + WM_MODALKEY(FLY_MODAL_PRECISION_ENABLE), + WM_MODALKEY(FLY_MODAL_FREELOOK_ENABLE), + WM_MODALKEY(FLY_MODAL_AXIS_LOCK_X), + WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF), + WM_MODALKEY(FLY_MODAL_AXIS_LOCK_Z), + WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF), + WM_MODALKEY(FLY_MODAL_ACCELERATE), + WM_MODALKEY(FLY_MODAL_DECELERATE)); #undef WM_MODALKEY - ED_workspace_status_text(C, header); + ED_workspace_status_text(C, header); } /* FlyInfo->state */ enum { - FLY_RUNNING = 0, - FLY_CANCEL = 1, - FLY_CONFIRM = 2, + FLY_RUNNING = 0, + FLY_CANCEL = 1, + FLY_CONFIRM = 2, }; static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { - wmWindow *win = CTX_wm_window(C); - rctf viewborder; + wmWindow *win = CTX_wm_window(C); + rctf viewborder; - float upvec[3]; /* tmp */ - float mat[3][3]; + float upvec[3]; /* tmp */ + float mat[3][3]; - fly->rv3d = CTX_wm_region_view3d(C); - fly->v3d = CTX_wm_view3d(C); - fly->ar = CTX_wm_region(C); - fly->depsgraph = CTX_data_depsgraph(C); - fly->scene = CTX_data_scene(C); + fly->rv3d = CTX_wm_region_view3d(C); + fly->v3d = CTX_wm_view3d(C); + fly->ar = CTX_wm_region(C); + fly->depsgraph = CTX_data_depsgraph(C); + fly->scene = CTX_data_scene(C); #ifdef NDOF_FLY_DEBUG - puts("\n-- fly begin --"); + puts("\n-- fly begin --"); #endif - /* sanity check: for rare but possible case (if lib-linking the camera fails) */ - if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { - fly->rv3d->persp = RV3D_PERSP; - } - - if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) { - BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); - return false; - } - - if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) { - BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked"); - return false; - } - - if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) { - BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); - return false; - } - - fly->state = FLY_RUNNING; - fly->speed = 0.0f; - fly->axis = 2; - fly->pan_view = false; - fly->xlock = FLY_AXISLOCK_STATE_OFF; - fly->zlock = FLY_AXISLOCK_STATE_OFF; - fly->xlock_momentum = 0.0f; - fly->zlock_momentum = 0.0f; - fly->grid = 1.0f; - fly->use_precision = false; - fly->use_freelook = false; + /* sanity check: for rare but possible case (if lib-linking the camera fails) */ + if ((fly->rv3d->persp == RV3D_CAMOB) && (fly->v3d->camera == NULL)) { + fly->rv3d->persp = RV3D_PERSP; + } + + if (fly->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(fly->v3d->camera)) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); + return false; + } + + if (ED_view3d_offset_lock_check(fly->v3d, fly->rv3d)) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view offset is locked"); + return false; + } + + if (fly->rv3d->persp == RV3D_CAMOB && fly->v3d->camera->constraints.first) { + BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); + return false; + } + + fly->state = FLY_RUNNING; + fly->speed = 0.0f; + fly->axis = 2; + fly->pan_view = false; + fly->xlock = FLY_AXISLOCK_STATE_OFF; + fly->zlock = FLY_AXISLOCK_STATE_OFF; + fly->xlock_momentum = 0.0f; + fly->zlock_momentum = 0.0f; + fly->grid = 1.0f; + fly->use_precision = false; + fly->use_freelook = false; #ifdef NDOF_FLY_DRAW_TOOMUCH - fly->redraw = 1; + fly->redraw = 1; #endif - zero_v3(fly->dvec_prev); + zero_v3(fly->dvec_prev); - fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); + fly->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); - copy_v2_v2_int(fly->mval, event->mval); + copy_v2_v2_int(fly->mval, event->mval); #ifdef WITH_INPUT_NDOF - fly->ndof = NULL; + fly->ndof = NULL; #endif - fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); - - fly->draw_handle_pixel = ED_region_draw_cb_activate(fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL); - - fly->rv3d->rflag |= RV3D_NAVIGATING; - - /* detect whether to start with Z locking */ - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - copy_m3_m4(mat, fly->rv3d->viewinv); - mul_m3_v3(mat, upvec); - if (fabsf(upvec[2]) < 0.1f) { - fly->zlock = FLY_AXISLOCK_STATE_IDLE; - } - - fly->v3d_camera_control = ED_view3d_cameracontrol_acquire( - CTX_data_depsgraph(C), fly->scene, fly->v3d, fly->rv3d, - (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); - - /* calculate center */ - if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) { - ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); - - fly->width = BLI_rctf_size_x(&viewborder); - fly->height = BLI_rctf_size_y(&viewborder); - - fly->center_mval[0] = viewborder.xmin + fly->width / 2; - fly->center_mval[1] = viewborder.ymin + fly->height / 2; - } - else { - fly->width = fly->ar->winx; - fly->height = fly->ar->winy; - - fly->center_mval[0] = fly->width / 2; - fly->center_mval[1] = fly->height / 2; - } - - /* center the mouse, probably the UI mafia are against this but without its quite annoying */ - WM_cursor_warp(win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]); - - fly_update_header(C, op, fly); - return 1; + fly->time_lastdraw = fly->time_lastwheel = PIL_check_seconds_timer(); + + fly->draw_handle_pixel = ED_region_draw_cb_activate( + fly->ar->type, drawFlyPixel, fly, REGION_DRAW_POST_PIXEL); + + fly->rv3d->rflag |= RV3D_NAVIGATING; + + /* detect whether to start with Z locking */ + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + copy_m3_m4(mat, fly->rv3d->viewinv); + mul_m3_v3(mat, upvec); + if (fabsf(upvec[2]) < 0.1f) { + fly->zlock = FLY_AXISLOCK_STATE_IDLE; + } + + fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(CTX_data_depsgraph(C), + fly->scene, + fly->v3d, + fly->rv3d, + (U.uiflag & USER_CAM_LOCK_NO_PARENT) == + 0); + + /* calculate center */ + if (ED_view3d_cameracontrol_object_get(fly->v3d_camera_control)) { + ED_view3d_calc_camera_border( + fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false); + + fly->width = BLI_rctf_size_x(&viewborder); + fly->height = BLI_rctf_size_y(&viewborder); + + fly->center_mval[0] = viewborder.xmin + fly->width / 2; + fly->center_mval[1] = viewborder.ymin + fly->height / 2; + } + else { + fly->width = fly->ar->winx; + fly->height = fly->ar->winy; + + fly->center_mval[0] = fly->width / 2; + fly->center_mval[1] = fly->height / 2; + } + + /* center the mouse, probably the UI mafia are against this but without its quite annoying */ + WM_cursor_warp( + win, fly->ar->winrct.xmin + fly->center_mval[0], fly->ar->winrct.ymin + fly->center_mval[1]); + + fly_update_header(C, op, fly); + return 1; } static int flyEnd(bContext *C, FlyInfo *fly) { - wmWindow *win; - RegionView3D *rv3d; + wmWindow *win; + RegionView3D *rv3d; - if (fly->state == FLY_RUNNING) { - return OPERATOR_RUNNING_MODAL; - } + if (fly->state == FLY_RUNNING) { + return OPERATOR_RUNNING_MODAL; + } #ifdef NDOF_FLY_DEBUG - puts("\n-- fly end --"); + puts("\n-- fly end --"); #endif - win = CTX_wm_window(C); - rv3d = fly->rv3d; + win = CTX_wm_window(C); + rv3d = fly->rv3d; - WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer); + WM_event_remove_timer(CTX_wm_manager(C), win, fly->timer); - ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel); + ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel); - ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL); + ED_view3d_cameracontrol_release(fly->v3d_camera_control, fly->state == FLY_CANCEL); - rv3d->rflag &= ~RV3D_NAVIGATING; + rv3d->rflag &= ~RV3D_NAVIGATING; #ifdef WITH_INPUT_NDOF - if (fly->ndof) { - MEM_freeN(fly->ndof); - } + if (fly->ndof) { + MEM_freeN(fly->ndof); + } #endif - if (fly->state == FLY_CONFIRM) { - MEM_freeN(fly); - return OPERATOR_FINISHED; - } + if (fly->state == FLY_CONFIRM) { + MEM_freeN(fly); + return OPERATOR_FINISHED; + } - MEM_freeN(fly); - return OPERATOR_CANCELLED; + MEM_freeN(fly); + return OPERATOR_CANCELLED; } static void flyEvent(bContext *C, wmOperator *op, FlyInfo *fly, const wmEvent *event) { - if (event->type == TIMER && event->customdata == fly->timer) { - fly->redraw = 1; - } - else if (event->type == MOUSEMOVE) { - copy_v2_v2_int(fly->mval, event->mval); - } + if (event->type == TIMER && event->customdata == fly->timer) { + fly->redraw = 1; + } + else if (event->type == MOUSEMOVE) { + copy_v2_v2_int(fly->mval, event->mval); + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - /* do these automagically get delivered? yes. */ - // puts("ndof motion detected in fly mode!"); - // static const char *tag_name = "3D mouse position"; - - const wmNDOFMotionData *incoming_ndof = event->customdata; - switch (incoming_ndof->progress) { - case P_STARTING: - /* start keeping track of 3D mouse position */ + else if (event->type == NDOF_MOTION) { + /* do these automagically get delivered? yes. */ + // puts("ndof motion detected in fly mode!"); + // static const char *tag_name = "3D mouse position"; + + const wmNDOFMotionData *incoming_ndof = event->customdata; + switch (incoming_ndof->progress) { + case P_STARTING: + /* start keeping track of 3D mouse position */ # ifdef NDOF_FLY_DEBUG - puts("start keeping track of 3D mouse position"); + puts("start keeping track of 3D mouse position"); # endif - /* fall-through */ - case P_IN_PROGRESS: - /* update 3D mouse position */ + /* fall-through */ + case P_IN_PROGRESS: + /* update 3D mouse position */ # ifdef NDOF_FLY_DEBUG - putchar('.'); fflush(stdout); + putchar('.'); + fflush(stdout); # endif - if (fly->ndof == NULL) { - // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); - fly->ndof = MEM_dupallocN(incoming_ndof); - // fly->ndof = malloc(sizeof(wmNDOFMotionData)); - } - else { - memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); - } - break; - case P_FINISHING: - /* stop keeping track of 3D mouse position */ + if (fly->ndof == NULL) { + // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); + fly->ndof = MEM_dupallocN(incoming_ndof); + // fly->ndof = malloc(sizeof(wmNDOFMotionData)); + } + else { + memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + } + break; + case P_FINISHING: + /* stop keeping track of 3D mouse position */ # ifdef NDOF_FLY_DEBUG - puts("stop keeping track of 3D mouse position"); + puts("stop keeping track of 3D mouse position"); # endif - if (fly->ndof) { - MEM_freeN(fly->ndof); - // free(fly->ndof); - fly->ndof = NULL; - } - /* update the time else the view will jump when 2D mouse/timer resume */ - fly->time_lastdraw = PIL_check_seconds_timer(); - break; - default: - break; /* should always be one of the above 3 */ - } - } + if (fly->ndof) { + MEM_freeN(fly->ndof); + // free(fly->ndof); + fly->ndof = NULL; + } + /* update the time else the view will jump when 2D mouse/timer resume */ + fly->time_lastdraw = PIL_check_seconds_timer(); + break; + default: + break; /* should always be one of the above 3 */ + } + } #endif /* WITH_INPUT_NDOF */ - /* handle modal keymap first */ - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case FLY_MODAL_CANCEL: - fly->state = FLY_CANCEL; - break; - case FLY_MODAL_CONFIRM: - fly->state = FLY_CONFIRM; - break; - - /* speed adjusting with mousepan (trackpad) */ - case FLY_MODAL_SPEED: - { - float fac = 0.02f * (event->prevy - event->y); - - /* allowing to brake immediate */ - if (fac > 0.0f && fly->speed < 0.0f) { - fly->speed = 0.0f; - } - else if (fac < 0.0f && fly->speed > 0.0f) { - fly->speed = 0.0f; - } - else { - fly->speed += fly->grid * fac; - } - - break; - } - case FLY_MODAL_ACCELERATE: - { - double time_currwheel; - float time_wheel; - - /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ - if (fly->axis == -1) { - fly->axis = 2; - fly->speed = fabsf(fly->speed); - } - - time_currwheel = PIL_check_seconds_timer(); - time_wheel = (float)(time_currwheel - fly->time_lastwheel); - fly->time_lastwheel = time_currwheel; - /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */ - /* 0-0.5 -> 0-5.0 */ - time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); - - if (fly->speed < 0.0f) { - fly->speed = 0.0f; - } - else { - fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); - } - break; - } - case FLY_MODAL_DECELERATE: - { - double time_currwheel; - float time_wheel; - - /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ - if (fly->axis == -1) { - fly->axis = 2; - fly->speed = -fabsf(fly->speed); - } - - time_currwheel = PIL_check_seconds_timer(); - time_wheel = (float)(time_currwheel - fly->time_lastwheel); - fly->time_lastwheel = time_currwheel; - /* 0-0.5 -> 0-5.0 */ - time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); - - if (fly->speed > 0.0f) { - fly->speed = 0; - } - else { - fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); - } - break; - } - case FLY_MODAL_PAN_ENABLE: - fly->pan_view = true; - break; - case FLY_MODAL_PAN_DISABLE: - fly->pan_view = false; - break; - - /* implement WASD keys, - * comments only for 'forward '*/ - case FLY_MODAL_DIR_FORWARD: - if (fly->axis == 2 && fly->speed < 0.0f) { - /* reverse direction stops, tap again to continue */ - fly->axis = -1; - } - else { - /* flip speed rather than stopping, game like motion, - * else increase like mousewheel if were already moving in that direction */ - if (fly->speed < 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 2) { - fly->speed += fly->grid; - } - fly->axis = 2; - } - break; - case FLY_MODAL_DIR_BACKWARD: - if (fly->axis == 2 && fly->speed > 0.0f) { - fly->axis = -1; - } - else { - if (fly->speed > 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 2) { - fly->speed -= fly->grid; - } - - fly->axis = 2; - } - break; - case FLY_MODAL_DIR_LEFT: - if (fly->axis == 0 && fly->speed < 0.0f) { - fly->axis = -1; - } - else { - if (fly->speed < 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 0) { - fly->speed += fly->grid; - } - - fly->axis = 0; - } - break; - case FLY_MODAL_DIR_RIGHT: - if (fly->axis == 0 && fly->speed > 0.0f) { - fly->axis = -1; - } - else { - if (fly->speed > 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 0) { - fly->speed -= fly->grid; - } - - fly->axis = 0; - } - break; - case FLY_MODAL_DIR_DOWN: - if (fly->axis == 1 && fly->speed < 0.0f) { - fly->axis = -1; - } - else { - if (fly->speed < 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 1) { - fly->speed += fly->grid; - } - fly->axis = 1; - } - break; - case FLY_MODAL_DIR_UP: - if (fly->axis == 1 && fly->speed > 0.0f) { - fly->axis = -1; - } - else { - if (fly->speed > 0.0f) { - fly->speed = -fly->speed; - } - else if (fly->axis == 1) { - fly->speed -= fly->grid; - } - fly->axis = 1; - } - break; - - case FLY_MODAL_AXIS_LOCK_X: - if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { - fly->xlock = FLY_AXISLOCK_STATE_OFF; - } - else { - fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; - fly->xlock_momentum = 0.0; - } - fly_update_header(C, op, fly); - break; - case FLY_MODAL_AXIS_LOCK_Z: - if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { - fly->zlock = FLY_AXISLOCK_STATE_OFF; - } - else { - fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; - fly->zlock_momentum = 0.0; - } - fly_update_header(C, op, fly); - break; - - case FLY_MODAL_PRECISION_ENABLE: - fly->use_precision = true; - break; - case FLY_MODAL_PRECISION_DISABLE: - fly->use_precision = false; - break; - - case FLY_MODAL_FREELOOK_ENABLE: - fly->use_freelook = true; - break; - case FLY_MODAL_FREELOOK_DISABLE: - fly->use_freelook = false; - break; - } - } + /* handle modal keymap first */ + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case FLY_MODAL_CANCEL: + fly->state = FLY_CANCEL; + break; + case FLY_MODAL_CONFIRM: + fly->state = FLY_CONFIRM; + break; + + /* speed adjusting with mousepan (trackpad) */ + case FLY_MODAL_SPEED: { + float fac = 0.02f * (event->prevy - event->y); + + /* allowing to brake immediate */ + if (fac > 0.0f && fly->speed < 0.0f) { + fly->speed = 0.0f; + } + else if (fac < 0.0f && fly->speed > 0.0f) { + fly->speed = 0.0f; + } + else { + fly->speed += fly->grid * fac; + } + + break; + } + case FLY_MODAL_ACCELERATE: { + double time_currwheel; + float time_wheel; + + /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ + if (fly->axis == -1) { + fly->axis = 2; + fly->speed = fabsf(fly->speed); + } + + time_currwheel = PIL_check_seconds_timer(); + time_wheel = (float)(time_currwheel - fly->time_lastwheel); + fly->time_lastwheel = time_currwheel; + /* Mouse wheel delays range from (0.5 == slow) to (0.01 == fast) */ + /* 0-0.5 -> 0-5.0 */ + time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); + + if (fly->speed < 0.0f) { + fly->speed = 0.0f; + } + else { + fly->speed += fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); + } + break; + } + case FLY_MODAL_DECELERATE: { + double time_currwheel; + float time_wheel; + + /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ + if (fly->axis == -1) { + fly->axis = 2; + fly->speed = -fabsf(fly->speed); + } + + time_currwheel = PIL_check_seconds_timer(); + time_wheel = (float)(time_currwheel - fly->time_lastwheel); + fly->time_lastwheel = time_currwheel; + /* 0-0.5 -> 0-5.0 */ + time_wheel = 1.0f + (10.0f - (20.0f * min_ff(time_wheel, 0.5f))); + + if (fly->speed > 0.0f) { + fly->speed = 0; + } + else { + fly->speed -= fly->grid * time_wheel * (fly->use_precision ? 0.1f : 1.0f); + } + break; + } + case FLY_MODAL_PAN_ENABLE: + fly->pan_view = true; + break; + case FLY_MODAL_PAN_DISABLE: + fly->pan_view = false; + break; + + /* implement WASD keys, + * comments only for 'forward '*/ + case FLY_MODAL_DIR_FORWARD: + if (fly->axis == 2 && fly->speed < 0.0f) { + /* reverse direction stops, tap again to continue */ + fly->axis = -1; + } + else { + /* flip speed rather than stopping, game like motion, + * else increase like mousewheel if were already moving in that direction */ + if (fly->speed < 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 2) { + fly->speed += fly->grid; + } + fly->axis = 2; + } + break; + case FLY_MODAL_DIR_BACKWARD: + if (fly->axis == 2 && fly->speed > 0.0f) { + fly->axis = -1; + } + else { + if (fly->speed > 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 2) { + fly->speed -= fly->grid; + } + + fly->axis = 2; + } + break; + case FLY_MODAL_DIR_LEFT: + if (fly->axis == 0 && fly->speed < 0.0f) { + fly->axis = -1; + } + else { + if (fly->speed < 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 0) { + fly->speed += fly->grid; + } + + fly->axis = 0; + } + break; + case FLY_MODAL_DIR_RIGHT: + if (fly->axis == 0 && fly->speed > 0.0f) { + fly->axis = -1; + } + else { + if (fly->speed > 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 0) { + fly->speed -= fly->grid; + } + + fly->axis = 0; + } + break; + case FLY_MODAL_DIR_DOWN: + if (fly->axis == 1 && fly->speed < 0.0f) { + fly->axis = -1; + } + else { + if (fly->speed < 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 1) { + fly->speed += fly->grid; + } + fly->axis = 1; + } + break; + case FLY_MODAL_DIR_UP: + if (fly->axis == 1 && fly->speed > 0.0f) { + fly->axis = -1; + } + else { + if (fly->speed > 0.0f) { + fly->speed = -fly->speed; + } + else if (fly->axis == 1) { + fly->speed -= fly->grid; + } + fly->axis = 1; + } + break; + + case FLY_MODAL_AXIS_LOCK_X: + if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { + fly->xlock = FLY_AXISLOCK_STATE_OFF; + } + else { + fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; + fly->xlock_momentum = 0.0; + } + fly_update_header(C, op, fly); + break; + case FLY_MODAL_AXIS_LOCK_Z: + if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { + fly->zlock = FLY_AXISLOCK_STATE_OFF; + } + else { + fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; + fly->zlock_momentum = 0.0; + } + fly_update_header(C, op, fly); + break; + + case FLY_MODAL_PRECISION_ENABLE: + fly->use_precision = true; + break; + case FLY_MODAL_PRECISION_DISABLE: + fly->use_precision = false; + break; + + case FLY_MODAL_FREELOOK_ENABLE: + fly->use_freelook = true; + break; + case FLY_MODAL_FREELOOK_DISABLE: + fly->use_freelook = false; + break; + } + } } -static void flyMoveCamera(bContext *C, FlyInfo *fly, - const bool do_rotate, const bool do_translate) +static void flyMoveCamera(bContext *C, FlyInfo *fly, const bool do_rotate, const bool do_translate) { - ED_view3d_cameracontrol_update(fly->v3d_camera_control, true, C, do_rotate, do_translate); + ED_view3d_cameracontrol_update(fly->v3d_camera_control, true, C, do_rotate, do_translate); } static int flyApply(bContext *C, FlyInfo *fly) { -#define FLY_ROTATE_FAC 10.0f /* more is faster */ -#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */ +#define FLY_ROTATE_FAC 10.0f /* more is faster */ +#define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */ #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */ -#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */ +#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */ - /* fly mode - Shift+F - * a fly loop where the user can move move the view as if they are flying - */ - RegionView3D *rv3d = fly->rv3d; + /* fly mode - Shift+F + * a fly loop where the user can move move the view as if they are flying + */ + RegionView3D *rv3d = fly->rv3d; - /* 3x3 copy of the view matrix so we can move along the view axis */ - float mat[3][3]; - /* this is the direction that's added to the view offset per redraw */ - float dvec[3] = {0, 0, 0}; + /* 3x3 copy of the view matrix so we can move along the view axis */ + float mat[3][3]; + /* this is the direction that's added to the view offset per redraw */ + float dvec[3] = {0, 0, 0}; - /* Camera Uprighting variables */ - float moffset[2]; /* mouse offset from the views center */ - float tmp_quat[4]; /* used for rotating the view */ + /* Camera Uprighting variables */ + float moffset[2]; /* mouse offset from the views center */ + float tmp_quat[4]; /* used for rotating the view */ - /* x and y margin are define the safe area where the mouses movement wont rotate the view */ - int xmargin, ymargin; + /* x and y margin are define the safe area where the mouses movement wont rotate the view */ + int xmargin, ymargin; #ifdef NDOF_FLY_DEBUG - { - static uint iteration = 1; - printf("fly timer %d\n", iteration++); - } + { + static uint iteration = 1; + printf("fly timer %d\n", iteration++); + } #endif - xmargin = fly->width / 20.0f; - ymargin = fly->height / 20.0f; - - { - - /* mouse offset from the center */ - moffset[0] = fly->mval[0] - fly->center_mval[0]; - moffset[1] = fly->mval[1] - fly->center_mval[1]; - - /* enforce a view margin */ - if (moffset[0] > xmargin) { - moffset[0] -= xmargin; - } - else if (moffset[0] < -xmargin) { - moffset[0] += xmargin; - } - else { - moffset[0] = 0; - } - - if (moffset[1] > ymargin) { - moffset[1] -= ymargin; - } - else if (moffset[1] < -ymargin) { - moffset[1] += ymargin; - } - else { - moffset[1] = 0; - } - - - /* scale the mouse movement by this value - scales mouse movement to the view size - * moffset[0] / (ar->winx-xmargin * 2) - window size minus margin (same for y) - * - * the mouse moves isn't linear */ - - if (moffset[0]) { - moffset[0] /= fly->width - (xmargin * 2); - moffset[0] *= fabsf(moffset[0]); - } - - if (moffset[1]) { - moffset[1] /= fly->height - (ymargin * 2); - moffset[1] *= fabsf(moffset[1]); - } - - /* Should we redraw? */ - if ((fly->speed != 0.0f) || - moffset[0] || moffset[1] || - (fly->zlock != FLY_AXISLOCK_STATE_OFF) || - (fly->xlock != FLY_AXISLOCK_STATE_OFF) || - dvec[0] || dvec[1] || dvec[2]) - { - float dvec_tmp[3]; - - /* time how fast it takes for us to redraw, - * this is so simple scenes don't fly too fast */ - double time_current; - float time_redraw; - float time_redraw_clamped; + xmargin = fly->width / 20.0f; + ymargin = fly->height / 20.0f; + + { + + /* mouse offset from the center */ + moffset[0] = fly->mval[0] - fly->center_mval[0]; + moffset[1] = fly->mval[1] - fly->center_mval[1]; + + /* enforce a view margin */ + if (moffset[0] > xmargin) { + moffset[0] -= xmargin; + } + else if (moffset[0] < -xmargin) { + moffset[0] += xmargin; + } + else { + moffset[0] = 0; + } + + if (moffset[1] > ymargin) { + moffset[1] -= ymargin; + } + else if (moffset[1] < -ymargin) { + moffset[1] += ymargin; + } + else { + moffset[1] = 0; + } + + /* scale the mouse movement by this value - scales mouse movement to the view size + * moffset[0] / (ar->winx-xmargin * 2) - window size minus margin (same for y) + * + * the mouse moves isn't linear */ + + if (moffset[0]) { + moffset[0] /= fly->width - (xmargin * 2); + moffset[0] *= fabsf(moffset[0]); + } + + if (moffset[1]) { + moffset[1] /= fly->height - (ymargin * 2); + moffset[1] *= fabsf(moffset[1]); + } + + /* Should we redraw? */ + if ((fly->speed != 0.0f) || moffset[0] || moffset[1] || + (fly->zlock != FLY_AXISLOCK_STATE_OFF) || (fly->xlock != FLY_AXISLOCK_STATE_OFF) || + dvec[0] || dvec[1] || dvec[2]) { + float dvec_tmp[3]; + + /* time how fast it takes for us to redraw, + * this is so simple scenes don't fly too fast */ + double time_current; + float time_redraw; + float time_redraw_clamped; #ifdef NDOF_FLY_DRAW_TOOMUCH - fly->redraw = 1; + fly->redraw = 1; #endif - time_current = PIL_check_seconds_timer(); - time_redraw = (float)(time_current - fly->time_lastdraw); - - /* clamp redraw time to avoid jitter in roll correction */ - time_redraw_clamped = min_ff(0.05f, time_redraw); - - fly->time_lastdraw = time_current; - - /* Scale the time to use shift to scale the speed down- just like - * shift slows many other areas of blender down */ - if (fly->use_precision) { - fly->speed = fly->speed * (1.0f - time_redraw_clamped); - } - - copy_m3_m4(mat, rv3d->viewinv); - - if (fly->pan_view == true) { - /* pan only */ - copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f); - - if (fly->use_precision) { - dvec_tmp[0] *= 0.1f; - dvec_tmp[1] *= 0.1f; - } - - mul_m3_v3(mat, dvec_tmp); - mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid); - } - else { - float roll; /* similar to the angle between the camera's up and the Z-up, - * but its very rough so just roll */ - - /* rotate about the X axis- look up/down */ - if (moffset[1]) { - float upvec[3]; - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - - if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { - fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */ - } - if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { - fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; - } - fly->xlock_momentum = 0.0f; - } - - /* rotate about the Y axis- look left/right */ - if (moffset[0]) { - float upvec[3]; - /* if we're upside down invert the moffset */ - copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); - mul_m3_v3(mat, upvec); - - if (upvec[2] < 0.0f) { - moffset[0] = -moffset[0]; - } - - /* make the lock vectors */ - if (fly->zlock) { - copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); - } - else { - copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); - mul_m3_v3(mat, upvec); - } - - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - - if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { - fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */ - } - if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { - fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; - } - } - - if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) { - float upvec[3]; - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - mul_m3_v3(mat, upvec); - - /* make sure we have some z rolling */ - if (fabsf(upvec[2]) > 0.00001f) { - roll = upvec[2] * 5.0f; - /* rotate the view about this axis */ - copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); - mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, - roll * time_redraw_clamped * fly->zlock_momentum * FLY_ZUP_CORRECT_FAC); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - - fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL; - } - else { - /* don't check until the view rotates again */ - fly->zlock = FLY_AXISLOCK_STATE_IDLE; - fly->zlock_momentum = 0.0f; - } - } - - /* only apply xcorrect when mouse isn't applying x rot */ - if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) { - float upvec[3]; - copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); - mul_m3_v3(mat, upvec); - /* make sure we have some z rolling */ - if (fabsf(upvec[2]) > 0.00001f) { - roll = upvec[2] * -5.0f; - /* rotate the view about this axis */ - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - mul_m3_v3(mat, upvec); - - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - - fly->xlock_momentum += 0.05f; - } - else { - fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */ - fly->xlock_momentum = 0.0f; - } - } - - if (fly->axis == -1) { - /* pause */ - zero_v3(dvec_tmp); - } - else if (!fly->use_freelook) { - /* Normal operation */ - /* define dvec, view direction vector */ - zero_v3(dvec_tmp); - /* move along the current axis */ - dvec_tmp[fly->axis] = 1.0f; - - mul_m3_v3(mat, dvec_tmp); - } - else { - normalize_v3_v3(dvec_tmp, fly->dvec_prev); - if (fly->speed < 0.0f) { - negate_v3(dvec_tmp); - } - } - - mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f); - } - - /* impose a directional lag */ - interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC)))); - - if (rv3d->persp == RV3D_CAMOB) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); - if (lock_ob->protectflag & OB_LOCK_LOCX) { - dvec[0] = 0.0; - } - if (lock_ob->protectflag & OB_LOCK_LOCY) { - dvec[1] = 0.0; - } - if (lock_ob->protectflag & OB_LOCK_LOCZ) { - dvec[2] = 0.0; - } - } - - add_v3_v3(rv3d->ofs, dvec); - - if (rv3d->persp == RV3D_CAMOB) { - const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) || - (fly->zlock != FLY_AXISLOCK_STATE_OFF) || - ((moffset[0] || moffset[1]) && !fly->pan_view)); - const bool do_translate = (fly->speed != 0.0f || fly->pan_view); - flyMoveCamera(C, fly, do_rotate, do_translate); - } - - } - else { - /* we're not redrawing but we need to update the time else the view will jump */ - fly->time_lastdraw = PIL_check_seconds_timer(); - } - /* end drawing */ - copy_v3_v3(fly->dvec_prev, dvec); - } - - return OPERATOR_FINISHED; + time_current = PIL_check_seconds_timer(); + time_redraw = (float)(time_current - fly->time_lastdraw); + + /* clamp redraw time to avoid jitter in roll correction */ + time_redraw_clamped = min_ff(0.05f, time_redraw); + + fly->time_lastdraw = time_current; + + /* Scale the time to use shift to scale the speed down- just like + * shift slows many other areas of blender down */ + if (fly->use_precision) { + fly->speed = fly->speed * (1.0f - time_redraw_clamped); + } + + copy_m3_m4(mat, rv3d->viewinv); + + if (fly->pan_view == true) { + /* pan only */ + copy_v3_fl3(dvec_tmp, -moffset[0], -moffset[1], 0.0f); + + if (fly->use_precision) { + dvec_tmp[0] *= 0.1f; + dvec_tmp[1] *= 0.1f; + } + + mul_m3_v3(mat, dvec_tmp); + mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid); + } + else { + float roll; /* similar to the angle between the camera's up and the Z-up, + * but its very rough so just roll */ + + /* rotate about the X axis- look up/down */ + if (moffset[1]) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, moffset[1] * time_redraw * -FLY_ROTATE_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { + fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */ + } + if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { + fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; + } + fly->xlock_momentum = 0.0f; + } + + /* rotate about the Y axis- look left/right */ + if (moffset[0]) { + float upvec[3]; + /* if we're upside down invert the moffset */ + copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); + mul_m3_v3(mat, upvec); + + if (upvec[2] < 0.0f) { + moffset[0] = -moffset[0]; + } + + /* make the lock vectors */ + if (fly->zlock) { + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + } + else { + copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); + mul_m3_v3(mat, upvec); + } + + /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, moffset[0] * time_redraw * FLY_ROTATE_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + if (fly->xlock != FLY_AXISLOCK_STATE_OFF) { + fly->xlock = FLY_AXISLOCK_STATE_ACTIVE; /* check for rotation */ + } + if (fly->zlock != FLY_AXISLOCK_STATE_OFF) { + fly->zlock = FLY_AXISLOCK_STATE_ACTIVE; + } + } + + if (fly->zlock == FLY_AXISLOCK_STATE_ACTIVE) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* make sure we have some z rolling */ + if (fabsf(upvec[2]) > 0.00001f) { + roll = upvec[2] * 5.0f; + /* rotate the view about this axis */ + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, + upvec, + roll * time_redraw_clamped * fly->zlock_momentum * + FLY_ZUP_CORRECT_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL; + } + else { + /* don't check until the view rotates again */ + fly->zlock = FLY_AXISLOCK_STATE_IDLE; + fly->zlock_momentum = 0.0f; + } + } + + /* only apply xcorrect when mouse isn't applying x rot */ + if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) { + float upvec[3]; + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* make sure we have some z rolling */ + if (fabsf(upvec[2]) > 0.00001f) { + roll = upvec[2] * -5.0f; + /* rotate the view about this axis */ + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* Rotate about the relative up vec */ + axis_angle_to_quat( + tmp_quat, upvec, roll * time_redraw_clamped * fly->xlock_momentum * 0.1f); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + fly->xlock_momentum += 0.05f; + } + else { + fly->xlock = FLY_AXISLOCK_STATE_IDLE; /* see above */ + fly->xlock_momentum = 0.0f; + } + } + + if (fly->axis == -1) { + /* pause */ + zero_v3(dvec_tmp); + } + else if (!fly->use_freelook) { + /* Normal operation */ + /* define dvec, view direction vector */ + zero_v3(dvec_tmp); + /* move along the current axis */ + dvec_tmp[fly->axis] = 1.0f; + + mul_m3_v3(mat, dvec_tmp); + } + else { + normalize_v3_v3(dvec_tmp, fly->dvec_prev); + if (fly->speed < 0.0f) { + negate_v3(dvec_tmp); + } + } + + mul_v3_fl(dvec_tmp, fly->speed * time_redraw * 0.25f); + } + + /* impose a directional lag */ + interp_v3_v3v3( + dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC)))); + + if (rv3d->persp == RV3D_CAMOB) { + Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); + if (lock_ob->protectflag & OB_LOCK_LOCX) { + dvec[0] = 0.0; + } + if (lock_ob->protectflag & OB_LOCK_LOCY) { + dvec[1] = 0.0; + } + if (lock_ob->protectflag & OB_LOCK_LOCZ) { + dvec[2] = 0.0; + } + } + + add_v3_v3(rv3d->ofs, dvec); + + if (rv3d->persp == RV3D_CAMOB) { + const bool do_rotate = ((fly->xlock != FLY_AXISLOCK_STATE_OFF) || + (fly->zlock != FLY_AXISLOCK_STATE_OFF) || + ((moffset[0] || moffset[1]) && !fly->pan_view)); + const bool do_translate = (fly->speed != 0.0f || fly->pan_view); + flyMoveCamera(C, fly, do_rotate, do_translate); + } + } + else { + /* we're not redrawing but we need to update the time else the view will jump */ + fly->time_lastdraw = PIL_check_seconds_timer(); + } + /* end drawing */ + copy_v3_v3(fly->dvec_prev, dvec); + } + + return OPERATOR_FINISHED; } #ifdef WITH_INPUT_NDOF static void flyApply_ndof(bContext *C, FlyInfo *fly) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); - bool has_translate, has_rotate; - - view3d_ndof_fly(fly->ndof, - fly->v3d, fly->rv3d, - fly->use_precision, lock_ob ? lock_ob->protectflag : 0, - &has_translate, &has_rotate); - - if (has_translate || has_rotate) { - fly->redraw = true; - - if (fly->rv3d->persp == RV3D_CAMOB) { - flyMoveCamera(C, fly, has_rotate, has_translate); - } - } + Object *lock_ob = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); + bool has_translate, has_rotate; + + view3d_ndof_fly(fly->ndof, + fly->v3d, + fly->rv3d, + fly->use_precision, + lock_ob ? lock_ob->protectflag : 0, + &has_translate, + &has_rotate); + + if (has_translate || has_rotate) { + fly->redraw = true; + + if (fly->rv3d->persp == RV3D_CAMOB) { + flyMoveCamera(C, fly, has_rotate, has_translate); + } + } } #endif /* WITH_INPUT_NDOF */ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - FlyInfo *fly; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + FlyInfo *fly; - if (rv3d->viewlock & RV3D_LOCKED) { - return OPERATOR_CANCELLED; - } + if (rv3d->viewlock & RV3D_LOCKED) { + return OPERATOR_CANCELLED; + } - fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation"); + fly = MEM_callocN(sizeof(FlyInfo), "FlyOperation"); - op->customdata = fly; + op->customdata = fly; - if (initFlyInfo(C, fly, op, event) == false) { - MEM_freeN(op->customdata); - return OPERATOR_CANCELLED; - } + if (initFlyInfo(C, fly, op, event) == false) { + MEM_freeN(op->customdata); + return OPERATOR_CANCELLED; + } - flyEvent(C, op, fly, event); + flyEvent(C, op, fly, event); - WM_event_add_modal_handler(C, op); + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static void fly_cancel(bContext *C, wmOperator *op) { - FlyInfo *fly = op->customdata; + FlyInfo *fly = op->customdata; - fly->state = FLY_CANCEL; - flyEnd(C, fly); - op->customdata = NULL; + fly->state = FLY_CANCEL; + flyEnd(C, fly); + op->customdata = NULL; } static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event) { - int exit_code; - bool do_draw = false; - FlyInfo *fly = op->customdata; - RegionView3D *rv3d = fly->rv3d; - Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); + int exit_code; + bool do_draw = false; + FlyInfo *fly = op->customdata; + RegionView3D *rv3d = fly->rv3d; + Object *fly_object = ED_view3d_cameracontrol_object_get(fly->v3d_camera_control); - fly->redraw = 0; + fly->redraw = 0; - flyEvent(C, op, fly, event); + flyEvent(C, op, fly, event); #ifdef WITH_INPUT_NDOF - if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ - if (event->type == NDOF_MOTION) { - flyApply_ndof(C, fly); - } - } - else + if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ + if (event->type == NDOF_MOTION) { + flyApply_ndof(C, fly); + } + } + else #endif /* WITH_INPUT_NDOF */ - if (event->type == TIMER && event->customdata == fly->timer) { - flyApply(C, fly); - } + if (event->type == TIMER && event->customdata == fly->timer) { + flyApply(C, fly); + } - do_draw |= fly->redraw; + do_draw |= fly->redraw; - exit_code = flyEnd(C, fly); + exit_code = flyEnd(C, fly); - if (exit_code != OPERATOR_RUNNING_MODAL) { - do_draw = true; - } + if (exit_code != OPERATOR_RUNNING_MODAL) { + do_draw = true; + } - if (do_draw) { - if (rv3d->persp == RV3D_CAMOB) { - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, fly_object); - } + if (do_draw) { + if (rv3d->persp == RV3D_CAMOB) { + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, fly_object); + } - // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now - ED_region_tag_redraw(CTX_wm_region(C)); - } + // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now + ED_region_tag_redraw(CTX_wm_region(C)); + } - if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { - ED_workspace_status_text(C, NULL); - } + if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { + ED_workspace_status_text(C, NULL); + } - return exit_code; + return exit_code; } void VIEW3D_OT_fly(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Fly Navigation"; - ot->description = "Interactively fly around the scene"; - ot->idname = "VIEW3D_OT_fly"; - - /* api callbacks */ - ot->invoke = fly_invoke; - ot->cancel = fly_cancel; - ot->modal = fly_modal; - ot->poll = ED_operator_region_view3d_active; - - /* flags */ - ot->flag = OPTYPE_BLOCKING; + /* identifiers */ + ot->name = "Fly Navigation"; + ot->description = "Interactively fly around the scene"; + ot->idname = "VIEW3D_OT_fly"; + + /* api callbacks */ + ot->invoke = fly_invoke; + ot->cancel = fly_cancel; + ot->modal = fly_modal; + ot->poll = ED_operator_region_view3d_active; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_armature.c b/source/blender/editors/space_view3d/view3d_gizmo_armature.c index 64617b03c5e..ae186505456 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_armature.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_armature.c @@ -43,8 +43,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "view3d_intern.h" /* own include */ - +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Armature Spline Gizmo @@ -63,166 +62,165 @@ #define BBONE_SCALE_Y 3.0f struct BoneSplineHandle { - wmGizmo *gizmo; - bPoseChannel *pchan; - /* We could remove, keep since at the moment for checking the conversion. */ - float co[3]; - int index; + wmGizmo *gizmo; + bPoseChannel *pchan; + /* We could remove, keep since at the moment for checking the conversion. */ + float co[3]; + int index; }; struct BoneSplineWidgetGroup { - struct BoneSplineHandle handles[2]; + struct BoneSplineHandle handles[2]; }; -static void gizmo_bbone_offset_get( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - void *value_p) +static void gizmo_bbone_offset_get(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) { - struct BoneSplineHandle *bh = gz_prop->custom_func.user_data; - bPoseChannel *pchan = bh->pchan; - - float *value = value_p; - BLI_assert(gz_prop->type->array_length == 3); - - if (bh->index == 0) { - bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y; - bh->co[0] = pchan->curveInX; - bh->co[2] = pchan->curveInY; - } - else { - bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y; - bh->co[0] = pchan->curveOutX; - bh->co[2] = pchan->curveOutY; - } - copy_v3_v3(value, bh->co); + struct BoneSplineHandle *bh = gz_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + float *value = value_p; + BLI_assert(gz_prop->type->array_length == 3); + + if (bh->index == 0) { + bh->co[1] = pchan->bone->ease1 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveInX; + bh->co[2] = pchan->curveInY; + } + else { + bh->co[1] = -pchan->bone->ease2 / BBONE_SCALE_Y; + bh->co[0] = pchan->curveOutX; + bh->co[2] = pchan->curveOutY; + } + copy_v3_v3(value, bh->co); } -static void gizmo_bbone_offset_set( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - const void *value_p) +static void gizmo_bbone_offset_set(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) { - struct BoneSplineHandle *bh = gz_prop->custom_func.user_data; - bPoseChannel *pchan = bh->pchan; - - const float *value = value_p; - - BLI_assert(gz_prop->type->array_length == 3); - copy_v3_v3(bh->co, value); - - if (bh->index == 0) { - pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y); - pchan->curveInX = bh->co[0]; - pchan->curveInY = bh->co[2]; - } - else { - pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y); - pchan->curveOutX = bh->co[0]; - pchan->curveOutY = bh->co[2]; - } - + struct BoneSplineHandle *bh = gz_prop->custom_func.user_data; + bPoseChannel *pchan = bh->pchan; + + const float *value = value_p; + + BLI_assert(gz_prop->type->array_length == 3); + copy_v3_v3(bh->co, value); + + if (bh->index == 0) { + pchan->bone->ease1 = max_ff(0.0f, bh->co[1] * BBONE_SCALE_Y); + pchan->curveInX = bh->co[0]; + pchan->curveInY = bh->co[2]; + } + else { + pchan->bone->ease2 = max_ff(0.0f, -bh->co[1] * BBONE_SCALE_Y); + pchan->curveOutX = bh->co[0]; + pchan->curveOutY = bh->co[2]; + } } static bool WIDGETGROUP_armature_spline_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = BKE_object_pose_armature_get(base->object); - if (ob) { - const bArmature *arm = ob->data; - if (arm->drawtype == ARM_B_BONE) { - bPoseChannel *pchan = BKE_pose_channel_active(ob); - if (pchan && pchan->bone->segments > 1) { - return true; - } - } - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = BKE_object_pose_armature_get(base->object); + if (ob) { + const bArmature *arm = ob->data; + if (arm->drawtype == ARM_B_BONE) { + bPoseChannel *pchan = BKE_pose_channel_active(ob); + if (pchan && pchan->bone->segments > 1) { + return true; + } + } + } + } + return false; } - static void WIDGETGROUP_armature_spline_setup(const bContext *C, wmGizmoGroup *gzgroup) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); - bPoseChannel *pchan = BKE_pose_channel_active(ob); - - const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true); - - struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), __func__); - gzgroup->customdata = bspline_group; - - /* Handles */ - for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { - wmGizmo *gz; - gz = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL); - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D); - RNA_enum_set(gz->ptr, "draw_options", - ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW); - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true); - - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); - - gz->scale_basis = 0.06f; - - if (i == 0) { - copy_v3_v3(gz->matrix_basis[3], pchan->loc); - } - } + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + const wmGizmoType *gzt_move = WM_gizmotype_find("GIZMO_GT_move_3d", true); + + struct BoneSplineWidgetGroup *bspline_group = MEM_callocN(sizeof(struct BoneSplineWidgetGroup), + __func__); + gzgroup->customdata = bspline_group; + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmGizmo *gz; + gz = bspline_group->handles[i].gizmo = WM_gizmo_new_ptr(gzt_move, gzgroup, NULL); + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_RING_2D); + RNA_enum_set(gz->ptr, + "draw_options", + ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_VALUE, true); + + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + + gz->scale_basis = 0.06f; + + if (i == 0) { + copy_v3_v3(gz->matrix_basis[3], pchan->loc); + } + } } static void WIDGETGROUP_armature_spline_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); - - if (!gzgroup->customdata) { - return; - } - - struct BoneSplineWidgetGroup *bspline_group = gzgroup->customdata; - bPoseChannel *pchan = BKE_pose_channel_active(ob); - - /* Handles */ - for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { - wmGizmo *gz = bspline_group->handles[i].gizmo; - bspline_group->handles[i].pchan = pchan; - bspline_group->handles[i].index = i; - - float mat[4][4]; - mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); - copy_m4_m4(gz->matrix_space, mat); - - /* need to set property here for undo. TODO would prefer to do this in _init */ - WM_gizmo_target_property_def_func( - gz, "offset", - &(const struct wmGizmoPropertyFnParams) { - .value_get_fn = gizmo_bbone_offset_get, - .value_set_fn = gizmo_bbone_offset_set, - .range_get_fn = NULL, - .user_data = &bspline_group->handles[i], - }); - } + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = BKE_object_pose_armature_get(OBACT(view_layer)); + + if (!gzgroup->customdata) { + return; + } + + struct BoneSplineWidgetGroup *bspline_group = gzgroup->customdata; + bPoseChannel *pchan = BKE_pose_channel_active(ob); + + /* Handles */ + for (int i = 0; i < ARRAY_SIZE(bspline_group->handles); i++) { + wmGizmo *gz = bspline_group->handles[i].gizmo; + bspline_group->handles[i].pchan = pchan; + bspline_group->handles[i].index = i; + + float mat[4][4]; + mul_m4_m4m4(mat, ob->obmat, (i == 0) ? pchan->disp_mat : pchan->disp_tail_mat); + copy_m4_m4(gz->matrix_space, mat); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_gizmo_target_property_def_func(gz, + "offset", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_bbone_offset_get, + .value_set_fn = gizmo_bbone_offset_set, + .range_get_fn = NULL, + .user_data = &bspline_group->handles[i], + }); + } } void VIEW3D_GGT_armature_spline(wmGizmoGroupType *gzgt) { - gzgt->name = "Armature Spline Widgets"; - gzgt->idname = "VIEW3D_GGT_armature_spline"; + gzgt->name = "Armature Spline Widgets"; + gzgt->idname = "VIEW3D_GGT_armature_spline"; - gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D); + gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D); - gzgt->poll = WIDGETGROUP_armature_spline_poll; - gzgt->setup = WIDGETGROUP_armature_spline_setup; - gzgt->refresh = WIDGETGROUP_armature_spline_refresh; + gzgt->poll = WIDGETGROUP_armature_spline_poll; + gzgt->setup = WIDGETGROUP_armature_spline_setup; + gzgt->refresh = WIDGETGROUP_armature_spline_refresh; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c index 590597145a0..0b8c3b8cd28 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c @@ -18,7 +18,6 @@ * \ingroup spview3d */ - #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -45,276 +44,279 @@ #include "DEG_depsgraph.h" -#include "view3d_intern.h" /* own include */ - +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Camera Gizmos * \{ */ struct CameraWidgetGroup { - wmGizmo *dop_dist; - wmGizmo *focal_len; - wmGizmo *ortho_scale; + wmGizmo *dop_dist; + wmGizmo *focal_len; + wmGizmo *ortho_scale; }; static bool WIDGETGROUP_camera_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0 && - (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST) == 0) - { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->type == OB_CAMERA) { - Camera *camera = ob->data; - /* TODO: support overrides. */ - if (camera->id.lib == NULL) { - return true; - } - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0 && + (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->type == OB_CAMERA) { + Camera *camera = ob->data; + /* TODO: support overrides. */ + if (camera->id.lib == NULL) { + return true; + } + } + } + return false; } static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - float dir[3]; - - const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); - - struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__); - gzgroup->customdata = cagzgroup; - - negate_v3_v3(dir, ob->obmat[2]); - - /* dof distance */ - { - wmGizmo *gz; - gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS); - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); - - UI_GetThemeColor3fv(TH_GIZMO_A, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); - } - - /* focal length - * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */ - { - wmGizmo *gz; - gz = cagzgroup->focal_len = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); - gz->flag |= WM_GIZMO_DRAW_NO_SCALE; - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE); - RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); - - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); - - gz = cagzgroup->ortho_scale = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); - gz->flag |= WM_GIZMO_DRAW_NO_SCALE; - RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE); - RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); - - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); - } + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + float dir[3]; + + const wmGizmoType *gzt_arrow = WM_gizmotype_find("GIZMO_GT_arrow_3d", true); + + struct CameraWidgetGroup *cagzgroup = MEM_callocN(sizeof(struct CameraWidgetGroup), __func__); + gzgroup->customdata = cagzgroup; + + negate_v3_v3(dir, ob->obmat[2]); + + /* dof distance */ + { + wmGizmo *gz; + gz = cagzgroup->dop_dist = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CROSS); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + + UI_GetThemeColor3fv(TH_GIZMO_A, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + } + + /* focal length + * - logic/calculations are similar to BKE_camera_view_frame_ex, better keep in sync */ + { + wmGizmo *gz; + gz = cagzgroup->focal_len = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); + gz->flag |= WM_GIZMO_DRAW_NO_SCALE; + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE); + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); + + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + + gz = cagzgroup->ortho_scale = WM_gizmo_new_ptr(gzt_arrow, gzgroup, NULL); + gz->flag |= WM_GIZMO_DRAW_NO_SCALE; + RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_ARROW_STYLE_CONE); + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); + + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + } } static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - if (!gzgroup->customdata) { - return; - } - - struct CameraWidgetGroup *cagzgroup = gzgroup->customdata; - View3D *v3d = CTX_wm_view3d(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Camera *ca = ob->data; - PointerRNA camera_ptr; - float dir[3]; - - RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); - - negate_v3_v3(dir, ob->obmat[2]); - - if ((ca->flag & CAM_SHOWLIMITS) && - (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST)) - { - WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir); - WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); - WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); - - /* need to set property here for undo. TODO would prefer to do this in _init */ - WM_gizmo_target_property_def_rna(cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1); - } - else { - WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true); - } - - /* TODO - make focal length/ortho ob_scale_inv widget optional */ - const Scene *scene = CTX_data_scene(C); - const float aspx = (float)scene->r.xsch * scene->r.xasp; - const float aspy = (float)scene->r.ysch * scene->r.yasp; - const bool is_ortho = (ca->type == CAM_ORTHO); - const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy); - /* Important to use camera value, not calculated fit since 'AUTO' uses width always. */ - const float sensor_size = BKE_camera_sensor_size(ca->sensor_fit, ca->sensor_x, ca->sensor_y); - wmGizmo *widget = is_ortho ? cagzgroup->ortho_scale : cagzgroup->focal_len; - float scale_matrix; - if (true) { - float offset[3]; - float aspect[2]; - - WM_gizmo_set_flag(widget, WM_GIZMO_HIDDEN, false); - WM_gizmo_set_flag(is_ortho ? cagzgroup->focal_len : cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true); - - - /* account for lens shifting */ - offset[0] = ((ob->scale[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx; - offset[1] = 2.0f * ca->shifty; - offset[2] = 0.0f; - - /* get aspect */ - aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy; - aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f; - - unit_m4(widget->matrix_basis); - WM_gizmo_set_matrix_location(widget, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir); - - if (is_ortho) { - scale_matrix = ca->ortho_scale * 0.5f; - } - else { - const float ob_scale_inv[3] = { - 1.0f / len_v3(ob->obmat[0]), - 1.0f / len_v3(ob->obmat[1]), - 1.0f / len_v3(ob->obmat[2]), - }; - const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / 3.0f; - scale_matrix = (ca->drawsize * 0.5f) / ob_scale_uniform_inv; - } - mul_v3_fl(widget->matrix_basis[0], scale_matrix); - mul_v3_fl(widget->matrix_basis[1], scale_matrix); - - RNA_float_set_array(widget->ptr, "aspect", aspect); - - WM_gizmo_set_matrix_offset_location(widget, offset); - } - - /* define & update properties */ - { - const char *propname = is_ortho ? "ortho_scale" : "lens"; - PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname); - const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(widget->type, "offset"); - - WM_gizmo_target_property_clear_rna_ptr(widget, gz_prop_type); - - float min, max, range; - float step, precision; - - /* get property range */ - RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision); - range = max - min; - - ED_gizmo_arrow3d_set_range_fac( - widget, is_ortho ? - ((range / ca->ortho_scale) * ca->drawsize) : - (scale_matrix * range / - /* Half sensor, intentionally use sensor from camera and not calculated above. */ - (0.5f * sensor_size))); - - WM_gizmo_target_property_def_rna_ptr(widget, gz_prop_type, &camera_ptr, prop, -1); - } - - /* This could be handled more elegently (split into two gizmo groups). */ - if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0) { - WM_gizmo_set_flag(cagzgroup->focal_len, WM_GIZMO_HIDDEN, true); - WM_gizmo_set_flag(cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true); - } + if (!gzgroup->customdata) { + return; + } + + struct CameraWidgetGroup *cagzgroup = gzgroup->customdata; + View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Camera *ca = ob->data; + PointerRNA camera_ptr; + float dir[3]; + + RNA_pointer_create(&ca->id, &RNA_Camera, ca, &camera_ptr); + + negate_v3_v3(dir, ob->obmat[2]); + + if ((ca->flag & CAM_SHOWLIMITS) && (v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_DOF_DIST)) { + WM_gizmo_set_matrix_location(cagzgroup->dop_dist, ob->obmat[3]); + WM_gizmo_set_matrix_rotation_from_yz_axis(cagzgroup->dop_dist, ob->obmat[1], dir); + WM_gizmo_set_scale(cagzgroup->dop_dist, ca->drawsize); + WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, false); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_gizmo_target_property_def_rna( + cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1); + } + else { + WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true); + } + + /* TODO - make focal length/ortho ob_scale_inv widget optional */ + const Scene *scene = CTX_data_scene(C); + const float aspx = (float)scene->r.xsch * scene->r.xasp; + const float aspy = (float)scene->r.ysch * scene->r.yasp; + const bool is_ortho = (ca->type == CAM_ORTHO); + const int sensor_fit = BKE_camera_sensor_fit(ca->sensor_fit, aspx, aspy); + /* Important to use camera value, not calculated fit since 'AUTO' uses width always. */ + const float sensor_size = BKE_camera_sensor_size(ca->sensor_fit, ca->sensor_x, ca->sensor_y); + wmGizmo *widget = is_ortho ? cagzgroup->ortho_scale : cagzgroup->focal_len; + float scale_matrix; + if (true) { + float offset[3]; + float aspect[2]; + + WM_gizmo_set_flag(widget, WM_GIZMO_HIDDEN, false); + WM_gizmo_set_flag( + is_ortho ? cagzgroup->focal_len : cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true); + + /* account for lens shifting */ + offset[0] = ((ob->scale[0] > 0.0f) ? -2.0f : 2.0f) * ca->shiftx; + offset[1] = 2.0f * ca->shifty; + offset[2] = 0.0f; + + /* get aspect */ + aspect[0] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? 1.0f : aspx / aspy; + aspect[1] = (sensor_fit == CAMERA_SENSOR_FIT_HOR) ? aspy / aspx : 1.0f; + + unit_m4(widget->matrix_basis); + WM_gizmo_set_matrix_location(widget, ob->obmat[3]); + WM_gizmo_set_matrix_rotation_from_yz_axis(widget, ob->obmat[1], dir); + + if (is_ortho) { + scale_matrix = ca->ortho_scale * 0.5f; + } + else { + const float ob_scale_inv[3] = { + 1.0f / len_v3(ob->obmat[0]), + 1.0f / len_v3(ob->obmat[1]), + 1.0f / len_v3(ob->obmat[2]), + }; + const float ob_scale_uniform_inv = (ob_scale_inv[0] + ob_scale_inv[1] + ob_scale_inv[2]) / + 3.0f; + scale_matrix = (ca->drawsize * 0.5f) / ob_scale_uniform_inv; + } + mul_v3_fl(widget->matrix_basis[0], scale_matrix); + mul_v3_fl(widget->matrix_basis[1], scale_matrix); + + RNA_float_set_array(widget->ptr, "aspect", aspect); + + WM_gizmo_set_matrix_offset_location(widget, offset); + } + + /* define & update properties */ + { + const char *propname = is_ortho ? "ortho_scale" : "lens"; + PropertyRNA *prop = RNA_struct_find_property(&camera_ptr, propname); + const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(widget->type, + "offset"); + + WM_gizmo_target_property_clear_rna_ptr(widget, gz_prop_type); + + float min, max, range; + float step, precision; + + /* get property range */ + RNA_property_float_ui_range(&camera_ptr, prop, &min, &max, &step, &precision); + range = max - min; + + ED_gizmo_arrow3d_set_range_fac( + widget, + is_ortho ? + ((range / ca->ortho_scale) * ca->drawsize) : + (scale_matrix * range / + /* Half sensor, intentionally use sensor from camera and not calculated above. */ + (0.5f * sensor_size))); + + WM_gizmo_target_property_def_rna_ptr(widget, gz_prop_type, &camera_ptr, prop, -1); + } + + /* This could be handled more elegently (split into two gizmo groups). */ + if ((v3d->gizmo_show_camera & V3D_GIZMO_SHOW_CAMERA_LENS) == 0) { + WM_gizmo_set_flag(cagzgroup->focal_len, WM_GIZMO_HIDDEN, true); + WM_gizmo_set_flag(cagzgroup->ortho_scale, WM_GIZMO_HIDDEN, true); + } } -static void WIDGETGROUP_camera_message_subscribe( - const bContext *C, wmGizmoGroup *gzgroup, struct wmMsgBus *mbus) +static void WIDGETGROUP_camera_message_subscribe(const bContext *C, + wmGizmoGroup *gzgroup, + struct wmMsgBus *mbus) { - ARegion *ar = CTX_wm_region(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Camera *ca = ob->data; - - wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = { - .owner = ar, - .user_data = gzgroup->parent_gzmap, - .notify = WM_gizmo_do_msg_notify_tag_refresh, - }; - - { - extern PropertyRNA rna_Camera_dof_distance; - extern PropertyRNA rna_Camera_display_size; - extern PropertyRNA rna_Camera_ortho_scale; - extern PropertyRNA rna_Camera_sensor_fit; - extern PropertyRNA rna_Camera_sensor_width; - extern PropertyRNA rna_Camera_sensor_height; - extern PropertyRNA rna_Camera_shift_x; - extern PropertyRNA rna_Camera_shift_y; - extern PropertyRNA rna_Camera_type; - extern PropertyRNA rna_Camera_lens; - const PropertyRNA *props[] = { - &rna_Camera_dof_distance, - &rna_Camera_display_size, - &rna_Camera_ortho_scale, - &rna_Camera_sensor_fit, - &rna_Camera_sensor_width, - &rna_Camera_sensor_height, - &rna_Camera_shift_x, - &rna_Camera_shift_y, - &rna_Camera_type, - &rna_Camera_lens, - }; - - PointerRNA idptr; - RNA_id_pointer_create(&ca->id, &idptr); - - for (int i = 0; i < ARRAY_SIZE(props); i++) { - WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_gz_tag_refresh, __func__); - } - } - - /* Subscribe to render settings */ - { - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_gz_tag_refresh); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_gz_tag_refresh); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_gz_tag_refresh); - WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_gz_tag_refresh); - } + ARegion *ar = CTX_wm_region(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Camera *ca = ob->data; + + wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = { + .owner = ar, + .user_data = gzgroup->parent_gzmap, + .notify = WM_gizmo_do_msg_notify_tag_refresh, + }; + + { + extern PropertyRNA rna_Camera_dof_distance; + extern PropertyRNA rna_Camera_display_size; + extern PropertyRNA rna_Camera_ortho_scale; + extern PropertyRNA rna_Camera_sensor_fit; + extern PropertyRNA rna_Camera_sensor_width; + extern PropertyRNA rna_Camera_sensor_height; + extern PropertyRNA rna_Camera_shift_x; + extern PropertyRNA rna_Camera_shift_y; + extern PropertyRNA rna_Camera_type; + extern PropertyRNA rna_Camera_lens; + const PropertyRNA *props[] = { + &rna_Camera_dof_distance, + &rna_Camera_display_size, + &rna_Camera_ortho_scale, + &rna_Camera_sensor_fit, + &rna_Camera_sensor_width, + &rna_Camera_sensor_height, + &rna_Camera_shift_x, + &rna_Camera_shift_y, + &rna_Camera_type, + &rna_Camera_lens, + }; + + PointerRNA idptr; + RNA_id_pointer_create(&ca->id, &idptr); + + for (int i = 0; i < ARRAY_SIZE(props); i++) { + WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_gz_tag_refresh, __func__); + } + } + + /* Subscribe to render settings */ + { + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, resolution_x, &msg_sub_value_gz_tag_refresh); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, resolution_y, &msg_sub_value_gz_tag_refresh); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_gz_tag_refresh); + WM_msg_subscribe_rna_anon_prop( + mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_gz_tag_refresh); + } } void VIEW3D_GGT_camera(wmGizmoGroupType *gzgt) { - gzgt->name = "Camera Widgets"; - gzgt->idname = "VIEW3D_GGT_camera"; + gzgt->name = "Camera Widgets"; + gzgt->idname = "VIEW3D_GGT_camera"; - gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D | - WM_GIZMOGROUPTYPE_DEPTH_3D); + gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D); - gzgt->poll = WIDGETGROUP_camera_poll; - gzgt->setup = WIDGETGROUP_camera_setup; - gzgt->refresh = WIDGETGROUP_camera_refresh; - gzgt->message_subscribe = WIDGETGROUP_camera_message_subscribe; + gzgt->poll = WIDGETGROUP_camera_poll; + gzgt->setup = WIDGETGROUP_camera_setup; + gzgt->refresh = WIDGETGROUP_camera_refresh; + gzgt->message_subscribe = WIDGETGROUP_camera_message_subscribe; } /** \} */ @@ -324,177 +326,191 @@ void VIEW3D_GGT_camera(wmGizmoGroupType *gzgt) * \{ */ struct CameraViewWidgetGroup { - Scene *scene; - bool is_camera; + Scene *scene; + bool is_camera; - wmGizmo *border; + wmGizmo *border; - struct { - rctf *edit_border; - rctf view_border; - } state; + struct { + rctf *edit_border; + rctf view_border; + } state; }; /* scale callbacks */ -static void gizmo_render_border_prop_matrix_get( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - void *value_p) +static void gizmo_render_border_prop_matrix_get(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) { - float (*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data; - const rctf *border = viewgroup->state.edit_border; - - unit_m4(matrix); - matrix[0][0] = BLI_rctf_size_x(border); - matrix[1][1] = BLI_rctf_size_y(border); - matrix[3][0] = BLI_rctf_cent_x(border); - matrix[3][1] = BLI_rctf_cent_y(border); + float(*matrix)[4] = value_p; + BLI_assert(gz_prop->type->array_length == 16); + struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data; + const rctf *border = viewgroup->state.edit_border; + + unit_m4(matrix); + matrix[0][0] = BLI_rctf_size_x(border); + matrix[1][1] = BLI_rctf_size_y(border); + matrix[3][0] = BLI_rctf_cent_x(border); + matrix[3][1] = BLI_rctf_cent_y(border); } -static void gizmo_render_border_prop_matrix_set( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - const void *value_p) +static void gizmo_render_border_prop_matrix_set(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) { - const float (*matrix)[4] = value_p; - struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data; - rctf *border = viewgroup->state.edit_border; - BLI_assert(gz_prop->type->array_length == 16); - - BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1])); - BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]); - BLI_rctf_isect(&(rctf){ .xmin = 0, .ymin = 0, .xmax = 1, .ymax = 1, }, border, border); - - if (viewgroup->is_camera) { - DEG_id_tag_update(&viewgroup->scene->id, ID_RECALC_COPY_ON_WRITE); - } + const float(*matrix)[4] = value_p; + struct CameraViewWidgetGroup *viewgroup = gz_prop->custom_func.user_data; + rctf *border = viewgroup->state.edit_border; + BLI_assert(gz_prop->type->array_length == 16); + + BLI_rctf_resize(border, len_v3(matrix[0]), len_v3(matrix[1])); + BLI_rctf_recenter(border, matrix[3][0], matrix[3][1]); + BLI_rctf_isect( + &(rctf){ + .xmin = 0, + .ymin = 0, + .xmax = 1, + .ymax = 1, + }, + border, + border); + + if (viewgroup->is_camera) { + DEG_id_tag_update(&viewgroup->scene->id, ID_RECALC_COPY_ON_WRITE); + } } static bool WIDGETGROUP_camera_view_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - Scene *scene = CTX_data_scene(C); - - /* This is just so the border isn't always in the way, - * stealing mouse clicks from regular usage. - * We could change the rules for when to show. */ - { - ViewLayer *view_layer = CTX_data_view_layer(C); - if (scene->camera != OBACT(view_layer)) { - return false; - } - } - - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - if (rv3d->persp == RV3D_CAMOB) { - if (scene->r.mode & R_BORDER) { - /* TODO: support overrides. */ - if (scene->id.lib == NULL) { - return true; - } - } - } - else if (v3d->flag2 & V3D_RENDER_BORDER) { - return true; - } - return false; + Scene *scene = CTX_data_scene(C); + + /* This is just so the border isn't always in the way, + * stealing mouse clicks from regular usage. + * We could change the rules for when to show. */ + { + ViewLayer *view_layer = CTX_data_view_layer(C); + if (scene->camera != OBACT(view_layer)) { + return false; + } + } + + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + if (scene->r.mode & R_BORDER) { + /* TODO: support overrides. */ + if (scene->id.lib == NULL) { + return true; + } + } + } + else if (v3d->flag2 & V3D_RENDER_BORDER) { + return true; + } + return false; } static void WIDGETGROUP_camera_view_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), __func__); + struct CameraViewWidgetGroup *viewgroup = MEM_mallocN(sizeof(struct CameraViewWidgetGroup), + __func__); - viewgroup->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); + viewgroup->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); - RNA_enum_set(viewgroup->border->ptr, "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); - /* Box style is more subtle in this case. */ - RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX); + RNA_enum_set(viewgroup->border->ptr, + "transform", + ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); + /* Box style is more subtle in this case. */ + RNA_enum_set(viewgroup->border->ptr, "draw_style", ED_GIZMO_CAGE2D_STYLE_BOX); - - gzgroup->customdata = viewgroup; + gzgroup->customdata = viewgroup; } static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { - struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata; - - ARegion *ar = CTX_wm_region(C); - struct Depsgraph *depsgraph = CTX_data_depsgraph(C); - RegionView3D *rv3d = ar->regiondata; - if (rv3d->persp == RV3D_CAMOB) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewgroup->state.view_border, false); - } - else { - viewgroup->state.view_border = (rctf){ .xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy, }; - } - - wmGizmo *gz = viewgroup->border; - unit_m4(gz->matrix_space); - mul_v3_fl(gz->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border)); - mul_v3_fl(gz->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border)); - gz->matrix_space[3][0] = viewgroup->state.view_border.xmin; - gz->matrix_space[3][1] = viewgroup->state.view_border.ymin; + struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata; + + ARegion *ar = CTX_wm_region(C); + struct Depsgraph *depsgraph = CTX_data_depsgraph(C); + RegionView3D *rv3d = ar->regiondata; + if (rv3d->persp == RV3D_CAMOB) { + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ED_view3d_calc_camera_border( + scene, depsgraph, ar, v3d, rv3d, &viewgroup->state.view_border, false); + } + else { + viewgroup->state.view_border = (rctf){ + .xmin = 0, + .ymin = 0, + .xmax = ar->winx, + .ymax = ar->winy, + }; + } + + wmGizmo *gz = viewgroup->border; + unit_m4(gz->matrix_space); + mul_v3_fl(gz->matrix_space[0], BLI_rctf_size_x(&viewgroup->state.view_border)); + mul_v3_fl(gz->matrix_space[1], BLI_rctf_size_y(&viewgroup->state.view_border)); + gz->matrix_space[3][0] = viewgroup->state.view_border.xmin; + gz->matrix_space[3][1] = viewgroup->state.view_border.ymin; } static void WIDGETGROUP_camera_view_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata; - - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - Scene *scene = CTX_data_scene(C); - - viewgroup->scene = scene; - - { - wmGizmo *gz = viewgroup->border; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - - RNA_enum_set(viewgroup->border->ptr, "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); - - if (rv3d->persp == RV3D_CAMOB) { - viewgroup->state.edit_border = &scene->r.border; - viewgroup->is_camera = true; - } - else { - viewgroup->state.edit_border = &v3d->render_border; - viewgroup->is_camera = false; - } - - WM_gizmo_target_property_def_func( - gz, "matrix", - &(const struct wmGizmoPropertyFnParams) { - .value_get_fn = gizmo_render_border_prop_matrix_get, - .value_set_fn = gizmo_render_border_prop_matrix_set, - .range_get_fn = NULL, - .user_data = viewgroup, - }); - } - + struct CameraViewWidgetGroup *viewgroup = gzgroup->customdata; + + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + Scene *scene = CTX_data_scene(C); + + viewgroup->scene = scene; + + { + wmGizmo *gz = viewgroup->border; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + + RNA_enum_set(viewgroup->border->ptr, + "transform", + ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); + + if (rv3d->persp == RV3D_CAMOB) { + viewgroup->state.edit_border = &scene->r.border; + viewgroup->is_camera = true; + } + else { + viewgroup->state.edit_border = &v3d->render_border; + viewgroup->is_camera = false; + } + + WM_gizmo_target_property_def_func(gz, + "matrix", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_render_border_prop_matrix_get, + .value_set_fn = gizmo_render_border_prop_matrix_set, + .range_get_fn = NULL, + .user_data = viewgroup, + }); + } } void VIEW3D_GGT_camera_view(wmGizmoGroupType *gzgt) { - gzgt->name = "Camera View Widgets"; - gzgt->idname = "VIEW3D_GGT_camera_view"; + gzgt->name = "Camera View Widgets"; + gzgt->idname = "VIEW3D_GGT_camera_view"; - gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_SCALE); + gzgt->flag = (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_SCALE); - gzgt->poll = WIDGETGROUP_camera_view_poll; - gzgt->setup = WIDGETGROUP_camera_view_setup; - gzgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare; - gzgt->refresh = WIDGETGROUP_camera_view_refresh; + gzgt->poll = WIDGETGROUP_camera_view_poll; + gzgt->setup = WIDGETGROUP_camera_view_setup; + gzgt->draw_prepare = WIDGETGROUP_camera_view_draw_prepare; + gzgt->refresh = WIDGETGROUP_camera_view_refresh; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c index 8e78fe8a18e..6a3979ae458 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c @@ -18,7 +18,6 @@ * \ingroup spview3d */ - #include "BLI_math.h" #include "BLI_utildefines.h" @@ -43,167 +42,165 @@ #include "WM_api.h" #include "WM_types.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Empty Image Gizmos * \{ */ struct EmptyImageWidgetGroup { - wmGizmo *gizmo; - struct { - Object *ob; - float dims[2]; - } state; + wmGizmo *gizmo; + struct { + Object *ob; + float dims[2]; + } state; }; /* translate callbacks */ -static void gizmo_empty_image_prop_matrix_get( - const wmGizmo *gz, wmGizmoProperty *gz_prop, - void *value_p) +static void gizmo_empty_image_prop_matrix_get(const wmGizmo *gz, + wmGizmoProperty *gz_prop, + void *value_p) { - float (*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data; - const Object *ob = igzgroup->state.ob; - - unit_m4(matrix); - matrix[0][0] = ob->empty_drawsize; - matrix[1][1] = ob->empty_drawsize; - - float dims[2] = {0.0f, 0.0f}; - RNA_float_get_array(gz->ptr, "dimensions", dims); - dims[0] *= ob->empty_drawsize; - dims[1] *= ob->empty_drawsize; - - matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]); - matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]); + float(*matrix)[4] = value_p; + BLI_assert(gz_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data; + const Object *ob = igzgroup->state.ob; + + unit_m4(matrix); + matrix[0][0] = ob->empty_drawsize; + matrix[1][1] = ob->empty_drawsize; + + float dims[2] = {0.0f, 0.0f}; + RNA_float_get_array(gz->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; + + matrix[3][0] = (ob->ima_ofs[0] * dims[0]) + (0.5f * dims[0]); + matrix[3][1] = (ob->ima_ofs[1] * dims[1]) + (0.5f * dims[1]); } -static void gizmo_empty_image_prop_matrix_set( - const wmGizmo *gz, wmGizmoProperty *gz_prop, - const void *value_p) +static void gizmo_empty_image_prop_matrix_set(const wmGizmo *gz, + wmGizmoProperty *gz_prop, + const void *value_p) { - const float (*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data; - Object *ob = igzgroup->state.ob; + const float(*matrix)[4] = value_p; + BLI_assert(gz_prop->type->array_length == 16); + struct EmptyImageWidgetGroup *igzgroup = gz_prop->custom_func.user_data; + Object *ob = igzgroup->state.ob; - ob->empty_drawsize = matrix[0][0]; - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + ob->empty_drawsize = matrix[0][0]; + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - float dims[2]; - RNA_float_get_array(gz->ptr, "dimensions", dims); - dims[0] *= ob->empty_drawsize; - dims[1] *= ob->empty_drawsize; + float dims[2]; + RNA_float_get_array(gz->ptr, "dimensions", dims); + dims[0] *= ob->empty_drawsize; + dims[1] *= ob->empty_drawsize; - ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0]; - ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1]; + ob->ima_ofs[0] = (matrix[3][0] - (0.5f * dims[0])) / dims[0]; + ob->ima_ofs[1] = (matrix[3][1] - (0.5f * dims[1])) / dims[1]; } static bool WIDGETGROUP_empty_image_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_IMAGE) == 0) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->type == OB_EMPTY) { - if (ob->empty_drawtype == OB_EMPTY_IMAGE) { - return BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d); - } - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_IMAGE) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->type == OB_EMPTY) { + if (ob->empty_drawtype == OB_EMPTY_IMAGE) { + return BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d); + } + } + } + return false; } static void WIDGETGROUP_empty_image_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - struct EmptyImageWidgetGroup *igzgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), __func__); - igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); - wmGizmo *gz = igzgroup->gizmo; - RNA_enum_set(gz->ptr, "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); + struct EmptyImageWidgetGroup *igzgroup = MEM_mallocN(sizeof(struct EmptyImageWidgetGroup), + __func__); + igzgroup->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); + wmGizmo *gz = igzgroup->gizmo; + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); - gzgroup->customdata = igzgroup; + gzgroup->customdata = igzgroup; - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); } static void WIDGETGROUP_empty_image_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata; - wmGizmo *gz = igzgroup->gizmo; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - - copy_m4_m4(gz->matrix_basis, ob->obmat); - - RNA_enum_set(gz->ptr, "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | - ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | - ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); - - igzgroup->state.ob = ob; - - /* Use dimensions for aspect. */ - if (ob->data != NULL) { - const Image *image = ob->data; - ImageUser iuser = *ob->iuser; - float size[2]; - BKE_image_get_size_fl(ob->data, &iuser, size); - - /* Get the image aspect even if the buffer is invalid */ - if (image->aspx > image->aspy) { - size[1] *= image->aspy / image->aspx; - } - else if (image->aspx < image->aspy) { - size[0] *= image->aspx / image->aspy; - } - - const float dims_max = max_ff(size[0], size[1]); - igzgroup->state.dims[0] = size[0] / dims_max; - igzgroup->state.dims[1] = size[1] / dims_max; - } - else { - copy_v2_fl(igzgroup->state.dims, 1.0f); - } - RNA_float_set_array(gz->ptr, "dimensions", igzgroup->state.dims); - - WM_gizmo_target_property_def_func( - gz, "matrix", - &(const struct wmGizmoPropertyFnParams) { - .value_get_fn = gizmo_empty_image_prop_matrix_get, - .value_set_fn = gizmo_empty_image_prop_matrix_set, - .range_get_fn = NULL, - .user_data = igzgroup, - }); + struct EmptyImageWidgetGroup *igzgroup = gzgroup->customdata; + wmGizmo *gz = igzgroup->gizmo; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + + copy_m4_m4(gz->matrix_basis, ob->obmat); + + RNA_enum_set(gz->ptr, + "transform", + ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE | + ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM); + + igzgroup->state.ob = ob; + + /* Use dimensions for aspect. */ + if (ob->data != NULL) { + const Image *image = ob->data; + ImageUser iuser = *ob->iuser; + float size[2]; + BKE_image_get_size_fl(ob->data, &iuser, size); + + /* Get the image aspect even if the buffer is invalid */ + if (image->aspx > image->aspy) { + size[1] *= image->aspy / image->aspx; + } + else if (image->aspx < image->aspy) { + size[0] *= image->aspx / image->aspy; + } + + const float dims_max = max_ff(size[0], size[1]); + igzgroup->state.dims[0] = size[0] / dims_max; + igzgroup->state.dims[1] = size[1] / dims_max; + } + else { + copy_v2_fl(igzgroup->state.dims, 1.0f); + } + RNA_float_set_array(gz->ptr, "dimensions", igzgroup->state.dims); + + WM_gizmo_target_property_def_func(gz, + "matrix", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_empty_image_prop_matrix_get, + .value_set_fn = gizmo_empty_image_prop_matrix_set, + .range_get_fn = NULL, + .user_data = igzgroup, + }); } void VIEW3D_GGT_empty_image(wmGizmoGroupType *gzgt) { - gzgt->name = "Area Light Widgets"; - gzgt->idname = "VIEW3D_GGT_empty_image"; + gzgt->name = "Area Light Widgets"; + gzgt->idname = "VIEW3D_GGT_empty_image"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D | - WM_GIZMOGROUPTYPE_DEPTH_3D); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D); - gzgt->poll = WIDGETGROUP_empty_image_poll; - gzgt->setup = WIDGETGROUP_empty_image_setup; - gzgt->refresh = WIDGETGROUP_empty_image_refresh; + gzgt->poll = WIDGETGROUP_empty_image_poll; + gzgt->setup = WIDGETGROUP_empty_image_setup; + gzgt->refresh = WIDGETGROUP_empty_image_refresh; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c index 34cf38b3466..7d3e22b4d70 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c @@ -18,7 +18,6 @@ * \ingroup spview3d */ - #include "BLI_utildefines.h" #include "BKE_context.h" @@ -39,7 +38,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Force Field Gizmos @@ -47,80 +46,78 @@ static bool WIDGETGROUP_forcefield_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD) == 0) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->pd && ob->pd->forcefield) { - return true; - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_empty & V3D_GIZMO_SHOW_EMPTY_FORCE_FIELD) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->pd && ob->pd->forcefield) { + return true; + } + } + return false; } static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - /* only wind effector for now */ - wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); - gzgroup->customdata = wwrapper; - - wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL); - wmGizmo *gz = wwrapper->gizmo; - RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); - ED_gizmo_arrow3d_set_ui_range(gz, -200.0f, 200.0f); - ED_gizmo_arrow3d_set_range_fac(gz, 6.0f); - - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + /* only wind effector for now */ + wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + gzgroup->customdata = wwrapper; + + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL); + wmGizmo *gz = wwrapper->gizmo; + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED); + ED_gizmo_arrow3d_set_ui_range(gz, -200.0f, 200.0f); + ED_gizmo_arrow3d_set_range_fac(gz, 6.0f); + + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); } static void WIDGETGROUP_forcefield_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = gzgroup->customdata; - wmGizmo *gz = wwrapper->gizmo; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - PartDeflect *pd = ob->pd; - - if (pd->forcefield == PFIELD_WIND) { - const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; - const float ofs[3] = {0.0f, -size, 0.0f}; - PointerRNA field_ptr; - - RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr); - WM_gizmo_set_matrix_location(gz, ob->obmat[3]); - WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]); - WM_gizmo_set_matrix_offset_location(gz, ofs); - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1); - } - else { - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); - } + wmGizmoWrapper *wwrapper = gzgroup->customdata; + wmGizmo *gz = wwrapper->gizmo; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + PartDeflect *pd = ob->pd; + + if (pd->forcefield == PFIELD_WIND) { + const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f; + const float ofs[3] = {0.0f, -size, 0.0f}; + PointerRNA field_ptr; + + RNA_pointer_create(&ob->id, &RNA_FieldSettings, pd, &field_ptr); + WM_gizmo_set_matrix_location(gz, ob->obmat[3]); + WM_gizmo_set_matrix_rotation_from_z_axis(gz, ob->obmat[2]); + WM_gizmo_set_matrix_offset_location(gz, ofs); + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + WM_gizmo_target_property_def_rna(gz, "offset", &field_ptr, "strength", -1); + } + else { + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); + } } void VIEW3D_GGT_force_field(wmGizmoGroupType *gzgt) { - gzgt->name = "Force Field Widgets"; - gzgt->idname = "VIEW3D_GGT_force_field"; + gzgt->name = "Force Field Widgets"; + gzgt->idname = "VIEW3D_GGT_force_field"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D | - WM_GIZMOGROUPTYPE_SCALE | - WM_GIZMOGROUPTYPE_DEPTH_3D); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | + WM_GIZMOGROUPTYPE_DEPTH_3D); - gzgt->poll = WIDGETGROUP_forcefield_poll; - gzgt->setup = WIDGETGROUP_forcefield_setup; - gzgt->refresh = WIDGETGROUP_forcefield_refresh; + gzgt->poll = WIDGETGROUP_forcefield_poll; + gzgt->setup = WIDGETGROUP_forcefield_setup; + gzgt->refresh = WIDGETGROUP_forcefield_refresh; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_light.c b/source/blender/editors/space_view3d/view3d_gizmo_light.c index 5fd5336f4ca..8c6f783de61 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_light.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_light.c @@ -18,7 +18,6 @@ * \ingroup spview3d */ - #include "BLI_math.h" #include "BLI_utildefines.h" @@ -42,7 +41,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Spot Light Gizmos @@ -50,74 +49,72 @@ static bool WIDGETGROUP_light_spot_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->type == OB_LAMP) { - Light *la = ob->data; - return (la->type == LA_SPOT); - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->type == OB_LAMP) { + Light *la = ob->data; + return (la->type == LA_SPOT); + } + } + return false; } static void WIDGETGROUP_light_spot_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); - wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL); - wmGizmo *gz = wwrapper->gizmo; - RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED); + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_arrow_3d", gzgroup, NULL); + wmGizmo *gz = wwrapper->gizmo; + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_ARROW_XFORM_FLAG_INVERTED); - gzgroup->customdata = wwrapper; + gzgroup->customdata = wwrapper; - ED_gizmo_arrow3d_set_range_fac(gz, 4.0f); + ED_gizmo_arrow3d_set_range_fac(gz, 4.0f); - UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_SECONDARY, gz->color); } static void WIDGETGROUP_light_spot_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = gzgroup->customdata; - wmGizmo *gz = wwrapper->gizmo; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Light *la = ob->data; - float dir[3]; - - negate_v3_v3(dir, ob->obmat[2]); - - WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir); - WM_gizmo_set_matrix_location(gz, ob->obmat[3]); - - /* need to set property here for undo. TODO would prefer to do this in _init */ - PointerRNA lamp_ptr; - const char *propname = "spot_size"; - RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr); - WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1); + wmGizmoWrapper *wwrapper = gzgroup->customdata; + wmGizmo *gz = wwrapper->gizmo; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Light *la = ob->data; + float dir[3]; + + negate_v3_v3(dir, ob->obmat[2]); + + WM_gizmo_set_matrix_rotation_from_z_axis(gz, dir); + WM_gizmo_set_matrix_location(gz, ob->obmat[3]); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + PointerRNA lamp_ptr; + const char *propname = "spot_size"; + RNA_pointer_create(&la->id, &RNA_Light, la, &lamp_ptr); + WM_gizmo_target_property_def_rna(gz, "offset", &lamp_ptr, propname, -1); } void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt) { - gzgt->name = "Spot Light Widgets"; - gzgt->idname = "VIEW3D_GGT_light_spot"; + gzgt->name = "Spot Light Widgets"; + gzgt->idname = "VIEW3D_GGT_light_spot"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D | - WM_GIZMOGROUPTYPE_DEPTH_3D); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D); - gzgt->poll = WIDGETGROUP_light_spot_poll; - gzgt->setup = WIDGETGROUP_light_spot_setup; - gzgt->refresh = WIDGETGROUP_light_spot_refresh; + gzgt->poll = WIDGETGROUP_light_spot_poll; + gzgt->setup = WIDGETGROUP_light_spot_setup; + gzgt->refresh = WIDGETGROUP_light_spot_refresh; } /** \} */ @@ -127,204 +124,200 @@ void VIEW3D_GGT_light_spot(wmGizmoGroupType *gzgt) * \{ */ /* scale callbacks */ -static void gizmo_area_light_prop_matrix_get( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - void *value_p) +static void gizmo_area_light_prop_matrix_get(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + void *value_p) { - BLI_assert(gz_prop->type->array_length == 16); - float (*matrix)[4] = value_p; - const Light *la = gz_prop->custom_func.user_data; + BLI_assert(gz_prop->type->array_length == 16); + float(*matrix)[4] = value_p; + const Light *la = gz_prop->custom_func.user_data; - matrix[0][0] = la->area_size; - matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : la->area_size; + matrix[0][0] = la->area_size; + matrix[1][1] = ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE) ? la->area_sizey : + la->area_size; } -static void gizmo_area_light_prop_matrix_set( - const wmGizmo *UNUSED(gz), wmGizmoProperty *gz_prop, - const void *value_p) +static void gizmo_area_light_prop_matrix_set(const wmGizmo *UNUSED(gz), + wmGizmoProperty *gz_prop, + const void *value_p) { - const float (*matrix)[4] = value_p; - BLI_assert(gz_prop->type->array_length == 16); - Light *la = gz_prop->custom_func.user_data; - - if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { - la->area_size = len_v3(matrix[0]); - la->area_sizey = len_v3(matrix[1]); - } - else { - la->area_size = len_v3(matrix[0]); - } - - DEG_id_tag_update(&la->id, ID_RECALC_COPY_ON_WRITE); - WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la); + const float(*matrix)[4] = value_p; + BLI_assert(gz_prop->type->array_length == 16); + Light *la = gz_prop->custom_func.user_data; + + if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { + la->area_size = len_v3(matrix[0]); + la->area_sizey = len_v3(matrix[1]); + } + else { + la->area_size = len_v3(matrix[0]); + } + + DEG_id_tag_update(&la->id, ID_RECALC_COPY_ON_WRITE); + WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la); } static bool WIDGETGROUP_light_area_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->type == OB_LAMP) { - Light *la = ob->data; - return (la->type == LA_AREA); - } - } - return false; + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_SIZE) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->type == OB_LAMP) { + Light *la = ob->data; + return (la->type == LA_AREA); + } + } + return false; } static void WIDGETGROUP_light_area_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); - wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); - wmGizmo *gz = wwrapper->gizmo; - RNA_enum_set(gz->ptr, "transform", - ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); + wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL); + wmGizmo *gz = wwrapper->gizmo; + RNA_enum_set(gz->ptr, "transform", ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE); - gzgroup->customdata = wwrapper; + gzgroup->customdata = wwrapper; - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER, true); - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); } static void WIDGETGROUP_light_area_refresh(const bContext *C, wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = gzgroup->customdata; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Light *la = ob->data; - wmGizmo *gz = wwrapper->gizmo; - - copy_m4_m4(gz->matrix_basis, ob->obmat); - - int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE; - if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) { - flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM; - } - RNA_enum_set(gz->ptr, "transform", flag); - - /* need to set property here for undo. TODO would prefer to do this in _init */ - WM_gizmo_target_property_def_func( - gz, "matrix", - &(const struct wmGizmoPropertyFnParams) { - .value_get_fn = gizmo_area_light_prop_matrix_get, - .value_set_fn = gizmo_area_light_prop_matrix_set, - .range_get_fn = NULL, - .user_data = la, - }); + wmGizmoWrapper *wwrapper = gzgroup->customdata; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Light *la = ob->data; + wmGizmo *gz = wwrapper->gizmo; + + copy_m4_m4(gz->matrix_basis, ob->obmat); + + int flag = ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE; + if (ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_DISK)) { + flag |= ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM; + } + RNA_enum_set(gz->ptr, "transform", flag); + + /* need to set property here for undo. TODO would prefer to do this in _init */ + WM_gizmo_target_property_def_func(gz, + "matrix", + &(const struct wmGizmoPropertyFnParams){ + .value_get_fn = gizmo_area_light_prop_matrix_get, + .value_set_fn = gizmo_area_light_prop_matrix_set, + .range_get_fn = NULL, + .user_data = la, + }); } void VIEW3D_GGT_light_area(wmGizmoGroupType *gzgt) { - gzgt->name = "Area Light Widgets"; - gzgt->idname = "VIEW3D_GGT_light_area"; + gzgt->name = "Area Light Widgets"; + gzgt->idname = "VIEW3D_GGT_light_area"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D | - WM_GIZMOGROUPTYPE_DEPTH_3D); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_DEPTH_3D); - gzgt->poll = WIDGETGROUP_light_area_poll; - gzgt->setup = WIDGETGROUP_light_area_setup; - gzgt->refresh = WIDGETGROUP_light_area_refresh; + gzgt->poll = WIDGETGROUP_light_area_poll; + gzgt->setup = WIDGETGROUP_light_area_setup; + gzgt->refresh = WIDGETGROUP_light_area_refresh; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Light Target Gizmo * \{ */ static bool WIDGETGROUP_light_target_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { - return false; - } - if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_LOOK_AT) == 0) { - return false; - } - - ViewLayer *view_layer = CTX_data_view_layer(C); - Base *base = BASACT(view_layer); - if (base && BASE_SELECTABLE(v3d, base)) { - Object *ob = base->object; - if (ob->type == OB_LAMP) { - Light *la = ob->data; - return (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)); - } + View3D *v3d = CTX_wm_view3d(C); + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_CONTEXT)) { + return false; + } + if ((v3d->gizmo_show_light & V3D_GIZMO_SHOW_LIGHT_LOOK_AT) == 0) { + return false; + } + + ViewLayer *view_layer = CTX_data_view_layer(C); + Base *base = BASACT(view_layer); + if (base && BASE_SELECTABLE(v3d, base)) { + Object *ob = base->object; + if (ob->type == OB_LAMP) { + Light *la = ob->data; + return (ELEM(la->type, LA_SUN, LA_SPOT, LA_AREA)); + } #if 0 - else if (ob->type == OB_CAMERA) { - return true; - } + else if (ob->type == OB_CAMERA) { + return true; + } #endif - } - return false; + } + return false; } static void WIDGETGROUP_light_target_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); - wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL); - wmGizmo *gz = wwrapper->gizmo; + wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__); + wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL); + wmGizmo *gz = wwrapper->gizmo; - gzgroup->customdata = wwrapper; + gzgroup->customdata = wwrapper; - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); - gz->scale_basis = 0.06f; + gz->scale_basis = 0.06f; - wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true); + wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true); - RNA_enum_set(gz->ptr, "draw_options", - ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW); + RNA_enum_set( + gz->ptr, "draw_options", ED_GIZMO_MOVE_DRAW_FLAG_FILL | ED_GIZMO_MOVE_DRAW_FLAG_ALIGN_VIEW); - WM_gizmo_operator_set(gz, 0, ot, NULL); + WM_gizmo_operator_set(gz, 0, ot, NULL); } static void WIDGETGROUP_light_target_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { - wmGizmoWrapper *wwrapper = gzgroup->customdata; - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - wmGizmo *gz = wwrapper->gizmo; - - normalize_m4_m4(gz->matrix_basis, ob->obmat); - unit_m4(gz->matrix_offset); - - if (ob->type == OB_LAMP) { - Light *la = ob->data; - if (la->type == LA_SPOT) { - /* Draw just past the light size angle gizmo. */ - madd_v3_v3fl(gz->matrix_basis[3], gz->matrix_basis[2], -la->spotsize); - } - } - gz->matrix_offset[3][2] -= 23.0; - WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true); + wmGizmoWrapper *wwrapper = gzgroup->customdata; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + wmGizmo *gz = wwrapper->gizmo; + + normalize_m4_m4(gz->matrix_basis, ob->obmat); + unit_m4(gz->matrix_offset); + + if (ob->type == OB_LAMP) { + Light *la = ob->data; + if (la->type == LA_SPOT) { + /* Draw just past the light size angle gizmo. */ + madd_v3_v3fl(gz->matrix_basis[3], gz->matrix_basis[2], -la->spotsize); + } + } + gz->matrix_offset[3][2] -= 23.0; + WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_OFFSET_SCALE, true); } void VIEW3D_GGT_light_target(wmGizmoGroupType *gzgt) { - gzgt->name = "Target Light Widgets"; - gzgt->idname = "VIEW3D_GGT_light_target"; + gzgt->name = "Target Light Widgets"; + gzgt->idname = "VIEW3D_GGT_light_target"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_3D); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_3D); - gzgt->poll = WIDGETGROUP_light_target_poll; - gzgt->setup = WIDGETGROUP_light_target_setup; - gzgt->draw_prepare = WIDGETGROUP_light_target_draw_prepare; + gzgt->poll = WIDGETGROUP_light_target_poll; + gzgt->setup = WIDGETGROUP_light_target_setup; + gzgt->draw_prepare = WIDGETGROUP_light_target_draw_prepare; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index a6fd195b04d..f98a87e84a8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -39,7 +39,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name View3D Navigation Gizmo Group @@ -54,278 +54,280 @@ /* How much mini buttons offset from the primary. */ #define GIZMO_MINI_OFFSET_FAC 0.38f - enum { - GZ_INDEX_MOVE = 0, - GZ_INDEX_ROTATE = 1, - GZ_INDEX_ZOOM = 2, + GZ_INDEX_MOVE = 0, + GZ_INDEX_ROTATE = 1, + GZ_INDEX_ZOOM = 2, - /* just buttons */ - /* overlaps GZ_INDEX_ORTHO (switch between) */ - GZ_INDEX_PERSP = 3, - GZ_INDEX_ORTHO = 4, - GZ_INDEX_CAMERA = 5, + /* just buttons */ + /* overlaps GZ_INDEX_ORTHO (switch between) */ + GZ_INDEX_PERSP = 3, + GZ_INDEX_ORTHO = 4, + GZ_INDEX_CAMERA = 5, - GZ_INDEX_TOTAL = 6, + GZ_INDEX_TOTAL = 6, }; struct NavigateGizmoInfo { - const char *opname; - const char *gizmo; - uint icon; + const char *opname; + const char *gizmo; + uint icon; }; static struct NavigateGizmoInfo g_navigate_params[GZ_INDEX_TOTAL] = { - { - .opname = "VIEW3D_OT_move", - .gizmo = "GIZMO_GT_button_2d", - ICON_VIEW_PAN, - }, { - .opname = "VIEW3D_OT_rotate", - .gizmo = "VIEW3D_GT_navigate_rotate", - 0, - }, { - .opname = "VIEW3D_OT_zoom", - .gizmo = "GIZMO_GT_button_2d", - ICON_VIEW_ZOOM, - }, { - .opname = "VIEW3D_OT_view_persportho", - .gizmo = "GIZMO_GT_button_2d", - ICON_VIEW_PERSPECTIVE, - }, { - .opname = "VIEW3D_OT_view_persportho", - .gizmo = "GIZMO_GT_button_2d", - ICON_VIEW_ORTHO, - }, { - .opname = "VIEW3D_OT_view_camera", - .gizmo = "GIZMO_GT_button_2d", - ICON_VIEW_CAMERA, - }, + { + .opname = "VIEW3D_OT_move", + .gizmo = "GIZMO_GT_button_2d", + ICON_VIEW_PAN, + }, + { + .opname = "VIEW3D_OT_rotate", + .gizmo = "VIEW3D_GT_navigate_rotate", + 0, + }, + { + .opname = "VIEW3D_OT_zoom", + .gizmo = "GIZMO_GT_button_2d", + ICON_VIEW_ZOOM, + }, + { + .opname = "VIEW3D_OT_view_persportho", + .gizmo = "GIZMO_GT_button_2d", + ICON_VIEW_PERSPECTIVE, + }, + { + .opname = "VIEW3D_OT_view_persportho", + .gizmo = "GIZMO_GT_button_2d", + ICON_VIEW_ORTHO, + }, + { + .opname = "VIEW3D_OT_view_camera", + .gizmo = "GIZMO_GT_button_2d", + ICON_VIEW_CAMERA, + }, }; struct NavigateWidgetGroup { - wmGizmo *gz_array[GZ_INDEX_TOTAL]; - /* Store the view state to check for changes. */ - struct { - rcti rect_visible; - struct { - char is_persp; - char is_camera; - char viewlock; - } rv3d; - } state; - int region_size[2]; + wmGizmo *gz_array[GZ_INDEX_TOTAL]; + /* Store the view state to check for changes. */ + struct { + rcti rect_visible; + struct { + char is_persp; + char is_camera; + char viewlock; + } rv3d; + } state; + int region_size[2]; }; static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt)) { - View3D *v3d = CTX_wm_view3d(C); - if (((U.uiflag & USER_SHOW_GIZMO_AXIS) == 0) || - (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) - { - return false; - } - return true; + View3D *v3d = CTX_wm_view3d(C); + if (((U.uiflag & USER_SHOW_GIZMO_AXIS) == 0) || + (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_NAVIGATE))) { + return false; + } + return true; } static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__); - - navgroup->region_size[0] = -1; - navgroup->region_size[1] = -1; - - wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true); - wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true); - - for (int i = 0; i < GZ_INDEX_TOTAL; i++) { - const struct NavigateGizmoInfo *info = &g_navigate_params[i]; - navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL); - wmGizmo *gz = navgroup->gz_array[i]; - gz->flag |= WM_GIZMO_MOVE_CURSOR | WM_GIZMO_DRAW_MODAL; - - if (i == GZ_INDEX_ROTATE) { - gz->color[3] = 0.0f; - copy_v3_fl(gz->color_hi, 0.5f); - gz->color_hi[3] = 0.5f; - } - else { - uchar icon_color[3]; - UI_GetThemeColor3ubv(TH_TEXT, icon_color); - int color_tint, color_tint_hi; - if (icon_color[0] > 128) { - color_tint = -40; - color_tint_hi = 60; - gz->color[3] = 0.5f; - gz->color_hi[3] = 0.5f; - } - else { - color_tint = 60; - color_tint_hi = 60; - gz->color[3] = 0.5f; - gz->color_hi[3] = 0.75f; - } - UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color); - UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi); - } - - /* may be overwritten later */ - gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2; - if (info->icon != 0) { - PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); - RNA_property_enum_set(gz->ptr, prop, info->icon); - RNA_enum_set(gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE | ED_GIZMO_BUTTON_SHOW_BACKDROP); - } - - wmOperatorType *ot = WM_operatortype_find(info->opname, true); - WM_gizmo_operator_set(gz, 0, ot, NULL); - } - - { - wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA]; - WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL); - } - - /* Click only buttons (not modal). */ - { - int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA}; - for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) { - wmGizmo *gz = navgroup->gz_array[gz_ids[i]]; - RNA_boolean_set(gz->ptr, "show_drag", false); - } - } - - /* Modal operators, don't use initial mouse location since we're clicking on a button. */ - { - int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM}; - for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) { - wmGizmo *gz = navgroup->gz_array[gz_ids[i]]; - wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0); - RNA_boolean_set(&gzop->ptr, "use_mouse_init", false); - } - } - - { - wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE]; - gz->scale_basis = GIZMO_SIZE / 2; - char mapping[6] = { - RV3D_VIEW_LEFT, - RV3D_VIEW_RIGHT, - RV3D_VIEW_FRONT, - RV3D_VIEW_BACK, - RV3D_VIEW_BOTTOM, - RV3D_VIEW_TOP, - }; - - for (int part_index = 0; part_index < 6; part_index += 1) { - PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL); - RNA_enum_set(ptr, "type", mapping[part_index]); - } - - /* When dragging an axis, use this instead. */ - gz->drag_part = 0; - } - - gzgroup->customdata = navgroup; + struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__); + + navgroup->region_size[0] = -1; + navgroup->region_size[1] = -1; + + wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true); + wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true); + + for (int i = 0; i < GZ_INDEX_TOTAL; i++) { + const struct NavigateGizmoInfo *info = &g_navigate_params[i]; + navgroup->gz_array[i] = WM_gizmo_new(info->gizmo, gzgroup, NULL); + wmGizmo *gz = navgroup->gz_array[i]; + gz->flag |= WM_GIZMO_MOVE_CURSOR | WM_GIZMO_DRAW_MODAL; + + if (i == GZ_INDEX_ROTATE) { + gz->color[3] = 0.0f; + copy_v3_fl(gz->color_hi, 0.5f); + gz->color_hi[3] = 0.5f; + } + else { + uchar icon_color[3]; + UI_GetThemeColor3ubv(TH_TEXT, icon_color); + int color_tint, color_tint_hi; + if (icon_color[0] > 128) { + color_tint = -40; + color_tint_hi = 60; + gz->color[3] = 0.5f; + gz->color_hi[3] = 0.5f; + } + else { + color_tint = 60; + color_tint_hi = 60; + gz->color[3] = 0.5f; + gz->color_hi[3] = 0.75f; + } + UI_GetThemeColorShade3fv(TH_HEADER, color_tint, gz->color); + UI_GetThemeColorShade3fv(TH_HEADER, color_tint_hi, gz->color_hi); + } + + /* may be overwritten later */ + gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2; + if (info->icon != 0) { + PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); + RNA_property_enum_set(gz->ptr, prop, info->icon); + RNA_enum_set( + gz->ptr, "draw_options", ED_GIZMO_BUTTON_SHOW_OUTLINE | ED_GIZMO_BUTTON_SHOW_BACKDROP); + } + + wmOperatorType *ot = WM_operatortype_find(info->opname, true); + WM_gizmo_operator_set(gz, 0, ot, NULL); + } + + { + wmGizmo *gz = navgroup->gz_array[GZ_INDEX_CAMERA]; + WM_gizmo_operator_set(gz, 0, ot_view_camera, NULL); + } + + /* Click only buttons (not modal). */ + { + int gz_ids[] = {GZ_INDEX_PERSP, GZ_INDEX_ORTHO, GZ_INDEX_CAMERA}; + for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) { + wmGizmo *gz = navgroup->gz_array[gz_ids[i]]; + RNA_boolean_set(gz->ptr, "show_drag", false); + } + } + + /* Modal operators, don't use initial mouse location since we're clicking on a button. */ + { + int gz_ids[] = {GZ_INDEX_MOVE, GZ_INDEX_ROTATE, GZ_INDEX_ZOOM}; + for (int i = 0; i < ARRAY_SIZE(gz_ids); i++) { + wmGizmo *gz = navgroup->gz_array[gz_ids[i]]; + wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0); + RNA_boolean_set(&gzop->ptr, "use_mouse_init", false); + } + } + + { + wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE]; + gz->scale_basis = GIZMO_SIZE / 2; + char mapping[6] = { + RV3D_VIEW_LEFT, + RV3D_VIEW_RIGHT, + RV3D_VIEW_FRONT, + RV3D_VIEW_BACK, + RV3D_VIEW_BOTTOM, + RV3D_VIEW_TOP, + }; + + for (int part_index = 0; part_index < 6; part_index += 1) { + PointerRNA *ptr = WM_gizmo_operator_set(gz, part_index + 1, ot_view_axis, NULL); + RNA_enum_set(ptr, "type", mapping[part_index]); + } + + /* When dragging an axis, use this instead. */ + gz->drag_part = 0; + } + + gzgroup->customdata = navgroup; } static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup) { - struct NavigateWidgetGroup *navgroup = gzgroup->customdata; - ARegion *ar = CTX_wm_region(C); - const RegionView3D *rv3d = ar->regiondata; - - for (int i = 0; i < 3; i++) { - copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]); - } - - rcti rect_visible; - ED_region_visible_rect(ar, &rect_visible); - - if ((navgroup->state.rect_visible.xmax == rect_visible.xmax) && - (navgroup->state.rect_visible.ymax == rect_visible.ymax) && - (navgroup->state.rv3d.is_persp == rv3d->is_persp) && - (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) && - (navgroup->state.rv3d.viewlock == rv3d->viewlock)) - { - return; - } - - navgroup->state.rect_visible = rect_visible; - navgroup->state.rv3d.is_persp = rv3d->is_persp; - navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB); - navgroup->state.rv3d.viewlock = rv3d->viewlock; - - const bool show_rotate = ( - ((rv3d->viewlock & RV3D_LOCKED) == 0) && - (navgroup->state.rv3d.is_camera == false)); - const bool show_fixed_offset = navgroup->state.rv3d.is_camera; - const float icon_size = GIZMO_SIZE; - const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC; - const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; - const float co_rotate[2] = { - rect_visible.xmax - icon_offset, - rect_visible.ymax - icon_offset, - }; - const float co[2] = { - rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)), - rect_visible.ymax - icon_offset_mini * 0.75f, - }; - - wmGizmo *gz; - - for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) { - gz = navgroup->gz_array[i]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); - } - - /* RV3D_LOCKED or Camera: only show supported buttons. */ - if (show_rotate) { - gz = navgroup->gz_array[GZ_INDEX_ROTATE]; - gz->matrix_basis[3][0] = co_rotate[0]; - gz->matrix_basis[3][1] = co_rotate[1]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - } - - int icon_mini_slot = 0; - - gz = navgroup->gz_array[GZ_INDEX_ZOOM]; - gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); - gz->matrix_basis[3][1] = co[1]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - - gz = navgroup->gz_array[GZ_INDEX_MOVE]; - gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); - gz->matrix_basis[3][1] = co[1]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - gz = navgroup->gz_array[GZ_INDEX_CAMERA]; - gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); - gz->matrix_basis[3][1] = co[1]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - - if (navgroup->state.rv3d.is_camera == false) { - gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO]; - gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); - gz->matrix_basis[3][1] = co[1]; - WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); - } - } + struct NavigateWidgetGroup *navgroup = gzgroup->customdata; + ARegion *ar = CTX_wm_region(C); + const RegionView3D *rv3d = ar->regiondata; + + for (int i = 0; i < 3; i++) { + copy_v3_v3(navgroup->gz_array[GZ_INDEX_ROTATE]->matrix_offset[i], rv3d->viewmat[i]); + } + + rcti rect_visible; + ED_region_visible_rect(ar, &rect_visible); + + if ((navgroup->state.rect_visible.xmax == rect_visible.xmax) && + (navgroup->state.rect_visible.ymax == rect_visible.ymax) && + (navgroup->state.rv3d.is_persp == rv3d->is_persp) && + (navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) && + (navgroup->state.rv3d.viewlock == rv3d->viewlock)) { + return; + } + + navgroup->state.rect_visible = rect_visible; + navgroup->state.rv3d.is_persp = rv3d->is_persp; + navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB); + navgroup->state.rv3d.viewlock = rv3d->viewlock; + + const bool show_rotate = (((rv3d->viewlock & RV3D_LOCKED) == 0) && + (navgroup->state.rv3d.is_camera == false)); + const bool show_fixed_offset = navgroup->state.rv3d.is_camera; + const float icon_size = GIZMO_SIZE; + const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; + const float co_rotate[2] = { + rect_visible.xmax - icon_offset, + rect_visible.ymax - icon_offset, + }; + const float co[2] = { + rect_visible.xmax - + ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)), + rect_visible.ymax - icon_offset_mini * 0.75f, + }; + + wmGizmo *gz; + + for (uint i = 0; i < ARRAY_SIZE(navgroup->gz_array); i++) { + gz = navgroup->gz_array[i]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true); + } + + /* RV3D_LOCKED or Camera: only show supported buttons. */ + if (show_rotate) { + gz = navgroup->gz_array[GZ_INDEX_ROTATE]; + gz->matrix_basis[3][0] = co_rotate[0]; + gz->matrix_basis[3][1] = co_rotate[1]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + } + + int icon_mini_slot = 0; + + gz = navgroup->gz_array[GZ_INDEX_ZOOM]; + gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + gz->matrix_basis[3][1] = co[1]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + + gz = navgroup->gz_array[GZ_INDEX_MOVE]; + gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + gz->matrix_basis[3][1] = co[1]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + gz = navgroup->gz_array[GZ_INDEX_CAMERA]; + gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + gz->matrix_basis[3][1] = co[1]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + + if (navgroup->state.rv3d.is_camera == false) { + gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO]; + gz->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++); + gz->matrix_basis[3][1] = co[1]; + WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false); + } + } } void VIEW3D_GGT_navigate(wmGizmoGroupType *gzgt) { - gzgt->name = "View3D Navigate"; - gzgt->idname = "VIEW3D_GGT_navigate"; + gzgt->name = "View3D Navigate"; + gzgt->idname = "VIEW3D_GGT_navigate"; - gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | - WM_GIZMOGROUPTYPE_SCALE | - WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL); + gzgt->flag |= (WM_GIZMOGROUPTYPE_PERSISTENT | WM_GIZMOGROUPTYPE_SCALE | + WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL); - gzgt->poll = WIDGETGROUP_navigate_poll; - gzgt->setup = WIDGETGROUP_navigate_setup; - gzgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare; + gzgt->poll = WIDGETGROUP_navigate_poll; + gzgt->setup = WIDGETGROUP_navigate_setup; + gzgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c index f9b67a430e6..539b5d93bdf 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c @@ -33,7 +33,6 @@ #include "BKE_context.h" - #include "GPU_immediate.h" #include "GPU_immediate_util.h" #include "GPU_matrix.h" @@ -71,12 +70,12 @@ #define AXIS_HANDLE_OFFSET (1.0f - AXIS_HANDLE_SIZE_FG) struct AxisDrawInfo { - /* Matrix is needed for screen-aligned font drawing. */ + /* Matrix is needed for screen-aligned font drawing. */ #ifdef USE_AXIS_FONT - float matrix_final[4][4]; + float matrix_final[4][4]; #endif #ifdef USE_FADE_BACKGROUND - float color_bg[3]; + float color_bg[3]; #endif }; @@ -86,451 +85,453 @@ struct AxisDrawInfo { * copied into a 3x3 matrix and normalized. */ static void draw_xyz_wire( - uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis) + uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis) { - int line_type; - float buffer[4][3]; - int n = 0; + int line_type; + float buffer[4][3]; + int n = 0; - float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; - float dim = size * 0.1f; - float dx[3], dy[3]; + float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; + float dim = size * 0.1f; + float dx[3], dy[3]; - dx[0] = dim; dx[1] = 0.0f; dx[2] = 0.0f; - dy[0] = 0.0f; dy[1] = dim; dy[2] = 0.0f; + dx[0] = dim; + dx[1] = 0.0f; + dx[2] = 0.0f; + dy[0] = 0.0f; + dy[1] = dim; + dy[2] = 0.0f; - switch (axis) { - case 0: /* x axis */ - line_type = GPU_PRIM_LINES; + switch (axis) { + case 0: /* x axis */ + line_type = GPU_PRIM_LINES; - /* bottom left to top right */ - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); + /* bottom left to top right */ + negate_v3_v3(v1, dx); + sub_v3_v3(v1, dy); + copy_v3_v3(v2, dx); + add_v3_v3(v2, dy); - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); + copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v2); - /* top left to bottom right */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - sub_v3_v3(v2, dy); + /* top left to bottom right */ + mul_v3_fl(dy, 2.0f); + add_v3_v3(v1, dy); + sub_v3_v3(v2, dy); - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); + copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v2); - break; - case 1: /* y axis */ - line_type = GPU_PRIM_LINES; + break; + case 1: /* y axis */ + line_type = GPU_PRIM_LINES; - /* bottom left to top right */ - mul_v3_fl(dx, 0.75f); - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); + /* bottom left to top right */ + mul_v3_fl(dx, 0.75f); + negate_v3_v3(v1, dx); + sub_v3_v3(v1, dy); + copy_v3_v3(v2, dx); + add_v3_v3(v2, dy); - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); + copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v2); - /* top left to center */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - zero_v3(v2); + /* top left to center */ + mul_v3_fl(dy, 2.0f); + add_v3_v3(v1, dy); + zero_v3(v2); - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); + copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v2); - break; - case 2: /* z axis */ - line_type = GPU_PRIM_LINE_STRIP; + break; + case 2: /* z axis */ + line_type = GPU_PRIM_LINE_STRIP; - /* start at top left */ - negate_v3_v3(v1, dx); - add_v3_v3(v1, dy); + /* start at top left */ + negate_v3_v3(v1, dx); + add_v3_v3(v1, dy); - copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v1); - mul_v3_fl(dx, 2.0f); - add_v3_v3(v1, dx); + mul_v3_fl(dx, 2.0f); + add_v3_v3(v1, dx); - copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v1); - mul_v3_fl(dy, 2.0f); - sub_v3_v3(v1, dx); - sub_v3_v3(v1, dy); + mul_v3_fl(dy, 2.0f); + sub_v3_v3(v1, dx); + sub_v3_v3(v1, dy); - copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v1); - add_v3_v3(v1, dx); + add_v3_v3(v1, dx); - copy_v3_v3(buffer[n++], v1); + copy_v3_v3(buffer[n++], v1); - break; - default: - BLI_assert(0); - return; - } + break; + default: + BLI_assert(0); + return; + } - for (int i = 0; i < n; i++) { - mul_transposed_m3_v3((float (*)[3])viewmat_local_unit, buffer[i]); - add_v3_v3(buffer[i], c); - } + for (int i = 0; i < n; i++) { + mul_transposed_m3_v3((float(*)[3])viewmat_local_unit, buffer[i]); + add_v3_v3(buffer[i], c); + } - immBegin(line_type, n); - for (int i = 0; i < n; i++) { - immVertex3fv(pos_id, buffer[i]); - } - immEnd(); + immBegin(line_type, n); + for (int i = 0; i < n; i++) { + immVertex3fv(pos_id, buffer[i]); + } + immEnd(); } -#endif /* !USE_AXIS_FONT */ +#endif /* !USE_AXIS_FONT */ /** * \param draw_info: Extra data needed for drawing. */ -static void axis_geom_draw( - const wmGizmo *gz, const float color[4], const bool select, - const struct AxisDrawInfo *draw_info) +static void axis_geom_draw(const wmGizmo *gz, + const float color[4], + const bool select, + const struct AxisDrawInfo *draw_info) { - GPU_line_width(gz->line_width); - - GPUVertFormat *format = immVertexFormat(); - const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - struct { - float depth; - char index; - char axis; - bool is_pos; - } axis_order[6] = { - {-gz->matrix_offset[0][2], 0, 0, false}, - {+gz->matrix_offset[0][2], 1, 0, true}, - {-gz->matrix_offset[1][2], 2, 1, false}, - {+gz->matrix_offset[1][2], 3, 1, true}, - {-gz->matrix_offset[2][2], 4, 2, false}, - {+gz->matrix_offset[2][2], 5, 2, true}, - }; - - int axis_align = -1; - for (int axis = 0; axis < 3; axis++) { - if (len_squared_v2(gz->matrix_offset[axis]) < 1e-6f) { - axis_align = axis; - break; - } - } - - /* Show backwards pointing highlight on-top (else we can't see it at all). */ - if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) { - if (axis_order[gz->highlight_part - 1].is_pos == false) { - axis_order[gz->highlight_part - 1].depth = FLT_MAX; - } - } - - qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float); - - static const float axis_highlight[4] = {1, 1, 1, 1}; - static const float axis_black[4] = {0, 0, 0, 1}; - static float axis_color[3][4]; - - const float axis_depth_bias = 0.01f; + GPU_line_width(gz->line_width); + + GPUVertFormat *format = immVertexFormat(); + const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + struct { + float depth; + char index; + char axis; + bool is_pos; + } axis_order[6] = { + {-gz->matrix_offset[0][2], 0, 0, false}, + {+gz->matrix_offset[0][2], 1, 0, true}, + {-gz->matrix_offset[1][2], 2, 1, false}, + {+gz->matrix_offset[1][2], 3, 1, true}, + {-gz->matrix_offset[2][2], 4, 2, false}, + {+gz->matrix_offset[2][2], 5, 2, true}, + }; + + int axis_align = -1; + for (int axis = 0; axis < 3; axis++) { + if (len_squared_v2(gz->matrix_offset[axis]) < 1e-6f) { + axis_align = axis; + break; + } + } + + /* Show backwards pointing highlight on-top (else we can't see it at all). */ + if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) { + if (axis_order[gz->highlight_part - 1].is_pos == false) { + axis_order[gz->highlight_part - 1].depth = FLT_MAX; + } + } + + qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float); + + static const float axis_highlight[4] = {1, 1, 1, 1}; + static const float axis_black[4] = {0, 0, 0, 1}; + static float axis_color[3][4]; + + const float axis_depth_bias = 0.01f; #ifdef USE_AXIS_FONT - struct { - float matrix[4][4]; - int id; - } font; - - if (select == false) { - font.id = blf_mono_font; - BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); - BLF_color4fv(font.id, axis_black); - BLF_size(font.id, 11 * U.dpi_fac, 72); - - /* Calculate the inverse of the (matrix_final * matrix_offset). - * This allows us to use the final location, while reversing the rotation so fonts - * show without any rotation. */ - float m3[3][3]; - float m3_offset[3][3]; - copy_m3_m4(m3, draw_info->matrix_final); - copy_m3_m4(m3_offset, gz->matrix_offset); - mul_m3_m3m3(m3, m3, m3_offset); - invert_m3(m3); - copy_m4_m3(font.matrix, m3); - } + struct { + float matrix[4][4]; + int id; + } font; + + if (select == false) { + font.id = blf_mono_font; + BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); + BLF_color4fv(font.id, axis_black); + BLF_size(font.id, 11 * U.dpi_fac, 72); + + /* Calculate the inverse of the (matrix_final * matrix_offset). + * This allows us to use the final location, while reversing the rotation so fonts + * show without any rotation. */ + float m3[3][3]; + float m3_offset[3][3]; + copy_m3_m4(m3, draw_info->matrix_final); + copy_m3_m4(m3_offset, gz->matrix_offset); + mul_m3_m3m3(m3, m3, m3_offset); + invert_m3(m3); + copy_m4_m3(font.matrix, m3); + } #endif - /* When the cursor is over any of the gizmos (show circle backdrop). */ - const bool is_active = (color[3] != 0.0f); - - /* Circle defining active area. */ - if (is_active) { - immUniformColor4fv(color); - imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION); - } - - GPU_matrix_push(); - GPU_matrix_mul(gz->matrix_offset); - - for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) { - const int index = axis_order[axis_index].index; - const int axis = axis_order[axis_index].axis; - const bool is_pos = axis_order[axis_index].is_pos; - const bool is_highlight = index + 1 == gz->highlight_part; - - UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]); - axis_color[axis][3] = 1.0f; - - const int index_z = axis; - const int index_y = (axis + 1) % 3; - const int index_x = (axis + 2) % 3; - - bool ok = true; - - /* Skip view align axis when selecting (allows to switch to opposite side). */ - if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) { - ok = false; - } - if (ok) { - /* Check aligned, since the front axis won't display in this case, - * and we want to make sure all 3 axes have a character at all times. */ - const bool show_axis_char = (is_pos || (axis == axis_align)); - const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)}; - const float v_final[3] = {v[index_x], v[index_y], v[index_z]}; - const float *color_current = is_highlight ? axis_highlight : axis_color[axis]; - float color_current_fade[4]; - - /* Flip the faded state when axis aligned, since we're hiding the front-mode axis - * otherwise we see the color for the back-most axis, which is useful for - * click-to-rotate 180d but not useful to visualize. - * - * Use depth bias so axis-aligned views show the positive axis as being in-front. - * This is a detail so primary axes show as dominant. - */ - const bool is_pos_color = ( - axis_order[axis_index].depth > (axis_depth_bias * (is_pos ? -1 : 1))); - - - if (select == false) { + /* When the cursor is over any of the gizmos (show circle backdrop). */ + const bool is_active = (color[3] != 0.0f); + + /* Circle defining active area. */ + if (is_active) { + immUniformColor4fv(color); + imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION); + } + + GPU_matrix_push(); + GPU_matrix_mul(gz->matrix_offset); + + for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) { + const int index = axis_order[axis_index].index; + const int axis = axis_order[axis_index].axis; + const bool is_pos = axis_order[axis_index].is_pos; + const bool is_highlight = index + 1 == gz->highlight_part; + + UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]); + axis_color[axis][3] = 1.0f; + + const int index_z = axis; + const int index_y = (axis + 1) % 3; + const int index_x = (axis + 2) % 3; + + bool ok = true; + + /* Skip view align axis when selecting (allows to switch to opposite side). */ + if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) { + ok = false; + } + if (ok) { + /* Check aligned, since the front axis won't display in this case, + * and we want to make sure all 3 axes have a character at all times. */ + const bool show_axis_char = (is_pos || (axis == axis_align)); + const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)}; + const float v_final[3] = {v[index_x], v[index_y], v[index_z]}; + const float *color_current = is_highlight ? axis_highlight : axis_color[axis]; + float color_current_fade[4]; + + /* Flip the faded state when axis aligned, since we're hiding the front-mode axis + * otherwise we see the color for the back-most axis, which is useful for + * click-to-rotate 180d but not useful to visualize. + * + * Use depth bias so axis-aligned views show the positive axis as being in-front. + * This is a detail so primary axes show as dominant. + */ + const bool is_pos_color = (axis_order[axis_index].depth > + (axis_depth_bias * (is_pos ? -1 : 1))); + + if (select == false) { #ifdef USE_FADE_BACKGROUND - interp_v3_v3v3(color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f); - color_current_fade[3] = color_current[3]; + interp_v3_v3v3( + color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f); + color_current_fade[3] = color_current[3]; #else - copy_v4_v4(color_current_fade, color_current); - color_current_fade[3] *= 0.2; + copy_v4_v4(color_current_fade, color_current); + color_current_fade[3] *= 0.2; #endif - } - else { - copy_v4_fl(color_current_fade, 1.0f); - } - - /* Axis Line. */ - if (is_pos) { - float v_start[3]; - GPU_line_width(2.0f); - immUniformColor4fv(is_pos_color ? color_current : color_current_fade); - immBegin(GPU_PRIM_LINES, 2); - if (axis_align == -1) { - zero_v3(v_start); - } - else { - /* When axis aligned we don't draw the front most axis - * (allowing us to switch to the opposite side). - * In this case don't draw lines over axis pointing away from us - * because it obscures character and looks noisy. - */ - mul_v3_v3fl(v_start, v_final, 0.3f); - } - immVertex3fv(pos_id, v_start); - immVertex3fv(pos_id, v_final); - immEnd(); - } - - /* Axis Ball. */ - { - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); - - GPUBatch *sphere = GPU_batch_preset_sphere(0); - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - - /* Black outlines for negative axis balls, otherwise they can be hard to see since - * they use a faded color which can be similar to the circle backdrop in tone. */ - if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { - static const float axis_black_faded[4] = {0, 0, 0, 0.2f}; - const float scale = 1.15f; - GPU_matrix_scale_1f(scale); - GPU_batch_uniform_4fv(sphere, "color", axis_black_faded); - GPU_batch_draw(sphere); - GPU_matrix_scale_1f(1.0 / scale); - } - - GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade); - GPU_batch_draw(sphere); - GPU_matrix_pop(); - } - - /* Axis XYZ Character. */ - if (show_axis_char && (select == false)) { + } + else { + copy_v4_fl(color_current_fade, 1.0f); + } + + /* Axis Line. */ + if (is_pos) { + float v_start[3]; + GPU_line_width(2.0f); + immUniformColor4fv(is_pos_color ? color_current : color_current_fade); + immBegin(GPU_PRIM_LINES, 2); + if (axis_align == -1) { + zero_v3(v_start); + } + else { + /* When axis aligned we don't draw the front most axis + * (allowing us to switch to the opposite side). + * In this case don't draw lines over axis pointing away from us + * because it obscures character and looks noisy. + */ + mul_v3_v3fl(v_start, v_final, 0.3f); + } + immVertex3fv(pos_id, v_start); + immVertex3fv(pos_id, v_final); + immEnd(); + } + + /* Axis Ball. */ + { + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final); + GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); + + GPUBatch *sphere = GPU_batch_preset_sphere(0); + GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + + /* Black outlines for negative axis balls, otherwise they can be hard to see since + * they use a faded color which can be similar to the circle backdrop in tone. */ + if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { + static const float axis_black_faded[4] = {0, 0, 0, 0.2f}; + const float scale = 1.15f; + GPU_matrix_scale_1f(scale); + GPU_batch_uniform_4fv(sphere, "color", axis_black_faded); + GPU_batch_draw(sphere); + GPU_matrix_scale_1f(1.0 / scale); + } + + GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade); + GPU_batch_draw(sphere); + GPU_matrix_pop(); + } + + /* Axis XYZ Character. */ + if (show_axis_char && (select == false)) { #ifdef USE_AXIS_FONT - immUnbindProgram(); + immUnbindProgram(); - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_mul(font.matrix); + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final); + GPU_matrix_mul(font.matrix); - const char axis_str[2] = {'X' + axis, 0}; - float offset[2] = {0}; - BLF_width_and_height(font.id, axis_str, 2, &offset[0], &offset[1]); - BLF_position(font.id, roundf(offset[0] * -0.5f), roundf(offset[1] * -0.5f), 0); - BLF_draw_ascii(font.id, axis_str, 2); - GPU_blend(true); /* XXX, blf disables */ - GPU_matrix_pop(); + const char axis_str[2] = {'X' + axis, 0}; + float offset[2] = {0}; + BLF_width_and_height(font.id, axis_str, 2, &offset[0], &offset[1]); + BLF_position(font.id, roundf(offset[0] * -0.5f), roundf(offset[1] * -0.5f), 0); + BLF_draw_ascii(font.id, axis_str, 2); + GPU_blend(true); /* XXX, blf disables */ + GPU_matrix_pop(); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); #else - GPU_line_width(1.0f); - float m3[3][3]; - copy_m3_m4(m3, gz->matrix_offset); - immUniformColor4fv(axis_black); - draw_xyz_wire(pos_id, m3, v_final, 1.0, axis); + GPU_line_width(1.0f); + float m3[3][3]; + copy_m3_m4(m3, gz->matrix_offset); + immUniformColor4fv(axis_black); + draw_xyz_wire(pos_id, m3, v_final, 1.0, axis); #endif - } - } - } + } + } + } - GPU_matrix_pop(); - immUnbindProgram(); + GPU_matrix_pop(); + immUnbindProgram(); } -static void axis3d_draw_intern( - const bContext *C, wmGizmo *gz, - const bool select, const bool highlight) +static void axis3d_draw_intern(const bContext *C, + wmGizmo *gz, + const bool select, + const bool highlight) { - const float *color = highlight ? gz->color_hi : gz->color; - float matrix_final[4][4]; - float matrix_unit[4][4]; - - unit_m4(matrix_unit); + const float *color = highlight ? gz->color_hi : gz->color; + float matrix_final[4][4]; + float matrix_unit[4][4]; - WM_gizmo_calc_matrix_final_params( - gz, - &((struct WM_GizmoMatrixParams) { - .matrix_offset = matrix_unit, - }), matrix_final); + unit_m4(matrix_unit); - GPU_matrix_push(); - GPU_matrix_mul(matrix_final); + WM_gizmo_calc_matrix_final_params(gz, + &((struct WM_GizmoMatrixParams){ + .matrix_offset = matrix_unit, + }), + matrix_final); + GPU_matrix_push(); + GPU_matrix_mul(matrix_final); - struct AxisDrawInfo draw_info; + struct AxisDrawInfo draw_info; #ifdef USE_AXIS_FONT - if (select == false) { - copy_m4_m4(draw_info.matrix_final, matrix_final); - } + if (select == false) { + copy_m4_m4(draw_info.matrix_final, matrix_final); + } #endif #ifdef USE_FADE_BACKGROUND - if (select == false) { - ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg); - } + if (select == false) { + ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg); + } #else - UNUSED_VARS(C); + UNUSED_VARS(C); #endif - GPU_blend(true); - axis_geom_draw( - gz, color, select, - &draw_info); - GPU_blend(false); - GPU_matrix_pop(); + GPU_blend(true); + axis_geom_draw(gz, color, select, &draw_info); + GPU_blend(false); + GPU_matrix_pop(); } static void gizmo_axis_draw(const bContext *C, wmGizmo *gz) { - const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL; - const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0; + const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL; + const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0; - (void)is_modal; + (void)is_modal; - GPU_blend(true); - axis3d_draw_intern(C, gz, false, is_highlight); - GPU_blend(false); + GPU_blend(true); + axis3d_draw_intern(C, gz, false, is_highlight); + GPU_blend(false); } -static int gizmo_axis_test_select( - bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) +static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) { - float point_local[2] = {UNPACK2(mval)}; - sub_v2_v2(point_local, gz->matrix_basis[3]); - mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC)); - - const float len_sq = len_squared_v2(point_local); - if (len_sq > 1.0) { - return -1; - } - - int part_best = -1; - int part_index = 1; - /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */ - float i_best_len_sq = FLT_MAX; - for (int i = 0; i < 3; i++) { - for (int is_pos = 0; is_pos < 2; is_pos++) { - float co[2] = { - gz->matrix_offset[i][0] * (is_pos ? 1 : -1), - gz->matrix_offset[i][1] * (is_pos ? 1 : -1), - }; - - bool ok = true; - - /* Check if we're viewing on an axis, - * there is no point to clicking on the current axis so show the reverse. */ - if (len_squared_v2(co) < 1e-6f && (gz->matrix_offset[i][2] > 0.0f) == is_pos) { - ok = false; - } - - if (ok) { - const float len_axis_sq = len_squared_v2v2(co, point_local); - if (len_axis_sq < i_best_len_sq) { - part_best = part_index; - i_best_len_sq = len_axis_sq; - } - } - part_index += 1; - } - } - - if (part_best != -1) { - return part_best; - } - - /* The 'gz->scale_final' is already applied when projecting. */ - if (len_sq < 1.0f) { - return 0; - } - - return -1; + float point_local[2] = {UNPACK2(mval)}; + sub_v2_v2(point_local, gz->matrix_basis[3]); + mul_v2_fl(point_local, 1.0f / (gz->scale_basis * UI_DPI_FAC)); + + const float len_sq = len_squared_v2(point_local); + if (len_sq > 1.0) { + return -1; + } + + int part_best = -1; + int part_index = 1; + /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */ + float i_best_len_sq = FLT_MAX; + for (int i = 0; i < 3; i++) { + for (int is_pos = 0; is_pos < 2; is_pos++) { + float co[2] = { + gz->matrix_offset[i][0] * (is_pos ? 1 : -1), + gz->matrix_offset[i][1] * (is_pos ? 1 : -1), + }; + + bool ok = true; + + /* Check if we're viewing on an axis, + * there is no point to clicking on the current axis so show the reverse. */ + if (len_squared_v2(co) < 1e-6f && (gz->matrix_offset[i][2] > 0.0f) == is_pos) { + ok = false; + } + + if (ok) { + const float len_axis_sq = len_squared_v2v2(co, point_local); + if (len_axis_sq < i_best_len_sq) { + part_best = part_index; + i_best_len_sq = len_axis_sq; + } + } + part_index += 1; + } + } + + if (part_best != -1) { + return part_best; + } + + /* The 'gz->scale_final' is already applied when projecting. */ + if (len_sq < 1.0f) { + return 0; + } + + return -1; } static int gizmo_axis_cursor_get(wmGizmo *gz) { - if (gz->highlight_part > 0) { - return CURSOR_EDIT; - } - return BC_NSEW_SCROLLCURSOR; + if (gz->highlight_part > 0) { + return CURSOR_EDIT; + } + return BC_NSEW_SCROLLCURSOR; } void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt) { - /* identifiers */ - gzt->idname = "VIEW3D_GT_navigate_rotate"; + /* identifiers */ + gzt->idname = "VIEW3D_GT_navigate_rotate"; - /* api callbacks */ - gzt->draw = gizmo_axis_draw; - gzt->test_select = gizmo_axis_test_select; - gzt->cursor_get = gizmo_axis_cursor_get; + /* api callbacks */ + gzt->draw = gizmo_axis_draw; + gzt->test_select = gizmo_axis_test_select; + gzt->cursor_get = gizmo_axis_cursor_get; - gzt->struct_size = sizeof(wmGizmo); + gzt->struct_size = sizeof(wmGizmo); } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c index b71c03684d6..b9dc287b9cb 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c @@ -33,7 +33,7 @@ #include "WM_types.h" #include "WM_toolsystem.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Mesh Pre-Select Element Gizmo @@ -41,32 +41,32 @@ * \{ */ struct GizmoGroupPreSelElem { - wmGizmo *gizmo; + wmGizmo *gizmo; }; static void WIDGETGROUP_mesh_preselect_elem_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_elem_3d", true); - struct GizmoGroupPreSelElem *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelElem), __func__); - gzgroup->customdata = ggd; + const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_elem_3d", true); + struct GizmoGroupPreSelElem *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelElem), __func__); + gzgroup->customdata = ggd; - wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL); - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); } void VIEW3D_GGT_mesh_preselect_elem(wmGizmoGroupType *gzgt) { - gzgt->name = "Mesh Preselect Element"; - gzgt->idname = "VIEW3D_GGT_mesh_preselect_elem"; + gzgt->name = "Mesh Preselect Element"; + gzgt->idname = "VIEW3D_GGT_mesh_preselect_elem"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_3D; - gzgt->gzmap_params.spaceid = SPACE_VIEW3D; - gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; - gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; - gzgt->setup = WIDGETGROUP_mesh_preselect_elem_setup; + gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; + gzgt->setup = WIDGETGROUP_mesh_preselect_elem_setup; } /** \} */ @@ -77,32 +77,34 @@ void VIEW3D_GGT_mesh_preselect_elem(wmGizmoGroupType *gzgt) * \{ */ struct GizmoGroupPreSelEdgeRing { - wmGizmo *gizmo; + wmGizmo *gizmo; }; -static void WIDGETGROUP_mesh_preselect_edgering_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) +static void WIDGETGROUP_mesh_preselect_edgering_setup(const bContext *UNUSED(C), + wmGizmoGroup *gzgroup) { - const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_edgering_3d", true); - struct GizmoGroupPreSelEdgeRing *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelEdgeRing), __func__); - gzgroup->customdata = ggd; - - wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL); - UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); - UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); + const wmGizmoType *gzt_presel = WM_gizmotype_find("GIZMO_GT_mesh_preselect_edgering_3d", true); + struct GizmoGroupPreSelEdgeRing *ggd = MEM_callocN(sizeof(struct GizmoGroupPreSelEdgeRing), + __func__); + gzgroup->customdata = ggd; + + wmGizmo *gz = ggd->gizmo = WM_gizmo_new_ptr(gzt_presel, gzgroup, NULL); + UI_GetThemeColor3fv(TH_GIZMO_PRIMARY, gz->color); + UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi); } void VIEW3D_GGT_mesh_preselect_edgering(wmGizmoGroupType *gzgt) { - gzgt->name = "Mesh Preselect Edge Ring"; - gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering"; + gzgt->name = "Mesh Preselect Edge Ring"; + gzgt->idname = "VIEW3D_GGT_mesh_preselect_edgering"; - gzgt->flag = WM_GIZMOGROUPTYPE_3D; + gzgt->flag = WM_GIZMOGROUPTYPE_3D; - gzgt->gzmap_params.spaceid = SPACE_VIEW3D; - gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; - gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; - gzgt->setup = WIDGETGROUP_mesh_preselect_edgering_setup; + gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; + gzgt->setup = WIDGETGROUP_mesh_preselect_edgering_setup; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c index 418a9e76678..6f35c0aa748 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c @@ -55,196 +55,194 @@ * * \{ */ - typedef struct MeshElemGizmo3D { - wmGizmo gizmo; - Base **bases; - uint bases_len; - int base_index; - int vert_index; - int edge_index; - int face_index; - struct EditMesh_PreSelElem *psel; + wmGizmo gizmo; + Base **bases; + uint bases_len; + int base_index; + int vert_index; + int edge_index; + int face_index; + struct EditMesh_PreSelElem *psel; } MeshElemGizmo3D; static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz) { - MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; - if (gz_ele->base_index != -1) { - Object *ob = gz_ele->bases[gz_ele->base_index]->object; - EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat); - } + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + if (gz_ele->base_index != -1) { + Object *ob = gz_ele->bases[gz_ele->base_index]->object; + EDBM_preselect_elem_draw(gz_ele->psel, ob->obmat); + } } -static int gizmo_preselect_elem_test_select( - bContext *C, wmGizmo *gz, const int mval[2]) +static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { - MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; - struct { - Object *ob; - BMElem *ele; - float dist; - int base_index; - } best = { - .dist = ED_view3d_select_dist_px(), - }; - - struct { - int base_index; - int vert_index; - int edge_index; - int face_index; - } prev = { - .base_index = gz_ele->base_index, - .vert_index = gz_ele->vert_index, - .edge_index = gz_ele->edge_index, - .face_index = gz_ele->face_index, - }; - - { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - if (((gz_ele->bases)) == NULL || - (gz_ele->bases[0] != view_layer->basact)) - { - MEM_SAFE_FREE(gz_ele->bases); - gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, v3d, &gz_ele->bases_len); - } - } - - ViewContext vc; - em_setup_viewcontext(C, &vc); - copy_v2_v2_int(vc.mval, mval); - - { - /* TODO: support faces. */ - int base_index = -1; - BMVert *eve_test; - BMEdge *eed_test; - - if (EDBM_unified_findnearest_from_raycast( - &vc, gz_ele->bases, gz_ele->bases_len, - true, &base_index, &eve_test, &eed_test, NULL)) - { - Base *base = gz_ele->bases[base_index]; - best.ob = base->object; - if (eve_test) { - best.ele = (BMElem *)eve_test; - } - else if (eed_test) { - best.ele = (BMElem *)eed_test; - } - else { - BLI_assert(0); - } - best.base_index = base_index; - /* Check above should never fail, if it does it's an internal error. */ - BLI_assert(best.base_index != -1); - } - } - - BMesh *bm = NULL; - - gz_ele->base_index = -1; - gz_ele->vert_index = -1; - gz_ele->edge_index = -1; - gz_ele->face_index = -1; - - if (best.ele) { - gz_ele->base_index = best.base_index; - bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm; - BM_mesh_elem_index_ensure(bm, best.ele->head.htype); - - if (best.ele->head.htype == BM_VERT) { - gz_ele->vert_index = BM_elem_index_get(best.ele); - } - else if (best.ele->head.htype == BM_EDGE) { - gz_ele->edge_index = BM_elem_index_get(best.ele); - } - else if (best.ele->head.htype == BM_FACE) { - gz_ele->face_index = BM_elem_index_get(best.ele); - } - } - - if ((prev.base_index == gz_ele->base_index) && - (prev.vert_index == gz_ele->vert_index) && - (prev.edge_index == gz_ele->edge_index) && - (prev.face_index == gz_ele->face_index)) - { - /* pass (only recalculate on change) */ - } - else { - if (best.ele) { - const float (*coords)[3] = NULL; - { - Object *ob = gz_ele->bases[gz_ele->base_index]->object; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); - if (me_eval->runtime.edit_data) { - coords = me_eval->runtime.edit_data->vertexCos; - } - } - EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); - } - else { - EDBM_preselect_elem_clear(gz_ele->psel); - } - - RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); - RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); - RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); - RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); - - ARegion *ar = CTX_wm_region(C); - ED_region_tag_redraw(ar); - } - - // return best.eed ? 0 : -1; - return -1; + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + struct { + Object *ob; + BMElem *ele; + float dist; + int base_index; + } best = { + .dist = ED_view3d_select_dist_px(), + }; + + struct { + int base_index; + int vert_index; + int edge_index; + int face_index; + } prev = { + .base_index = gz_ele->base_index, + .vert_index = gz_ele->vert_index, + .edge_index = gz_ele->edge_index, + .face_index = gz_ele->face_index, + }; + + { + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + if (((gz_ele->bases)) == NULL || (gz_ele->bases[0] != view_layer->basact)) { + MEM_SAFE_FREE(gz_ele->bases); + gz_ele->bases = BKE_view_layer_array_from_bases_in_edit_mode( + view_layer, v3d, &gz_ele->bases_len); + } + } + + ViewContext vc; + em_setup_viewcontext(C, &vc); + copy_v2_v2_int(vc.mval, mval); + + { + /* TODO: support faces. */ + int base_index = -1; + BMVert *eve_test; + BMEdge *eed_test; + + if (EDBM_unified_findnearest_from_raycast(&vc, + gz_ele->bases, + gz_ele->bases_len, + true, + &base_index, + &eve_test, + &eed_test, + NULL)) { + Base *base = gz_ele->bases[base_index]; + best.ob = base->object; + if (eve_test) { + best.ele = (BMElem *)eve_test; + } + else if (eed_test) { + best.ele = (BMElem *)eed_test; + } + else { + BLI_assert(0); + } + best.base_index = base_index; + /* Check above should never fail, if it does it's an internal error. */ + BLI_assert(best.base_index != -1); + } + } + + BMesh *bm = NULL; + + gz_ele->base_index = -1; + gz_ele->vert_index = -1; + gz_ele->edge_index = -1; + gz_ele->face_index = -1; + + if (best.ele) { + gz_ele->base_index = best.base_index; + bm = BKE_editmesh_from_object(gz_ele->bases[gz_ele->base_index]->object)->bm; + BM_mesh_elem_index_ensure(bm, best.ele->head.htype); + + if (best.ele->head.htype == BM_VERT) { + gz_ele->vert_index = BM_elem_index_get(best.ele); + } + else if (best.ele->head.htype == BM_EDGE) { + gz_ele->edge_index = BM_elem_index_get(best.ele); + } + else if (best.ele->head.htype == BM_FACE) { + gz_ele->face_index = BM_elem_index_get(best.ele); + } + } + + if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) && + (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) { + /* pass (only recalculate on change) */ + } + else { + if (best.ele) { + const float(*coords)[3] = NULL; + { + Object *ob = gz_ele->bases[gz_ele->base_index]->object; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); + if (me_eval->runtime.edit_data) { + coords = me_eval->runtime.edit_data->vertexCos; + } + } + EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords); + } + else { + EDBM_preselect_elem_clear(gz_ele->psel); + } + + RNA_int_set(gz->ptr, "object_index", gz_ele->base_index); + RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index); + RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index); + RNA_int_set(gz->ptr, "face_index", gz_ele->face_index); + + ARegion *ar = CTX_wm_region(C); + ED_region_tag_redraw(ar); + } + + // return best.eed ? 0 : -1; + return -1; } static void gizmo_preselect_elem_setup(wmGizmo *gz) { - MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; - if (gz_ele->psel == NULL) { - gz_ele->psel = EDBM_preselect_elem_create(); - } - gz_ele->base_index = -1; + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + if (gz_ele->psel == NULL) { + gz_ele->psel = EDBM_preselect_elem_create(); + } + gz_ele->base_index = -1; } static void gizmo_preselect_elem_free(wmGizmo *gz) { - MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; - EDBM_preselect_elem_destroy(gz_ele->psel); - gz_ele->psel = NULL; - MEM_SAFE_FREE(gz_ele->bases); + MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz; + EDBM_preselect_elem_destroy(gz_ele->psel); + gz_ele->psel = NULL; + MEM_SAFE_FREE(gz_ele->bases); } -static int gizmo_preselect_elem_invoke( - bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event)) +static int gizmo_preselect_elem_invoke(bContext *UNUSED(C), + wmGizmo *UNUSED(gz), + const wmEvent *UNUSED(event)) { - return OPERATOR_PASS_THROUGH; + return OPERATOR_PASS_THROUGH; } static void GIZMO_GT_mesh_preselect_elem_3d(wmGizmoType *gzt) { - /* identifiers */ - gzt->idname = "GIZMO_GT_mesh_preselect_elem_3d"; - - /* api callbacks */ - gzt->invoke = gizmo_preselect_elem_invoke; - gzt->draw = gizmo_preselect_elem_draw; - gzt->test_select = gizmo_preselect_elem_test_select; - gzt->setup = gizmo_preselect_elem_setup; - gzt->free = gizmo_preselect_elem_free; - - gzt->struct_size = sizeof(MeshElemGizmo3D); - - RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); - RNA_def_int(gzt->srna, "vert_index", -1, -1, INT_MAX, "Vert Index", "", -1, INT_MAX); - RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); - RNA_def_int(gzt->srna, "face_index", -1, -1, INT_MAX, "Face Index", "", -1, INT_MAX); + /* identifiers */ + gzt->idname = "GIZMO_GT_mesh_preselect_elem_3d"; + + /* api callbacks */ + gzt->invoke = gizmo_preselect_elem_invoke; + gzt->draw = gizmo_preselect_elem_draw; + gzt->test_select = gizmo_preselect_elem_test_select; + gzt->setup = gizmo_preselect_elem_setup; + gzt->free = gizmo_preselect_elem_free; + + gzt->struct_size = sizeof(MeshElemGizmo3D); + + RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "vert_index", -1, -1, INT_MAX, "Vert Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "face_index", -1, -1, INT_MAX, "Face Index", "", -1, INT_MAX); } /** \} */ @@ -255,162 +253,155 @@ static void GIZMO_GT_mesh_preselect_elem_3d(wmGizmoType *gzt) * \{ */ typedef struct MeshEdgeRingGizmo3D { - wmGizmo gizmo; - Base **bases; - uint bases_len; - int base_index; - int edge_index; - struct EditMesh_PreSelEdgeRing *psel; + wmGizmo gizmo; + Base **bases; + uint bases_len; + int base_index; + int edge_index; + struct EditMesh_PreSelEdgeRing *psel; } MeshEdgeRingGizmo3D; static void gizmo_preselect_edgering_draw(const bContext *UNUSED(C), wmGizmo *gz) { - MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; - if (gz_ring->base_index != -1) { - Object *ob = gz_ring->bases[gz_ring->base_index]->object; - EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat); - } + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + if (gz_ring->base_index != -1) { + Object *ob = gz_ring->bases[gz_ring->base_index]->object; + EDBM_preselect_edgering_draw(gz_ring->psel, ob->obmat); + } } -static int gizmo_preselect_edgering_test_select( - bContext *C, wmGizmo *gz, const int mval[2]) +static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { - MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; - struct { - Object *ob; - BMEdge *eed; - float dist; - int base_index; - } best = { - .dist = ED_view3d_select_dist_px(), - }; - - struct { - int base_index; - int edge_index; - } prev = { - .base_index = gz_ring->base_index, - .edge_index = gz_ring->edge_index, - }; - - { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - if (((gz_ring->bases)) == NULL || - (gz_ring->bases[0] != view_layer->basact)) - { - MEM_SAFE_FREE(gz_ring->bases); - gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( - view_layer, v3d, &gz_ring->bases_len); - } - } - - ViewContext vc; - em_setup_viewcontext(C, &vc); - copy_v2_v2_int(vc.mval, mval); - - for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) { - Object *ob_iter = gz_ring->bases[base_index]->object; - ED_view3d_viewcontext_init_object(&vc, ob_iter); - BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL); - if (eed_test) { - best.ob = ob_iter; - best.eed = eed_test; - best.base_index = base_index; - } - } - - BMesh *bm = NULL; - if (best.eed) { - gz_ring->base_index = best.base_index; - bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm; - BM_mesh_elem_index_ensure(bm, BM_EDGE); - gz_ring->edge_index = BM_elem_index_get(best.eed); - } - else { - gz_ring->base_index = -1; - gz_ring->edge_index = -1; - } - - - if ((prev.base_index == gz_ring->base_index) && - (prev.edge_index == gz_ring->edge_index)) - { - /* pass (only recalculate on change) */ - } - else { - if (best.eed) { - const float (*coords)[3] = NULL; - { - Object *ob = gz_ring->bases[gz_ring->base_index]->object; - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); - if (me_eval->runtime.edit_data) { - coords = me_eval->runtime.edit_data->vertexCos; - } - } - EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords); - } - else { - EDBM_preselect_edgering_clear(gz_ring->psel); - } - - RNA_int_set(gz->ptr, "object_index", gz_ring->base_index); - RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); - - ARegion *ar = CTX_wm_region(C); - ED_region_tag_redraw(ar); - } - - // return best.eed ? 0 : -1; - return -1; + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + struct { + Object *ob; + BMEdge *eed; + float dist; + int base_index; + } best = { + .dist = ED_view3d_select_dist_px(), + }; + + struct { + int base_index; + int edge_index; + } prev = { + .base_index = gz_ring->base_index, + .edge_index = gz_ring->edge_index, + }; + + { + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + if (((gz_ring->bases)) == NULL || (gz_ring->bases[0] != view_layer->basact)) { + MEM_SAFE_FREE(gz_ring->bases); + gz_ring->bases = BKE_view_layer_array_from_bases_in_edit_mode( + view_layer, v3d, &gz_ring->bases_len); + } + } + + ViewContext vc; + em_setup_viewcontext(C, &vc); + copy_v2_v2_int(vc.mval, mval); + + for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) { + Object *ob_iter = gz_ring->bases[base_index]->object; + ED_view3d_viewcontext_init_object(&vc, ob_iter); + BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL); + if (eed_test) { + best.ob = ob_iter; + best.eed = eed_test; + best.base_index = base_index; + } + } + + BMesh *bm = NULL; + if (best.eed) { + gz_ring->base_index = best.base_index; + bm = BKE_editmesh_from_object(gz_ring->bases[gz_ring->base_index]->object)->bm; + BM_mesh_elem_index_ensure(bm, BM_EDGE); + gz_ring->edge_index = BM_elem_index_get(best.eed); + } + else { + gz_ring->base_index = -1; + gz_ring->edge_index = -1; + } + + if ((prev.base_index == gz_ring->base_index) && (prev.edge_index == gz_ring->edge_index)) { + /* pass (only recalculate on change) */ + } + else { + if (best.eed) { + const float(*coords)[3] = NULL; + { + Object *ob = gz_ring->bases[gz_ring->base_index]->object; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data); + if (me_eval->runtime.edit_data) { + coords = me_eval->runtime.edit_data->vertexCos; + } + } + EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords); + } + else { + EDBM_preselect_edgering_clear(gz_ring->psel); + } + + RNA_int_set(gz->ptr, "object_index", gz_ring->base_index); + RNA_int_set(gz->ptr, "edge_index", gz_ring->edge_index); + + ARegion *ar = CTX_wm_region(C); + ED_region_tag_redraw(ar); + } + + // return best.eed ? 0 : -1; + return -1; } static void gizmo_preselect_edgering_setup(wmGizmo *gz) { - MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; - if (gz_ring->psel == NULL) { - gz_ring->psel = EDBM_preselect_edgering_create(); - } - gz_ring->base_index = -1; + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + if (gz_ring->psel == NULL) { + gz_ring->psel = EDBM_preselect_edgering_create(); + } + gz_ring->base_index = -1; } static void gizmo_preselect_edgering_free(wmGizmo *gz) { - MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; - EDBM_preselect_edgering_destroy(gz_ring->psel); - gz_ring->psel = NULL; - MEM_SAFE_FREE(gz_ring->bases); + MeshEdgeRingGizmo3D *gz_ring = (MeshEdgeRingGizmo3D *)gz; + EDBM_preselect_edgering_destroy(gz_ring->psel); + gz_ring->psel = NULL; + MEM_SAFE_FREE(gz_ring->bases); } -static int gizmo_preselect_edgering_invoke( - bContext *UNUSED(C), wmGizmo *UNUSED(gz), const wmEvent *UNUSED(event)) +static int gizmo_preselect_edgering_invoke(bContext *UNUSED(C), + wmGizmo *UNUSED(gz), + const wmEvent *UNUSED(event)) { - return OPERATOR_PASS_THROUGH; + return OPERATOR_PASS_THROUGH; } - static void GIZMO_GT_mesh_preselect_edgering_3d(wmGizmoType *gzt) { - /* identifiers */ - gzt->idname = "GIZMO_GT_mesh_preselect_edgering_3d"; + /* identifiers */ + gzt->idname = "GIZMO_GT_mesh_preselect_edgering_3d"; - /* api callbacks */ - gzt->invoke = gizmo_preselect_edgering_invoke; - gzt->draw = gizmo_preselect_edgering_draw; - gzt->test_select = gizmo_preselect_edgering_test_select; - gzt->setup = gizmo_preselect_edgering_setup; - gzt->free = gizmo_preselect_edgering_free; + /* api callbacks */ + gzt->invoke = gizmo_preselect_edgering_invoke; + gzt->draw = gizmo_preselect_edgering_draw; + gzt->test_select = gizmo_preselect_edgering_test_select; + gzt->setup = gizmo_preselect_edgering_setup; + gzt->free = gizmo_preselect_edgering_free; - gzt->struct_size = sizeof(MeshEdgeRingGizmo3D); + gzt->struct_size = sizeof(MeshEdgeRingGizmo3D); - RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); - RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "object_index", -1, -1, INT_MAX, "Object Index", "", -1, INT_MAX); + RNA_def_int(gzt->srna, "edge_index", -1, -1, INT_MAX, "Edge Index", "", -1, INT_MAX); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Gizmo API * @@ -418,13 +409,12 @@ static void GIZMO_GT_mesh_preselect_edgering_3d(wmGizmoType *gzt) void ED_gizmotypes_preselect_3d(void) { - WM_gizmotype_append(GIZMO_GT_mesh_preselect_elem_3d); - WM_gizmotype_append(GIZMO_GT_mesh_preselect_edgering_3d); + WM_gizmotype_append(GIZMO_GT_mesh_preselect_elem_3d); + WM_gizmotype_append(GIZMO_GT_mesh_preselect_edgering_3d); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Gizmo Accessors * @@ -432,53 +422,55 @@ void ED_gizmotypes_preselect_3d(void) * the information from this gizmo. * \{ */ -void ED_view3d_gizmo_mesh_preselect_get_active( - bContext *C, wmGizmo *gz, - Base **r_base, BMElem **r_ele) +void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C, + wmGizmo *gz, + Base **r_base, + BMElem **r_ele) { - ViewLayer *view_layer = CTX_data_view_layer(C); - - const int object_index = RNA_int_get(gz->ptr, "object_index"); - - /* weak, allocate an array just to access the index. */ - Base *base = NULL; - Object *obedit = NULL; - { - uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, CTX_wm_view3d(C), &bases_len); - if (object_index < bases_len) { - base = bases[object_index]; - obedit = base->object; - } - MEM_freeN(bases); - } - - *r_base = base; - *r_ele = NULL; - - if (obedit) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - PropertyRNA *prop; - - /* Ring select only defines edge, check properties exist first. */ - prop = RNA_struct_find_property(gz->ptr, "vert_index"); - const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; - prop = RNA_struct_find_property(gz->ptr, "edge_index"); - const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; - prop = RNA_struct_find_property(gz->ptr, "face_index"); - const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; - - if (vert_index != -1) { - *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index); - } - else if (edge_index != -1) { - *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index); - } - else if (face_index != -1) { - *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index); - } - } + ViewLayer *view_layer = CTX_data_view_layer(C); + + const int object_index = RNA_int_get(gz->ptr, "object_index"); + + /* weak, allocate an array just to access the index. */ + Base *base = NULL; + Object *obedit = NULL; + { + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode( + view_layer, CTX_wm_view3d(C), &bases_len); + if (object_index < bases_len) { + base = bases[object_index]; + obedit = base->object; + } + MEM_freeN(bases); + } + + *r_base = base; + *r_ele = NULL; + + if (obedit) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + PropertyRNA *prop; + + /* Ring select only defines edge, check properties exist first. */ + prop = RNA_struct_find_property(gz->ptr, "vert_index"); + const int vert_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; + prop = RNA_struct_find_property(gz->ptr, "edge_index"); + const int edge_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; + prop = RNA_struct_find_property(gz->ptr, "face_index"); + const int face_index = prop ? RNA_property_int_get(gz->ptr, prop) : -1; + + if (vert_index != -1) { + *r_ele = (BMElem *)BM_vert_at_index_find(bm, vert_index); + } + else if (edge_index != -1) { + *r_ele = (BMElem *)BM_edge_at_index_find(bm, edge_index); + } + else if (face_index != -1) { + *r_ele = (BMElem *)BM_face_at_index_find(bm, face_index); + } + } } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c index 253e02ca639..566a15cc7b7 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c @@ -57,7 +57,7 @@ #include "WM_types.h" #include "WM_toolsystem.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ #include "GPU_immediate.h" #include "GPU_immediate_util.h" @@ -68,20 +68,18 @@ static const char *view3d_gzgt_ruler_id = "VIEW3D_GGT_ruler"; - #define MVAL_MAX_PX_DIST 12.0f /* -------------------------------------------------------------------- */ /* Ruler Item (we can have many) */ enum { - /** Use protractor. */ - RULERITEM_USE_ANGLE = (1 << 0), - /** Protractor vertex is selected (deleting removes it). */ - RULERITEM_USE_ANGLE_ACTIVE = (1 << 1), + /** Use protractor. */ + RULERITEM_USE_ANGLE = (1 << 0), + /** Protractor vertex is selected (deleting removes it). */ + RULERITEM_USE_ANGLE_ACTIVE = (1 << 1), }; - /* keep smaller then selection, since we may want click elsewhere without selecting a ruler */ #define RULER_PICK_DIST 12.0f #define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST) @@ -93,47 +91,47 @@ enum { /* Ruler Info (wmGizmoGroup customdata) */ enum { - RULER_STATE_NORMAL = 0, - RULER_STATE_DRAG, + RULER_STATE_NORMAL = 0, + RULER_STATE_DRAG, }; enum { - RULER_SNAP_OK = (1 << 0), + RULER_SNAP_OK = (1 << 0), }; struct RulerItem; typedef struct RulerInfo { - struct RulerItem *item_active; - int flag; - int snap_flag; - int state; + struct RulerItem *item_active; + int flag; + int snap_flag; + int state; - struct SnapObjectContext *snap_context; + struct SnapObjectContext *snap_context; - /* wm state */ - wmWindow *win; - ScrArea *sa; - ARegion *ar; /* re-assigned every modal update */ + /* wm state */ + wmWindow *win; + ScrArea *sa; + ARegion *ar; /* re-assigned every modal update */ } RulerInfo; /* -------------------------------------------------------------------- */ /* Ruler Item (two or three points) */ typedef struct RulerItem { - wmGizmo gz; + wmGizmo gz; - /* worldspace coords, middle being optional */ - float co[3][3]; + /* worldspace coords, middle being optional */ + float co[3][3]; - int flag; - int raycast_dir; /* RULER_DIRECTION_* */ + int flag; + int raycast_dir; /* RULER_DIRECTION_* */ } RulerItem; typedef struct RulerInteraction { - /* selected coord */ - char co_index; /* 0 -> 2 */ - float drag_start_co[3]; + /* selected coord */ + char co_index; /* 0 -> 2 */ + float drag_start_co[3]; } RulerInteraction; /* -------------------------------------------------------------------- */ @@ -142,121 +140,123 @@ typedef struct RulerInteraction { static RulerItem *ruler_item_add(wmGizmoGroup *gzgroup) { - /* could pass this as an arg */ - const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true); - RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL); - WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true); - return ruler_item; + /* could pass this as an arg */ + const wmGizmoType *gzt_ruler = WM_gizmotype_find("VIEW3D_GT_ruler_item", true); + RulerItem *ruler_item = (RulerItem *)WM_gizmo_new_ptr(gzt_ruler, gzgroup, NULL); + WM_gizmo_set_flag(&ruler_item->gz, WM_GIZMO_DRAW_MODAL, true); + return ruler_item; } static void ruler_item_remove(bContext *C, wmGizmoGroup *gzgroup, RulerItem *ruler_item) { - RulerInfo *ruler_info = gzgroup->customdata; - if (ruler_info->item_active == ruler_item) { - ruler_info->item_active = NULL; - } - WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C); + RulerInfo *ruler_info = gzgroup->customdata; + if (ruler_info->item_active == ruler_item) { + ruler_info->item_active = NULL; + } + WM_gizmo_unlink(&gzgroup->gizmos, gzgroup->parent_gzmap, &ruler_item->gz, C); } -static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, - char *numstr, size_t numstr_size, int prec) +static void ruler_item_as_string( + RulerItem *ruler_item, UnitSettings *unit, char *numstr, size_t numstr_size, int prec) { - if (ruler_item->flag & RULERITEM_USE_ANGLE) { - const float ruler_angle = angle_v3v3v3(ruler_item->co[0], - ruler_item->co[1], - ruler_item->co[2]); - - if (unit->system == USER_UNIT_NONE) { - BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); - } - else { - bUnit_AsString2( - numstr, numstr_size, (double)ruler_angle, - prec, B_UNIT_ROTATION, unit, false); - } - } - else { - const float ruler_len = len_v3v3(ruler_item->co[0], - ruler_item->co[2]); - - if (unit->system == USER_UNIT_NONE) { - BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); - } - else { - bUnit_AsString2( - numstr, numstr_size, (double)(ruler_len * unit->scale_length), - prec, B_UNIT_LENGTH, unit, false); - } - } + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + const float ruler_angle = angle_v3v3v3( + ruler_item->co[0], ruler_item->co[1], ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); + } + else { + bUnit_AsString2( + numstr, numstr_size, (double)ruler_angle, prec, B_UNIT_ROTATION, unit, false); + } + } + else { + const float ruler_len = len_v3v3(ruler_item->co[0], ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); + } + else { + bUnit_AsString2(numstr, + numstr_size, + (double)(ruler_len * unit->scale_length), + prec, + B_UNIT_LENGTH, + unit, + false); + } + } } -static bool view3d_ruler_pick( - wmGizmoGroup *gzgroup, RulerItem *ruler_item, const float mval[2], - int *r_co_index) +static bool view3d_ruler_pick(wmGizmoGroup *gzgroup, + RulerItem *ruler_item, + const float mval[2], + int *r_co_index) { - RulerInfo *ruler_info = gzgroup->customdata; - ARegion *ar = ruler_info->ar; - bool found = false; - - float dist_best = RULER_PICK_DIST_SQ; - int co_index_best = -1; - - { - float co_ss[3][2]; - float dist; - int j; - - /* should these be checked? - ok for now not to */ - for (j = 0; j < 3; j++) { - ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); - } - - if (ruler_item->flag & RULERITEM_USE_ANGLE) { - dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]), - dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2])); - if (dist < dist_best) { - dist_best = dist; - found = true; - - { - const float dist_points[3] = { - len_squared_v2v2(co_ss[0], mval), - len_squared_v2v2(co_ss[1], mval), - len_squared_v2v2(co_ss[2], mval), - }; - if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) { - co_index_best = min_axis_v3(dist_points); - } - else { - co_index_best = -1; - } - } - } - } - else { - dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]); - if (dist < dist_best) { - dist_best = dist; - found = true; - - { - const float dist_points[2] = { - len_squared_v2v2(co_ss[0], mval), - len_squared_v2v2(co_ss[2], mval), - }; - if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) { - co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2; - } - else { - co_index_best = -1; - } - } - } - } - } - - *r_co_index = co_index_best; - return found; + RulerInfo *ruler_info = gzgroup->customdata; + ARegion *ar = ruler_info->ar; + bool found = false; + + float dist_best = RULER_PICK_DIST_SQ; + int co_index_best = -1; + + { + float co_ss[3][2]; + float dist; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]), + dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2])); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[3] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[1], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = min_axis_v3(dist_points); + } + else { + co_index_best = -1; + } + } + } + } + else { + dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]); + if (dist < dist_best) { + dist_best = dist; + found = true; + + { + const float dist_points[2] = { + len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[2], mval), + }; + if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2; + } + else { + co_index_best = -1; + } + } + } + } + } + + *r_co_index = co_index_best; + return found; } /** @@ -265,113 +265,114 @@ static bool view3d_ruler_pick( */ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state) { - Main *bmain = CTX_data_main(C); - if (state == ruler_info->state) { - return; - } - - /* always remove */ - if (ruler_info->snap_context) { - ED_transform_snap_object_context_destroy(ruler_info->snap_context); - ruler_info->snap_context = NULL; - } - - if (state == RULER_STATE_NORMAL) { - /* pass */ - } - else if (state == RULER_STATE_DRAG) { - ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( - bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0, - ruler_info->ar, CTX_wm_view3d(C)); - } - else { - BLI_assert(0); - } - - ruler_info->state = state; + Main *bmain = CTX_data_main(C); + if (state == ruler_info->state) { + return; + } + + /* always remove */ + if (ruler_info->snap_context) { + ED_transform_snap_object_context_destroy(ruler_info->snap_context); + ruler_info->snap_context = NULL; + } + + if (state == RULER_STATE_NORMAL) { + /* pass */ + } + else if (state == RULER_STATE_DRAG) { + ruler_info->snap_context = ED_transform_snap_object_context_create_view3d( + bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C)); + } + else { + BLI_assert(0); + } + + ruler_info->state = state; } -static void view3d_ruler_item_project( - RulerInfo *ruler_info, float r_co[3], - const int xy[2]) +static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], const int xy[2]) { - ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co); + ED_view3d_win_to_3d_int(ruler_info->sa->spacedata.first, ruler_info->ar, r_co, xy, r_co); } /* use for mousemove events */ -static bool view3d_ruler_item_mousemove( - RulerInfo *ruler_info, RulerItem *ruler_item, const int mval[2], - const bool do_thickness, const bool do_snap) +static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info, + RulerItem *ruler_item, + const int mval[2], + const bool do_thickness, + const bool do_snap) { - const float eps_bias = 0.0002f; - float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ - - ruler_info->snap_flag &= ~RULER_SNAP_OK; - - if (ruler_item) { - RulerInteraction *inter = ruler_item->gz.interaction_data; - float *co = ruler_item->co[inter->co_index]; - /* restore the initial depth */ - copy_v3_v3(co, inter->drag_start_co); - view3d_ruler_item_project(ruler_info, co, mval); - if (do_thickness && inter->co_index != 1) { - // Scene *scene = CTX_data_scene(C); - // View3D *v3d = ruler_info->sa->spacedata.first; - const float mval_fl[2] = {UNPACK2(mval)}; - float ray_normal[3]; - float ray_start[3]; - float *co_other; - - co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0]; - - if (ED_transform_snap_object_project_view3d( - ruler_info->snap_context, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - .use_object_edit_cage = true, - }, - mval_fl, &dist_px, - co, ray_normal)) - { - negate_v3(ray_normal); - /* add some bias */ - madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias); - ED_transform_snap_object_project_ray( - ruler_info->snap_context, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - .use_object_edit_cage = true, - }, - ray_start, ray_normal, NULL, - co_other, NULL); - } - } - else if (do_snap) { - const float mval_fl[2] = {UNPACK2(mval)}; - - if (ED_transform_snap_object_project_view3d( - ruler_info->snap_context, - (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE), - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - .use_object_edit_cage = true, - .use_occlusion_test = true, - }, - mval_fl, &dist_px, - co, NULL)) - { - ruler_info->snap_flag |= RULER_SNAP_OK; - } - } - return true; - } - else { - return false; - } + const float eps_bias = 0.0002f; + float dist_px = MVAL_MAX_PX_DIST * U.pixelsize; /* snap dist */ + + ruler_info->snap_flag &= ~RULER_SNAP_OK; + + if (ruler_item) { + RulerInteraction *inter = ruler_item->gz.interaction_data; + float *co = ruler_item->co[inter->co_index]; + /* restore the initial depth */ + copy_v3_v3(co, inter->drag_start_co); + view3d_ruler_item_project(ruler_info, co, mval); + if (do_thickness && inter->co_index != 1) { + // Scene *scene = CTX_data_scene(C); + // View3D *v3d = ruler_info->sa->spacedata.first; + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_normal[3]; + float ray_start[3]; + float *co_other; + + co_other = ruler_item->co[inter->co_index == 0 ? 2 : 0]; + + if (ED_transform_snap_object_project_view3d(ruler_info->snap_context, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + mval_fl, + &dist_px, + co, + ray_normal)) { + negate_v3(ray_normal); + /* add some bias */ + madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias); + ED_transform_snap_object_project_ray(ruler_info->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + }, + ray_start, + ray_normal, + NULL, + co_other, + NULL); + } + } + else if (do_snap) { + const float mval_fl[2] = {UNPACK2(mval)}; + + if (ED_transform_snap_object_project_view3d( + ruler_info->snap_context, + (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE), + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + .use_object_edit_cage = true, + .use_occlusion_test = true, + }, + mval_fl, + &dist_px, + co, + NULL)) { + ruler_info->snap_flag |= RULER_SNAP_OK; + } + } + return true; + } + else { + return false; + } } - /** \} */ /* -------------------------------------------------------------------- */ @@ -381,114 +382,115 @@ static bool view3d_ruler_item_mousemove( #define RULER_ID "RulerData3D" static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup) { - // RulerInfo *ruler_info = gzgroup->customdata; - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - - bGPdata *gpd; - bGPDlayer *gpl; - bGPDframe *gpf; - bGPDstroke *gps; - RulerItem *ruler_item; - const char *ruler_name = RULER_ID; - bool changed = false; - - if (scene->gpd == NULL) { - scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations"); - } - gpd = scene->gpd; - - gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info)); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false); - copy_v4_v4(gpl->color, U.gpencil_new_layer_col); - gpl->thickness = 1; - gpl->flag |= GP_LAYER_HIDE; - } - - gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW); - BKE_gpencil_free_strokes(gpf); - - for (ruler_item = gzgroup->gizmos.first; ruler_item; ruler_item = (RulerItem *)ruler_item->gz.next) { - bGPDspoint *pt; - int j; - - /* allocate memory for a new stroke */ - gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); - if (ruler_item->flag & RULERITEM_USE_ANGLE) { - gps->totpoints = 3; - pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - for (j = 0; j < 3; j++) { - copy_v3_v3(&pt->x, ruler_item->co[j]); - pt->pressure = 1.0f; - pt->strength = 1.0f; - pt++; - } - } - else { - gps->totpoints = 2; - pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - for (j = 0; j < 3; j += 2) { - copy_v3_v3(&pt->x, ruler_item->co[j]); - pt->pressure = 1.0f; - pt->strength = 1.0f; - pt++; - } - } - gps->flag = GP_STROKE_3DSPACE; - gps->thickness = 3; - gps->gradient_f = 1.0f; - gps->gradient_s[0] = 1.0f; - gps->gradient_s[1] = 1.0f; - - BLI_addtail(&gpf->strokes, gps); - changed = true; - } - - return changed; + // RulerInfo *ruler_info = gzgroup->customdata; + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + + bGPdata *gpd; + bGPDlayer *gpl; + bGPDframe *gpf; + bGPDstroke *gps; + RulerItem *ruler_item; + const char *ruler_name = RULER_ID; + bool changed = false; + + if (scene->gpd == NULL) { + scene->gpd = BKE_gpencil_data_addnew(bmain, "Annotations"); + } + gpd = scene->gpd; + + gpl = BLI_findstring(&gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false); + copy_v4_v4(gpl->color, U.gpencil_new_layer_col); + gpl->thickness = 1; + gpl->flag |= GP_LAYER_HIDE; + } + + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW); + BKE_gpencil_free_strokes(gpf); + + for (ruler_item = gzgroup->gizmos.first; ruler_item; + ruler_item = (RulerItem *)ruler_item->gz.next) { + bGPDspoint *pt; + int j; + + /* allocate memory for a new stroke */ + gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + gps->totpoints = 3; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j++) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + else { + gps->totpoints = 2; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt++; + } + } + gps->flag = GP_STROKE_3DSPACE; + gps->thickness = 3; + gps->gradient_f = 1.0f; + gps->gradient_s[0] = 1.0f; + gps->gradient_s[1] = 1.0f; + + BLI_addtail(&gpf->strokes, gps); + changed = true; + } + + return changed; } static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup) { - Scene *scene = CTX_data_scene(C); - bool changed = false; - - if (scene->gpd) { - bGPDlayer *gpl; - const char *ruler_name = RULER_ID; - gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); - if (gpl) { - bGPDframe *gpf; - gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); - if (gpf) { - bGPDstroke *gps; - for (gps = gpf->strokes.first; gps; gps = gps->next) { - bGPDspoint *pt = gps->points; - int j; - RulerItem *ruler_item = NULL; - if (gps->totpoints == 3) { - ruler_item = ruler_item_add(gzgroup); - for (j = 0; j < 3; j++) { - copy_v3_v3(ruler_item->co[j], &pt->x); - pt++; - } - ruler_item->flag |= RULERITEM_USE_ANGLE; - changed = true; - } - else if (gps->totpoints == 2) { - ruler_item = ruler_item_add(gzgroup); - for (j = 0; j < 3; j += 2) { - copy_v3_v3(ruler_item->co[j], &pt->x); - pt++; - } - changed = true; - } - } - } - } - } - - return changed; + Scene *scene = CTX_data_scene(C); + bool changed = false; + + if (scene->gpd) { + bGPDlayer *gpl; + const char *ruler_name = RULER_ID; + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl) { + bGPDframe *gpf; + gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_USE_PREV); + if (gpf) { + bGPDstroke *gps; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt = gps->points; + int j; + RulerItem *ruler_item = NULL; + if (gps->totpoints == 3) { + ruler_item = ruler_item_add(gzgroup); + for (j = 0; j < 3; j++) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + ruler_item->flag |= RULERITEM_USE_ANGLE; + changed = true; + } + else if (gps->totpoints == 2) { + ruler_item = ruler_item_add(gzgroup); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + changed = true; + } + } + } + } + } + + return changed; } /** \} */ @@ -499,488 +501,492 @@ static bool view3d_ruler_from_gpencil(const bContext *C, wmGizmoGroup *gzgroup) static void gizmo_ruler_draw(const bContext *C, wmGizmo *gz) { - Scene *scene = CTX_data_scene(C); - UnitSettings *unit = &scene->unit; - RulerInfo *ruler_info = gz->parent_gzgroup->customdata; - RulerItem *ruler_item = (RulerItem *)gz; - ARegion *ar = ruler_info->ar; - RegionView3D *rv3d = ar->regiondata; - const float cap_size = 4.0f; - const float bg_margin = 4.0f * U.pixelsize; - const float arc_size = 64.0f * U.pixelsize; + Scene *scene = CTX_data_scene(C); + UnitSettings *unit = &scene->unit; + RulerInfo *ruler_info = gz->parent_gzgroup->customdata; + RulerItem *ruler_item = (RulerItem *)gz; + ARegion *ar = ruler_info->ar; + RegionView3D *rv3d = ar->regiondata; + const float cap_size = 4.0f; + const float bg_margin = 4.0f * U.pixelsize; + const float arc_size = 64.0f * U.pixelsize; #define ARC_STEPS 24 - const int arc_steps = ARC_STEPS; - const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - uchar color_text[3]; - uchar color_wire[3]; - float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; - - /* anti-aliased lines for more consistent appearance */ - GPU_line_smooth(true); - GPU_line_width(1.0f); - - BLF_enable(blf_mono_font, BLF_ROTATION); - BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); - BLF_rotation(blf_mono_font, 0.0f); - - UI_GetThemeColor3ubv(TH_TEXT, color_text); - UI_GetThemeColor3ubv(TH_WIRE, color_wire); - - /* Avoid white on white text. (TODO Fix by using theme) */ - if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) { - copy_v3_fl(color_back, 0.0f); - } - - const bool is_act = (ruler_info->item_active == ruler_item); - float dir_ruler[2]; - float co_ss[3][2]; - int j; - - /* should these be checked? - ok for now not to */ - for (j = 0; j < 3; j++) { - ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); - } - - GPU_blend(true); - - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - if (ruler_item->flag & RULERITEM_USE_ANGLE) { - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - - immUniform1i("colors_len", 2); /* "advanced" mode */ - const float *col = is_act ? color_act : color_base; - immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); - immUniform1f("dash_width", 6.0f); - - immBegin(GPU_PRIM_LINE_STRIP, 3); - - immVertex2fv(shdr_pos, co_ss[0]); - immVertex2fv(shdr_pos, co_ss[1]); - immVertex2fv(shdr_pos, co_ss[2]); - - immEnd(); - - immUnbindProgram(); + const int arc_steps = ARC_STEPS; + const float color_act[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float color_base[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + uchar color_text[3]; + uchar color_wire[3]; + float color_back[4] = {1.0f, 1.0f, 1.0f, 0.5f}; - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + /* anti-aliased lines for more consistent appearance */ + GPU_line_smooth(true); + GPU_line_width(1.0f); - /* arc */ - { - float dir_tmp[3]; - float co_tmp[3]; - float arc_ss_coord[2]; + BLF_enable(blf_mono_font, BLF_ROTATION); + BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); + BLF_rotation(blf_mono_font, 0.0f); - float dir_a[3]; - float dir_b[3]; - float quat[4]; - float axis[3]; - float angle; - const float px_scale = (ED_view3d_pixel_size_no_ui_scale(rv3d, ruler_item->co[1]) * - min_fff(arc_size, - len_v2v2(co_ss[0], co_ss[1]) / 2.0f, - len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); + UI_GetThemeColor3ubv(TH_TEXT, color_text); + UI_GetThemeColor3ubv(TH_WIRE, color_wire); - sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); - sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); - normalize_v3(dir_a); - normalize_v3(dir_b); + /* Avoid white on white text. (TODO Fix by using theme) */ + if ((int)color_text[0] + (int)color_text[1] + (int)color_text[2] > 127 * 3 * 0.6f) { + copy_v3_fl(color_back, 0.0f); + } - cross_v3_v3v3(axis, dir_a, dir_b); - angle = angle_normalized_v3v3(dir_a, dir_b); + const bool is_act = (ruler_info->item_active == ruler_item); + float dir_ruler[2]; + float co_ss[3][2]; + int j; - axis_angle_to_quat(quat, axis, angle / arc_steps); + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + GPU_blend(true); + + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - copy_v3_v3(dir_tmp, dir_a); + immUniform1i("colors_len", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv( + "colors", + (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, + 2); + immUniform1f("dash_width", 6.0f); + + immBegin(GPU_PRIM_LINE_STRIP, 3); - immUniformColor3ubv(color_wire); + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[1]); + immVertex2fv(shdr_pos, co_ss[2]); + + immEnd(); + + immUnbindProgram(); - immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1); - - for (j = 0; j <= arc_steps; j++) { - madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); - ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); - mul_qt_v3(quat, dir_tmp); - - immVertex2fv(shdr_pos, arc_ss_coord); - } - - immEnd(); - } - - /* capping */ - { - float rot_90_vec_a[2]; - float rot_90_vec_b[2]; - float cap[2]; + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); - rot_90_vec_a[0] = -dir_ruler[1]; - rot_90_vec_a[1] = dir_ruler[0]; - normalize_v2(rot_90_vec_a); + /* arc */ + { + float dir_tmp[3]; + float co_tmp[3]; + float arc_ss_coord[2]; - sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); - rot_90_vec_b[0] = -dir_ruler[1]; - rot_90_vec_b[1] = dir_ruler[0]; - normalize_v2(rot_90_vec_b); + float dir_a[3]; + float dir_b[3]; + float quat[4]; + float axis[3]; + float angle; + const float px_scale = (ED_view3d_pixel_size_no_ui_scale(rv3d, ruler_item->co[1]) * + min_fff(arc_size, + len_v2v2(co_ss[0], co_ss[1]) / 2.0f, + len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); - GPU_blend(true); + sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); + sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); + normalize_v3(dir_a); + normalize_v3(dir_b); + + cross_v3_v3v3(axis, dir_a, dir_b); + angle = angle_normalized_v3v3(dir_a, dir_b); + + axis_angle_to_quat(quat, axis, angle / arc_steps); + + copy_v3_v3(dir_tmp, dir_a); + + immUniformColor3ubv(color_wire); + + immBegin(GPU_PRIM_LINE_STRIP, arc_steps + 1); + + for (j = 0; j <= arc_steps; j++) { + madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coord, V3D_PROJ_TEST_NOP); + mul_qt_v3(quat, dir_tmp); + + immVertex2fv(shdr_pos, arc_ss_coord); + } + + immEnd(); + } + + /* capping */ + { + float rot_90_vec_a[2]; + float rot_90_vec_b[2]; + float cap[2]; + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); + rot_90_vec_a[0] = -dir_ruler[1]; + rot_90_vec_a[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_a); + + sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); + rot_90_vec_b[0] = -dir_ruler[1]; + rot_90_vec_b[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_b); + + GPU_blend(true); - if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) { - GPU_line_width(3.0f); - immUniformColor3fv(color_act); - immBegin(GPU_PRIM_LINES, 4); - /* angle vertex */ - immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); - immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); - immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); - immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + if (is_act && (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) { + GPU_line_width(3.0f); + immUniformColor3fv(color_act); + immBegin(GPU_PRIM_LINES, 4); + /* angle vertex */ + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); - immEnd(); - GPU_line_width(1.0f); - } + immEnd(); + GPU_line_width(1.0f); + } - immUniformColor3ubv(color_wire); + immUniformColor3ubv(color_wire); - immBegin(GPU_PRIM_LINES, 8); + immBegin(GPU_PRIM_LINES, 8); - madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); - immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); - immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); + immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); - immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); - immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); + immVertex2fv(shdr_pos, cap); - /* angle vertex */ - immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); - immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); - immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); - immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + /* angle vertex */ + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + immVertex2f(shdr_pos, co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); - immEnd(); + immEnd(); - GPU_blend(false); - } + GPU_blend(false); + } - /* text */ - char numstr[256]; - float numstr_size[2]; - float posit[2]; - const int prec = 2; /* XXX, todo, make optional */ + /* text */ + char numstr[256]; + float numstr_size[2]; + float posit[2]; + const int prec = 2; /* XXX, todo, make optional */ - ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); - BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - posit[0] = co_ss[1][0] + (cap_size * 2.0f); - posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + posit[0] = co_ss[1][0] + (cap_size * 2.0f); + posit[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); - /* draw text (bg) */ - { - immUniformColor4fv(color_back); - GPU_blend(true); - immRectf(shdr_pos, - posit[0] - bg_margin, posit[1] - bg_margin, - posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1]); - GPU_blend(false); - } + /* draw text (bg) */ + { + immUniformColor4fv(color_back); + GPU_blend(true); + immRectf(shdr_pos, + posit[0] - bg_margin, + posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], + posit[1] + bg_margin + numstr_size[1]); + GPU_blend(false); + } - immUnbindProgram(); + immUnbindProgram(); - /* draw text */ - { - BLF_color3ubv(blf_mono_font, color_text); - BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); - BLF_rotation(blf_mono_font, 0.0f); - BLF_draw(blf_mono_font, numstr, sizeof(numstr)); - } - } - else { - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + /* draw text */ + { + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } + else { + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 2); /* "advanced" mode */ - const float *col = is_act ? color_act : color_base; - immUniformArray4fv("colors", (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, 2); - immUniform1f("dash_width", 6.0f); + immUniform1i("colors_len", 2); /* "advanced" mode */ + const float *col = is_act ? color_act : color_base; + immUniformArray4fv( + "colors", + (float *)(float[][4]){{0.67f, 0.67f, 0.67f, 1.0f}, {col[0], col[1], col[2], col[3]}}, + 2); + immUniform1f("dash_width", 6.0f); - immBegin(GPU_PRIM_LINES, 2); + immBegin(GPU_PRIM_LINES, 2); - immVertex2fv(shdr_pos, co_ss[0]); - immVertex2fv(shdr_pos, co_ss[2]); + immVertex2fv(shdr_pos, co_ss[0]); + immVertex2fv(shdr_pos, co_ss[2]); - immEnd(); + immEnd(); - immUnbindProgram(); + immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); - /* capping */ - { - float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; - float cap[2]; + /* capping */ + { + float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; + float cap[2]; - normalize_v2(rot_90_vec); + normalize_v2(rot_90_vec); - GPU_blend(true); + GPU_blend(true); - immUniformColor3ubv(color_wire); + immUniformColor3ubv(color_wire); - immBegin(GPU_PRIM_LINES, 4); + immBegin(GPU_PRIM_LINES, 4); - madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); - immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); - immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); - immVertex2fv(shdr_pos, cap); - madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); - immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); + immVertex2fv(shdr_pos, cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); + immVertex2fv(shdr_pos, cap); - immEnd(); + immEnd(); - GPU_blend(false); - } + GPU_blend(false); + } - /* text */ - char numstr[256]; - float numstr_size[2]; - const int prec = 6; /* XXX, todo, make optional */ - float posit[2]; + /* text */ + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float posit[2]; - ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); - BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); + BLF_width_and_height(blf_mono_font, numstr, sizeof(numstr), &numstr_size[0], &numstr_size[1]); - mid_v2_v2v2(posit, co_ss[0], co_ss[2]); + mid_v2_v2v2(posit, co_ss[0], co_ss[2]); - /* center text */ - posit[0] -= numstr_size[0] / 2.0f; - posit[1] -= numstr_size[1] / 2.0f; + /* center text */ + posit[0] -= numstr_size[0] / 2.0f; + posit[1] -= numstr_size[1] / 2.0f; - /* draw text (bg) */ - { - immUniformColor4fv(color_back); - GPU_blend(true); - immRectf(shdr_pos, - posit[0] - bg_margin, posit[1] - bg_margin, - posit[0] + bg_margin + numstr_size[0], posit[1] + bg_margin + numstr_size[1]); - GPU_blend(false); - } + /* draw text (bg) */ + { + immUniformColor4fv(color_back); + GPU_blend(true); + immRectf(shdr_pos, + posit[0] - bg_margin, + posit[1] - bg_margin, + posit[0] + bg_margin + numstr_size[0], + posit[1] + bg_margin + numstr_size[1]); + GPU_blend(false); + } - immUnbindProgram(); + immUnbindProgram(); - /* draw text */ - { - BLF_color3ubv(blf_mono_font, color_text); - BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); - BLF_draw(blf_mono_font, numstr, sizeof(numstr)); - } - } + /* draw text */ + { + BLF_color3ubv(blf_mono_font, color_text); + BLF_position(blf_mono_font, posit[0], posit[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + } - GPU_line_smooth(false); + GPU_line_smooth(false); - BLF_disable(blf_mono_font, BLF_ROTATION); + BLF_disable(blf_mono_font, BLF_ROTATION); #undef ARC_STEPS - /* draw snap */ - if ((ruler_info->snap_flag & RULER_SNAP_OK) && - (ruler_info->state == RULER_STATE_DRAG) && - (ruler_item->gz.interaction_data != NULL)) - { - RulerInteraction *inter = ruler_item->gz.interaction_data; - /* size from drawSnapping */ - const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); - float co_ss_snap[3]; - ED_view3d_project_float_global(ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP); + /* draw snap */ + if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG) && + (ruler_item->gz.interaction_data != NULL)) { + RulerInteraction *inter = ruler_item->gz.interaction_data; + /* size from drawSnapping */ + const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE); + float co_ss_snap[3]; + ED_view3d_project_float_global( + ar, ruler_item->co[inter->co_index], co_ss_snap, V3D_PROJ_TEST_NOP); - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4fv(color_act); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color_act); - imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32); + imm_draw_circle_wire_2d(pos, co_ss_snap[0], co_ss_snap[1], size * U.pixelsize, 32); - immUnbindProgram(); - } + immUnbindProgram(); + } } -static int gizmo_ruler_test_select( - bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) +static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) { - RulerItem *ruler_item_pick = (RulerItem *)gz; - float mval_fl[2] = {UNPACK2(mval)}; - int co_index; - - /* select and drag */ - if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) { - if (co_index == -1) { - if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { - return PART_LINE; - } - } - else { - return co_index; - } - } - return -1; + RulerItem *ruler_item_pick = (RulerItem *)gz; + float mval_fl[2] = {UNPACK2(mval)}; + int co_index; + + /* select and drag */ + if (view3d_ruler_pick(gz->parent_gzgroup, ruler_item_pick, mval_fl, &co_index)) { + if (co_index == -1) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + return PART_LINE; + } + } + else { + return co_index; + } + } + return -1; } -static int gizmo_ruler_modal( - bContext *C, wmGizmo *gz, const wmEvent *event, - eWM_GizmoFlagTweak UNUSED(tweak_flag)) +static int gizmo_ruler_modal(bContext *C, + wmGizmo *gz, + const wmEvent *event, + eWM_GizmoFlagTweak UNUSED(tweak_flag)) { - bool do_draw = false; - int exit_code = OPERATOR_RUNNING_MODAL; - RulerInfo *ruler_info = gz->parent_gzgroup->customdata; - RulerItem *ruler_item = (RulerItem *)gz; - ARegion *ar = CTX_wm_region(C); - - ruler_info->ar = ar; - - switch (event->type) { - case MOUSEMOVE: - { - if (ruler_info->state == RULER_STATE_DRAG) { - if (view3d_ruler_item_mousemove( - ruler_info, ruler_item, event->mval, - event->shift != 0, event->ctrl != 0)) - { - do_draw = true; - } - } - break; - } - } - if (do_draw) { - ED_region_tag_redraw(ar); - } - return exit_code; + bool do_draw = false; + int exit_code = OPERATOR_RUNNING_MODAL; + RulerInfo *ruler_info = gz->parent_gzgroup->customdata; + RulerItem *ruler_item = (RulerItem *)gz; + ARegion *ar = CTX_wm_region(C); + + ruler_info->ar = ar; + + switch (event->type) { + case MOUSEMOVE: { + if (ruler_info->state == RULER_STATE_DRAG) { + if (view3d_ruler_item_mousemove( + ruler_info, ruler_item, event->mval, event->shift != 0, event->ctrl != 0)) { + do_draw = true; + } + } + break; + } + } + if (do_draw) { + ED_region_tag_redraw(ar); + } + return exit_code; } -static int gizmo_ruler_invoke( - bContext *C, wmGizmo *gz, const wmEvent *event) +static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event) { - wmGizmoGroup *gzgroup = gz->parent_gzgroup; - RulerInfo *ruler_info = gzgroup->customdata; - RulerItem *ruler_item_pick = (RulerItem *)gz; - RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__); - gz->interaction_data = inter; - - ARegion *ar = ruler_info->ar; - - const float mval_fl[2] = {UNPACK2(event->mval)}; - - /* select and drag */ - if (gz->highlight_part == PART_LINE) { - if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { - /* Add Center Point */ - ruler_item_pick->flag |= RULERITEM_USE_ANGLE; - inter->co_index = 1; - ruler_state_set(C, ruler_info, RULER_STATE_DRAG); - - /* find the factor */ - { - float co_ss[2][2]; - float fac; - - ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP); - - fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]); - CLAMP(fac, 0.0f, 1.0f); - - interp_v3_v3v3(ruler_item_pick->co[1], - ruler_item_pick->co[0], - ruler_item_pick->co[2], fac); - } - - /* update the new location */ - view3d_ruler_item_mousemove( - ruler_info, ruler_item_pick, event->mval, - event->shift != 0, event->ctrl != 0); - } - } - else { - inter->co_index = gz->highlight_part; - ruler_state_set(C, ruler_info, RULER_STATE_DRAG); - - /* store the initial depth */ - copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]); - } - - if (inter->co_index == 1) { - ruler_item_pick->flag |= RULERITEM_USE_ANGLE_ACTIVE; - } - else { - ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE; - } - - ruler_info->item_active = ruler_item_pick; - - return OPERATOR_RUNNING_MODAL; + wmGizmoGroup *gzgroup = gz->parent_gzgroup; + RulerInfo *ruler_info = gzgroup->customdata; + RulerItem *ruler_item_pick = (RulerItem *)gz; + RulerInteraction *inter = MEM_callocN(sizeof(RulerInteraction), __func__); + gz->interaction_data = inter; + + ARegion *ar = ruler_info->ar; + + const float mval_fl[2] = {UNPACK2(event->mval)}; + + /* select and drag */ + if (gz->highlight_part == PART_LINE) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + /* Add Center Point */ + ruler_item_pick->flag |= RULERITEM_USE_ANGLE; + inter->co_index = 1; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* find the factor */ + { + float co_ss[2][2]; + float fac; + + ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP); + + fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]); + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3( + ruler_item_pick->co[1], ruler_item_pick->co[0], ruler_item_pick->co[2], fac); + } + + /* update the new location */ + view3d_ruler_item_mousemove( + ruler_info, ruler_item_pick, event->mval, event->shift != 0, event->ctrl != 0); + } + } + else { + inter->co_index = gz->highlight_part; + ruler_state_set(C, ruler_info, RULER_STATE_DRAG); + + /* store the initial depth */ + copy_v3_v3(inter->drag_start_co, ruler_item_pick->co[inter->co_index]); + } + + if (inter->co_index == 1) { + ruler_item_pick->flag |= RULERITEM_USE_ANGLE_ACTIVE; + } + else { + ruler_item_pick->flag &= ~RULERITEM_USE_ANGLE_ACTIVE; + } + + ruler_info->item_active = ruler_item_pick; + + return OPERATOR_RUNNING_MODAL; } static void gizmo_ruler_exit(bContext *C, wmGizmo *gz, const bool cancel) { - wmGizmoGroup *gzgroup = gz->parent_gzgroup; - RulerInfo *ruler_info = gzgroup->customdata; - - if (!cancel) { - if (ruler_info->state == RULER_STATE_DRAG) { - if (ruler_info->snap_flag & RULER_SNAP_OK) { - ruler_info->snap_flag &= ~RULER_SNAP_OK; - } - ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); - } - /* We could convert only the current gizmo, for now just re-generate. */ - view3d_ruler_to_gpencil(C, gzgroup); - } - - if (gz) { - MEM_SAFE_FREE(gz->interaction_data); - } - - ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); + wmGizmoGroup *gzgroup = gz->parent_gzgroup; + RulerInfo *ruler_info = gzgroup->customdata; + + if (!cancel) { + if (ruler_info->state == RULER_STATE_DRAG) { + if (ruler_info->snap_flag & RULER_SNAP_OK) { + ruler_info->snap_flag &= ~RULER_SNAP_OK; + } + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); + } + /* We could convert only the current gizmo, for now just re-generate. */ + view3d_ruler_to_gpencil(C, gzgroup); + } + + if (gz) { + MEM_SAFE_FREE(gz->interaction_data); + } + + ruler_state_set(C, ruler_info, RULER_STATE_NORMAL); } static int gizmo_ruler_cursor_get(wmGizmo *gz) { - if (gz->highlight_part == PART_LINE) { - return BC_CROSSCURSOR; - } - return BC_NSEW_SCROLLCURSOR; + if (gz->highlight_part == PART_LINE) { + return BC_CROSSCURSOR; + } + return BC_NSEW_SCROLLCURSOR; } void VIEW3D_GT_ruler_item(wmGizmoType *gzt) { - /* identifiers */ - gzt->idname = "VIEW3D_GT_ruler_item"; - - /* api callbacks */ - gzt->draw = gizmo_ruler_draw; - gzt->test_select = gizmo_ruler_test_select; - gzt->modal = gizmo_ruler_modal; - gzt->invoke = gizmo_ruler_invoke; - gzt->exit = gizmo_ruler_exit; - gzt->cursor_get = gizmo_ruler_cursor_get; - - gzt->struct_size = sizeof(RulerItem); + /* identifiers */ + gzt->idname = "VIEW3D_GT_ruler_item"; + + /* api callbacks */ + gzt->draw = gizmo_ruler_draw; + gzt->test_select = gizmo_ruler_test_select; + gzt->modal = gizmo_ruler_modal; + gzt->invoke = gizmo_ruler_invoke; + gzt->exit = gizmo_ruler_exit; + gzt->cursor_get = gizmo_ruler_cursor_get; + + gzt->struct_size = sizeof(RulerItem); } /** \} */ @@ -991,34 +997,34 @@ void VIEW3D_GT_ruler_item(wmGizmoType *gzt) static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup) { - RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__); + RulerInfo *ruler_info = MEM_callocN(sizeof(RulerInfo), __func__); - if (view3d_ruler_from_gpencil(C, gzgroup)) { - /* nop */ - } + if (view3d_ruler_from_gpencil(C, gzgroup)) { + /* nop */ + } - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = CTX_wm_region(C); - ruler_info->win = win; - ruler_info->sa = sa; - ruler_info->ar = ar; + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + ruler_info->win = win; + ruler_info->sa = sa; + ruler_info->ar = ar; - gzgroup->customdata = ruler_info; + gzgroup->customdata = ruler_info; } void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt) { - gzgt->name = "Ruler Widgets"; - gzgt->idname = view3d_gzgt_ruler_id; + gzgt->name = "Ruler Widgets"; + gzgt->idname = view3d_gzgt_ruler_id; - gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL; + gzgt->flag |= WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL; - gzgt->gzmap_params.spaceid = SPACE_VIEW3D; - gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; + gzgt->gzmap_params.spaceid = SPACE_VIEW3D; + gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW; - gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; - gzgt->setup = WIDGETGROUP_ruler_setup; + gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; + gzgt->setup = WIDGETGROUP_ruler_setup; } /** \} */ @@ -1029,72 +1035,68 @@ void VIEW3D_GGT_ruler(wmGizmoGroupType *gzgt) static bool view3d_ruler_poll(bContext *C) { - bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); - if ((tref_rt == NULL) || - !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) || - CTX_wm_region_view3d(C) == NULL) - { - return false; - } - return true; + bToolRef_Runtime *tref_rt = WM_toolsystem_runtime_from_context((bContext *)C); + if ((tref_rt == NULL) || !STREQ(view3d_gzgt_ruler_id, tref_rt->gizmo_group) || + CTX_wm_region_view3d(C) == NULL) { + return false; + } + return true; } static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = ar->regiondata; - - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { - BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view"); - return OPERATOR_CANCELLED; - } - - wmGizmoMap *gzmap = ar->gizmo_map; - wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); - const bool use_depth = (v3d->shading.type >= OB_SOLID); - - /* Create new line */ - RulerItem *ruler_item; - ruler_item = ruler_item_add(gzgroup); - - /* This is a little weak, but there is no real good way to tweak directly. */ - WM_gizmo_highlight_set(gzmap, &ruler_item->gz); - if (WM_operator_name_call( - C, "GIZMOGROUP_OT_gizmo_tweak", - WM_OP_INVOKE_REGION_WIN, NULL) == OPERATOR_RUNNING_MODAL) - { - RulerInfo *ruler_info = gzgroup->customdata; - RulerInteraction *inter = ruler_item->gz.interaction_data; - if (use_depth) { - /* snap the first point added, not essential but handy */ - inter->co_index = 0; - view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true); - copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]); - } - else { - negate_v3_v3(inter->drag_start_co, rv3d->ofs); - copy_v3_v3(ruler_item->co[0], inter->drag_start_co); - view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); - } - - copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); - ruler_item->gz.highlight_part = inter->co_index = 2; - } - return OPERATOR_FINISHED; + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ar->regiondata; + + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { + BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view"); + return OPERATOR_CANCELLED; + } + + wmGizmoMap *gzmap = ar->gizmo_map; + wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); + const bool use_depth = (v3d->shading.type >= OB_SOLID); + + /* Create new line */ + RulerItem *ruler_item; + ruler_item = ruler_item_add(gzgroup); + + /* This is a little weak, but there is no real good way to tweak directly. */ + WM_gizmo_highlight_set(gzmap, &ruler_item->gz); + if (WM_operator_name_call(C, "GIZMOGROUP_OT_gizmo_tweak", WM_OP_INVOKE_REGION_WIN, NULL) == + OPERATOR_RUNNING_MODAL) { + RulerInfo *ruler_info = gzgroup->customdata; + RulerInteraction *inter = ruler_item->gz.interaction_data; + if (use_depth) { + /* snap the first point added, not essential but handy */ + inter->co_index = 0; + view3d_ruler_item_mousemove(ruler_info, ruler_item, event->mval, false, true); + copy_v3_v3(inter->drag_start_co, ruler_item->co[inter->co_index]); + } + else { + negate_v3_v3(inter->drag_start_co, rv3d->ofs); + copy_v3_v3(ruler_item->co[0], inter->drag_start_co); + view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); + } + + copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); + ruler_item->gz.highlight_part = inter->co_index = 2; + } + return OPERATOR_FINISHED; } void VIEW3D_OT_ruler_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Ruler Add"; - ot->idname = "VIEW3D_OT_ruler_add"; + /* identifiers */ + ot->name = "Ruler Add"; + ot->idname = "VIEW3D_OT_ruler_add"; - ot->invoke = view3d_ruler_add_invoke; - ot->poll = view3d_ruler_poll; + ot->invoke = view3d_ruler_add_invoke; + ot->poll = view3d_ruler_poll; - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /** \} */ @@ -1105,46 +1107,45 @@ void VIEW3D_OT_ruler_add(wmOperatorType *ot) static int view3d_ruler_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - ARegion *ar = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); - - if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { - BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view"); - return OPERATOR_CANCELLED; - } - - wmGizmoMap *gzmap = ar->gizmo_map; - wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); - if (gzgroup) { - RulerInfo *ruler_info = gzgroup->customdata; - if (ruler_info->item_active) { - RulerItem *ruler_item = ruler_info->item_active; - if ((ruler_item->flag & RULERITEM_USE_ANGLE) && - (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) - { - ruler_item->flag &= ~(RULERITEM_USE_ANGLE | RULERITEM_USE_ANGLE_ACTIVE); - } - else { - ruler_item_remove(C, gzgroup, ruler_item); - } - ED_region_tag_redraw(ar); - return OPERATOR_FINISHED; - } - } - return OPERATOR_PASS_THROUGH; + ARegion *ar = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + + if (v3d->gizmo_flag & (V3D_GIZMO_HIDE | V3D_GIZMO_HIDE_TOOL)) { + BKE_report(op->reports, RPT_WARNING, "Gizmos hidden in this view"); + return OPERATOR_CANCELLED; + } + + wmGizmoMap *gzmap = ar->gizmo_map; + wmGizmoGroup *gzgroup = WM_gizmomap_group_find(gzmap, view3d_gzgt_ruler_id); + if (gzgroup) { + RulerInfo *ruler_info = gzgroup->customdata; + if (ruler_info->item_active) { + RulerItem *ruler_item = ruler_info->item_active; + if ((ruler_item->flag & RULERITEM_USE_ANGLE) && + (ruler_item->flag & RULERITEM_USE_ANGLE_ACTIVE)) { + ruler_item->flag &= ~(RULERITEM_USE_ANGLE | RULERITEM_USE_ANGLE_ACTIVE); + } + else { + ruler_item_remove(C, gzgroup, ruler_item); + } + ED_region_tag_redraw(ar); + return OPERATOR_FINISHED; + } + } + return OPERATOR_PASS_THROUGH; } void VIEW3D_OT_ruler_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Ruler Remove"; - ot->idname = "VIEW3D_OT_ruler_remove"; + /* identifiers */ + ot->name = "Ruler Remove"; + ot->idname = "VIEW3D_OT_ruler_remove"; - ot->invoke = view3d_ruler_remove_invoke; - ot->poll = view3d_ruler_poll; + ot->invoke = view3d_ruler_remove_invoke; + ot->poll = view3d_ruler_poll; - /* flags */ - ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_UNDO | OPTYPE_INTERNAL; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index de3f0392ff0..6984562337c 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -57,9 +57,9 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event); -#define B_SEL_VERT 110 -#define B_SEL_EDGE 111 -#define B_SEL_FACE 112 +#define B_SEL_VERT 110 +#define B_SEL_EDGE 111 +#define B_SEL_FACE 112 /* -------------------------------------------------------------------- */ /** \name Toggle Matcap Flip Operator @@ -67,31 +67,31 @@ static void do_view3d_header_buttons(bContext *C, void *arg, int event); static int toggle_matcap_flip(bContext *C, wmOperator *UNUSED(op)) { - View3D *v3d = CTX_wm_view3d(C); - - if (v3d) { - v3d->shading.flag ^= V3D_SHADING_MATCAP_FLIP_X; - ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C)); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - } - else { - Scene *scene = CTX_data_scene(C); - scene->display.shading.flag ^= V3D_SHADING_MATCAP_FLIP_X; - WM_event_add_notifier(C, NC_SCENE | NA_EDITED, v3d); - } - - return OPERATOR_FINISHED; + View3D *v3d = CTX_wm_view3d(C); + + if (v3d) { + v3d->shading.flag ^= V3D_SHADING_MATCAP_FLIP_X; + ED_view3d_shade_update(CTX_data_main(C), v3d, CTX_wm_area(C)); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + } + else { + Scene *scene = CTX_data_scene(C); + scene->display.shading.flag ^= V3D_SHADING_MATCAP_FLIP_X; + WM_event_add_notifier(C, NC_SCENE | NA_EDITED, v3d); + } + + return OPERATOR_FINISHED; } void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Flip MatCap"; - ot->description = "Flip MatCap"; - ot->idname = "VIEW3D_OT_toggle_matcap_flip"; + /* identifiers */ + ot->name = "Flip MatCap"; + ot->description = "Flip MatCap"; + ot->idname = "VIEW3D_OT_toggle_matcap_flip"; - /* api callbacks */ - ot->exec = toggle_matcap_flip; + /* api callbacks */ + ot->exec = toggle_matcap_flip; } /** \} */ @@ -102,95 +102,136 @@ void VIEW3D_OT_toggle_matcap_flip(wmOperatorType *ot) static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { - wmWindow *win = CTX_wm_window(C); - const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; - - /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ - - switch (event) { - case B_SEL_VERT: - if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { - ED_undo_push(C, "Selectmode Set: Vertex"); - } - break; - case B_SEL_EDGE: - if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { - ED_undo_push(C, "Selectmode Set: Edge"); - } - break; - case B_SEL_FACE: - if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { - ED_undo_push(C, "Selectmode Set: Face"); - } - break; - default: - break; - } + wmWindow *win = CTX_wm_window(C); + const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; + + /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ + + switch (event) { + case B_SEL_VERT: + if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { + ED_undo_push(C, "Selectmode Set: Vertex"); + } + break; + case B_SEL_EDGE: + if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { + ED_undo_push(C, "Selectmode Set: Edge"); + } + break; + case B_SEL_FACE: + if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { + ED_undo_push(C, "Selectmode Set: Face"); + } + break; + default: + break; + } } void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) { - Object *obedit = CTX_data_edit_object(C); - uiBlock *block = uiLayoutGetBlock(layout); - - UI_block_func_handle_set(block, do_view3d_header_buttons, NULL); - - if (obedit && (obedit->type == OB_MESH)) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - uiLayout *row; - - row = uiLayoutRow(layout, true); - block = uiLayoutGetBlock(row); - uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, - 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, - TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection")); - uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, - 0, 0, ceilf(UI_UNIT_X - U.pixelsize), UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, - TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click expands/contracts selection")); - uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, - 0, 0, ceilf(UI_UNIT_X - U.pixelsize), UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, - TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection")); - } + Object *obedit = CTX_data_edit_object(C); + uiBlock *block = uiLayoutGetBlock(layout); + + UI_block_func_handle_set(block, do_view3d_header_buttons, NULL); + + if (obedit && (obedit->type == OB_MESH)) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + uiLayout *row; + + row = uiLayoutRow(layout, true); + block = uiLayoutGetBlock(row); + uiDefIconButBitS( + block, + UI_BTYPE_TOGGLE, + SCE_SELECT_VERTEX, + B_SEL_VERT, + ICON_VERTEXSEL, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + &em->selectmode, + 1.0, + 0.0, + 0, + 0, + TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection")); + uiDefIconButBitS(block, + UI_BTYPE_TOGGLE, + SCE_SELECT_EDGE, + B_SEL_EDGE, + ICON_EDGESEL, + 0, + 0, + ceilf(UI_UNIT_X - U.pixelsize), + UI_UNIT_Y, + &em->selectmode, + 1.0, + 0.0, + 0, + 0, + TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click " + "expands/contracts selection")); + uiDefIconButBitS( + block, + UI_BTYPE_TOGGLE, + SCE_SELECT_FACE, + B_SEL_FACE, + ICON_FACESEL, + 0, + 0, + ceilf(UI_UNIT_X - U.pixelsize), + UI_UNIT_Y, + &em->selectmode, + 1.0, + 0.0, + 0, + 0, + TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection")); + } } static void uiTemplatePaintModeSelection(uiLayout *layout, struct bContext *C) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - - /* Gizmos aren't used in paint modes */ - if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) { - /* masks aren't used for sculpt and particle painting */ - PointerRNA meshptr; - - RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr); - if (ob->mode & (OB_MODE_TEXTURE_PAINT)) { - uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - } - else { - uiLayout *row = uiLayoutRow(layout, true); - uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - } - } + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + + /* Gizmos aren't used in paint modes */ + if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) { + /* masks aren't used for sculpt and particle painting */ + PointerRNA meshptr; + + RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr); + if (ob->mode & (OB_MODE_TEXTURE_PAINT)) { + uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + } + else { + uiLayout *row = uiLayoutRow(layout, true); + uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + } + } } void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *ob = OBACT(view_layer); - Object *obedit = CTX_data_edit_object(C); - bGPdata *gpd = CTX_data_gpencil_data(C); - - bool is_paint = ( - ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) && - ELEM(ob->mode, - OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT)); - - uiTemplateEditModeSelection(layout, C); - if ((obedit == NULL) && is_paint) { - uiTemplatePaintModeSelection(layout, C); - } + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *ob = OBACT(view_layer); + Object *obedit = CTX_data_edit_object(C); + bGPdata *gpd = CTX_data_gpencil_data(C); + + bool is_paint = (ob && !(gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) && + ELEM(ob->mode, + OB_MODE_SCULPT, + OB_MODE_VERTEX_PAINT, + OB_MODE_WEIGHT_PAINT, + OB_MODE_TEXTURE_PAINT)); + + uiTemplateEditModeSelection(layout, C); + if ((obedit == NULL) && is_paint) { + uiTemplatePaintModeSelection(layout, C); + } } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index e85558765b6..fd306619577 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -50,9 +50,9 @@ struct wmWindowManager; /* drawing flags: */ enum { - DRAW_PICKING = (1 << 0), - DRAW_CONSTCOLOR = (1 << 1), - DRAW_SCENESET = (1 << 2), + DRAW_PICKING = (1 << 0), + DRAW_CONSTCOLOR = (1 << 1), + DRAW_SCENESET = (1 << 2), }; /* view3d_header.c */ @@ -101,18 +101,22 @@ void VIEW3D_OT_toggle_xray(struct wmOperatorType *ot); void view3d_boxview_copy(struct ScrArea *sa, struct ARegion *ar); void view3d_boxview_sync(struct ScrArea *sa, struct ARegion *ar); -void view3d_orbit_apply_dyn_ofs( - float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], - const float viewquat_new[4], const float dyn_ofs[3]); +void view3d_orbit_apply_dyn_ofs(float r_ofs[3], + const float ofs_old[3], + const float viewquat_old[4], + const float viewquat_new[4], + const float dyn_ofs[3]); #ifdef WITH_INPUT_NDOF struct wmNDOFMotionData; -void view3d_ndof_fly( - const struct wmNDOFMotionData *ndof, - struct View3D *v3d, struct RegionView3D *rv3d, - const bool use_precision, const short protectflag, - bool *r_has_translate, bool *r_has_rotate); +void view3d_ndof_fly(const struct wmNDOFMotionData *ndof, + struct View3D *v3d, + struct RegionView3D *rv3d, + const bool use_precision, + const short protectflag, + bool *r_has_translate, + bool *r_has_rotate); #endif /* WITH_INPUT_NDOF */ /* view3d_fly.c */ @@ -123,10 +127,12 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot); void VIEW3D_OT_walk(struct wmOperatorType *ot); /* drawobject.c */ -void draw_object_select_id( - struct Depsgraph *depsgraph, Scene *scene, - View3D *v3d, RegionView3D *rv3d, struct Object *ob, - short select_mode); +void draw_object_select_id(struct Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + struct Object *ob, + short select_mode); void draw_object_depth(RegionView3D *rv3d, struct Object *ob); @@ -136,19 +142,30 @@ int view3d_effective_drawtype(const struct View3D *v3d); void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar); void view3d_draw_region_info(const struct bContext *C, struct ARegion *ar); -void ED_view3d_draw_depth( - struct Depsgraph *depsgraph, - struct ARegion *ar, View3D *v3d, bool alphaoverride); +void ED_view3d_draw_depth(struct Depsgraph *depsgraph, + struct ARegion *ar, + View3D *v3d, + bool alphaoverride); /* view3d_draw_legacy.c */ -void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph, Scene *scene, struct ARegion *ar, View3D *v3d); - -void ED_view3d_draw_select_loop( - struct Depsgraph *depsgraph, ViewContext *vc, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, struct ARegion *ar, - bool use_obedit_skip, bool use_nearest); - -void ED_view3d_draw_depth_loop( - struct Depsgraph *depsgraph, Scene *scene, struct ARegion *ar, View3D *v3d); +void ED_view3d_draw_depth_gpencil(struct Depsgraph *depsgraph, + Scene *scene, + struct ARegion *ar, + View3D *v3d); + +void ED_view3d_draw_select_loop(struct Depsgraph *depsgraph, + ViewContext *vc, + Scene *scene, + struct ViewLayer *view_layer, + View3D *v3d, + struct ARegion *ar, + bool use_obedit_skip, + bool use_nearest); + +void ED_view3d_draw_depth_loop(struct Depsgraph *depsgraph, + Scene *scene, + struct ARegion *ar, + View3D *v3d); void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect); float view3d_depth_near(struct ViewDepths *d); @@ -168,37 +185,46 @@ void VIEW3D_OT_object_as_camera(struct wmOperatorType *ot); void VIEW3D_OT_localview(struct wmOperatorType *ot); void VIEW3D_OT_localview_remove_from(struct wmOperatorType *ot); -bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const struct BoundBox *bb, float obmat[4][4]); +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, + const struct BoundBox *bb, + float obmat[4][4]); bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const struct BoundBox *bb); typedef struct V3D_SmoothParams { - struct Object *camera_old, *camera; - const float *ofs, *quat, *dist, *lens; - /* alternate rotation center (ofs = must be NULL) */ - const float *dyn_ofs; + struct Object *camera_old, *camera; + const float *ofs, *quat, *dist, *lens; + /* alternate rotation center (ofs = must be NULL) */ + const float *dyn_ofs; } V3D_SmoothParams; -void ED_view3d_smooth_view_ex( - const struct Depsgraph *depsgraph, - struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa, - struct View3D *v3d, struct ARegion *ar, const int smooth_viewtx, - const V3D_SmoothParams *sview); - -void ED_view3d_smooth_view( - struct bContext *C, - struct View3D *v3d, struct ARegion *ar, const int smooth_viewtx, - const V3D_SmoothParams *sview); - -void ED_view3d_smooth_view_force_finish( - struct bContext *C, - struct View3D *v3d, struct ARegion *ar); - -void view3d_winmatrix_set( - struct Depsgraph *depsgraph, - struct ARegion *ar, const View3D *v3d, const rcti *rect); -void view3d_viewmatrix_set( - struct Depsgraph *depsgraph, Scene *scene, - const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]); +void ED_view3d_smooth_view_ex(const struct Depsgraph *depsgraph, + struct wmWindowManager *wm, + struct wmWindow *win, + struct ScrArea *sa, + struct View3D *v3d, + struct ARegion *ar, + const int smooth_viewtx, + const V3D_SmoothParams *sview); + +void ED_view3d_smooth_view(struct bContext *C, + struct View3D *v3d, + struct ARegion *ar, + const int smooth_viewtx, + const V3D_SmoothParams *sview); + +void ED_view3d_smooth_view_force_finish(struct bContext *C, + struct View3D *v3d, + struct ARegion *ar); + +void view3d_winmatrix_set(struct Depsgraph *depsgraph, + struct ARegion *ar, + const View3D *v3d, + const rcti *rect); +void view3d_viewmatrix_set(struct Depsgraph *depsgraph, + Scene *scene, + const View3D *v3d, + RegionView3D *rv3d, + const float rect_scale[2]); void fly_modal_keymap(struct wmKeyConfig *keyconf); void walk_modal_keymap(struct wmKeyConfig *keyconf); @@ -213,18 +239,18 @@ void VIEW3D_OT_object_mode_pie_or_toggle(struct wmOperatorType *ot); void view3d_buttons_register(struct ARegionType *art); /* view3d_camera_control.c */ -struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - struct Depsgraph *depsgraph, Scene *scene, View3D *v3d, RegionView3D *rv3d, - const bool use_parent_root); -void ED_view3d_cameracontrol_update( - struct View3DCameraControl *vctrl, - const bool use_autokey, - struct bContext *C, const bool do_rotate, const bool do_translate); -void ED_view3d_cameracontrol_release( - struct View3DCameraControl *vctrl, - const bool restore); -struct Object *ED_view3d_cameracontrol_object_get( - struct View3DCameraControl *vctrl); +struct View3DCameraControl *ED_view3d_cameracontrol_acquire(struct Depsgraph *depsgraph, + Scene *scene, + View3D *v3d, + RegionView3D *rv3d, + const bool use_parent_root); +void ED_view3d_cameracontrol_update(struct View3DCameraControl *vctrl, + const bool use_autokey, + struct bContext *C, + const bool do_rotate, + const bool do_translate); +void ED_view3d_cameracontrol_release(struct View3DCameraControl *vctrl, const bool restore); +struct Object *ED_view3d_cameracontrol_object_get(struct View3DCameraControl *vctrl); /* view3d_toolbar.c */ void VIEW3D_OT_toolshelf(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index daa1cd38164..b6efc0ff136 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -49,36 +49,39 @@ #include "ED_view3d.h" typedef struct foreachScreenObjectVert_userData { - void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index); - void *userData; - ViewContext vc; - eV3DProjTest clip_flag; + void (*func)(void *userData, MVert *mv, const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + eV3DProjTest clip_flag; } foreachScreenObjectVert_userData; typedef struct foreachScreenVert_userData { - void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index); - void *userData; - ViewContext vc; - eV3DProjTest clip_flag; + void (*func)(void *userData, BMVert *eve, const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + eV3DProjTest clip_flag; } foreachScreenVert_userData; /* user data structures for derived mesh callbacks */ typedef struct foreachScreenEdge_userData { - void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index); - void *userData; - ViewContext vc; - rctf win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */ - eV3DProjTest clip_flag; + void (*func)(void *userData, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index); + void *userData; + ViewContext vc; + rctf win_rect; /* copy of: vc.ar->winx/winy, use for faster tests, minx/y will always be 0 */ + eV3DProjTest clip_flag; } foreachScreenEdge_userData; typedef struct foreachScreenFace_userData { - void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index); - void *userData; - ViewContext vc; - eV3DProjTest clip_flag; + void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index); + void *userData; + ViewContext vc; + eV3DProjTest clip_flag; } foreachScreenFace_userData; - /** * \note foreach funcs should be called while drawing or directly after * if not, #ED_view3d_init_mats_rv3d() can be used for selection tools @@ -88,392 +91,447 @@ typedef struct foreachScreenFace_userData { /* ------------------------------------------------------------------------ */ - -static void meshobject_foreachScreenVert__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +static void meshobject_foreachScreenVert__mapFunc(void *userData, + int index, + const float co[3], + const float UNUSED(no_f[3]), + const short UNUSED(no_s[3])) { - foreachScreenObjectVert_userData *data = userData; - struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index]; + foreachScreenObjectVert_userData *data = userData; + struct MVert *mv = &((Mesh *)(data->vc.obact->data))->mvert[index]; - if (!(mv->flag & ME_HIDE)) { - float screen_co[2]; + if (!(mv->flag & ME_HIDE)) { + float screen_co[2]; - if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) { - return; - } + if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != + V3D_PROJ_RET_OK) { + return; + } - data->func(data->userData, mv, screen_co, index); - } + data->func(data->userData, mv, screen_co, index); + } } void meshobject_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, MVert *eve, const float screen_co[2], int index), - void *userData, eV3DProjTest clip_flag) + ViewContext *vc, + void (*func)(void *userData, MVert *eve, const float screen_co[2], int index), + void *userData, + eV3DProjTest clip_flag) { - foreachScreenObjectVert_userData data; - Mesh *me; + foreachScreenObjectVert_userData data; + Mesh *me; - Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph); - Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + Scene *scene_eval = DEG_get_evaluated_scene(vc->depsgraph); + Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); + me = mesh_get_eval_deform(vc->depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); - ED_view3d_check_mats_rv3d(vc->rv3d); + ED_view3d_check_mats_rv3d(vc->rv3d); - data.vc = *vc; - data.func = func; - data.userData = userData; - data.clip_flag = clip_flag; + data.vc = *vc; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; - if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat); - } + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obact->obmat); + } - BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); + BKE_mesh_foreach_mapped_vert(me, meshobject_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); } -static void mesh_foreachScreenVert__mapFunc(void *userData, int index, const float co[3], - const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) +static void mesh_foreachScreenVert__mapFunc(void *userData, + int index, + const float co[3], + const float UNUSED(no_f[3]), + const short UNUSED(no_s[3])) { - foreachScreenVert_userData *data = userData; - BMVert *eve = BM_vert_at_index(data->vc.em->bm, index); + foreachScreenVert_userData *data = userData; + BMVert *eve = BM_vert_at_index(data->vc.em->bm, index); - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - float screen_co[2]; + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + float screen_co[2]; - if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != V3D_PROJ_RET_OK) { - return; - } + if (ED_view3d_project_float_object(data->vc.ar, co, screen_co, data->clip_flag) != + V3D_PROJ_RET_OK) { + return; + } - data->func(data->userData, eve, screen_co, index); - } + data->func(data->userData, eve, screen_co, index); + } } void mesh_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index), - void *userData, eV3DProjTest clip_flag) + ViewContext *vc, + void (*func)(void *userData, BMVert *eve, const float screen_co[2], int index), + void *userData, + eV3DProjTest clip_flag) { - foreachScreenVert_userData data; + foreachScreenVert_userData data; - Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); + Mesh *me = editbmesh_get_eval_cage_from_orig( + vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); - ED_view3d_check_mats_rv3d(vc->rv3d); + ED_view3d_check_mats_rv3d(vc->rv3d); - data.vc = *vc; - data.func = func; - data.userData = userData; - data.clip_flag = clip_flag; + data.vc = *vc; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; - if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - } + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } - BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT); - BKE_mesh_foreach_mapped_vert(me, mesh_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); + BM_mesh_elem_table_ensure(vc->em->bm, BM_VERT); + BKE_mesh_foreach_mapped_vert(me, mesh_foreachScreenVert__mapFunc, &data, MESH_FOREACH_NOP); } /* ------------------------------------------------------------------------ */ -static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, const float v0co[3], const float v1co[3]) +static void mesh_foreachScreenEdge__mapFunc(void *userData, + int index, + const float v0co[3], + const float v1co[3]) { - foreachScreenEdge_userData *data = userData; - BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index); - - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - float screen_co_a[2]; - float screen_co_b[2]; - eV3DProjTest clip_flag_nowin = data->clip_flag &= ~V3D_PROJ_TEST_CLIP_WIN; - - if (ED_view3d_project_float_object(data->vc.ar, v0co, screen_co_a, clip_flag_nowin) != V3D_PROJ_RET_OK) { - return; - } - if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) != V3D_PROJ_RET_OK) { - return; - } - - if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) { - if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) { - return; - } - } - - data->func(data->userData, eed, screen_co_a, screen_co_b, index); - } + foreachScreenEdge_userData *data = userData; + BMEdge *eed = BM_edge_at_index(data->vc.em->bm, index); + + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + float screen_co_a[2]; + float screen_co_b[2]; + eV3DProjTest clip_flag_nowin = data->clip_flag &= ~V3D_PROJ_TEST_CLIP_WIN; + + if (ED_view3d_project_float_object(data->vc.ar, v0co, screen_co_a, clip_flag_nowin) != + V3D_PROJ_RET_OK) { + return; + } + if (ED_view3d_project_float_object(data->vc.ar, v1co, screen_co_b, clip_flag_nowin) != + V3D_PROJ_RET_OK) { + return; + } + + if (data->clip_flag & V3D_PROJ_TEST_CLIP_WIN) { + if (!BLI_rctf_isect_segment(&data->win_rect, screen_co_a, screen_co_b)) { + return; + } + } + + data->func(data->userData, eed, screen_co_a, screen_co_b, index); + } } -void mesh_foreachScreenEdge( - ViewContext *vc, - void (*func)(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index), - void *userData, eV3DProjTest clip_flag) +void mesh_foreachScreenEdge(ViewContext *vc, + void (*func)(void *userData, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int index), + void *userData, + eV3DProjTest clip_flag) { - foreachScreenEdge_userData data; + foreachScreenEdge_userData data; - Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); + Mesh *me = editbmesh_get_eval_cage_from_orig( + vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); - ED_view3d_check_mats_rv3d(vc->rv3d); + ED_view3d_check_mats_rv3d(vc->rv3d); - data.vc = *vc; + data.vc = *vc; - data.win_rect.xmin = 0; - data.win_rect.ymin = 0; - data.win_rect.xmax = vc->ar->winx; - data.win_rect.ymax = vc->ar->winy; + data.win_rect.xmin = 0; + data.win_rect.ymin = 0; + data.win_rect.xmax = vc->ar->winx; + data.win_rect.ymax = vc->ar->winy; - data.func = func; - data.userData = userData; - data.clip_flag = clip_flag; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; - if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - } + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } - BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE); - BKE_mesh_foreach_mapped_edge(me, mesh_foreachScreenEdge__mapFunc, &data); + BM_mesh_elem_table_ensure(vc->em->bm, BM_EDGE); + BKE_mesh_foreach_mapped_edge(me, mesh_foreachScreenEdge__mapFunc, &data); } /* ------------------------------------------------------------------------ */ -static void mesh_foreachScreenFace__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3])) +static void mesh_foreachScreenFace__mapFunc(void *userData, + int index, + const float cent[3], + const float UNUSED(no[3])) { - foreachScreenFace_userData *data = userData; - BMFace *efa = BM_face_at_index(data->vc.em->bm, index); - - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - float screen_co[2]; - if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == V3D_PROJ_RET_OK) { - data->func(data->userData, efa, screen_co, index); - } - } + foreachScreenFace_userData *data = userData; + BMFace *efa = BM_face_at_index(data->vc.em->bm, index); + + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + float screen_co[2]; + if (ED_view3d_project_float_object(data->vc.ar, cent, screen_co, data->clip_flag) == + V3D_PROJ_RET_OK) { + data->func(data->userData, efa, screen_co, index); + } + } } void mesh_foreachScreenFace( - ViewContext *vc, - void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index), - void *userData, const eV3DProjTest clip_flag) + ViewContext *vc, + void (*func)(void *userData, BMFace *efa, const float screen_co_b[2], int index), + void *userData, + const eV3DProjTest clip_flag) { - foreachScreenFace_userData data; + foreachScreenFace_userData data; - Mesh *me = editbmesh_get_eval_cage_from_orig(vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); - ED_view3d_check_mats_rv3d(vc->rv3d); + Mesh *me = editbmesh_get_eval_cage_from_orig( + vc->depsgraph, vc->scene, vc->obedit, vc->em, &CD_MASK_BAREMESH); + ED_view3d_check_mats_rv3d(vc->rv3d); - data.vc = *vc; - data.func = func; - data.userData = userData; - data.clip_flag = clip_flag; + data.vc = *vc; + data.func = func; + data.userData = userData; + data.clip_flag = clip_flag; - BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE); - BKE_mesh_foreach_mapped_face_center(me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); + BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE); + BKE_mesh_foreach_mapped_face_center( + me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); } /* ------------------------------------------------------------------------ */ -void nurbs_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co_b[2]), - void *userData, const eV3DProjTest clip_flag) +void nurbs_foreachScreenVert(ViewContext *vc, + void (*func)(void *userData, + Nurb *nu, + BPoint *bp, + BezTriple *bezt, + int beztindex, + const float screen_co_b[2]), + void *userData, + const eV3DProjTest clip_flag) { - Curve *cu = vc->obedit->data; - Nurb *nu; - int i; - ListBase *nurbs = BKE_curve_editNurbs_get(cu); - - ED_view3d_check_mats_rv3d(vc->rv3d); - - if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ - } - - for (nu = nurbs->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - for (i = 0; i < nu->pntsu; i++) { - BezTriple *bezt = &nu->bezt[i]; - - if (bezt->hide == 0) { - float screen_co[2]; - - if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - if (ED_view3d_project_float_object(vc->ar, bezt->vec[1], screen_co, - V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) - { - func(userData, nu, NULL, bezt, 1, screen_co); - } - } - else { - if (ED_view3d_project_float_object(vc->ar, bezt->vec[0], screen_co, - V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) - { - func(userData, nu, NULL, bezt, 0, screen_co); - } - if (ED_view3d_project_float_object(vc->ar, bezt->vec[1], screen_co, - V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) - { - func(userData, nu, NULL, bezt, 1, screen_co); - } - if (ED_view3d_project_float_object(vc->ar, bezt->vec[2], screen_co, - V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) - { - func(userData, nu, NULL, bezt, 2, screen_co); - } - } - } - } - } - else { - for (i = 0; i < nu->pntsu * nu->pntsv; i++) { - BPoint *bp = &nu->bp[i]; - - if (bp->hide == 0) { - float screen_co[2]; - if (ED_view3d_project_float_object(vc->ar, bp->vec, screen_co, - V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == V3D_PROJ_RET_OK) - { - func(userData, nu, bp, NULL, -1, screen_co); - } - } - } - } - } + Curve *cu = vc->obedit->data; + Nurb *nu; + int i; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + + ED_view3d_check_mats_rv3d(vc->rv3d); + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, vc->obedit->obmat); /* for local clipping lookups */ + } + + for (nu = nurbs->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + for (i = 0; i < nu->pntsu; i++) { + BezTriple *bezt = &nu->bezt[i]; + + if (bezt->hide == 0) { + float screen_co[2]; + + if ((vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { + if (ED_view3d_project_float_object(vc->ar, + bezt->vec[1], + screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == + V3D_PROJ_RET_OK) { + func(userData, nu, NULL, bezt, 1, screen_co); + } + } + else { + if (ED_view3d_project_float_object(vc->ar, + bezt->vec[0], + screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == + V3D_PROJ_RET_OK) { + func(userData, nu, NULL, bezt, 0, screen_co); + } + if (ED_view3d_project_float_object(vc->ar, + bezt->vec[1], + screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == + V3D_PROJ_RET_OK) { + func(userData, nu, NULL, bezt, 1, screen_co); + } + if (ED_view3d_project_float_object(vc->ar, + bezt->vec[2], + screen_co, + V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == + V3D_PROJ_RET_OK) { + func(userData, nu, NULL, bezt, 2, screen_co); + } + } + } + } + } + else { + for (i = 0; i < nu->pntsu * nu->pntsv; i++) { + BPoint *bp = &nu->bp[i]; + + if (bp->hide == 0) { + float screen_co[2]; + if (ED_view3d_project_float_object( + vc->ar, bp->vec, screen_co, V3D_PROJ_RET_CLIP_BB | V3D_PROJ_RET_CLIP_WIN) == + V3D_PROJ_RET_OK) { + func(userData, nu, bp, NULL, -1, screen_co); + } + } + } + } + } } /* ------------------------------------------------------------------------ */ /* ED_view3d_init_mats_rv3d must be called first */ -void mball_foreachScreenElem( - struct ViewContext *vc, - void (*func)(void *userData, struct MetaElem *ml, const float screen_co_b[2]), - void *userData, const eV3DProjTest clip_flag) +void mball_foreachScreenElem(struct ViewContext *vc, + void (*func)(void *userData, + struct MetaElem *ml, + const float screen_co_b[2]), + void *userData, + const eV3DProjTest clip_flag) { - MetaBall *mb = (MetaBall *)vc->obedit->data; - MetaElem *ml; + MetaBall *mb = (MetaBall *)vc->obedit->data; + MetaElem *ml; - ED_view3d_check_mats_rv3d(vc->rv3d); + ED_view3d_check_mats_rv3d(vc->rv3d); - for (ml = mb->editelems->first; ml; ml = ml->next) { - float screen_co[2]; - if (ED_view3d_project_float_object(vc->ar, &ml->x, screen_co, clip_flag) == V3D_PROJ_RET_OK) { - func(userData, ml, screen_co); - } - } + for (ml = mb->editelems->first; ml; ml = ml->next) { + float screen_co[2]; + if (ED_view3d_project_float_object(vc->ar, &ml->x, screen_co, clip_flag) == V3D_PROJ_RET_OK) { + func(userData, ml, screen_co); + } + } } /* ------------------------------------------------------------------------ */ -void lattice_foreachScreenVert( - ViewContext *vc, - void (*func)(void *userData, BPoint *bp, const float screen_co[2]), - void *userData, const eV3DProjTest clip_flag) +void lattice_foreachScreenVert(ViewContext *vc, + void (*func)(void *userData, BPoint *bp, const float screen_co[2]), + void *userData, + const eV3DProjTest clip_flag) { - Object *obedit = vc->obedit; - Lattice *lt = obedit->data; - BPoint *bp = lt->editlatt->latt->def; - DispList *dl = obedit->runtime.curve_cache ? BKE_displist_find(&obedit->runtime.curve_cache->disp, DL_VERTS) : NULL; - const float *co = dl ? dl->verts : NULL; - int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; - - ED_view3d_check_mats_rv3d(vc->rv3d); - - if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { - ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */ - } - - for (i = 0; i < N; i++, bp++, co += 3) { - if (bp->hide == 0) { - float screen_co[2]; - if (ED_view3d_project_float_object(vc->ar, dl ? co : bp->vec, screen_co, clip_flag) == V3D_PROJ_RET_OK) { - func(userData, bp, screen_co); - } - } - } + Object *obedit = vc->obedit; + Lattice *lt = obedit->data; + BPoint *bp = lt->editlatt->latt->def; + DispList *dl = obedit->runtime.curve_cache ? + BKE_displist_find(&obedit->runtime.curve_cache->disp, DL_VERTS) : + NULL; + const float *co = dl ? dl->verts : NULL; + int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; + + ED_view3d_check_mats_rv3d(vc->rv3d); + + if (clip_flag & V3D_PROJ_TEST_CLIP_BB) { + ED_view3d_clipping_local(vc->rv3d, obedit->obmat); /* for local clipping lookups */ + } + + for (i = 0; i < N; i++, bp++, co += 3) { + if (bp->hide == 0) { + float screen_co[2]; + if (ED_view3d_project_float_object(vc->ar, dl ? co : bp->vec, screen_co, clip_flag) == + V3D_PROJ_RET_OK) { + func(userData, bp, screen_co); + } + } + } } /* ------------------------------------------------------------------------ */ /* ED_view3d_init_mats_rv3d must be called first */ -void armature_foreachScreenBone( - struct ViewContext *vc, - void (*func)(void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]), - void *userData, const eV3DProjTest clip_flag) +void armature_foreachScreenBone(struct ViewContext *vc, + void (*func)(void *userData, + struct EditBone *ebone, + const float screen_co_a[2], + const float screen_co_b[2]), + void *userData, + const eV3DProjTest clip_flag) { - bArmature *arm = vc->obedit->data; - EditBone *ebone; - - ED_view3d_check_mats_rv3d(vc->rv3d); - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (EBONE_VISIBLE(arm, ebone)) { - float screen_co_a[2], screen_co_b[2]; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, ebone->head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_a[0] = IS_CLIPPED; /* weak */ - /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ - } - - /* project tail location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_b[0] = IS_CLIPPED; /* weak */ - /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ - } - - if (points_proj_tot) { /* at least one point's projection worked */ - func(userData, ebone, screen_co_a, screen_co_b); - } - } - } + bArmature *arm = vc->obedit->data; + EditBone *ebone; + + ED_view3d_check_mats_rv3d(vc->rv3d); + + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone)) { + float screen_co_a[2], screen_co_b[2]; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, ebone->head, screen_co_a, clip_flag) == + V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_a[0] = IS_CLIPPED; /* weak */ + /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ + } + + /* project tail location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, ebone->tail, screen_co_b, clip_flag) == + V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_b[0] = IS_CLIPPED; /* weak */ + /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ + } + + if (points_proj_tot) { /* at least one point's projection worked */ + func(userData, ebone, screen_co_a, screen_co_b); + } + } + } } /* ------------------------------------------------------------------------ */ /* ED_view3d_init_mats_rv3d must be called first */ /* almost _exact_ copy of #armature_foreachScreenBone */ -void pose_foreachScreenBone( - struct ViewContext *vc, - void (*func)(void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]), - void *userData, const eV3DProjTest clip_flag) +void pose_foreachScreenBone(struct ViewContext *vc, + void (*func)(void *userData, + struct bPoseChannel *pchan, + const float screen_co_a[2], + const float screen_co_b[2]), + void *userData, + const eV3DProjTest clip_flag) { - const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); - const bArmature *arm_eval = ob_eval->data; - bPose *pose = vc->obact->pose; - bPoseChannel *pchan; - - ED_view3d_check_mats_rv3d(vc->rv3d); - - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (PBONE_VISIBLE(arm_eval, pchan->bone)) { - bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); - float screen_co_a[2], screen_co_b[2]; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_a[0] = IS_CLIPPED; /* weak */ - /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ - } - - /* project tail location to screenspace */ - if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) == V3D_PROJ_RET_OK) { - points_proj_tot++; - } - else { - screen_co_b[0] = IS_CLIPPED; /* weak */ - /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ - } - - if (points_proj_tot) { /* at least one point's projection worked */ - func(userData, pchan, screen_co_a, screen_co_b); - } - } - } + const Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact); + const bArmature *arm_eval = ob_eval->data; + bPose *pose = vc->obact->pose; + bPoseChannel *pchan; + + ED_view3d_check_mats_rv3d(vc->rv3d); + + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (PBONE_VISIBLE(arm_eval, pchan->bone)) { + bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name); + float screen_co_a[2], screen_co_b[2]; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_head, screen_co_a, clip_flag) == + V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_a[0] = IS_CLIPPED; /* weak */ + /* screen_co_a[1]: intentionally dont set this so we get errors on misuse */ + } + + /* project tail location to screenspace */ + if (ED_view3d_project_float_object(vc->ar, pchan_eval->pose_tail, screen_co_b, clip_flag) == + V3D_PROJ_RET_OK) { + points_proj_tot++; + } + else { + screen_co_b[0] = IS_CLIPPED; /* weak */ + /* screen_co_b[1]: intentionally dont set this so we get errors on misuse */ + } + + if (points_proj_tot) { /* at least one point's projection worked */ + func(userData, pchan, screen_co_a, screen_co_b); + } + } + } } diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 3efd0e32440..4e33005ebc0 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -21,11 +21,9 @@ * \ingroup spview3d */ - #include <stdlib.h> #include <math.h> - #include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -63,175 +61,177 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - char str[FILE_MAX]; - int num_copied = 0; + Main *bmain = CTX_data_main(C); + char str[FILE_MAX]; + int num_copied = 0; - BKE_copybuffer_begin(bmain); + BKE_copybuffer_begin(bmain); - /* context, selection, could be generalized */ - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) - { - if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - BKE_copybuffer_tag_ID(&ob->id); - num_copied++; - } - } - CTX_DATA_END; + /* context, selection, could be generalized */ + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { + if ((ob->id.tag & LIB_TAG_DOIT) == 0) { + BKE_copybuffer_tag_ID(&ob->id); + num_copied++; + } + } + CTX_DATA_END; - BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); - BKE_copybuffer_save(bmain, str, op->reports); + BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); + BKE_copybuffer_save(bmain, str, op->reports); - BKE_reportf(op->reports, RPT_INFO, "Copied %d selected objects", num_copied); + BKE_reportf(op->reports, RPT_INFO, "Copied %d selected objects", num_copied); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void VIEW3D_OT_copybuffer(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Objects"; - ot->idname = "VIEW3D_OT_copybuffer"; - ot->description = "Selected objects are copied to the clipboard"; - - /* api callbacks */ - ot->exec = view3d_copybuffer_exec; - ot->poll = ED_operator_scene; + /* identifiers */ + ot->name = "Copy Objects"; + ot->idname = "VIEW3D_OT_copybuffer"; + ot->description = "Selected objects are copied to the clipboard"; + + /* api callbacks */ + ot->exec = view3d_copybuffer_exec; + ot->poll = ED_operator_scene; } static int view3d_pastebuffer_exec(bContext *C, wmOperator *op) { - char str[FILE_MAX]; - short flag = 0; + char str[FILE_MAX]; + short flag = 0; - if (RNA_boolean_get(op->ptr, "autoselect")) { - flag |= FILE_AUTOSELECT; - } - if (RNA_boolean_get(op->ptr, "active_collection")) { - flag |= FILE_ACTIVE_COLLECTION; - } + if (RNA_boolean_get(op->ptr, "autoselect")) { + flag |= FILE_AUTOSELECT; + } + if (RNA_boolean_get(op->ptr, "active_collection")) { + flag |= FILE_ACTIVE_COLLECTION; + } - BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); + BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend"); - const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, FILTER_ID_OB); - if (num_pasted == 0) { - BKE_report(op->reports, RPT_INFO, "No objects to paste"); - return OPERATOR_CANCELLED; - } + const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, FILTER_ID_OB); + if (num_pasted == 0) { + BKE_report(op->reports, RPT_INFO, "No objects to paste"); + return OPERATOR_CANCELLED; + } - WM_event_add_notifier(C, NC_WINDOW, NULL); + WM_event_add_notifier(C, NC_WINDOW, NULL); - BKE_reportf(op->reports, RPT_INFO, "%d objects pasted", num_pasted); + BKE_reportf(op->reports, RPT_INFO, "%d objects pasted", num_pasted); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static void VIEW3D_OT_pastebuffer(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Objects"; - ot->idname = "VIEW3D_OT_pastebuffer"; - ot->description = "Objects from the clipboard are pasted"; + /* identifiers */ + ot->name = "Paste Objects"; + ot->idname = "VIEW3D_OT_pastebuffer"; + ot->description = "Objects from the clipboard are pasted"; - /* api callbacks */ - ot->exec = view3d_pastebuffer_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = view3d_pastebuffer_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects"); - RNA_def_boolean(ot->srna, "active_collection", true, - "Active Collection", "Put pasted objects in the active collection"); + RNA_def_boolean(ot->srna, "autoselect", true, "Select", "Select pasted objects"); + RNA_def_boolean(ot->srna, + "active_collection", + true, + "Active Collection", + "Put pasted objects in the active collection"); } /* ************************** registration **********************************/ void view3d_operatortypes(void) { - WM_operatortype_append(VIEW3D_OT_rotate); - WM_operatortype_append(VIEW3D_OT_move); - WM_operatortype_append(VIEW3D_OT_zoom); - WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); - WM_operatortype_append(VIEW3D_OT_dolly); + WM_operatortype_append(VIEW3D_OT_rotate); + WM_operatortype_append(VIEW3D_OT_move); + WM_operatortype_append(VIEW3D_OT_zoom); + WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); + WM_operatortype_append(VIEW3D_OT_dolly); #ifdef WITH_INPUT_NDOF - WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom); - WM_operatortype_append(VIEW3D_OT_ndof_orbit); - WM_operatortype_append(VIEW3D_OT_ndof_pan); - WM_operatortype_append(VIEW3D_OT_ndof_all); + WM_operatortype_append(VIEW3D_OT_ndof_orbit_zoom); + WM_operatortype_append(VIEW3D_OT_ndof_orbit); + WM_operatortype_append(VIEW3D_OT_ndof_pan); + WM_operatortype_append(VIEW3D_OT_ndof_all); #endif /* WITH_INPUT_NDOF */ - WM_operatortype_append(VIEW3D_OT_view_all); - WM_operatortype_append(VIEW3D_OT_view_axis); - WM_operatortype_append(VIEW3D_OT_view_camera); - WM_operatortype_append(VIEW3D_OT_view_orbit); - WM_operatortype_append(VIEW3D_OT_view_roll); - WM_operatortype_append(VIEW3D_OT_view_pan); - WM_operatortype_append(VIEW3D_OT_view_persportho); - WM_operatortype_append(VIEW3D_OT_background_image_add); - WM_operatortype_append(VIEW3D_OT_background_image_remove); - WM_operatortype_append(VIEW3D_OT_view_selected); - WM_operatortype_append(VIEW3D_OT_view_lock_clear); - WM_operatortype_append(VIEW3D_OT_view_lock_to_active); - WM_operatortype_append(VIEW3D_OT_view_center_cursor); - WM_operatortype_append(VIEW3D_OT_view_center_pick); - WM_operatortype_append(VIEW3D_OT_view_center_camera); - WM_operatortype_append(VIEW3D_OT_view_center_lock); - WM_operatortype_append(VIEW3D_OT_select); - WM_operatortype_append(VIEW3D_OT_select_box); - WM_operatortype_append(VIEW3D_OT_clip_border); - WM_operatortype_append(VIEW3D_OT_select_circle); - WM_operatortype_append(VIEW3D_OT_smoothview); - WM_operatortype_append(VIEW3D_OT_render_border); - WM_operatortype_append(VIEW3D_OT_clear_render_border); - WM_operatortype_append(VIEW3D_OT_zoom_border); - WM_operatortype_append(VIEW3D_OT_cursor3d); - WM_operatortype_append(VIEW3D_OT_select_lasso); - WM_operatortype_append(VIEW3D_OT_select_menu); - WM_operatortype_append(VIEW3D_OT_camera_to_view); - WM_operatortype_append(VIEW3D_OT_camera_to_view_selected); - WM_operatortype_append(VIEW3D_OT_object_as_camera); - WM_operatortype_append(VIEW3D_OT_localview); - WM_operatortype_append(VIEW3D_OT_localview_remove_from); - WM_operatortype_append(VIEW3D_OT_fly); - WM_operatortype_append(VIEW3D_OT_walk); - WM_operatortype_append(VIEW3D_OT_navigate); - WM_operatortype_append(VIEW3D_OT_copybuffer); - WM_operatortype_append(VIEW3D_OT_pastebuffer); - - WM_operatortype_append(VIEW3D_OT_properties); - WM_operatortype_append(VIEW3D_OT_object_mode_pie_or_toggle); - WM_operatortype_append(VIEW3D_OT_toolshelf); - - WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid); - WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor); - WM_operatortype_append(VIEW3D_OT_snap_selected_to_active); - WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid); - WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center); - WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected); - WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active); - - 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_ruler_add); - WM_operatortype_append(VIEW3D_OT_ruler_remove); - - transform_operatortypes(); + WM_operatortype_append(VIEW3D_OT_view_all); + WM_operatortype_append(VIEW3D_OT_view_axis); + WM_operatortype_append(VIEW3D_OT_view_camera); + WM_operatortype_append(VIEW3D_OT_view_orbit); + WM_operatortype_append(VIEW3D_OT_view_roll); + WM_operatortype_append(VIEW3D_OT_view_pan); + WM_operatortype_append(VIEW3D_OT_view_persportho); + WM_operatortype_append(VIEW3D_OT_background_image_add); + WM_operatortype_append(VIEW3D_OT_background_image_remove); + WM_operatortype_append(VIEW3D_OT_view_selected); + WM_operatortype_append(VIEW3D_OT_view_lock_clear); + WM_operatortype_append(VIEW3D_OT_view_lock_to_active); + WM_operatortype_append(VIEW3D_OT_view_center_cursor); + WM_operatortype_append(VIEW3D_OT_view_center_pick); + WM_operatortype_append(VIEW3D_OT_view_center_camera); + WM_operatortype_append(VIEW3D_OT_view_center_lock); + WM_operatortype_append(VIEW3D_OT_select); + WM_operatortype_append(VIEW3D_OT_select_box); + WM_operatortype_append(VIEW3D_OT_clip_border); + WM_operatortype_append(VIEW3D_OT_select_circle); + WM_operatortype_append(VIEW3D_OT_smoothview); + WM_operatortype_append(VIEW3D_OT_render_border); + WM_operatortype_append(VIEW3D_OT_clear_render_border); + WM_operatortype_append(VIEW3D_OT_zoom_border); + WM_operatortype_append(VIEW3D_OT_cursor3d); + WM_operatortype_append(VIEW3D_OT_select_lasso); + WM_operatortype_append(VIEW3D_OT_select_menu); + WM_operatortype_append(VIEW3D_OT_camera_to_view); + WM_operatortype_append(VIEW3D_OT_camera_to_view_selected); + WM_operatortype_append(VIEW3D_OT_object_as_camera); + WM_operatortype_append(VIEW3D_OT_localview); + WM_operatortype_append(VIEW3D_OT_localview_remove_from); + WM_operatortype_append(VIEW3D_OT_fly); + WM_operatortype_append(VIEW3D_OT_walk); + WM_operatortype_append(VIEW3D_OT_navigate); + WM_operatortype_append(VIEW3D_OT_copybuffer); + WM_operatortype_append(VIEW3D_OT_pastebuffer); + + WM_operatortype_append(VIEW3D_OT_properties); + WM_operatortype_append(VIEW3D_OT_object_mode_pie_or_toggle); + WM_operatortype_append(VIEW3D_OT_toolshelf); + + WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid); + WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor); + WM_operatortype_append(VIEW3D_OT_snap_selected_to_active); + WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid); + WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center); + WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected); + WM_operatortype_append(VIEW3D_OT_snap_cursor_to_active); + + 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_ruler_add); + WM_operatortype_append(VIEW3D_OT_ruler_remove); + + transform_operatortypes(); } void view3d_keymap(wmKeyConfig *keyconf) { - WM_keymap_ensure(keyconf, "3D View Generic", SPACE_VIEW3D, 0); + WM_keymap_ensure(keyconf, "3D View Generic", SPACE_VIEW3D, 0); - /* only for region 3D window */ - WM_keymap_ensure(keyconf, "3D View", SPACE_VIEW3D, 0); + /* only for region 3D window */ + WM_keymap_ensure(keyconf, "3D View", SPACE_VIEW3D, 0); - fly_modal_keymap(keyconf); - walk_modal_keymap(keyconf); - viewrotate_modal_keymap(keyconf); - viewmove_modal_keymap(keyconf); - viewzoom_modal_keymap(keyconf); - viewdolly_modal_keymap(keyconf); + fly_modal_keymap(keyconf); + walk_modal_keymap(keyconf); + viewrotate_modal_keymap(keyconf); + viewmove_modal_keymap(keyconf); + viewzoom_modal_keymap(keyconf); + viewdolly_modal_keymap(keyconf); } diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index e5f8ac147de..6932e94e78d 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -27,7 +27,7 @@ #include "DNA_scene_types.h" #include "DNA_view3d_types.h" -#include "BLI_sys_types.h" /* int64_t */ +#include "BLI_sys_types.h" /* int64_t */ #include "BLI_math_vector.h" @@ -36,7 +36,7 @@ #include "GPU_matrix.h" -#include "ED_view3d.h" /* own include */ +#include "ED_view3d.h" /* own include */ #define BL_NEAR_CLIP 0.001 #define BL_ZERO_CLIP 0.001 @@ -47,238 +47,268 @@ /** * \note use #ED_view3d_ob_project_mat_get to get the projection matrix */ -void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r_co[2], float mat[4][4]) +void ED_view3d_project_float_v2_m4(const ARegion *ar, + const float co[3], + float r_co[2], + float mat[4][4]) { - float vec4[4]; + float vec4[4]; - copy_v3_v3(vec4, co); - vec4[3] = 1.0; - /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ + copy_v3_v3(vec4, co); + vec4[3] = 1.0; + /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ - mul_m4_v4(mat, vec4); + mul_m4_v4(mat, vec4); - if (vec4[3] > FLT_EPSILON) { - r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; - r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; - } - else { - zero_v2(r_co); - } + if (vec4[3] > FLT_EPSILON) { + r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; + r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; + } + else { + zero_v2(r_co); + } } /** * \note use #ED_view3d_ob_project_mat_get to get projecting mat */ -void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float r_co[3], float mat[4][4]) +void ED_view3d_project_float_v3_m4(const ARegion *ar, + const float vec[3], + float r_co[3], + float mat[4][4]) { - float vec4[4]; + float vec4[4]; - copy_v3_v3(vec4, vec); - vec4[3] = 1.0; - /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ + copy_v3_v3(vec4, vec); + vec4[3] = 1.0; + /* r_co[0] = IS_CLIPPED; */ /* always overwritten */ - mul_m4_v4(mat, vec4); + mul_m4_v4(mat, vec4); - if (vec4[3] > FLT_EPSILON) { - r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; - r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; - r_co[2] = vec4[2] / vec4[3]; - } - else { - zero_v3(r_co); - } + if (vec4[3] > FLT_EPSILON) { + r_co[0] = (float)(ar->winx / 2.0f) + (ar->winx / 2.0f) * vec4[0] / vec4[3]; + r_co[1] = (float)(ar->winy / 2.0f) + (ar->winy / 2.0f) * vec4[1] / vec4[3]; + r_co[2] = vec4[2] / vec4[3]; + } + else { + zero_v3(r_co); + } } - /* Clipping Projection Functions * ***************************** */ eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base) { - eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT); + eV3DProjStatus ret = ED_view3d_project_short_global( + ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT); - if (ret != V3D_PROJ_RET_OK) { - base->sx = IS_CLIPPED; - base->sy = 0; - } + if (ret != V3D_PROJ_RET_OK) { + base->sx = IS_CLIPPED; + base->sy = 0; + } - return ret; + return ret; } /* perspmat is typically... * - 'rv3d->perspmat', is_local == false * - 'rv3d->persmatob', is_local == true */ -static eV3DProjStatus ed_view3d_project__internal( - const ARegion *ar, - float perspmat[4][4], const bool is_local, /* normally hidden */ - const float co[3], float r_co[2], const eV3DProjTest flag) -{ - float vec4[4]; - - /* check for bad flags */ - BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag); - - if (flag & V3D_PROJ_TEST_CLIP_BB) { - RegionView3D *rv3d = ar->regiondata; - if (rv3d->rflag & RV3D_CLIPPING) { - if (ED_view3d_clipping_test(rv3d, co, is_local)) { - return V3D_PROJ_RET_CLIP_BB; - } - } - } - - copy_v3_v3(vec4, co); - vec4[3] = 1.0; - mul_m4_v4(perspmat, vec4); - - - - if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) { - if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) { - const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]) : 0.0f; - const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar)); - if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) { - const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar)); - if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) { - r_co[0] = fx; - r_co[1] = fy; - - /* check if the point is behind the view, we need to flip in this case */ - if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) { - negate_v2(r_co); - } - } - else { - return V3D_PROJ_RET_CLIP_WIN; - } - } - else { - return V3D_PROJ_RET_CLIP_WIN; - } - } - else { - return V3D_PROJ_RET_CLIP_NEAR; - } - } - else { - return V3D_PROJ_RET_CLIP_ZERO; - } - - return V3D_PROJ_RET_OK; -} - -eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, - const float co[3], short r_co[2], const eV3DProjTest flag) -{ - float tvec[2]; - eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); - if (ret == V3D_PROJ_RET_OK) { - if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) && - (tvec[1] > -32700.0f && tvec[1] < 32700.0f)) - { - r_co[0] = (short)floorf(tvec[0]); - r_co[1] = (short)floorf(tvec[1]); - } - else { - ret = V3D_PROJ_RET_OVERFLOW; - } - } - return ret; -} - -eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, - const float co[3], int r_co[2], const eV3DProjTest flag) -{ - float tvec[2]; - eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); - if (ret == V3D_PROJ_RET_OK) { - if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) && - (tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f)) - { - r_co[0] = (int)floorf(tvec[0]); - r_co[1] = (int)floorf(tvec[1]); - } - else { - ret = V3D_PROJ_RET_OVERFLOW; - } - } - return ret; -} - -eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, - const float co[3], float r_co[2], const eV3DProjTest flag) -{ - float tvec[2]; - eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); - if (ret == V3D_PROJ_RET_OK) { - if (isfinite(tvec[0]) && - isfinite(tvec[1])) - { - copy_v2_v2(r_co, tvec); - } - else { - ret = V3D_PROJ_RET_OVERFLOW; - } - } - return ret; +static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar, + float perspmat[4][4], + const bool is_local, /* normally hidden */ + const float co[3], + float r_co[2], + const eV3DProjTest flag) +{ + float vec4[4]; + + /* check for bad flags */ + BLI_assert((flag & V3D_PROJ_TEST_ALL) == flag); + + if (flag & V3D_PROJ_TEST_CLIP_BB) { + RegionView3D *rv3d = ar->regiondata; + if (rv3d->rflag & RV3D_CLIPPING) { + if (ED_view3d_clipping_test(rv3d, co, is_local)) { + return V3D_PROJ_RET_CLIP_BB; + } + } + } + + copy_v3_v3(vec4, co); + vec4[3] = 1.0; + mul_m4_v4(perspmat, vec4); + + if (((flag & V3D_PROJ_TEST_CLIP_ZERO) == 0) || (fabsf(vec4[3]) > (float)BL_ZERO_CLIP)) { + if (((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) || (vec4[3] > (float)BL_NEAR_CLIP)) { + const float scalar = (vec4[3] != 0.0f) ? (1.0f / vec4[3]) : 0.0f; + const float fx = ((float)ar->winx / 2.0f) * (1.0f + (vec4[0] * scalar)); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fx > 0.0f && fx < (float)ar->winx)) { + const float fy = ((float)ar->winy / 2.0f) * (1.0f + (vec4[1] * scalar)); + if (((flag & V3D_PROJ_TEST_CLIP_WIN) == 0) || (fy > 0.0f && fy < (float)ar->winy)) { + r_co[0] = fx; + r_co[1] = fy; + + /* check if the point is behind the view, we need to flip in this case */ + if (UNLIKELY((flag & V3D_PROJ_TEST_CLIP_NEAR) == 0) && (vec4[3] < 0.0f)) { + negate_v2(r_co); + } + } + else { + return V3D_PROJ_RET_CLIP_WIN; + } + } + else { + return V3D_PROJ_RET_CLIP_WIN; + } + } + else { + return V3D_PROJ_RET_CLIP_NEAR; + } + } + else { + return V3D_PROJ_RET_CLIP_ZERO; + } + + return V3D_PROJ_RET_OK; +} + +eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, + float perspmat[4][4], + const bool is_local, + const float co[3], + short r_co[2], + const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if ((tvec[0] > -32700.0f && tvec[0] < 32700.0f) && + (tvec[1] > -32700.0f && tvec[1] < 32700.0f)) { + r_co[0] = (short)floorf(tvec[0]); + r_co[1] = (short)floorf(tvec[1]); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; +} + +eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, + float perspmat[4][4], + const bool is_local, + const float co[3], + int r_co[2], + const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if ((tvec[0] > -2140000000.0f && tvec[0] < 2140000000.0f) && + (tvec[1] > -2140000000.0f && tvec[1] < 2140000000.0f)) { + r_co[0] = (int)floorf(tvec[0]); + r_co[1] = (int)floorf(tvec[1]); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; +} + +eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, + float perspmat[4][4], + const bool is_local, + const float co[3], + float r_co[2], + const eV3DProjTest flag) +{ + float tvec[2]; + eV3DProjStatus ret = ed_view3d_project__internal(ar, perspmat, is_local, co, tvec, flag); + if (ret == V3D_PROJ_RET_OK) { + if (isfinite(tvec[0]) && isfinite(tvec[1])) { + copy_v2_v2(r_co, tvec); + } + else { + ret = V3D_PROJ_RET_OVERFLOW; + } + } + return ret; } /* --- short --- */ -eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, + const float co[3], + short r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - return ED_view3d_project_short_ex(ar, rv3d->persmat, false, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_short_ex(ar, rv3d->persmat, false, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar, + const float co[3], + short r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - ED_view3d_check_mats_rv3d(rv3d); - return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + ED_view3d_check_mats_rv3d(rv3d); + return ED_view3d_project_short_ex(ar, rv3d->persmatob, true, co, r_co, flag); } /* --- int --- */ -eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, + const float co[3], + int r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - return ED_view3d_project_int_ex(ar, rv3d->persmat, false, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_int_ex(ar, rv3d->persmat, false, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar, + const float co[3], + int r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - ED_view3d_check_mats_rv3d(rv3d); - return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + ED_view3d_check_mats_rv3d(rv3d); + return ED_view3d_project_int_ex(ar, rv3d->persmatob, true, co, r_co, flag); } /* --- float --- */ -eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, + const float co[3], + float r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - return ED_view3d_project_float_ex(ar, rv3d->persmat, false, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + return ED_view3d_project_float_ex(ar, rv3d->persmat, false, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, + const float co[3], + float r_co[2], + const eV3DProjTest flag) { - RegionView3D *rv3d = ar->regiondata; - ED_view3d_check_mats_rv3d(rv3d); - return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag); + RegionView3D *rv3d = ar->regiondata; + ED_view3d_check_mats_rv3d(rv3d); + return ED_view3d_project_float_ex(ar, rv3d->persmatob, true, co, r_co, flag); } - - /* More Generic Window/Ray/Vector projection functions * *************************************************** */ float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3]) { - return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[3]) { - return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize; + return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize; } /** @@ -286,70 +316,72 @@ float ED_view3d_pixel_size_no_ui_scale(const RegionView3D *rv3d, const float co[ */ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip) { - float zfac = mul_project_m4_v3_zfac((float (*)[4])rv3d->persmat, co); - - if (r_flip) { - *r_flip = (zfac < 0.0f); - } - - /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that - * (accounting for near zero values) */ - if (zfac < 1.e-6f && zfac > -1.e-6f) { - zfac = 1.0f; - } - - /* Negative zfac means x, y, z was behind the camera (in perspective). - * This gives flipped directions, so revert back to ok default case. */ - if (zfac < 0.0f) { - zfac = -zfac; - } - - return zfac; -} - -static void view3d_win_to_ray_segment( - struct Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const float mval[2], - float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3]) -{ - RegionView3D *rv3d = ar->regiondata; - float _ray_co[3], _ray_dir[3], start_offset, end_offset; - - if (!r_ray_co) { - r_ray_co = _ray_co; - } - if (!r_ray_dir) { - r_ray_dir = _ray_dir; - } - - ED_view3d_win_to_origin(ar, mval, r_ray_co); - ED_view3d_win_to_vector(ar, mval, r_ray_dir); - - if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) { - end_offset = v3d->clip_end / 2.0f; - start_offset = -end_offset; - } - else { - ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false); - } - - if (r_ray_start) { - madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset); - } - if (r_ray_end) { - madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset); - } + float zfac = mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co); + + if (r_flip) { + *r_flip = (zfac < 0.0f); + } + + /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that + * (accounting for near zero values) */ + if (zfac < 1.e-6f && zfac > -1.e-6f) { + zfac = 1.0f; + } + + /* Negative zfac means x, y, z was behind the camera (in perspective). + * This gives flipped directions, so revert back to ok default case. */ + if (zfac < 0.0f) { + zfac = -zfac; + } + + return zfac; +} + +static void view3d_win_to_ray_segment(struct Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const float mval[2], + float r_ray_co[3], + float r_ray_dir[3], + float r_ray_start[3], + float r_ray_end[3]) +{ + RegionView3D *rv3d = ar->regiondata; + float _ray_co[3], _ray_dir[3], start_offset, end_offset; + + if (!r_ray_co) { + r_ray_co = _ray_co; + } + if (!r_ray_dir) { + r_ray_dir = _ray_dir; + } + + ED_view3d_win_to_origin(ar, mval, r_ray_co); + ED_view3d_win_to_vector(ar, mval, r_ray_dir); + + if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) { + end_offset = v3d->clip_end / 2.0f; + start_offset = -end_offset; + } + else { + ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false); + } + + if (r_ray_start) { + madd_v3_v3v3fl(r_ray_start, r_ray_co, r_ray_dir, start_offset); + } + if (r_ray_end) { + madd_v3_v3v3fl(r_ray_end, r_ray_co, r_ray_dir, end_offset); + } } bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]) { - if ((rv3d->rflag & RV3D_CLIPPING) && - (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, - ray_start, ray_end) == false)) - { - return false; - } - return true; + if ((rv3d->rflag & RV3D_CLIPPING) && + (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, ray_start, ray_end) == false)) { + return false; + } + return true; } /** @@ -368,21 +400,26 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float * \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes. * \return success, false if the ray is totally clipped. */ -bool ED_view3d_win_to_ray_clipped_ex( - struct Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const float mval[2], - float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip_planes) +bool ED_view3d_win_to_ray_clipped_ex(struct Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const float mval[2], + float r_ray_co[3], + float r_ray_normal[3], + float r_ray_start[3], + bool do_clip_planes) { - float ray_end[3]; + float ray_end[3]; - view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end); + view3d_win_to_ray_segment( + depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end); - /* bounds clipping */ - if (do_clip_planes) { - return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); - } + /* bounds clipping */ + if (do_clip_planes) { + return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); + } - return true; + return true; } /** @@ -398,12 +435,16 @@ bool ED_view3d_win_to_ray_clipped_ex( * \param do_clip_planes: Optionally clip the start of the ray by the view clipping planes. * \return success, false if the ray is totally clipped. */ -bool ED_view3d_win_to_ray_clipped( - struct Depsgraph *depsgraph, - const ARegion *ar, const View3D *v3d, const float mval[2], - float r_ray_start[3], float r_ray_normal[3], const bool do_clip_planes) +bool ED_view3d_win_to_ray_clipped(struct Depsgraph *depsgraph, + const ARegion *ar, + const View3D *v3d, + const float mval[2], + float r_ray_start[3], + float r_ray_normal[3], + const bool do_clip_planes) { - return ED_view3d_win_to_ray_clipped_ex(depsgraph, ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes); + return ED_view3d_win_to_ray_clipped_ex( + depsgraph, ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip_planes); } /** @@ -416,12 +457,13 @@ bool ED_view3d_win_to_ray_clipped( * * \note Ignores view near/far clipping, to take this into account use #ED_view3d_win_to_ray_clipped. */ -void ED_view3d_win_to_ray( - const ARegion *ar, const float mval[2], - float r_ray_start[3], float r_ray_normal[3]) +void ED_view3d_win_to_ray(const ARegion *ar, + const float mval[2], + float r_ray_start[3], + float r_ray_normal[3]) { - ED_view3d_win_to_origin(ar, mval, r_ray_start); - ED_view3d_win_to_vector(ar, mval, r_ray_normal); + ED_view3d_win_to_origin(ar, mval, r_ray_start); + ED_view3d_win_to_vector(ar, mval, r_ray_normal); } /** @@ -433,57 +475,57 @@ void ED_view3d_win_to_ray( */ void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3]) { - if (rv3d->is_persp) { - float p1[4], p2[4]; + if (rv3d->is_persp) { + float p1[4], p2[4]; - copy_v3_v3(p1, coord); - p1[3] = 1.0f; - copy_v3_v3(p2, p1); - p2[3] = 1.0f; - mul_m4_v4((float (*)[4])rv3d->viewmat, p2); + copy_v3_v3(p1, coord); + p1[3] = 1.0f; + copy_v3_v3(p2, p1); + p2[3] = 1.0f; + mul_m4_v4((float(*)[4])rv3d->viewmat, p2); - mul_v3_fl(p2, 2.0f); + mul_v3_fl(p2, 2.0f); - mul_m4_v4((float (*)[4])rv3d->viewinv, p2); + mul_m4_v4((float(*)[4])rv3d->viewinv, p2); - sub_v3_v3v3(vec, p1, p2); - } - else { - copy_v3_v3(vec, rv3d->viewinv[2]); - } - normalize_v3(vec); + sub_v3_v3v3(vec, p1, p2); + } + else { + copy_v3_v3(vec, rv3d->viewinv[2]); + } + normalize_v3(vec); } /* very similar to ED_view3d_win_to_3d() but has no advantage, de-duplicating */ #if 0 bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback) { - RegionView3D *rv3d = ar->regiondata; - float dvec[3]; - int mval_cpy[2]; - eV3DProjStatus ret; - - ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP); - - if (ret == V3D_PROJ_RET_OK) { - const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), - (float)(mval_cpy[1] - mval[1])}; - const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - sub_v3_v3(fp, dvec); - - return true; - } - else { - /* fallback to the view center */ - if (do_fallback) { - negate_v3_v3(fp, rv3d->ofs); - return view3d_get_view_aligned_coordinate(ar, fp, mval, false); - } - else { - return false; - } - } + RegionView3D *rv3d = ar->regiondata; + float dvec[3]; + int mval_cpy[2]; + eV3DProjStatus ret; + + ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP); + + if (ret == V3D_PROJ_RET_OK) { + const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), + (float)(mval_cpy[1] - mval[1])}; + const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); + sub_v3_v3(fp, dvec); + + return true; + } + else { + /* fallback to the view center */ + if (do_fallback) { + negate_v3_v3(fp, rv3d->ofs); + return view3d_get_view_aligned_coordinate(ar, fp, mval, false); + } + else { + return false; + } + } } #endif @@ -494,90 +536,93 @@ bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval * \param mval: The area relative location (such as event->mval converted to floats). * \param r_out: The resulting world-space location. */ -void ED_view3d_win_to_3d( - const View3D *v3d, const ARegion *ar, - const float depth_pt[3], const float mval[2], - float r_out[3]) -{ - RegionView3D *rv3d = ar->regiondata; - - float ray_origin[3]; - float ray_direction[3]; - float lambda; - - if (rv3d->is_persp) { - float plane[4]; - - copy_v3_v3(ray_origin, rv3d->viewinv[3]); - ED_view3d_win_to_vector(ar, mval, ray_direction); - - /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the - * view no matter what, so apply the unsigned factor instead */ - plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); - - isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false); - lambda = fabsf(lambda); - } - else { - float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; - float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; - - if (rv3d->persp == RV3D_CAMOB) { - /* ortho camera needs offset applied */ - const Camera *cam = v3d->camera->data; - const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, ar->winx, ar->winy); - const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f; - const float aspx = ar->winx / (float)ar->winy; - const float aspy = ar->winy / (float)ar->winx; - const float shiftx = cam->shiftx * 0.5f * (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy); - const float shifty = cam->shifty * 0.5f * (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f); - - dx += (rv3d->camdx + shiftx) * zoomfac; - dy += (rv3d->camdy + shifty) * zoomfac; - } - ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; - ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; - ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; - - copy_v3_v3(ray_direction, rv3d->viewinv[2]); - lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction); - } - - madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda); -} - -void ED_view3d_win_to_3d_int( - const View3D *v3d, const ARegion *ar, - const float depth_pt[3], const int mval[2], - float r_out[3]) -{ - const float mval_fl[2] = {mval[0], mval[1]}; - ED_view3d_win_to_3d(v3d, ar, depth_pt, mval_fl, r_out); -} - -bool ED_view3d_win_to_3d_on_plane( - const ARegion *ar, - const float plane[4], const float mval[2], const bool do_clip, - float r_out[3]) -{ - float ray_co[3], ray_no[3]; - ED_view3d_win_to_origin(ar, mval, ray_co); - ED_view3d_win_to_vector(ar, mval, ray_no); - float lambda; - if (isect_ray_plane_v3(ray_co, ray_no, plane, &lambda, do_clip)) { - madd_v3_v3v3fl(r_out, ray_co, ray_no, lambda); - return true; - } - return false; +void ED_view3d_win_to_3d(const View3D *v3d, + const ARegion *ar, + const float depth_pt[3], + const float mval[2], + float r_out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + + float ray_origin[3]; + float ray_direction[3]; + float lambda; + + if (rv3d->is_persp) { + float plane[4]; + + copy_v3_v3(ray_origin, rv3d->viewinv[3]); + ED_view3d_win_to_vector(ar, mval, ray_direction); + + /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the + * view no matter what, so apply the unsigned factor instead */ + plane_from_point_normal_v3(plane, depth_pt, rv3d->viewinv[2]); + + isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, false); + lambda = fabsf(lambda); + } + else { + float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; + float dy = (2.0f * mval[1] / (float)ar->winy) - 1.0f; + + if (rv3d->persp == RV3D_CAMOB) { + /* ortho camera needs offset applied */ + const Camera *cam = v3d->camera->data; + const int sensor_fit = BKE_camera_sensor_fit(cam->sensor_fit, ar->winx, ar->winy); + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 4.0f; + const float aspx = ar->winx / (float)ar->winy; + const float aspy = ar->winy / (float)ar->winx; + const float shiftx = cam->shiftx * 0.5f * + (sensor_fit == CAMERA_SENSOR_FIT_HOR ? 1.0f : aspy); + const float shifty = cam->shifty * 0.5f * + (sensor_fit == CAMERA_SENSOR_FIT_HOR ? aspx : 1.0f); + + dx += (rv3d->camdx + shiftx) * zoomfac; + dy += (rv3d->camdy + shifty) * zoomfac; + } + ray_origin[0] = (rv3d->persinv[0][0] * dx) + (rv3d->persinv[1][0] * dy) + rv3d->viewinv[3][0]; + ray_origin[1] = (rv3d->persinv[0][1] * dx) + (rv3d->persinv[1][1] * dy) + rv3d->viewinv[3][1]; + ray_origin[2] = (rv3d->persinv[0][2] * dx) + (rv3d->persinv[1][2] * dy) + rv3d->viewinv[3][2]; + + copy_v3_v3(ray_direction, rv3d->viewinv[2]); + lambda = ray_point_factor_v3(depth_pt, ray_origin, ray_direction); + } + + madd_v3_v3v3fl(r_out, ray_origin, ray_direction, lambda); +} + +void ED_view3d_win_to_3d_int(const View3D *v3d, + const ARegion *ar, + const float depth_pt[3], + const int mval[2], + float r_out[3]) +{ + const float mval_fl[2] = {mval[0], mval[1]}; + ED_view3d_win_to_3d(v3d, ar, depth_pt, mval_fl, r_out); +} + +bool ED_view3d_win_to_3d_on_plane(const ARegion *ar, + const float plane[4], + const float mval[2], + const bool do_clip, + float r_out[3]) +{ + float ray_co[3], ray_no[3]; + ED_view3d_win_to_origin(ar, mval, ray_co); + ED_view3d_win_to_vector(ar, mval, ray_no); + float lambda; + if (isect_ray_plane_v3(ray_co, ray_no, plane, &lambda, do_clip)) { + madd_v3_v3v3fl(r_out, ray_co, ray_no, lambda); + return true; + } + return false; } bool ED_view3d_win_to_3d_on_plane_int( - const ARegion *ar, - const float plane[4], const int mval[2], const bool do_clip, - float r_out[3]) + const ARegion *ar, const float plane[4], const int mval[2], const bool do_clip, float r_out[3]) { - const float mval_fl[2] = {mval[0], mval[1]}; - return ED_view3d_win_to_3d_on_plane(ar, plane, mval_fl, do_clip, r_out); + const float mval_fl[2] = {mval[0], mval[1]}; + return ED_view3d_win_to_3d_on_plane(ar, plane, mval_fl, do_clip, r_out); } /** @@ -590,15 +635,15 @@ bool ED_view3d_win_to_3d_on_plane_int( */ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac) { - RegionView3D *rv3d = ar->regiondata; - float dx, dy; + RegionView3D *rv3d = ar->regiondata; + float dx, dy; - dx = 2.0f * mval[0] * zfac / ar->winx; - dy = 2.0f * mval[1] * zfac / ar->winy; + dx = 2.0f * mval[0] * zfac / ar->winx; + dy = 2.0f * mval[1] * zfac / ar->winy; - out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); - out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); - out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); + out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); + out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); + out[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy); } /** @@ -613,23 +658,23 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3] */ void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3]) { - RegionView3D *rv3d = ar->regiondata; - if (rv3d->is_persp) { - copy_v3_v3(out, rv3d->viewinv[3]); - } - else { - out[0] = 2.0f * mval[0] / ar->winx - 1.0f; - out[1] = 2.0f * mval[1] / ar->winy - 1.0f; + RegionView3D *rv3d = ar->regiondata; + if (rv3d->is_persp) { + copy_v3_v3(out, rv3d->viewinv[3]); + } + else { + out[0] = 2.0f * mval[0] / ar->winx - 1.0f; + out[1] = 2.0f * mval[1] / ar->winy - 1.0f; - if (rv3d->persp == RV3D_CAMOB) { - out[2] = -1.0f; - } - else { - out[2] = 0.0f; - } + if (rv3d->persp == RV3D_CAMOB) { + out[2] = -1.0f; + } + else { + out[2] = 0.0f; + } - mul_project_m4_v3(rv3d->persinv, out); - } + mul_project_m4_v3(rv3d->persinv, out); + } } /** @@ -647,19 +692,19 @@ void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3 */ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3]) { - RegionView3D *rv3d = ar->regiondata; + RegionView3D *rv3d = ar->regiondata; - if (rv3d->is_persp) { - out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f; - out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f; - out[2] = -0.5f; - mul_project_m4_v3(rv3d->persinv, out); - sub_v3_v3(out, rv3d->viewinv[3]); - } - else { - negate_v3_v3(out, rv3d->viewinv[2]); - } - normalize_v3(out); + if (rv3d->is_persp) { + out[0] = 2.0f * (mval[0] / ar->winx) - 1.0f; + out[1] = 2.0f * (mval[1] / ar->winy) - 1.0f; + out[2] = -0.5f; + mul_project_m4_v3(rv3d->persinv, out); + sub_v3_v3(out, rv3d->viewinv[3]); + } + else { + negate_v3_v3(out, rv3d->viewinv[2]); + } + normalize_v3(out); } /** @@ -676,19 +721,22 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3 * \param do_clip_planes: Optionally clip the ray by the view clipping planes. * \return success, false if the segment is totally clipped. */ -bool ED_view3d_win_to_segment_clipped( - struct Depsgraph *depsgraph, - const ARegion *ar, View3D *v3d, const float mval[2], - float r_ray_start[3], float r_ray_end[3], const bool do_clip_planes) +bool ED_view3d_win_to_segment_clipped(struct Depsgraph *depsgraph, + const ARegion *ar, + View3D *v3d, + const float mval[2], + float r_ray_start[3], + float r_ray_end[3], + const bool do_clip_planes) { - view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end); + view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end); - /* bounds clipping */ - if (do_clip_planes) { - return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); - } + /* bounds clipping */ + if (do_clip_planes) { + return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); + } - return true; + return true; } /* Utility functions for projection @@ -696,18 +744,20 @@ bool ED_view3d_win_to_segment_clipped( void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pmat[4][4]) { - float vmat[4][4]; + float vmat[4][4]; - mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, ob->obmat); - mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); + mul_m4_m4m4(vmat, (float(*)[4])rv3d->viewmat, ob->obmat); + mul_m4_m4m4(pmat, (float(*)[4])rv3d->winmat, vmat); } -void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]) +void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, + float obmat[4][4], + float pmat[4][4]) { - float vmat[4][4]; + float vmat[4][4]; - mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat); - mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); + mul_m4_m4m4(vmat, (float(*)[4])rv3d->viewmat, obmat); + mul_m4_m4m4(pmat, (float(*)[4])rv3d->winmat, vmat); } /** @@ -715,18 +765,19 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm * a point in world space. */ void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]) { - // viewport is set up to make coordinates relative to the region, not window - RegionView3D *rv3d = ar->regiondata; - int viewport[4] = {0, 0, ar->winx, ar->winy}; + // viewport is set up to make coordinates relative to the region, not window + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; - GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region); + GPU_matrix_project(world, rv3d->viewmat, rv3d->winmat, viewport, region); } -bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]) +bool ED_view3d_unproject( + const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]) { - RegionView3D *rv3d = ar->regiondata; - int viewport[4] = {0, 0, ar->winx, ar->winy}; - float region[3] = {regionx, regiony, regionz}; + RegionView3D *rv3d = ar->regiondata; + int viewport[4] = {0, 0, ar->winx, ar->winy}; + float region[3] = {regionx, regiony, regionz}; - return GPU_matrix_unproject(region, rv3d->viewmat, rv3d->winmat, viewport, world); + return GPU_matrix_unproject(region, rv3d->viewmat, rv3d->winmat, viewport, world); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index f57b31b2ed2..c0f2e563365 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -21,7 +21,6 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> #include <math.h> @@ -99,50 +98,49 @@ #include "GPU_glew.h" #include "GPU_matrix.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ // #include "PIL_time_utildefines.h" - /* -------------------------------------------------------------------- */ /** \name Public Utilities * \{ */ float ED_view3d_select_dist_px(void) { - return 75.0f * U.pixelsize; + return 75.0f * U.pixelsize; } /* TODO: should return whether there is valid context to continue */ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc) { - memset(vc, 0, sizeof(ViewContext)); - vc->C = C; - vc->ar = CTX_wm_region(C); - vc->bmain = CTX_data_main(C); - vc->depsgraph = CTX_data_depsgraph(C); - vc->scene = CTX_data_scene(C); - vc->view_layer = CTX_data_view_layer(C); - vc->v3d = CTX_wm_view3d(C); - vc->win = CTX_wm_window(C); - vc->rv3d = CTX_wm_region_view3d(C); - vc->obact = CTX_data_active_object(C); - vc->obedit = CTX_data_edit_object(C); + memset(vc, 0, sizeof(ViewContext)); + vc->C = C; + vc->ar = CTX_wm_region(C); + vc->bmain = CTX_data_main(C); + vc->depsgraph = CTX_data_depsgraph(C); + vc->scene = CTX_data_scene(C); + vc->view_layer = CTX_data_view_layer(C); + vc->v3d = CTX_wm_view3d(C); + vc->win = CTX_wm_window(C); + vc->rv3d = CTX_wm_region_view3d(C); + vc->obact = CTX_data_active_object(C); + vc->obedit = CTX_data_edit_object(C); } void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) { - vc->obact = obact; - if (vc->obedit) { - BLI_assert(BKE_object_is_in_editmode(obact)); - vc->obedit = obact; - /* previous selections are now invalid. */ - vc->v3d->flag |= V3D_INVALID_BACKBUF; + vc->obact = obact; + if (vc->obedit) { + BLI_assert(BKE_object_is_in_editmode(obact)); + vc->obedit = obact; + /* previous selections are now invalid. */ + vc->v3d->flag |= V3D_INVALID_BACKBUF; - if (vc->em) { - vc->em = BKE_editmesh_from_object(vc->obedit); - } - } + if (vc->em) { + vc->em = BKE_editmesh_from_object(vc->obedit); + } + } } /** \} */ @@ -153,31 +151,31 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact) static bool object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d) { - bool changed = false; - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (base->flag & BASE_SELECTED) { - if (BASE_SELECTABLE(v3d, base)) { - ED_object_base_select(base, BA_DESELECT); - changed = true; - } - } - } - return changed; + bool changed = false; + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->flag & BASE_SELECTED) { + if (BASE_SELECTABLE(v3d, base)) { + ED_object_base_select(base, BA_DESELECT); + changed = true; + } + } + } + return changed; } /* deselect all except b */ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) { - bool changed = false; - for (Base *base = view_layer->object_bases.first; base; base = base->next) { - if (base->flag & BASE_SELECTED) { - if (b != base) { - ED_object_base_select(base, BA_DESELECT); - changed = true; - } - } - } - return changed; + bool changed = false; + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->flag & BASE_SELECTED) { + if (b != base) { + ED_object_base_select(base, BA_DESELECT); + changed = true; + } + } + } + return changed; } /** \} */ @@ -188,114 +186,114 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b) static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op) { - BMVert *eve; - BMIter iter; - uint index = bm_wireoffs; - bool changed = false; - - 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 = EDBM_backbuf_check(index); - 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; - } - } - index++; - } - return changed; + BMVert *eve; + BMIter iter; + uint index = bm_wireoffs; + bool changed = false; + + 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 = EDBM_backbuf_check(index); + 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; + } + } + index++; + } + return changed; } static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op) { - BMEdge *eed; - BMIter iter; - uint index = bm_solidoffs; - bool changed = false; - - 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 = EDBM_backbuf_check(index); - 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; - } - } - index++; - } - return changed; + BMEdge *eed; + BMIter iter; + uint index = bm_solidoffs; + bool changed = false; + + 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 = EDBM_backbuf_check(index); + 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; + } + } + index++; + } + return changed; } static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op) { - BMFace *efa; - BMIter iter; - uint index = 1; - bool changed = false; - - 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 = EDBM_backbuf_check(index); - 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; - } - } - index++; - } - return changed; + BMFace *efa; + BMIter iter; + uint index = 1; + bool changed = false; + + 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 = EDBM_backbuf_check(index); + 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; + } + } + index++; + } + return changed; } /* object mode, edbm_ prefix is confusing here, rename? */ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op) { - MVert *mv = me->mvert; - uint index; - bool changed = false; - - if (mv) { - for (index = 1; index <= me->totvert; index++, mv++) { - if (!(mv->flag & ME_HIDE)) { - const bool is_select = mv->flag & SELECT; - const bool is_inside = EDBM_backbuf_check(index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); - changed = true; - } - } - } - } - return changed; + MVert *mv = me->mvert; + uint index; + bool changed = false; + + if (mv) { + for (index = 1; index <= me->totvert; index++, mv++) { + if (!(mv->flag & ME_HIDE)) { + const bool is_select = mv->flag & SELECT; + const bool is_inside = EDBM_backbuf_check(index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + changed = true; + } + } + } + } + return changed; } /* object mode, edbm_ prefix is confusing here, rename? */ static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op) { - MPoly *mpoly = me->mpoly; - uint index; - bool changed = false; - - if (mpoly) { - for (index = 1; index <= me->totpoly; index++, mpoly++) { - if (!(mpoly->flag & ME_HIDE)) { - const bool is_select = mpoly->flag & ME_FACE_SEL; - const bool is_inside = EDBM_backbuf_check(index); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); - changed = true; - } - } - } - } - return changed; + MPoly *mpoly = me->mpoly; + uint index; + bool changed = false; + + if (mpoly) { + for (index = 1; index <= me->totpoly; index++, mpoly++) { + if (!(mpoly->flag & ME_HIDE)) { + const bool is_select = mpoly->flag & ME_FACE_SEL; + const bool is_inside = EDBM_backbuf_check(index); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL); + changed = true; + } + } + } + } + return changed; } /** \} */ @@ -305,871 +303,911 @@ static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_o * \{ */ typedef struct LassoSelectUserData { - ViewContext *vc; - const rcti *rect; - const rctf *rect_fl; - rctf _rect_fl; - const int (*mcords)[2]; - int moves; - eSelectOp sel_op; - - /* runtime */ - int pass; - bool is_done; - bool is_changed; + ViewContext *vc; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + const int (*mcords)[2]; + int moves; + eSelectOp sel_op; + + /* runtime */ + int pass; + bool is_done; + bool is_changed; } LassoSelectUserData; -static void view3d_userdata_lassoselect_init( - LassoSelectUserData *r_data, - ViewContext *vc, const rcti *rect, const int (*mcords)[2], - const int moves, const eSelectOp sel_op) +static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, + ViewContext *vc, + const rcti *rect, + const int (*mcords)[2], + const int moves, + const eSelectOp sel_op) { - r_data->vc = vc; + r_data->vc = vc; - r_data->rect = rect; - r_data->rect_fl = &r_data->_rect_fl; - BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); + r_data->rect = rect; + r_data->rect_fl = &r_data->_rect_fl; + BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); - r_data->mcords = mcords; - r_data->moves = moves; - r_data->sel_op = sel_op; + r_data->mcords = mcords; + r_data->moves = moves; + r_data->sel_op = sel_op; - /* runtime */ - r_data->pass = 0; - r_data->is_done = false; - r_data->is_changed = false; + /* runtime */ + r_data->pass = 0; + r_data->is_done = false; + r_data->is_changed = false; } static bool view3d_selectable_data(bContext *C) { - Object *ob = CTX_data_active_object(C); + Object *ob = CTX_data_active_object(C); - if (!ED_operator_region_view3d_active(C)) { - return 0; - } + if (!ED_operator_region_view3d_active(C)) { + return 0; + } - if (ob) { - if (ob->mode & OB_MODE_EDIT) { - if (ob->type == OB_FONT) { - return 0; - } - } - else { - if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) && - !BKE_paint_select_elem_test(ob)) - { - return 0; - } - } - } + if (ob) { + if (ob->mode & OB_MODE_EDIT) { + if (ob->type == OB_FONT) { + return 0; + } + } + else { + if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) && + !BKE_paint_select_elem_test(ob)) { + return 0; + } + } + } - return 1; + return 1; } - /* 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); + 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 1; - } - - /* check points completely out rect */ - if (v1[0] < rect->xmin && v2[0] < rect->xmin) { - return 0; - } - if (v1[0] > rect->xmax && v2[0] > rect->xmax) { - return 0; - } - if (v1[1] < rect->ymin && v2[1] < rect->ymin) { - return 0; - } - if (v1[1] > rect->ymax && v2[1] > rect->ymax) { - return 0; - } - - /* 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 0; - } - if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) { - return 0; - } - - return 1; -} - -static void do_lasso_select_pose__do_tag( - void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) -{ - LassoSelectUserData *data = userData; - bArmature *arm = data->vc->obact->data; - - if (PBONE_SELECTABLE(arm, pchan->bone)) { - bool is_point_done = false; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) - { - is_point_done = true; - } - } - - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) - { - is_point_done = true; - } - } - - /* if one of points selected, we skip the bone itself */ - if ((is_point_done == true) || - ((is_point_done == false) && (points_proj_tot == 2) && - BLI_lasso_is_edge_inside(data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) - { - pchan->bone->flag |= BONE_DONE; - } - data->is_changed |= is_point_done; - } + int d1, d2, d3, d4; + + /* check points in rect */ + if (edge_fully_inside_rect(rect, v1, v2)) { + return 1; + } + + /* check points completely out rect */ + if (v1[0] < rect->xmin && v2[0] < rect->xmin) { + return 0; + } + if (v1[0] > rect->xmax && v2[0] > rect->xmax) { + return 0; + } + if (v1[1] < rect->ymin && v2[1] < rect->ymin) { + return 0; + } + if (v1[1] > rect->ymax && v2[1] > rect->ymax) { + return 0; + } + + /* 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 0; + } + if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) { + return 0; + } + + return 1; +} + +static void do_lasso_select_pose__do_tag(void *userData, + struct bPoseChannel *pchan, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + LassoSelectUserData *data = userData; + bArmature *arm = data->vc->obact->data; + + if (PBONE_SELECTABLE(arm, pchan->bone)) { + bool is_point_done = false; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + is_point_done = true; + } + } + + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + is_point_done = true; + } + } + + /* if one of points selected, we skip the bone itself */ + if ((is_point_done == true) || + ((is_point_done == false) && (points_proj_tot == 2) && + BLI_lasso_is_edge_inside( + data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) { + pchan->bone->flag |= BONE_DONE; + } + data->is_changed |= is_point_done; + } } static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves) { - ViewContext vc_tmp; - LassoSelectUserData data; - rcti rect; + ViewContext vc_tmp; + LassoSelectUserData data; + rcti rect; - if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) { - return; - } + if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) { + return; + } - vc_tmp = *vc; - vc_tmp.obact = ob; + vc_tmp = *vc; + vc_tmp.obact = ob; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcords, moves); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0); - ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); + ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); - pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT); } -static bool do_lasso_select_objects( - ViewContext *vc, const int mcords[][2], const short moves, - const eSelectOp sel_op) +static bool do_lasso_select_objects(ViewContext *vc, + const int mcords[][2], + const short moves, + const eSelectOp sel_op) { - View3D *v3d = vc->v3d; - Base *base; + View3D *v3d = vc->v3d; + Base *base; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); - } + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + } - for (base = vc->view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */ - const bool is_select = base->flag & BASE_SELECTED; - const bool is_inside = ( - (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT); - changed = true; - } - } - } + for (base = vc->view_layer->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */ + const bool is_select = base->flag & BASE_SELECTED; + const bool is_inside = ((ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) && + BLI_lasso_is_point_inside( + mcords, moves, base->sx, base->sy, IS_CLIPPED)); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT); + 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); - } - return changed; + if (changed) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); + } + return changed; } - /** * Use for lasso & box select. */ static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len) { - Base **bases = NULL; - BLI_array_declare(bases); - FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) { - Object *ob_iter = base_iter->object; - bArmature *arm = ob_iter->data; - for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) { - Bone *bone = pchan->bone; - bone->flag &= ~BONE_DONE; - } - arm->id.tag |= LIB_TAG_DOIT; - ob_iter->id.tag &= ~LIB_TAG_DOIT; - BLI_array_append(bases, base_iter); - } - FOREACH_BASE_IN_MODE_END; - *r_bases_len = BLI_array_len(bases); - return bases; + Base **bases = NULL; + BLI_array_declare(bases); + FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) { + Object *ob_iter = base_iter->object; + bArmature *arm = ob_iter->data; + for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; + bone->flag &= ~BONE_DONE; + } + arm->id.tag |= LIB_TAG_DOIT; + ob_iter->id.tag &= ~LIB_TAG_DOIT; + BLI_array_append(bases, base_iter); + } + FOREACH_BASE_IN_MODE_END; + *r_bases_len = BLI_array_len(bases); + return bases; } static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const eSelectOp sel_op) { - bool changed_multi = false; - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - for (int i = 0; i < bases_len; i++) { - Base *base_iter = bases[i]; - Object *ob_iter = base_iter->object; - if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) { - ED_pose_bone_select_tag_update(ob_iter); - changed_multi = true; - } - } - } - - for (int i = 0; i < bases_len; i++) { - Base *base_iter = bases[i]; - Object *ob_iter = base_iter->object; - bArmature *arm = ob_iter->data; - - /* Don't handle twice. */ - if (arm->id.tag & LIB_TAG_DOIT) { - arm->id.tag &= ~LIB_TAG_DOIT; - } - else { - continue; - } - - bool changed = true; - for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) { - Bone *bone = pchan->bone; - if ((bone->flag & BONE_UNSELECTABLE) == 0) { - const bool is_select = bone->flag & BONE_SELECTED; - const bool is_inside = bone->flag & BONE_DONE; - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bone->flag, sel_op_result, BONE_SELECTED); - if (sel_op_result == 0) { - if (arm->act_bone == bone) { - arm->act_bone = NULL; - } - } - changed = true; - } - } - } - if (changed) { - ED_pose_bone_select_tag_update(ob_iter); - changed_multi = true; - } - } - return changed_multi; -} - -static bool do_lasso_select_pose( - ViewContext *vc, const int mcords[][2], const short moves, - const eSelectOp sel_op) -{ - uint bases_len; - Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); - - for (int i = 0; i < bases_len; i++) { - Base *base_iter = bases[i]; - Object *ob_iter = base_iter->object; - do_lasso_tag_pose(vc, ob_iter, mcords, moves); - } - - const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); - if (changed_multi) { - DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); - WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); - } - - MEM_freeN(bases); - return changed_multi; -} - -static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) -{ - LassoSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = ( - BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); - const 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; - } + bool changed_multi = false; + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + for (int i = 0; i < bases_len; i++) { + Base *base_iter = bases[i]; + Object *ob_iter = base_iter->object; + if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) { + ED_pose_bone_select_tag_update(ob_iter); + changed_multi = true; + } + } + } + + for (int i = 0; i < bases_len; i++) { + Base *base_iter = bases[i]; + Object *ob_iter = base_iter->object; + bArmature *arm = ob_iter->data; + + /* Don't handle twice. */ + if (arm->id.tag & LIB_TAG_DOIT) { + arm->id.tag &= ~LIB_TAG_DOIT; + } + else { + continue; + } + + bool changed = true; + for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; + if ((bone->flag & BONE_UNSELECTABLE) == 0) { + const bool is_select = bone->flag & BONE_SELECTED; + const bool is_inside = bone->flag & BONE_DONE; + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bone->flag, sel_op_result, BONE_SELECTED); + if (sel_op_result == 0) { + if (arm->act_bone == bone) { + arm->act_bone = NULL; + } + } + changed = true; + } + } + } + if (changed) { + ED_pose_bone_select_tag_update(ob_iter); + changed_multi = true; + } + } + return changed_multi; +} + +static bool do_lasso_select_pose(ViewContext *vc, + const int mcords[][2], + const short moves, + const eSelectOp sel_op) +{ + uint bases_len; + Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); + + for (int i = 0; i < bases_len; i++) { + Base *base_iter = bases[i]; + Object *ob_iter = base_iter->object; + do_lasso_tag_pose(vc, ob_iter, mcords, moves); + } + + const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); + if (changed_multi) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene); + } + + MEM_freeN(bases); + return changed_multi; +} + +static void do_lasso_select_mesh__doSelectVert(void *userData, + BMVert *eve, + const float screen_co[2], + int UNUSED(index)) +{ + LassoSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); + const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const 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; + } } static void do_lasso_select_mesh__doSelectEdge_pass0( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - LassoSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = ( - EDBM_backbuf_check(bm_solidoffs + index) && - edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); - 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; - data->is_changed = true; - } + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +{ + LassoSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); + const bool is_inside = + (EDBM_backbuf_check(bm_solidoffs + index) && + edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); + 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; + data->is_changed = true; + } } static void do_lasso_select_mesh__doSelectEdge_pass1( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - LassoSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = ( - EDBM_backbuf_check(bm_solidoffs + index) && - BLI_lasso_is_edge_inside( - data->mcords, data->moves, 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); - if (sel_op_result != -1) { - BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); - data->is_changed = true; - } -} - -static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) -{ - LassoSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = ( - BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); - const 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; - } -} - -static bool do_lasso_select_mesh( - ViewContext *vc, - const int mcords[][2], short moves, const eSelectOp sel_op) -{ - LassoSelectUserData data; - ToolSettings *ts = vc->scene->toolsettings; - rcti rect; - int bbsel; - - /* set editmesh */ - vc->em = BKE_editmesh_from_object(vc->obedit); - - BLI_lasso_boundbox(&rect, mcords, moves); - - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - if (vc->em->bm->totvertsel) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); - data.is_changed = true; - } - } - - /* for non zbuf projections, don't change the GL state */ - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - - GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - - if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); - } - else { - mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); - if (data.is_done == false) { - mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); - } - } - - if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); - } - else { - mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - - EDBM_backbuf_free(); - - if (data.is_changed) { - EDBM_selectmode_flush(vc->em); - } - return data.is_changed; -} - -static void do_lasso_select_curve__doSelect( - void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) -{ - LassoSelectUserData *data = userData; - - const bool is_inside = BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED); - if (bp) { - const bool is_select = bp->f1 & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); - data->is_changed = true; - } - } - else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ - const bool is_select = bezt->f2 & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); - } - bezt->f1 = bezt->f3 = bezt->f2; - data->is_changed = true; - } - else { - char *flag_p = (&bezt->f1) + beztindex; - const bool is_select = *flag_p & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); - data->is_changed = true; - } - } - } -} - -static bool do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) -{ - LassoSelectUserData data; - rcti rect; - - BLI_lasso_boundbox(&rect, mcords, moves); - - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - Curve *curve = (Curve *) vc->obedit->data; - data.is_changed |= ED_curve_deselect_all(curve->editnurb); - } - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if (data.is_changed) { - BKE_curve_nurb_vert_active_validate(vc->obedit->data); - } - return data.is_changed; + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +{ + LassoSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); + const bool is_inside = + (EDBM_backbuf_check(bm_solidoffs + index) && + BLI_lasso_is_edge_inside( + data->mcords, data->moves, 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); + if (sel_op_result != -1) { + BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); + data->is_changed = true; + } +} + +static void do_lasso_select_mesh__doSelectFace(void *userData, + BMFace *efa, + const float screen_co[2], + int UNUSED(index)) +{ + LassoSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); + const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const 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; + } +} + +static bool do_lasso_select_mesh(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) +{ + LassoSelectUserData data; + ToolSettings *ts = vc->scene->toolsettings; + rcti rect; + int bbsel; + + /* set editmesh */ + vc->em = BKE_editmesh_from_object(vc->obedit); + + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + data.is_changed = true; + } + } + + /* for non zbuf projections, don't change the GL state */ + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + GPU_matrix_set(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_mask_init( + vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + if (ts->selectmode & SCE_SELECT_VERTEX) { + if (bbsel) { + data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + } + else { + mesh_foreachScreenVert( + vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + if (ts->selectmode & SCE_SELECT_EDGE) { + /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + mesh_foreachScreenEdge( + vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + if (data.is_done == false) { + mesh_foreachScreenEdge( + vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + } + } + + if (ts->selectmode & SCE_SELECT_FACE) { + if (bbsel) { + data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + } + else { + mesh_foreachScreenFace( + vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + + EDBM_backbuf_free(); + + if (data.is_changed) { + EDBM_selectmode_flush(vc->em); + } + return data.is_changed; +} + +static void do_lasso_select_curve__doSelect(void *userData, + Nurb *UNUSED(nu), + BPoint *bp, + BezTriple *bezt, + int beztindex, + const float screen_co[2]) +{ + LassoSelectUserData *data = userData; + + const bool is_inside = BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED); + if (bp) { + const bool is_select = bp->f1 & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; + } + } + else { + if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { + /* can only be (beztindex == 0) here since handles are hidden */ + const bool is_select = bezt->f2 & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); + } + bezt->f1 = bezt->f3 = bezt->f2; + data->is_changed = true; + } + else { + char *flag_p = (&bezt->f1) + beztindex; + const bool is_select = *flag_p & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); + data->is_changed = true; + } + } + } +} + +static bool do_lasso_select_curve(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) +{ + LassoSelectUserData data; + rcti rect; + + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + Curve *curve = (Curve *)vc->obedit->data; + data.is_changed |= ED_curve_deselect_all(curve->editnurb); + } + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + if (data.is_changed) { + BKE_curve_nurb_vert_active_validate(vc->obedit->data); + } + return data.is_changed; } static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - LassoSelectUserData *data = userData; - const bool is_select = bp->f1 & SELECT; - const bool is_inside = ( - BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); - data->is_changed = true; - } + LassoSelectUserData *data = userData; + const bool is_select = bp->f1 & SELECT; + const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; + } } -static bool do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_lattice(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) { - LassoSelectUserData data; - rcti rect; - - BLI_lasso_boundbox(&rect, mcords, moves); - - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); - } - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return data.is_changed; + LassoSelectUserData data; + rcti rect; + + BLI_lasso_boundbox(&rect, mcords, moves); + + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); + } + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + lattice_foreachScreenVert( + vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + return data.is_changed; } -static void do_lasso_select_armature__doSelectBone( - void *userData, EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) +static void do_lasso_select_armature__doSelectBone(void *userData, + EditBone *ebone, + const float screen_co_a[2], + const float screen_co_b[2]) { - LassoSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; - if (EBONE_VISIBLE(arm, ebone)) { - int is_ignore_flag = 0; - int is_inside_flag = 0; - - if (screen_co_a[0] != IS_CLIPPED) { - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) - { - is_inside_flag |= BONESEL_ROOT; - } - } - else { - is_ignore_flag |= BONESEL_ROOT; - } + LassoSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; + if (EBONE_VISIBLE(arm, ebone)) { + int is_ignore_flag = 0; + int is_inside_flag = 0; - if (screen_co_b[0] != IS_CLIPPED) { - if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) - { - is_inside_flag |= BONESEL_TIP; - } - } - else { - is_ignore_flag |= BONESEL_TIP; - } + if (screen_co_a[0] != IS_CLIPPED) { + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + is_inside_flag |= BONESEL_ROOT; + } + } + else { + is_ignore_flag |= BONESEL_ROOT; + } - if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) - { - is_inside_flag |= BONESEL_BONE; - } + if (screen_co_b[0] != IS_CLIPPED) { + if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && + BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + is_inside_flag |= BONESEL_TIP; + } + } + else { + is_ignore_flag |= BONESEL_TIP; + } + if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || + BLI_lasso_is_edge_inside( + data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { + is_inside_flag |= BONESEL_BONE; + } - ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16); - } + ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16); + } } -static bool do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_armature(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) { - LassoSelectUserData data; - rcti rect; + LassoSelectUserData data; + rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcords, moves); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); - } + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); + } - bArmature *arm = vc->obedit->data; + bArmature *arm = vc->obedit->data; - ED_armature_ebone_listbase_temp_clear(arm->edbo); + ED_armature_ebone_listbase_temp_clear(arm->edbo); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + armature_foreachScreenBone( + vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); + data.is_changed |= ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op); - if (data.is_changed) { - WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); - } - return data.is_changed; + if (data.is_changed) { + WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); + } + return data.is_changed; } -static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) +static void do_lasso_select_mball__doSelectElem(void *userData, + struct MetaElem *ml, + const float screen_co[2]) { - LassoSelectUserData *data = userData; - const bool is_select = ml->flag & SELECT; - const bool is_inside = ( - BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); - data->is_changed = true; - } + LassoSelectUserData *data = userData; + const bool is_select = ml->flag & SELECT; + const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)); + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); + data->is_changed = true; + } } -static bool do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_meta(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) { - LassoSelectUserData data; - rcti rect; + LassoSelectUserData data; + rcti rect; - MetaBall *mb = (MetaBall *)vc->obedit->data; + MetaBall *mb = (MetaBall *)vc->obedit->data; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcords, moves); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= BKE_mball_deselect_all(mb); - } + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= BKE_mball_deselect_all(mb); + } - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mball_foreachScreenElem( + vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return data.is_changed; + return data.is_changed; } -static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) +static void do_lasso_select_meshobject__doSelectVert(void *userData, + MVert *mv, + const float screen_co[2], + int UNUSED(index)) { - LassoSelectUserData *data = userData; - const bool is_select = mv->flag & SELECT; - const bool is_inside = ( - BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); - data->is_changed = true; - } + LassoSelectUserData *data = userData; + const bool is_select = mv->flag & SELECT; + const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + data->is_changed = true; + } } -static bool do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_paintvert(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) { - const bool use_zbuf = !XRAY_ENABLED(vc->v3d); - Object *ob = vc->obact; - Mesh *me = ob->data; - rcti rect; + const bool use_zbuf = !XRAY_ENABLED(vc->v3d); + Object *ob = vc->obact; + Mesh *me = ob->data; + rcti rect; - if (me == NULL || me->totvert == 0) { - return false; - } + if (me == NULL || me->totvert == 0) { + return false; + } - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - /* flush selection at the end */ - changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); - } + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + /* flush selection at the end */ + changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); + } - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcords, moves); - if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ + if (use_zbuf) { + bm_vertoffs = me->totvert + 1; /* max index array */ - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); + changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); - EDBM_backbuf_free(); - } - else { - LassoSelectUserData data; + EDBM_backbuf_free(); + } + else { + LassoSelectUserData data; - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); - ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + meshobject_foreachScreenVert( + vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; - } + changed |= data.is_changed; + } - if (changed) { - if (SEL_OP_CAN_DESELECT(sel_op)) { - BKE_mesh_mselect_validate(me); - } - paintvert_flush_flags(ob); - paintvert_tag_select_update(vc->C, ob); - } - return changed; + if (changed) { + if (SEL_OP_CAN_DESELECT(sel_op)) { + BKE_mesh_mselect_validate(me); + } + paintvert_flush_flags(ob); + paintvert_tag_select_update(vc->C, ob); + } + return changed; } -static bool do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool do_lasso_select_paintface(ViewContext *vc, + const int mcords[][2], + short moves, + const eSelectOp sel_op) { - Object *ob = vc->obact; - Mesh *me = ob->data; - rcti rect; + Object *ob = vc->obact; + Mesh *me = ob->data; + rcti rect; - if (me == NULL || me->totpoly == 0) { - return false; - } + if (me == NULL || me->totpoly == 0) { + return false; + } - bm_vertoffs = me->totpoly + 1; /* max index array */ + bm_vertoffs = me->totpoly + 1; /* max index array */ - BLI_lasso_boundbox(&rect, mcords, moves); - EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLI_lasso_boundbox(&rect, mcords, moves); + EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - /* flush selection at the end */ - changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); - } - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + /* flush selection at the end */ + changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); + } + changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); + EDBM_backbuf_free(); - if (changed) { - paintface_flush_flags(vc->C, ob, SELECT); - } - return changed; + if (changed) { + paintface_flush_flags(vc->C, ob, SELECT); + } + return changed; } #if 0 static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op) { - SpaceNode *snode = sa->spacedata.first; - - bNode *node; - rcti rect; - int node_cent[2]; - float node_centf[2]; - bool changed = false; - - BLI_lasso_boundbox(&rect, mcords, moves); - - /* store selection in temp test flag */ - for (node = snode->edittree->nodes.first; node; node = node->next) { - node_centf[0] = BLI_RCT_CENTER_X(&node->totr); - node_centf[1] = BLI_RCT_CENTER_Y(&node->totr); - - ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent); - const bool is_select = node->flag & SELECT; - const bool is_inside = ( - BLI_rcti_isect_pt_v(&rect, node_cent) && - BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT); - changed = true; - } - } - if (changed) { - BIF_undo_push("Lasso select nodes"); - } + SpaceNode *snode = sa->spacedata.first; + + bNode *node; + rcti rect; + int node_cent[2]; + float node_centf[2]; + bool changed = false; + + BLI_lasso_boundbox(&rect, mcords, moves); + + /* store selection in temp test flag */ + for (node = snode->edittree->nodes.first; node; node = node->next) { + node_centf[0] = BLI_RCT_CENTER_X(&node->totr); + node_centf[1] = BLI_RCT_CENTER_Y(&node->totr); + + ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent); + const bool is_select = node->flag & SELECT; + const bool is_inside = ( + BLI_rcti_isect_pt_v(&rect, node_cent) && + BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT); + changed = true; + } + } + if (changed) { + BIF_undo_push("Lasso select nodes"); + } } #endif static bool view3d_lasso_select( - bContext *C, ViewContext *vc, - const int mcords[][2], short moves, - const eSelectOp sel_op) -{ - Object *ob = CTX_data_active_object(C); - bool changed_multi = false; - - if (vc->obedit == NULL) { /* Object Mode */ - if (BKE_paint_select_face_test(ob)) { - changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op); - } - else if (BKE_paint_select_vert_test(ob)) { - changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op); - } - else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { - /* pass */ - } - else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - changed_multi |= PE_lasso_select(C, mcords, moves, sel_op); - } - else if (ob && (ob->mode & OB_MODE_POSE)) { - changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op); - } - else { - changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op); - } - } - else { /* Edit Mode */ - - FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { - ED_view3d_viewcontext_init_object(vc, ob_iter); - bool changed = false; - - switch (vc->obedit->type) { - case OB_MESH: - changed = do_lasso_select_mesh(vc, mcords, moves, sel_op); - break; - case OB_CURVE: - case OB_SURF: - changed = do_lasso_select_curve(vc, mcords, moves, sel_op); - break; - case OB_LATTICE: - changed = do_lasso_select_lattice(vc, mcords, moves, sel_op); - break; - case OB_ARMATURE: - changed = do_lasso_select_armature(vc, mcords, moves, sel_op); - break; - case OB_MBALL: - changed = do_lasso_select_meta(vc, mcords, moves, sel_op); - break; - default: - assert(!"lasso select on incorrect object type"); - break; - } - - if (changed) { - DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); - changed_multi = true; - } - } - FOREACH_OBJECT_IN_MODE_END; - } - return changed_multi; + bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +{ + Object *ob = CTX_data_active_object(C); + bool changed_multi = false; + + if (vc->obedit == NULL) { /* Object Mode */ + if (BKE_paint_select_face_test(ob)) { + changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op); + } + else if (BKE_paint_select_vert_test(ob)) { + changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op); + } + else if (ob && + (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { + /* pass */ + } + else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { + changed_multi |= PE_lasso_select(C, mcords, moves, sel_op); + } + else if (ob && (ob->mode & OB_MODE_POSE)) { + changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op); + } + else { + changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op); + } + } + else { /* Edit Mode */ + + FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) { + ED_view3d_viewcontext_init_object(vc, ob_iter); + bool changed = false; + + switch (vc->obedit->type) { + case OB_MESH: + changed = do_lasso_select_mesh(vc, mcords, moves, sel_op); + break; + case OB_CURVE: + case OB_SURF: + changed = do_lasso_select_curve(vc, mcords, moves, sel_op); + break; + case OB_LATTICE: + changed = do_lasso_select_lattice(vc, mcords, moves, sel_op); + break; + case OB_ARMATURE: + changed = do_lasso_select_armature(vc, mcords, moves, sel_op); + break; + case OB_MBALL: + changed = do_lasso_select_meta(vc, mcords, moves, sel_op); + break; + default: + assert(!"lasso select on incorrect object type"); + break; + } + + if (changed) { + DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data); + changed_multi = true; + } + } + FOREACH_OBJECT_IN_MODE_END; + } + return changed_multi; } - /* lasso operator gives properties, but since old code works * with short array we convert */ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) { - ViewContext vc; - int mcords_tot; - const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + ViewContext vc; + int mcords_tot; + const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); - if (mcords) { - view3d_operator_needs_opengl(C); + if (mcords) { + view3d_operator_needs_opengl(C); - /* setup view context for argument to callbacks */ - ED_view3d_viewcontext_init(C, &vc); + /* setup view context for argument to callbacks */ + ED_view3d_viewcontext_init(C, &vc); - eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); + eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcords); - if (changed_multi) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } - } - return OPERATOR_PASS_THROUGH; + if (changed_multi) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } + } + return OPERATOR_PASS_THROUGH; } void VIEW3D_OT_select_lasso(wmOperatorType *ot) { - ot->name = "Lasso Select"; - ot->description = "Select items using lasso selection"; - ot->idname = "VIEW3D_OT_select_lasso"; + ot->name = "Lasso Select"; + ot->description = "Select items using lasso selection"; + ot->idname = "VIEW3D_OT_select_lasso"; - ot->invoke = WM_gesture_lasso_invoke; - ot->modal = WM_gesture_lasso_modal; - ot->exec = view3d_lasso_select_exec; - ot->poll = view3d_selectable_data; - ot->cancel = WM_gesture_lasso_cancel; + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = view3d_lasso_select_exec; + ot->poll = view3d_selectable_data; + ot->cancel = WM_gesture_lasso_cancel; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - WM_operator_properties_gesture_lasso(ot); - WM_operator_properties_select_operation(ot); + /* properties */ + WM_operator_properties_gesture_lasso(ot); + WM_operator_properties_select_operation(ot); } /** \} */ @@ -1180,1015 +1218,1068 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot) /* The max number of menu items in an object select menu */ typedef struct SelMenuItemF { - char idname[MAX_ID_NAME - 2]; - int icon; + char idname[MAX_ID_NAME - 2]; + int icon; } SelMenuItemF; -#define SEL_MENU_SIZE 22 +#define SEL_MENU_SIZE 22 static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE]; /* special (crappy) operator only for menu select */ -static const EnumPropertyItem *object_select_menu_enum_itemf( - bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) +static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - EnumPropertyItem *item = NULL, item_tmp = {0}; - int totitem = 0; - int i = 0; + EnumPropertyItem *item = NULL, item_tmp = {0}; + int totitem = 0; + int i = 0; - /* don't need context but avoid docgen using this */ - if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') { - return DummyRNA_NULL_items; - } + /* don't need context but avoid docgen using this */ + if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') { + return DummyRNA_NULL_items; + } - for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) { - item_tmp.name = object_mouse_select_menu_data[i].idname; - item_tmp.identifier = object_mouse_select_menu_data[i].idname; - item_tmp.value = i; - item_tmp.icon = object_mouse_select_menu_data[i].icon; - RNA_enum_item_add(&item, &totitem, &item_tmp); - } + for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) { + item_tmp.name = object_mouse_select_menu_data[i].idname; + item_tmp.identifier = object_mouse_select_menu_data[i].idname; + item_tmp.value = i; + item_tmp.icon = object_mouse_select_menu_data[i].icon; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } - RNA_enum_item_end(&item, &totitem); - *r_free = true; + RNA_enum_item_end(&item, &totitem); + *r_free = true; - return item; + return item; } static int object_select_menu_exec(bContext *C, wmOperator *op) { - const int name_index = RNA_enum_get(op->ptr, "name"); - const bool toggle = RNA_boolean_get(op->ptr, "toggle"); - bool changed = false; - const char *name = object_mouse_select_menu_data[name_index].idname; - - if (!toggle) { - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) - { - if ((base->flag & BASE_SELECTED) != 0) { - ED_object_base_select(base, BA_DESELECT); - changed = true; - } - } - CTX_DATA_END; - } - - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) - { - /* This is a bit dodgy, there should only be ONE object with this name, - * but library objects can mess this up. */ - if (STREQ(name, base->object->id.name + 2)) { - ED_object_base_activate(C, base); - ED_object_base_select(base, BA_SELECT); - changed = true; - } - } - CTX_DATA_END; - - /* weak but ensures we activate menu again before using the enum */ - memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); - - /* undo? */ - if (changed) { - Scene *scene = CTX_data_scene(C); - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + const int name_index = RNA_enum_get(op->ptr, "name"); + const bool toggle = RNA_boolean_get(op->ptr, "toggle"); + bool changed = false; + const char *name = object_mouse_select_menu_data[name_index].idname; + + if (!toggle) { + CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { + if ((base->flag & BASE_SELECTED) != 0) { + ED_object_base_select(base, BA_DESELECT); + changed = true; + } + } + CTX_DATA_END; + } + + CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { + /* This is a bit dodgy, there should only be ONE object with this name, + * but library objects can mess this up. */ + if (STREQ(name, base->object->id.name + 2)) { + ED_object_base_activate(C, base); + ED_object_base_select(base, BA_SELECT); + changed = true; + } + } + CTX_DATA_END; + + /* weak but ensures we activate menu again before using the enum */ + memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); + + /* undo? */ + if (changed) { + Scene *scene = CTX_data_scene(C); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_select_menu(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Select Menu"; - ot->description = "Menu object selection"; - ot->idname = "VIEW3D_OT_select_menu"; + /* identifiers */ + ot->name = "Select Menu"; + ot->description = "Menu object selection"; + ot->idname = "VIEW3D_OT_select_menu"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = object_select_menu_exec; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = object_select_menu_exec; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* keyingset to use (dynamic enum) */ - prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", ""); - RNA_def_enum_funcs(prop, object_select_menu_enum_itemf); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE); - ot->prop = prop; + /* keyingset to use (dynamic enum) */ + prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", ""); + RNA_def_enum_funcs(prop, object_select_menu_enum_itemf); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE); + ot->prop = prop; - RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); + RNA_def_boolean( + ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } static Base *object_mouse_select_menu( - bContext *C, ViewContext *vc, uint *buffer, int hits, - const int mval[2], bool toggle) -{ - short baseCount = 0; - bool ok; - LinkNode *linklist = NULL; - - /* handle base->object->select_id */ - CTX_DATA_BEGIN (C, Base *, base, selectable_bases) - { - ok = false; - - /* two selection methods, the CTRL select uses max dist of 15 */ - if (buffer) { - for (int a = 0; a < hits; a++) { - /* index was converted */ - if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { - ok = true; - break; - } - } - } - else { - const int dist = 15 * U.pixelsize; - if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { - const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]}; - if (len_manhattan_v2_int(delta_px) < dist) { - ok = true; - } - } - } - - if (ok) { - baseCount++; - BLI_linklist_prepend(&linklist, base); - - if (baseCount == SEL_MENU_SIZE) { - break; - } - } - } - CTX_DATA_END; - - if (baseCount == 0) { - return NULL; - } - if (baseCount == 1) { - Base *base = (Base *)linklist->link; - BLI_linklist_free(linklist, NULL); - return base; - } - else { - /* UI, full in static array values that we later use in an enum function */ - LinkNode *node; - int i; - - memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); - - for (node = linklist, i = 0; node; node = node->next, i++) { - Base *base = node->link; - Object *ob = base->object; - const char *name = ob->id.name + 2; - - BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2); - object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id); - } - - { - wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false); - PointerRNA ptr; - - WM_operator_properties_create_ptr(&ptr, ot); - RNA_boolean_set(&ptr, "toggle", toggle); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); - WM_operator_properties_free(&ptr); - } - - BLI_linklist_free(linklist, NULL); - return NULL; - } + bContext *C, ViewContext *vc, uint *buffer, int hits, const int mval[2], bool toggle) +{ + short baseCount = 0; + bool ok; + LinkNode *linklist = NULL; + + /* handle base->object->select_id */ + CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { + ok = false; + + /* two selection methods, the CTRL select uses max dist of 15 */ + if (buffer) { + for (int a = 0; a < hits; a++) { + /* index was converted */ + if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) { + ok = true; + break; + } + } + } + else { + const int dist = 15 * U.pixelsize; + if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) { + const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]}; + if (len_manhattan_v2_int(delta_px) < dist) { + ok = true; + } + } + } + + if (ok) { + baseCount++; + BLI_linklist_prepend(&linklist, base); + + if (baseCount == SEL_MENU_SIZE) { + break; + } + } + } + CTX_DATA_END; + + if (baseCount == 0) { + return NULL; + } + if (baseCount == 1) { + Base *base = (Base *)linklist->link; + BLI_linklist_free(linklist, NULL); + return base; + } + else { + /* UI, full in static array values that we later use in an enum function */ + LinkNode *node; + int i; + + memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data)); + + for (node = linklist, i = 0; node; node = node->next, i++) { + Base *base = node->link; + Object *ob = base->object; + const char *name = ob->id.name + 2; + + BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2); + object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id); + } + + { + wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false); + PointerRNA ptr; + + WM_operator_properties_create_ptr(&ptr, ot); + RNA_boolean_set(&ptr, "toggle", toggle); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); + WM_operator_properties_free(&ptr); + } + + BLI_linklist_free(linklist, NULL); + return NULL; + } } static bool selectbuffer_has_bones(const uint *buffer, const uint hits) { - uint i; - for (i = 0; i < hits; i++) { - if (buffer[(4 * i) + 3] & 0xFFFF0000) { - return true; - } - } - return false; + uint i; + for (i = 0; i < hits; i++) { + if (buffer[(4 * i) + 3] & 0xFFFF0000) { + return true; + } + } + return false; } /* utility function for mixed_bones_object_selectbuffer */ static int selectbuffer_ret_hits_15(uint *UNUSED(buffer), const int hits15) { - return hits15; + return hits15; } static int selectbuffer_ret_hits_9(uint *buffer, const int hits15, const int hits9) { - const int offs = 4 * hits15; - memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(uint)); - return hits9; + const int offs = 4 * hits15; + memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(uint)); + return hits9; } -static int selectbuffer_ret_hits_5(uint *buffer, const int hits15, const int hits9, const int hits5) +static int selectbuffer_ret_hits_5(uint *buffer, + const int hits15, + const int hits9, + const int hits5) { - const int offs = 4 * hits15 + 4 * hits9; - memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(uint)); - return hits5; + const int offs = 4 * hits15 + 4 * hits9; + memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(uint)); + return hits5; } /** * Populate a select buffer with objects and bones, if there are any. * Checks three selection levels and compare. */ -static int mixed_bones_object_selectbuffer( - ViewContext *vc, uint *buffer, const int mval[2], eV3DSelectObjectFilter select_filter, - bool do_nearest) -{ - rcti rect; - int hits15, hits9 = 0, hits5 = 0; - bool has_bones15 = false, has_bones9 = false, has_bones5 = false; - - const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); - int hits = 0; - - /* we _must_ end cache before return, use 'goto finally' */ - view3d_opengl_select_cache_begin(); - - BLI_rcti_init_pt_radius(&rect, mval, 14); - hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); - if (hits15 == 1) { - hits = selectbuffer_ret_hits_15(buffer, hits15); - goto finally; - } - else if (hits15 > 0) { - int offs; - has_bones15 = selectbuffer_has_bones(buffer, hits15); - - offs = 4 * hits15; - BLI_rcti_init_pt_radius(&rect, mval, 9); - hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); - if (hits9 == 1) { - hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); - goto finally; - } - else if (hits9 > 0) { - has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); - - offs += 4 * hits9; - BLI_rcti_init_pt_radius(&rect, mval, 5); - hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); - if (hits5 == 1) { - hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); - goto finally; - } - else if (hits5 > 0) { - has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); - } - } - - if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } - else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } - else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } - - if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; } - else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; } - else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; } - } +static int mixed_bones_object_selectbuffer(ViewContext *vc, + uint *buffer, + const int mval[2], + eV3DSelectObjectFilter select_filter, + bool do_nearest) +{ + rcti rect; + int hits15, hits9 = 0, hits5 = 0; + bool has_bones15 = false, has_bones9 = false, has_bones5 = false; + + const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL); + int hits = 0; + + /* we _must_ end cache before return, use 'goto finally' */ + view3d_opengl_select_cache_begin(); + + BLI_rcti_init_pt_radius(&rect, mval, 14); + hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter); + if (hits15 == 1) { + hits = selectbuffer_ret_hits_15(buffer, hits15); + goto finally; + } + else if (hits15 > 0) { + int offs; + has_bones15 = selectbuffer_has_bones(buffer, hits15); + + offs = 4 * hits15; + BLI_rcti_init_pt_radius(&rect, mval, 9); + hits9 = view3d_opengl_select( + vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); + if (hits9 == 1) { + hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); + goto finally; + } + else if (hits9 > 0) { + has_bones9 = selectbuffer_has_bones(buffer + offs, hits9); + + offs += 4 * hits9; + BLI_rcti_init_pt_radius(&rect, mval, 5); + hits5 = view3d_opengl_select( + vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter); + if (hits5 == 1) { + hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + goto finally; + } + else if (hits5 > 0) { + has_bones5 = selectbuffer_has_bones(buffer + offs, hits5); + } + } + + if (has_bones5) { + hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + goto finally; + } + else if (has_bones9) { + hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); + goto finally; + } + else if (has_bones15) { + hits = selectbuffer_ret_hits_15(buffer, hits15); + goto finally; + } + + if (hits5 > 0) { + hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); + goto finally; + } + else if (hits9 > 0) { + hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); + goto finally; + } + else { + hits = selectbuffer_ret_hits_15(buffer, hits15); + goto finally; + } + } finally: - view3d_opengl_select_cache_end(); - return hits; -} - -static int mixed_bones_object_selectbuffer_extended( - ViewContext *vc, uint *buffer, const int mval[2], eV3DSelectObjectFilter select_filter, - bool use_cycle, bool enumerate, bool *r_do_nearest) -{ - static int last_mval[2] = {-100, -100}; - bool do_nearest = false; - View3D *v3d = vc->v3d; - - /* define if we use solid nearest select or not */ - if (use_cycle) { - if (!XRAY_ACTIVE(v3d)) { - do_nearest = true; - if (len_manhattan_v2v2_int(mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) { - do_nearest = false; - } - } - copy_v2_v2_int(last_mval, mval); - } - else { - if (!XRAY_ACTIVE(v3d)) { - do_nearest = true; - } - } - - if (r_do_nearest) { - *r_do_nearest = do_nearest; - } - - do_nearest = do_nearest && !enumerate; - - int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest); - - if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - const bool is_pose_mode = ( - (vc->obact && vc->obact->mode & OB_MODE_POSE) || - (select_filter == VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK)); - struct { - uint data[4]; - } *buffer4 = (void *)buffer; - uint j = 0; - for (uint i = 0; i < hits; i++) { - if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) { - if (i != j) { - buffer4[j] = buffer4[i]; - } - j++; - } - } - hits = j; - } - - return hits; + view3d_opengl_select_cache_end(); + return hits; +} + +static int mixed_bones_object_selectbuffer_extended(ViewContext *vc, + uint *buffer, + const int mval[2], + eV3DSelectObjectFilter select_filter, + bool use_cycle, + bool enumerate, + bool *r_do_nearest) +{ + static int last_mval[2] = {-100, -100}; + bool do_nearest = false; + View3D *v3d = vc->v3d; + + /* define if we use solid nearest select or not */ + if (use_cycle) { + if (!XRAY_ACTIVE(v3d)) { + do_nearest = true; + if (len_manhattan_v2v2_int(mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) { + do_nearest = false; + } + } + copy_v2_v2_int(last_mval, mval); + } + else { + if (!XRAY_ACTIVE(v3d)) { + do_nearest = true; + } + } + + if (r_do_nearest) { + *r_do_nearest = do_nearest; + } + + do_nearest = do_nearest && !enumerate; + + int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest); + + if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + const bool is_pose_mode = ((vc->obact && vc->obact->mode & OB_MODE_POSE) || + (select_filter == VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK)); + struct { + uint data[4]; + } *buffer4 = (void *)buffer; + uint j = 0; + for (uint i = 0; i < hits; i++) { + if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) { + if (i != j) { + buffer4[j] = buffer4[i]; + } + j++; + } + } + hits = j; + } + + return hits; } /* returns basact */ -static Base *mouse_select_eval_buffer( - ViewContext *vc, const uint *buffer, int hits, - Base *startbase, bool has_bones, bool do_nearest) -{ - ViewLayer *view_layer = vc->view_layer; - View3D *v3d = vc->v3d; - Base *base, *basact = NULL; - int a; - - if (do_nearest) { - uint min = 0xFFFFFFFF; - int selcol = 0, notcol = 0; - - - if (has_bones) { - /* we skip non-bone hits */ - for (a = 0; a < hits; a++) { - if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000) ) { - min = buffer[4 * a + 1]; - selcol = buffer[4 * a + 3] & 0xFFFF; - } - } - } - else { - /* only exclude active object when it is selected... */ - if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) { - notcol = BASACT(view_layer)->object->select_id; - } - - for (a = 0; a < hits; a++) { - if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { - min = buffer[4 * a + 1]; - selcol = buffer[4 * a + 3] & 0xFFFF; - } - } - } - - base = FIRSTBASE(view_layer); - while (base) { - if (BASE_SELECTABLE(v3d, base)) { - if (base->object->select_id == selcol) { - break; - } - } - base = base->next; - } - if (base) { - basact = base; - } - } - else { - - base = startbase; - while (base) { - /* skip objects with select restriction, to prevent prematurely ending this loop - * with an un-selectable choice */ - if ((base->flag & BASE_SELECTABLE) == 0) { - base = base->next; - if (base == NULL) { - base = FIRSTBASE(view_layer); - } - if (base == startbase) { - break; - } - } - - if (BASE_SELECTABLE(v3d, base)) { - for (a = 0; a < hits; a++) { - if (has_bones) { - /* skip non-bone objects */ - if ((buffer[4 * a + 3] & 0xFFFF0000)) { - if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { - basact = base; - } - } - } - else { - if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { - basact = base; - } - } - } - } - - if (basact) { - break; - } - - base = base->next; - if (base == NULL) { - base = FIRSTBASE(view_layer); - } - if (base == startbase) { - break; - } - } - } - - return basact; +static Base *mouse_select_eval_buffer(ViewContext *vc, + const uint *buffer, + int hits, + Base *startbase, + bool has_bones, + bool do_nearest) +{ + ViewLayer *view_layer = vc->view_layer; + View3D *v3d = vc->v3d; + Base *base, *basact = NULL; + int a; + + if (do_nearest) { + uint min = 0xFFFFFFFF; + int selcol = 0, notcol = 0; + + if (has_bones) { + /* we skip non-bone hits */ + for (a = 0; a < hits; a++) { + if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000)) { + min = buffer[4 * a + 1]; + selcol = buffer[4 * a + 3] & 0xFFFF; + } + } + } + else { + /* only exclude active object when it is selected... */ + if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) { + notcol = BASACT(view_layer)->object->select_id; + } + + for (a = 0; a < hits; a++) { + if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) { + min = buffer[4 * a + 1]; + selcol = buffer[4 * a + 3] & 0xFFFF; + } + } + } + + base = FIRSTBASE(view_layer); + while (base) { + if (BASE_SELECTABLE(v3d, base)) { + if (base->object->select_id == selcol) { + break; + } + } + base = base->next; + } + if (base) { + basact = base; + } + } + else { + + base = startbase; + while (base) { + /* skip objects with select restriction, to prevent prematurely ending this loop + * with an un-selectable choice */ + if ((base->flag & BASE_SELECTABLE) == 0) { + base = base->next; + if (base == NULL) { + base = FIRSTBASE(view_layer); + } + if (base == startbase) { + break; + } + } + + if (BASE_SELECTABLE(v3d, base)) { + for (a = 0; a < hits; a++) { + if (has_bones) { + /* skip non-bone objects */ + if ((buffer[4 * a + 3] & 0xFFFF0000)) { + if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { + basact = base; + } + } + } + else { + if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { + basact = base; + } + } + } + } + + if (basact) { + break; + } + + base = base->next; + if (base == NULL) { + base = FIRSTBASE(view_layer); + } + if (base == startbase) { + break; + } + } + } + + return basact; } /* mval comes from event->mval, only use within region handlers */ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) { - ViewContext vc; - Base *basact = NULL; - uint buffer[MAXPICKBUF]; + ViewContext vc; + Base *basact = NULL; + uint buffer[MAXPICKBUF]; - /* setup view context for argument to callbacks */ - view3d_operator_needs_opengl(C); + /* setup view context for argument to callbacks */ + view3d_operator_needs_opengl(C); - ED_view3d_viewcontext_init(C, &vc); + ED_view3d_viewcontext_init(C, &vc); - const bool do_nearest = !XRAY_ACTIVE(vc.v3d); - const int hits = mixed_bones_object_selectbuffer( - &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest); + const bool do_nearest = !XRAY_ACTIVE(vc.v3d); + const int hits = mixed_bones_object_selectbuffer( + &vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest); - if (hits > 0) { - const bool has_bones = selectbuffer_has_bones(buffer, hits); - basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest); - } + if (hits > 0) { + const bool has_bones = selectbuffer_has_bones(buffer, hits); + basact = mouse_select_eval_buffer( + &vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest); + } - return basact; + return basact; } Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2]) { - Base *base = ED_view3d_give_base_under_cursor(C, mval); - if (base) { - return base->object; - } - return NULL; + Base *base = ED_view3d_give_base_under_cursor(C, mval); + if (base) { + return base->object; + } + return NULL; } bool ED_view3d_is_object_under_cursor(bContext *C, const int mval[2]) { - return ED_view3d_give_object_under_cursor(C, mval) != NULL; + return ED_view3d_give_object_under_cursor(C, mval) != NULL; } static void deselect_all_tracks(MovieTracking *tracking) { - MovieTrackingObject *object; + MovieTrackingObject *object; - object = tracking->objects.first; - while (object) { - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; + object = tracking->objects.first; + while (object) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; - while (track) { - BKE_tracking_track_deselect(track, TRACK_AREA_ALL); + while (track) { + BKE_tracking_track_deselect(track, TRACK_AREA_ALL); - track = track->next; - } + track = track->next; + } - object = object->next; - } + object = object->next; + } } /* mval is region coords */ -static bool ed_object_select_pick( - bContext *C, const int mval[2], - bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object) -{ - ViewContext vc; - /* setup view context for argument to callbacks */ - ED_view3d_viewcontext_init(C, &vc); - - ARegion *ar = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - /* Don't set when the context has no active object (hidden), see: T60807. */ - const Base *oldbasact = vc.obact ? BASACT(view_layer) : NULL; - Base *base, *startbase = NULL, *basact = NULL; - const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT; - bool is_obedit; - float dist = ED_view3d_select_dist_px() * 1.3333f; - bool retval = false; - int hits; - const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; - - - is_obedit = (vc.obedit != NULL); - if (object) { - /* signal for view3d_opengl_select to skip editmode objects */ - vc.obedit = NULL; - } - - /* In pose mode we don't want to mess with object selection. */ - const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE); - - /* always start list from basact in wire mode */ - startbase = FIRSTBASE(view_layer); - if (oldbasact && oldbasact->next) { - startbase = oldbasact->next; - } - - /* This block uses the control key to make the object selected - * by its center point rather than its contents */ - - /* in editmode do not activate */ - if (obcenter) { - - /* note; shift+alt goes to group-flush-selecting */ - if (enumerate) { - basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); - } - else { - base = startbase; - while (base) { - if (BASE_SELECTABLE(v3d, base)) { - float screen_co[2]; - if (ED_view3d_project_float_global( - ar, base->object->obmat[3], screen_co, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) - { - float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); - if (base == oldbasact) { - dist_temp += 10.0f; - } - if (dist_temp < dist) { - dist = dist_temp; - basact = base; - } - } - } - base = base->next; - - if (base == NULL) { - base = FIRSTBASE(view_layer); - } - if (base == startbase) { - break; - } - } - } - if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - if (is_obedit == false) { - if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { - if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = CTX_data_main(C); - ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); - } - if (!BKE_object_is_mode_compat(basact->object, object_mode)) { - basact = NULL; - } - } - } - } - } - else { - uint buffer[MAXPICKBUF]; - bool do_nearest; - - // TIMEIT_START(select_time); - - /* if objects have posemode set, the bones are in the same selection buffer */ - const eV3DSelectObjectFilter select_filter = ( - (object == false) ? ED_view3d_select_filter_from_mode(scene, vc.obact) : VIEW3D_SELECT_FILTER_NOP); - hits = mixed_bones_object_selectbuffer_extended( - &vc, buffer, mval, select_filter, - true, enumerate, - &do_nearest); - - // TIMEIT_END(select_time); - - if (hits > 0) { - /* note: bundles are handling in the same way as bones */ - const bool has_bones = selectbuffer_has_bones(buffer, hits); - - /* note; shift+alt goes to group-flush-selecting */ - if (enumerate) { - basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); - } - else { - basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest); - } - - if (has_bones && basact) { - if (basact->object->type == OB_CAMERA) { - if (oldbasact == basact) { - int i, hitresult; - bool changed = false; - - for (i = 0; i < hits; i++) { - hitresult = buffer[3 + (i * 4)]; - - /* if there's bundles in buffer select bundles first, - * so non-camera elements should be ignored in buffer */ - if (basact->object->select_id != (hitresult & 0xFFFF)) { - continue; - } - - /* index of bundle is 1<<16-based. if there's no "bone" index - * in height word, this buffer value belongs to camera. not to bundle - */ - if (buffer[4 * i + 3] & 0xFFFF0000) { - MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false); - MovieTracking *tracking = &clip->tracking; - ListBase *tracksbase; - MovieTrackingTrack *track; - - track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase); - - if (TRACK_SELECTED(track) && extend) { - changed = false; - BKE_tracking_track_deselect(track, TRACK_AREA_ALL); - } - else { - int oldsel = TRACK_SELECTED(track) ? 1 : 0; - if (!extend) { - deselect_all_tracks(tracking); - } - - BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend); - - if (oldsel != (TRACK_SELECTED(track) ? 1 : 0)) { - changed = true; - } - } - - basact->flag |= BASE_SELECTED; - BKE_scene_object_base_flag_sync_from_base(basact); - - retval = true; - - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - DEG_id_tag_update(&clip->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - - break; - } - } - - if (!changed) { - /* fallback to regular object selection if no new bundles were selected, - * allows to select object parented to reconstruction object */ - basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest); - } - } - } - else if (ED_armature_pose_select_pick_with_buffer( - view_layer, v3d, basact, buffer, hits, extend, deselect, toggle, do_nearest)) - { - /* then bone is found */ - - /* we make the armature selected: - * not-selected active object in posemode won't work well for tools */ - basact->flag |= BASE_SELECTED; - BKE_scene_object_base_flag_sync_from_base(basact); - - retval = true; - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object); - - /* in weightpaint, we use selected bone to select vertexgroup, - * so no switch to new active object */ - if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) { - /* prevent activating */ - basact = NULL; - } - - } - /* prevent bone selecting to pass on to object selecting */ - if (basact == oldbasact) { - basact = NULL; - } - } - - if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - if (is_obedit == false) { - if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { - if (object_mode == OB_MODE_OBJECT) { - struct Main *bmain = CTX_data_main(C); - ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); - } - if (!BKE_object_is_mode_compat(basact->object, object_mode)) { - basact = NULL; - } - } - } - } - } - } - - if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - /* Disallow switching modes, - * special exception for edit-mode - vertex-parent operator. */ - if (is_obedit == false) { - if (oldbasact && basact) { - if ((oldbasact->object->mode != basact->object->mode) && - (oldbasact->object->mode & basact->object->mode) == 0) - { - basact = NULL; - } - } - } - } - - /* Ensure code above doesn't change the active base. */ - BLI_assert(oldbasact == (vc.obact ? BASACT(view_layer) : NULL)); - - /* so, do we have something selected? */ - if (basact) { - retval = true; - - if (vc.obedit) { - /* only do select */ - object_deselect_all_except(view_layer, basact); - ED_object_base_select(basact, BA_SELECT); - } - /* also prevent making it active on mouse selection */ - else if (BASE_SELECTABLE(v3d, basact)) { - if (extend) { - ED_object_base_select(basact, BA_SELECT); - } - else if (deselect) { - ED_object_base_select(basact, BA_DESELECT); - } - else if (toggle) { - if (basact->flag & BASE_SELECTED) { - if (basact == oldbasact) { - ED_object_base_select(basact, BA_DESELECT); - } - } - else { - ED_object_base_select(basact, BA_SELECT); - } - } - else { - /* When enabled, this puts other objects out of multi pose-mode. */ - if (is_pose_mode == false) { - object_deselect_all_except(view_layer, basact); - ED_object_base_select(basact, BA_SELECT); - } - } - - if ((oldbasact != basact) && (is_obedit == false)) { - ED_object_base_activate(C, basact); /* adds notifier */ - } - - /* Set special modes for grease pencil - The grease pencil modes are not real modes, but a hack to make the interface - consistent, so need some tricks to keep UI synchronized */ - // XXX: This stuff needs reviewing (Aligorith) - if (false && - (((oldbasact) && oldbasact->object->type == OB_GPENCIL) || - (basact->object->type == OB_GPENCIL))) - { - /* set cursor */ - if (ELEM(basact->object->mode, - OB_MODE_PAINT_GPENCIL, - OB_MODE_SCULPT_GPENCIL, - OB_MODE_WEIGHT_GPENCIL)) - { - ED_gpencil_toggle_brush_cursor(C, true, NULL); - } - else { - /* TODO: maybe is better use restore */ - ED_gpencil_toggle_brush_cursor(C, false, NULL); - } - } - } - - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - - return retval; +static bool ed_object_select_pick(bContext *C, + const int mval[2], + bool extend, + bool deselect, + bool toggle, + bool obcenter, + bool enumerate, + bool object) +{ + ViewContext vc; + /* setup view context for argument to callbacks */ + ED_view3d_viewcontext_init(C, &vc); + + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + /* Don't set when the context has no active object (hidden), see: T60807. */ + const Base *oldbasact = vc.obact ? BASACT(view_layer) : NULL; + Base *base, *startbase = NULL, *basact = NULL; + const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT; + bool is_obedit; + float dist = ED_view3d_select_dist_px() * 1.3333f; + bool retval = false; + int hits; + const float mval_fl[2] = {(float)mval[0], (float)mval[1]}; + + is_obedit = (vc.obedit != NULL); + if (object) { + /* signal for view3d_opengl_select to skip editmode objects */ + vc.obedit = NULL; + } + + /* In pose mode we don't want to mess with object selection. */ + const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE); + + /* always start list from basact in wire mode */ + startbase = FIRSTBASE(view_layer); + if (oldbasact && oldbasact->next) { + startbase = oldbasact->next; + } + + /* This block uses the control key to make the object selected + * by its center point rather than its contents */ + + /* in editmode do not activate */ + if (obcenter) { + + /* note; shift+alt goes to group-flush-selecting */ + if (enumerate) { + basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); + } + else { + base = startbase; + while (base) { + if (BASE_SELECTABLE(v3d, base)) { + float screen_co[2]; + if (ED_view3d_project_float_global(ar, + base->object->obmat[3], + screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | + V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { + float dist_temp = len_manhattan_v2v2(mval_fl, screen_co); + if (base == oldbasact) { + dist_temp += 10.0f; + } + if (dist_temp < dist) { + dist = dist_temp; + basact = base; + } + } + } + base = base->next; + + if (base == NULL) { + base = FIRSTBASE(view_layer); + } + if (base == startbase) { + break; + } + } + } + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (is_obedit == false) { + if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { + if (object_mode == OB_MODE_OBJECT) { + struct Main *bmain = CTX_data_main(C); + ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); + } + if (!BKE_object_is_mode_compat(basact->object, object_mode)) { + basact = NULL; + } + } + } + } + } + else { + uint buffer[MAXPICKBUF]; + bool do_nearest; + + // TIMEIT_START(select_time); + + /* if objects have posemode set, the bones are in the same selection buffer */ + const eV3DSelectObjectFilter select_filter = ((object == false) ? + ED_view3d_select_filter_from_mode(scene, + vc.obact) : + VIEW3D_SELECT_FILTER_NOP); + hits = mixed_bones_object_selectbuffer_extended( + &vc, buffer, mval, select_filter, true, enumerate, &do_nearest); + + // TIMEIT_END(select_time); + + if (hits > 0) { + /* note: bundles are handling in the same way as bones */ + const bool has_bones = selectbuffer_has_bones(buffer, hits); + + /* note; shift+alt goes to group-flush-selecting */ + if (enumerate) { + basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); + } + else { + basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest); + } + + if (has_bones && basact) { + if (basact->object->type == OB_CAMERA) { + if (oldbasact == basact) { + int i, hitresult; + bool changed = false; + + for (i = 0; i < hits; i++) { + hitresult = buffer[3 + (i * 4)]; + + /* if there's bundles in buffer select bundles first, + * so non-camera elements should be ignored in buffer */ + if (basact->object->select_id != (hitresult & 0xFFFF)) { + continue; + } + + /* index of bundle is 1<<16-based. if there's no "bone" index + * in height word, this buffer value belongs to camera. not to bundle + */ + if (buffer[4 * i + 3] & 0xFFFF0000) { + MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false); + MovieTracking *tracking = &clip->tracking; + ListBase *tracksbase; + MovieTrackingTrack *track; + + track = BKE_tracking_track_get_indexed( + &clip->tracking, hitresult >> 16, &tracksbase); + + if (TRACK_SELECTED(track) && extend) { + changed = false; + BKE_tracking_track_deselect(track, TRACK_AREA_ALL); + } + else { + int oldsel = TRACK_SELECTED(track) ? 1 : 0; + if (!extend) { + deselect_all_tracks(tracking); + } + + BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend); + + if (oldsel != (TRACK_SELECTED(track) ? 1 : 0)) { + changed = true; + } + } + + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); + + retval = true; + + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + DEG_id_tag_update(&clip->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + + break; + } + } + + if (!changed) { + /* fallback to regular object selection if no new bundles were selected, + * allows to select object parented to reconstruction object */ + basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest); + } + } + } + else if (ED_armature_pose_select_pick_with_buffer(view_layer, + v3d, + basact, + buffer, + hits, + extend, + deselect, + toggle, + do_nearest)) { + /* then bone is found */ + + /* we make the armature selected: + * not-selected active object in posemode won't work well for tools */ + basact->flag |= BASE_SELECTED; + BKE_scene_object_base_flag_sync_from_base(basact); + + retval = true; + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object); + + /* in weightpaint, we use selected bone to select vertexgroup, + * so no switch to new active object */ + if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) { + /* prevent activating */ + basact = NULL; + } + } + /* prevent bone selecting to pass on to object selecting */ + if (basact == oldbasact) { + basact = NULL; + } + } + + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (is_obedit == false) { + if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) { + if (object_mode == OB_MODE_OBJECT) { + struct Main *bmain = CTX_data_main(C); + ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object); + } + if (!BKE_object_is_mode_compat(basact->object, object_mode)) { + basact = NULL; + } + } + } + } + } + } + + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + /* Disallow switching modes, + * special exception for edit-mode - vertex-parent operator. */ + if (is_obedit == false) { + if (oldbasact && basact) { + if ((oldbasact->object->mode != basact->object->mode) && + (oldbasact->object->mode & basact->object->mode) == 0) { + basact = NULL; + } + } + } + } + + /* Ensure code above doesn't change the active base. */ + BLI_assert(oldbasact == (vc.obact ? BASACT(view_layer) : NULL)); + + /* so, do we have something selected? */ + if (basact) { + retval = true; + + if (vc.obedit) { + /* only do select */ + object_deselect_all_except(view_layer, basact); + ED_object_base_select(basact, BA_SELECT); + } + /* also prevent making it active on mouse selection */ + else if (BASE_SELECTABLE(v3d, basact)) { + if (extend) { + ED_object_base_select(basact, BA_SELECT); + } + else if (deselect) { + ED_object_base_select(basact, BA_DESELECT); + } + else if (toggle) { + if (basact->flag & BASE_SELECTED) { + if (basact == oldbasact) { + ED_object_base_select(basact, BA_DESELECT); + } + } + else { + ED_object_base_select(basact, BA_SELECT); + } + } + else { + /* When enabled, this puts other objects out of multi pose-mode. */ + if (is_pose_mode == false) { + object_deselect_all_except(view_layer, basact); + ED_object_base_select(basact, BA_SELECT); + } + } + + if ((oldbasact != basact) && (is_obedit == false)) { + ED_object_base_activate(C, basact); /* adds notifier */ + } + + /* Set special modes for grease pencil + The grease pencil modes are not real modes, but a hack to make the interface + consistent, so need some tricks to keep UI synchronized */ + // XXX: This stuff needs reviewing (Aligorith) + if (false && (((oldbasact) && oldbasact->object->type == OB_GPENCIL) || + (basact->object->type == OB_GPENCIL))) { + /* set cursor */ + if (ELEM(basact->object->mode, + OB_MODE_PAINT_GPENCIL, + OB_MODE_SCULPT_GPENCIL, + OB_MODE_WEIGHT_GPENCIL)) { + ED_gpencil_toggle_brush_cursor(C, true, NULL); + } + else { + /* TODO: maybe is better use restore */ + ED_gpencil_toggle_brush_cursor(C, false, NULL); + } + } + } + + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + } + + return retval; } /* mouse selection in weight paint */ /* gets called via generic mouse select operator */ static bool ed_wpaint_vertex_select_pick( - bContext *C, const int mval[2], - bool extend, bool deselect, bool toggle, Object *obact) -{ - View3D *v3d = CTX_wm_view3d(C); - const bool use_zbuf = !XRAY_ENABLED(v3d); - - Mesh *me = obact->data; /* already checked for NULL */ - uint index = 0; - MVert *mv; - - if (ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index)) { - mv = &me->mvert[index]; - if (extend) { - mv->flag |= SELECT; - } - else if (deselect) { - mv->flag &= ~SELECT; - } - else if (toggle) { - mv->flag ^= SELECT; - } - else { - paintvert_deselect_all_visible(obact, SEL_DESELECT, false); - mv->flag |= SELECT; - } - - /* update mselect */ - if (mv->flag & SELECT) { - BKE_mesh_mselect_active_set(me, index, ME_VSEL); - } - else { - BKE_mesh_mselect_validate(me); - } - - paintvert_flush_flags(obact); - paintvert_tag_select_update(C, obact); - return true; - } - return false; + bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact) +{ + View3D *v3d = CTX_wm_view3d(C); + const bool use_zbuf = !XRAY_ENABLED(v3d); + + Mesh *me = obact->data; /* already checked for NULL */ + uint index = 0; + MVert *mv; + + if (ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index)) { + mv = &me->mvert[index]; + if (extend) { + mv->flag |= SELECT; + } + else if (deselect) { + mv->flag &= ~SELECT; + } + else if (toggle) { + mv->flag ^= SELECT; + } + else { + paintvert_deselect_all_visible(obact, SEL_DESELECT, false); + mv->flag |= SELECT; + } + + /* update mselect */ + if (mv->flag & SELECT) { + BKE_mesh_mselect_active_set(me, index, ME_VSEL); + } + else { + BKE_mesh_mselect_validate(me); + } + + paintvert_flush_flags(obact); + paintvert_tag_select_update(C, obact); + return true; + } + return false; } static int view3d_select_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - Object *obact = CTX_data_active_object(C); - bool extend = RNA_boolean_get(op->ptr, "extend"); - bool deselect = RNA_boolean_get(op->ptr, "deselect"); - bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - bool toggle = RNA_boolean_get(op->ptr, "toggle"); - bool center = RNA_boolean_get(op->ptr, "center"); - bool enumerate = RNA_boolean_get(op->ptr, "enumerate"); - /* only force object select for editmode to support vertex parenting, - * or paint-select to allow pose bone select with vert/face select */ - bool object = (RNA_boolean_get(op->ptr, "object") && - (obedit || - BKE_paint_select_elem_test(obact) || - /* so its possible to select bones in weightpaint mode (LMB select) */ - (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact)))); - - bool retval = false; - int location[2]; - - RNA_int_get_array(op->ptr, "location", location); - - view3d_operator_needs_opengl(C); - - if (object) { - obedit = NULL; - obact = NULL; - - /* ack, this is incorrect but to do this correctly we would need an - * alternative editmode/objectmode keymap, this copies the functionality - * from 2.4x where Ctrl+Select in editmode does object select only */ - center = false; - } - - if (obedit && object == false) { - if (obedit->type == OB_MESH) { - retval = EDBM_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = EDBM_mesh_deselect_all_multi(C); - } - } - else if (obedit->type == OB_ARMATURE) { - retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = ED_armature_edit_deselect_all_visible_multi(C); - } - } - else if (obedit->type == OB_LATTICE) { - retval = ED_lattice_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = ED_lattice_deselect_all_multi(C); - } - } - else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { - retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = ED_curve_deselect_all_multi(C); - } - } - else if (obedit->type == OB_MBALL) { - retval = ED_mball_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = ED_mball_deselect_all_multi(C); - } - } - else if (obedit->type == OB_FONT) { - retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - /* pass */ - } - } - - } - else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { - retval = PE_mouse_particles(C, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = PE_deselect_all_visible(C); - } - } - else if (obact && BKE_paint_select_face_test(obact)) { - retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle); - if (!retval && deselect_all) { - retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false); - } - } - else if (BKE_paint_select_vert_test(obact)) { - retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact); - if (!retval && deselect_all) { - retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false); - } - } - else { - retval = ed_object_select_pick(C, location, extend, deselect, toggle, center, enumerate, object); - if (!retval && deselect_all) { - if (ED_pose_object_from_context(C)) { - retval = ED_pose_deselect_all_multi(C, SEL_DESELECT, false); - } - else { - retval = ED_object_base_deselect_all(CTX_data_view_layer(C), CTX_wm_view3d(C), SEL_DESELECT); - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - } - } - } - - /* passthrough allows tweaks - * FINISHED to signal one operator worked - * */ - if (retval) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; - } - else { - return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */ - } + Scene *scene = CTX_data_scene(C); + Object *obedit = CTX_data_edit_object(C); + Object *obact = CTX_data_active_object(C); + bool extend = RNA_boolean_get(op->ptr, "extend"); + bool deselect = RNA_boolean_get(op->ptr, "deselect"); + bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + bool toggle = RNA_boolean_get(op->ptr, "toggle"); + bool center = RNA_boolean_get(op->ptr, "center"); + bool enumerate = RNA_boolean_get(op->ptr, "enumerate"); + /* only force object select for editmode to support vertex parenting, + * or paint-select to allow pose bone select with vert/face select */ + bool object = (RNA_boolean_get(op->ptr, "object") && + (obedit || BKE_paint_select_elem_test(obact) || + /* so its possible to select bones in weightpaint mode (LMB select) */ + (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && + BKE_object_pose_armature_get(obact)))); + + bool retval = false; + int location[2]; + + RNA_int_get_array(op->ptr, "location", location); + + view3d_operator_needs_opengl(C); + + if (object) { + obedit = NULL; + obact = NULL; + + /* ack, this is incorrect but to do this correctly we would need an + * alternative editmode/objectmode keymap, this copies the functionality + * from 2.4x where Ctrl+Select in editmode does object select only */ + center = false; + } + + if (obedit && object == false) { + if (obedit->type == OB_MESH) { + retval = EDBM_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = EDBM_mesh_deselect_all_multi(C); + } + } + else if (obedit->type == OB_ARMATURE) { + retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = ED_armature_edit_deselect_all_visible_multi(C); + } + } + else if (obedit->type == OB_LATTICE) { + retval = ED_lattice_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = ED_lattice_deselect_all_multi(C); + } + } + else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = ED_curve_deselect_all_multi(C); + } + } + else if (obedit->type == OB_MBALL) { + retval = ED_mball_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = ED_mball_deselect_all_multi(C); + } + } + else if (obedit->type == OB_FONT) { + retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + /* pass */ + } + } + } + else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { + retval = PE_mouse_particles(C, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = PE_deselect_all_visible(C); + } + } + else if (obact && BKE_paint_select_face_test(obact)) { + retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle); + if (!retval && deselect_all) { + retval = paintface_deselect_all_visible(C, CTX_data_active_object(C), SEL_DESELECT, false); + } + } + else if (BKE_paint_select_vert_test(obact)) { + retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact); + if (!retval && deselect_all) { + retval = paintvert_deselect_all_visible(obact, SEL_DESELECT, false); + } + } + else { + retval = ed_object_select_pick( + C, location, extend, deselect, toggle, center, enumerate, object); + if (!retval && deselect_all) { + if (ED_pose_object_from_context(C)) { + retval = ED_pose_deselect_all_multi(C, SEL_DESELECT, false); + } + else { + retval = ED_object_base_deselect_all( + CTX_data_view_layer(C), CTX_wm_view3d(C), SEL_DESELECT); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + } + } + } + + /* passthrough allows tweaks + * FINISHED to signal one operator worked + * */ + if (retval) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */ + } } static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RNA_int_set_array(op->ptr, "location", event->mval); + RNA_int_set_array(op->ptr, "location", event->mval); - return view3d_select_exec(C, op); + return view3d_select_exec(C, op); } void VIEW3D_OT_select(wmOperatorType *ot) { - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Select"; - ot->description = "Select and activate item(s)"; - ot->idname = "VIEW3D_OT_select"; - - /* api callbacks */ - ot->invoke = view3d_select_invoke; - ot->exec = view3d_select_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_mouse_select(ot); - prop = RNA_def_boolean(ot->srna, "deselect_all", 0, "Deselect", "Deselect all when nothing under the cursor"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Select"; + ot->description = "Select and activate item(s)"; + ot->idname = "VIEW3D_OT_select"; + + /* api callbacks */ + ot->invoke = view3d_select_invoke; + ot->exec = view3d_select_exec; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_mouse_select(ot); + prop = RNA_def_boolean( + ot->srna, "deselect_all", 0, "Deselect", "Deselect all when nothing under the cursor"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_boolean( + ot->srna, + "center", + 0, + "Center", + "Use the object center when selecting, in editmode used to extend object selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_int_vector(ot->srna, + "location", + 2, + NULL, + INT_MIN, + INT_MAX, + "Location", + "Mouse location", + INT_MIN, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); } /** \} */ @@ -2198,453 +2289,468 @@ void VIEW3D_OT_select(wmOperatorType *ot) * \{ */ typedef struct BoxSelectUserData { - ViewContext *vc; - const rcti *rect; - const rctf *rect_fl; - rctf _rect_fl; - eSelectOp sel_op; - - /* runtime */ - bool is_done; - bool is_changed; + ViewContext *vc; + const rcti *rect; + const rctf *rect_fl; + rctf _rect_fl; + eSelectOp sel_op; + + /* runtime */ + bool is_done; + bool is_changed; } BoxSelectUserData; -static void view3d_userdata_boxselect_init( - BoxSelectUserData *r_data, - ViewContext *vc, const rcti *rect, const eSelectOp sel_op) -{ - r_data->vc = vc; - - r_data->rect = rect; - r_data->rect_fl = &r_data->_rect_fl; - BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); - - r_data->sel_op = sel_op; - - /* runtime */ - r_data->is_done = false; - r_data->is_changed = false; -} - -bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]) -{ - const float radius_squared = radius * radius; - return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared); -} - -static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) -{ - BoxSelectUserData *data = userData; - const bool is_select = mv->flag & 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); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); - data->is_changed = true; - } -} -static bool do_paintvert_box_select( - ViewContext *vc, const rcti *rect, const eSelectOp sel_op) -{ - const bool use_zbuf = !XRAY_ENABLED(vc->v3d); - Mesh *me; - - me = vc->obact->data; - if ((me == NULL) || (me->totvert == 0)) { - return OPERATOR_CANCELLED; - } - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false); - } - - if (BLI_rcti_is_empty(rect)) { - /* pass */ - } - else if (use_zbuf) { - MVert *mvert; - unsigned int *rt; - int a, index; - char *selar; - - selar = MEM_callocN(me->totvert + 1, "selar"); - - uint buf_len; - uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); - - rt = buf; - - a = buf_len; - while (a--) { - if (*rt) { - index = *rt; - if (index <= me->totvert) { - selar[index] = 1; - } - } - rt++; - } - - mvert = me->mvert; - for (a = 1; a <= me->totvert; a++, mvert++) { - if ((mvert->flag & ME_HIDE) == 0) { - const bool is_select = mvert->flag & SELECT; - const bool is_inside = (selar[a] != 0); - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT); - changed = true; - } - } - } - - MEM_freeN(buf); - MEM_freeN(selar); +static void view3d_userdata_boxselect_init(BoxSelectUserData *r_data, + ViewContext *vc, + const rcti *rect, + const eSelectOp sel_op) +{ + r_data->vc = vc; + + r_data->rect = rect; + r_data->rect_fl = &r_data->_rect_fl; + BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); + + r_data->sel_op = sel_op; + + /* runtime */ + r_data->is_done = false; + r_data->is_changed = false; +} + +bool edge_inside_circle(const float cent[2], + float radius, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + const float radius_squared = radius * radius; + return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared); +} + +static void do_paintvert_box_select__doSelectVert(void *userData, + MVert *mv, + const float screen_co[2], + int UNUSED(index)) +{ + BoxSelectUserData *data = userData; + const bool is_select = mv->flag & 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); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); + data->is_changed = true; + } +} +static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) +{ + const bool use_zbuf = !XRAY_ENABLED(vc->v3d); + Mesh *me; + + me = vc->obact->data; + if ((me == NULL) || (me->totvert == 0)) { + return OPERATOR_CANCELLED; + } + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false); + } + + if (BLI_rcti_is_empty(rect)) { + /* pass */ + } + else if (use_zbuf) { + MVert *mvert; + unsigned int *rt; + int a, index; + char *selar; + + selar = MEM_callocN(me->totvert + 1, "selar"); + + uint buf_len; + uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len); + + rt = buf; + + a = buf_len; + while (a--) { + if (*rt) { + index = *rt; + if (index <= me->totvert) { + selar[index] = 1; + } + } + rt++; + } + + mvert = me->mvert; + for (a = 1; a <= me->totvert; a++, mvert++) { + if ((mvert->flag & ME_HIDE) == 0) { + const bool is_select = mvert->flag & SELECT; + const bool is_inside = (selar[a] != 0); + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT); + changed = true; + } + } + } + + MEM_freeN(buf); + MEM_freeN(selar); #ifdef __APPLE__ - glReadBuffer(GL_BACK); + glReadBuffer(GL_BACK); #endif - } - else { - BoxSelectUserData data; - - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); - - ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); - - meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; - } - - if (changed) { - if (SEL_OP_CAN_DESELECT(sel_op)) { - BKE_mesh_mselect_validate(me); - } - paintvert_flush_flags(vc->obact); - paintvert_tag_select_update(vc->C, vc->obact); - } - return changed; -} - -static void do_nurbs_box_select__doSelect( - void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) -{ - BoxSelectUserData *data = userData; - - const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); - if (bp) { - const bool is_select = bp->f1 & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); - data->is_changed = true; - } - } - else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ - const bool is_select = bezt->f2 & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); - data->is_changed = true; - } - bezt->f1 = bezt->f3 = bezt->f2; - } - else { - char *flag_p = (&bezt->f1) + beztindex; - const bool is_select = *flag_p & SELECT; - const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); - data->is_changed = true; - } - } - } + } + else { + BoxSelectUserData data; + + view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); + + meshobject_foreachScreenVert( + vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + changed |= data.is_changed; + } + + if (changed) { + if (SEL_OP_CAN_DESELECT(sel_op)) { + BKE_mesh_mselect_validate(me); + } + paintvert_flush_flags(vc->obact); + paintvert_tag_select_update(vc->C, vc->obact); + } + return changed; +} + +static void do_nurbs_box_select__doSelect(void *userData, + Nurb *UNUSED(nu), + BPoint *bp, + BezTriple *bezt, + int beztindex, + const float screen_co[2]) +{ + BoxSelectUserData *data = userData; + + const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); + if (bp) { + const bool is_select = bp->f1 & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; + } + } + else { + if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { + /* can only be (beztindex == 0) here since handles are hidden */ + const bool is_select = bezt->f2 & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT); + data->is_changed = true; + } + bezt->f1 = bezt->f3 = bezt->f2; + } + else { + char *flag_p = (&bezt->f1) + beztindex; + const bool is_select = *flag_p & SELECT; + const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT); + data->is_changed = true; + } + } + } } static bool do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) { - BoxSelectUserData data; + BoxSelectUserData data; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data, vc, rect, sel_op); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - Curve *curve = (Curve *) vc->obedit->data; - data.is_changed |= ED_curve_deselect_all(curve->editnurb); - } + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + Curve *curve = (Curve *)vc->obedit->data; + data.is_changed |= ED_curve_deselect_all(curve->editnurb); + } - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - BKE_curve_nurb_vert_active_validate(vc->obedit->data); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + BKE_curve_nurb_vert_active_validate(vc->obedit->data); - return data.is_changed; + return data.is_changed; } static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - BoxSelectUserData *data = userData; - const bool is_select = bp->f1 & 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); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); - data->is_changed = true; - } + BoxSelectUserData *data = userData; + const bool is_select = bp->f1 & 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); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); + data->is_changed = true; + } } static bool do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) { - BoxSelectUserData data; + BoxSelectUserData data; - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + view3d_userdata_boxselect_init(&data, vc, rect, sel_op); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); - } + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); + } - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + lattice_foreachScreenVert( + vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return data.is_changed; + return data.is_changed; } -static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) +static void do_mesh_box_select__doSelectVert(void *userData, + BMVert *eve, + const float screen_co[2], + int UNUSED(index)) { - BoxSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); - 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; - } + BoxSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); + const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); + 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; + } } static void do_mesh_box_select__doSelectEdge_pass0( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - BoxSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = ( - EDBM_backbuf_check(bm_solidoffs + index) && - 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 (sel_op_result != -1) { - BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); - data->is_done = true; - data->is_changed = true; - } + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +{ + BoxSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); + const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && + 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 (sel_op_result != -1) { + BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); + data->is_done = true; + data->is_changed = true; + } } static void do_mesh_box_select__doSelectEdge_pass1( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) -{ - BoxSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = ( - EDBM_backbuf_check(bm_solidoffs + index) && - 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 (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 *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) -{ - BoxSelectUserData *data = userData; - const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); - 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; - } -} -static bool do_mesh_box_select( - ViewContext *vc, rcti *rect, const eSelectOp sel_op) -{ - BoxSelectUserData data; - ToolSettings *ts = vc->scene->toolsettings; - int bbsel; - - view3d_userdata_boxselect_init(&data, vc, rect, sel_op); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - if (vc->em->bm->totvertsel) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); - data.is_changed = true; - } - } - - /* for non zbuf projections, don't change the GL state */ - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - - GPU_matrix_set(vc->rv3d->viewmat); - bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); - - if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); - } - else { - mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - if (ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); - if (data.is_done == false) { - mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); - } - } - - if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); - } - else { - mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - - EDBM_backbuf_free(); - - if (data.is_changed) { - EDBM_selectmode_flush(vc->em); - } - return data.is_changed; -} - -static bool do_meta_box_select( - ViewContext *vc, - const rcti *rect, const eSelectOp sel_op) -{ - Object *ob = vc->obedit; - MetaBall *mb = (MetaBall *)ob->data; - MetaElem *ml; - int a; - bool changed = false; - - uint buffer[MAXPICKBUF]; - int hits; - - hits = view3d_opengl_select( - vc, buffer, MAXPICKBUF, rect, - VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= BKE_mball_deselect_all(mb); - } - - int metaelem_id = 0; - for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) { - bool is_inside_radius = false; - bool is_inside_stiff = false; - - for (a = 0; a < hits; a++) { - int hitresult = buffer[(4 * a) + 3]; - - if (hitresult == -1) { - continue; - } - else if (hitresult & MBALL_NOSEL) { - continue; - } - - const uint hit_object = hitresult & 0xFFFF; - if (vc->obedit->select_id != hit_object) { - continue; - } - - if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) { - continue; - } - - if (hitresult & MBALLSEL_RADIUS) { - is_inside_radius = true; - break; - } - - if (hitresult & MBALLSEL_STIFF) { - is_inside_stiff = true; - break; - } - } - const int flag_prev = ml->flag; - if (is_inside_radius) { - ml->flag |= MB_SCALE_RAD; - } - if (is_inside_stiff) { - ml->flag &= ~MB_SCALE_RAD; - } - - const bool is_select = (ml->flag & SELECT); - const bool is_inside = is_inside_radius || is_inside_stiff; - - const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); - if (sel_op_result != -1) { - SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); - } - changed |= (flag_prev != ml->flag); - } - - return changed; -} - -static bool do_armature_box_select( - ViewContext *vc, - const rcti *rect, const eSelectOp sel_op) -{ - bool changed = false; - int a; - - uint buffer[MAXPICKBUF]; - int hits; - - hits = view3d_opengl_select( - vc, buffer, MAXPICKBUF, rect, - VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); - - uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len); - } - - for (uint base_index = 0; base_index < bases_len; base_index++) { - Object *obedit = bases[base_index]->object; - obedit->id.tag &= ~LIB_TAG_DOIT; - - bArmature *arm = obedit->data; - ED_armature_ebone_listbase_temp_clear(arm->edbo); - } - - /* first we only check points inside the border */ - for (a = 0; a < hits; a++) { - int select_id = buffer[(4 * a) + 3]; - if (select_id != -1) { - if ((select_id & 0xFFFF0000) == 0) { - continue; - } - - EditBone *ebone; - Base *base_edit = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, select_id, &ebone); - ebone->temp.i |= select_id & BONESEL_ANY; - base_edit->object->id.tag |= LIB_TAG_DOIT; - } - } - - for (uint base_index = 0; base_index < bases_len; base_index++) { - Object *obedit = bases[base_index]->object; - if (obedit->id.tag & LIB_TAG_DOIT) { - obedit->id.tag &= ~LIB_TAG_DOIT; - changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op); - } - } - - MEM_freeN(bases); - - return changed; + void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index) +{ + BoxSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); + const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) && + 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 (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 *userData, + BMFace *efa, + const float screen_co[2], + int UNUSED(index)) +{ + BoxSelectUserData *data = userData; + const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); + const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co); + 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; + } +} +static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op) +{ + BoxSelectUserData data; + ToolSettings *ts = vc->scene->toolsettings; + int bbsel; + + view3d_userdata_boxselect_init(&data, vc, rect, sel_op); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + data.is_changed = true; + } + } + + /* for non zbuf projections, don't change the GL state */ + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + GPU_matrix_set(vc->rv3d->viewmat); + bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); + + if (ts->selectmode & SCE_SELECT_VERTEX) { + if (bbsel) { + data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op); + } + else { + mesh_foreachScreenVert( + vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + if (ts->selectmode & SCE_SELECT_EDGE) { + /* Does both bbsel and non-bbsel versions (need screen cos for both) */ + mesh_foreachScreenEdge( + vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR); + if (data.is_done == false) { + mesh_foreachScreenEdge( + vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR); + } + } + + if (ts->selectmode & SCE_SELECT_FACE) { + if (bbsel) { + data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op); + } + else { + mesh_foreachScreenFace( + vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + + EDBM_backbuf_free(); + + if (data.is_changed) { + EDBM_selectmode_flush(vc->em); + } + return data.is_changed; +} + +static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) +{ + Object *ob = vc->obedit; + MetaBall *mb = (MetaBall *)ob->data; + MetaElem *ml; + int a; + bool changed = false; + + uint buffer[MAXPICKBUF]; + int hits; + + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= BKE_mball_deselect_all(mb); + } + + int metaelem_id = 0; + for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) { + bool is_inside_radius = false; + bool is_inside_stiff = false; + + for (a = 0; a < hits; a++) { + int hitresult = buffer[(4 * a) + 3]; + + if (hitresult == -1) { + continue; + } + else if (hitresult & MBALL_NOSEL) { + continue; + } + + const uint hit_object = hitresult & 0xFFFF; + if (vc->obedit->select_id != hit_object) { + continue; + } + + if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) { + continue; + } + + if (hitresult & MBALLSEL_RADIUS) { + is_inside_radius = true; + break; + } + + if (hitresult & MBALLSEL_STIFF) { + is_inside_stiff = true; + break; + } + } + const int flag_prev = ml->flag; + if (is_inside_radius) { + ml->flag |= MB_SCALE_RAD; + } + if (is_inside_stiff) { + ml->flag &= ~MB_SCALE_RAD; + } + + const bool is_select = (ml->flag & SELECT); + const bool is_inside = is_inside_radius || is_inside_stiff; + + const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); + if (sel_op_result != -1) { + SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); + } + changed |= (flag_prev != ml->flag); + } + + return changed; +} + +static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op) +{ + bool changed = false; + int a; + + uint buffer[MAXPICKBUF]; + int hits; + + hits = view3d_opengl_select( + vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP); + + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc->view_layer, vc->v3d, &bases_len); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= ED_armature_edit_deselect_all_visible_multi_ex(bases, bases_len); + } + + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; + obedit->id.tag &= ~LIB_TAG_DOIT; + + bArmature *arm = obedit->data; + ED_armature_ebone_listbase_temp_clear(arm->edbo); + } + + /* first we only check points inside the border */ + for (a = 0; a < hits; a++) { + int select_id = buffer[(4 * a) + 3]; + if (select_id != -1) { + if ((select_id & 0xFFFF0000) == 0) { + continue; + } + + EditBone *ebone; + Base *base_edit = ED_armature_base_and_ebone_from_select_buffer( + bases, bases_len, select_id, &ebone); + ebone->temp.i |= select_id & BONESEL_ANY; + base_edit->object->id.tag |= LIB_TAG_DOIT; + } + } + + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; + if (obedit->id.tag & LIB_TAG_DOIT) { + obedit->id.tag &= ~LIB_TAG_DOIT; + changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op); + } + } + + MEM_freeN(bases); + + return changed; } /** @@ -2653,291 +2759,294 @@ static bool do_armature_box_select( */ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p) { - /* 4th element is select id */ - uint sel_a = ((uint *)sel_a_p)[3]; - uint sel_b = ((uint *)sel_b_p)[3]; + /* 4th element is select id */ + uint sel_a = ((uint *)sel_a_p)[3]; + uint sel_b = ((uint *)sel_b_p)[3]; #ifdef __BIG_ENDIAN__ - BLI_endian_switch_uint32(&sel_a); - BLI_endian_switch_uint32(&sel_b); + BLI_endian_switch_uint32(&sel_a); + BLI_endian_switch_uint32(&sel_b); #endif - if (sel_a < sel_b) { - return -1; - } - else if (sel_a > sel_b) { - return 1; - } - else { - return 0; - } + if (sel_a < sel_b) { + return -1; + } + else if (sel_a > sel_b) { + return 1; + } + else { + return 0; + } } static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) { - View3D *v3d = vc->v3d; - int totobj = MAXPICKBUF; /* XXX solve later */ - - /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ - uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer"); - const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); - const int hits = view3d_opengl_select( - vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, - VIEW3D_SELECT_ALL, select_filter); - - for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) { - base->object->id.tag &= ~LIB_TAG_DOIT; - } - - Base **bases = NULL; - BLI_array_declare(bases); - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); - } - - if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { - goto finally; - } - - for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { - if ((base->object->select_id & 0x0000FFFF) != 0) { - BLI_array_append(bases, base); - } - } - } - - /* The draw order doesn't always match the order we populate the engine, see: T51695. */ - qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp); - - for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) { - Bone *bone; - Base *base = ED_armature_base_and_bone_from_select_buffer(bases, BLI_array_len(bases), *col, &bone); - if (base != NULL) { - base->object->id.tag |= LIB_TAG_DOIT; - } - } - - for (Base *base = vc->view_layer->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; - } - } - } + View3D *v3d = vc->v3d; + int totobj = MAXPICKBUF; /* XXX solve later */ + + /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ + uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer"); + const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, + vc->obact); + const int hits = view3d_opengl_select( + vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter); + + for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) { + base->object->id.tag &= ~LIB_TAG_DOIT; + } + + Base **bases = NULL; + BLI_array_declare(bases); + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + } + + if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) { + goto finally; + } + + for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) { + if (BASE_SELECTABLE(v3d, base)) { + if ((base->object->select_id & 0x0000FFFF) != 0) { + BLI_array_append(bases, base); + } + } + } + + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp); + + for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) { + Bone *bone; + Base *base = ED_armature_base_and_bone_from_select_buffer( + bases, BLI_array_len(bases), *col, &bone); + if (base != NULL) { + base->object->id.tag |= LIB_TAG_DOIT; + } + } + + for (Base *base = vc->view_layer->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; + } + } + } finally: - if (bases != NULL) { - MEM_freeN(bases); - } + if (bases != NULL) { + MEM_freeN(bases); + } - MEM_freeN(vbuffer); + MEM_freeN(vbuffer); - if (changed) { - DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); - } - return changed; + if (changed) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); + } + return changed; } static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op) { - uint bases_len; - Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); - - int totobj = MAXPICKBUF; /* XXX solve later */ - - /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ - uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer"); - const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact); - const int hits = view3d_opengl_select( - vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, - VIEW3D_SELECT_ALL, select_filter); - /* - * LOGIC NOTES (theeth): - * The buffer and ListBase have the same relative order, which makes the selection - * very simple. Loop through both data sets at the same time, if the color - * is the same as the object, we have a hit and can move to the next color - * and object pair, if not, just move to the next object, - * keeping the same color until we have a hit. - */ - - if (hits > 0) { - /* no need to loop if there's no hit */ - - /* The draw order doesn't always match the order we populate the engine, see: T51695. */ - qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp); - - for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) { - Bone *bone; - Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone); - - if (base == NULL) { - continue; - } - - /* Loop over contiguous bone hits for 'base'. */ - for (; col != col_end; col += 4) { - /* should never fail */ - if (bone != NULL) { - base->object->id.tag |= LIB_TAG_DOIT; - bone->flag |= BONE_DONE; - } - - /* Select the next bone if we're not switching bases. */ - if (col + 4 != col_end) { - if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) { - break; - } - if (base->object->pose != NULL) { - const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16; - bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone); - bone = pchan ? pchan->bone : NULL; - } - else { - bone = NULL; - } - } - } - } - } - - const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); - if (changed_multi) { - DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); - } - - if (bases != NULL) { - MEM_freeN(bases); - } - MEM_freeN(vbuffer); - - return changed_multi; + uint bases_len; + Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len); + + int totobj = MAXPICKBUF; /* XXX solve later */ + + /* selection buffer now has bones potentially too, so we add MAXPICKBUF */ + uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer"); + const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, + vc->obact); + const int hits = view3d_opengl_select( + vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter); + /* + * LOGIC NOTES (theeth): + * The buffer and ListBase have the same relative order, which makes the selection + * very simple. Loop through both data sets at the same time, if the color + * is the same as the object, we have a hit and can move to the next color + * and object pair, if not, just move to the next object, + * keeping the same color until we have a hit. + */ + + if (hits > 0) { + /* no need to loop if there's no hit */ + + /* The draw order doesn't always match the order we populate the engine, see: T51695. */ + qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp); + + for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) { + Bone *bone; + Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone); + + if (base == NULL) { + continue; + } + + /* Loop over contiguous bone hits for 'base'. */ + for (; col != col_end; col += 4) { + /* should never fail */ + if (bone != NULL) { + base->object->id.tag |= LIB_TAG_DOIT; + bone->flag |= BONE_DONE; + } + + /* Select the next bone if we're not switching bases. */ + if (col + 4 != col_end) { + if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) { + break; + } + if (base->object->pose != NULL) { + const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16; + bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone); + bone = pchan ? pchan->bone : NULL; + } + else { + bone = NULL; + } + } + } + } + } + + const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); + if (changed_multi) { + DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene); + } + + if (bases != NULL) { + MEM_freeN(bases); + } + MEM_freeN(vbuffer); + + return changed_multi; } static int view3d_box_select_exec(bContext *C, wmOperator *op) { - ViewContext vc; - rcti rect; - bool changed_multi = false; - - view3d_operator_needs_opengl(C); - - /* setup view context for argument to callbacks */ - ED_view3d_viewcontext_init(C, &vc); - - eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - WM_operator_properties_border_to_rcti(op, &rect); - - if (vc.obedit) { - - FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { - ED_view3d_viewcontext_init_object(&vc, ob_iter); - bool changed = false; - - switch (vc.obedit->type) { - case OB_MESH: - vc.em = BKE_editmesh_from_object(vc.obedit); - changed = do_mesh_box_select(&vc, &rect, sel_op); - if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); - } - break; - case OB_CURVE: - case OB_SURF: - changed = do_nurbs_box_select(&vc, &rect, sel_op); - if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); - } - break; - case OB_MBALL: - changed = do_meta_box_select(&vc, &rect, sel_op); - if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); - } - break; - case OB_ARMATURE: - changed = do_armature_box_select(&vc, &rect, sel_op); - if (changed) { - DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); - } - break; - case OB_LATTICE: - changed = do_lattice_box_select(&vc, &rect, sel_op); - if (changed) { - DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); - } - break; - default: - assert(!"box select on incorrect object type"); - break; - } - changed_multi |= changed; - } - FOREACH_OBJECT_IN_MODE_END; - } - else { /* no editmode, unified for bones and objects */ - if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) { - /* XXX, this is not selection, could be it's own operator. */ - changed_multi = ED_sculpt_mask_box_select(C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); - } - else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { - changed_multi = do_paintface_box_select(&vc, &rect, sel_op); - } - else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { - changed_multi = do_paintvert_box_select(&vc, &rect, sel_op); - } - else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { - changed_multi = PE_box_select(C, &rect, sel_op); - } - else if (vc.obact && vc.obact->mode & OB_MODE_POSE) { - changed_multi = do_pose_box_select(C, &vc, &rect, sel_op); - } - else { /* object mode with none active */ - changed_multi = do_object_box_select(C, &vc, &rect, sel_op); - } - } - - if (changed_multi) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + ViewContext vc; + rcti rect; + bool changed_multi = false; + + view3d_operator_needs_opengl(C); + + /* setup view context for argument to callbacks */ + ED_view3d_viewcontext_init(C, &vc); + + eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + WM_operator_properties_border_to_rcti(op, &rect); + + if (vc.obedit) { + + FOREACH_OBJECT_IN_MODE_BEGIN ( + vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) { + ED_view3d_viewcontext_init_object(&vc, ob_iter); + bool changed = false; + + switch (vc.obedit->type) { + case OB_MESH: + vc.em = BKE_editmesh_from_object(vc.obedit); + changed = do_mesh_box_select(&vc, &rect, sel_op); + if (changed) { + DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); + } + break; + case OB_CURVE: + case OB_SURF: + changed = do_nurbs_box_select(&vc, &rect, sel_op); + if (changed) { + DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); + } + break; + case OB_MBALL: + changed = do_meta_box_select(&vc, &rect, sel_op); + if (changed) { + DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); + } + break; + case OB_ARMATURE: + changed = do_armature_box_select(&vc, &rect, sel_op); + if (changed) { + DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit); + } + break; + case OB_LATTICE: + changed = do_lattice_box_select(&vc, &rect, sel_op); + if (changed) { + DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data); + } + break; + default: + assert(!"box select on incorrect object type"); + break; + } + changed_multi |= changed; + } + FOREACH_OBJECT_IN_MODE_END; + } + else { /* no editmode, unified for bones and objects */ + if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) { + /* XXX, this is not selection, could be it's own operator. */ + changed_multi = ED_sculpt_mask_box_select( + C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false); + } + else if (vc.obact && BKE_paint_select_face_test(vc.obact)) { + changed_multi = do_paintface_box_select(&vc, &rect, sel_op); + } + else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) { + changed_multi = do_paintvert_box_select(&vc, &rect, sel_op); + } + else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) { + changed_multi = PE_box_select(C, &rect, sel_op); + } + else if (vc.obact && vc.obact->mode & OB_MODE_POSE) { + changed_multi = do_pose_box_select(C, &vc, &rect, sel_op); + } + else { /* object mode with none active */ + changed_multi = do_object_box_select(C, &vc, &rect, sel_op); + } + } + + if (changed_multi) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_select_box(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Box Select"; - ot->description = "Select items using box selection"; - ot->idname = "VIEW3D_OT_select_box"; + /* identifiers */ + ot->name = "Box Select"; + ot->description = "Select items using box selection"; + ot->idname = "VIEW3D_OT_select_box"; - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = view3d_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->poll = view3d_selectable_data; - ot->cancel = WM_gesture_box_cancel; + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = view3d_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->poll = view3d_selectable_data; + ot->cancel = WM_gesture_box_cancel; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* rna */ - WM_operator_properties_gesture_box(ot); - WM_operator_properties_select_operation(ot); + /* rna */ + WM_operator_properties_gesture_box(ot); + WM_operator_properties_select_operation(ot); } /** \} */ @@ -2947,638 +3056,691 @@ void VIEW3D_OT_select_box(wmOperatorType *ot) * \{ */ typedef struct CircleSelectUserData { - ViewContext *vc; - bool select; - int mval[2]; - float mval_fl[2]; - float radius; - float radius_squared; - - /* runtime */ - bool is_changed; + ViewContext *vc; + bool select; + int mval[2]; + float mval_fl[2]; + float radius; + float radius_squared; + + /* runtime */ + bool is_changed; } CircleSelectUserData; -static void view3d_userdata_circleselect_init( - CircleSelectUserData *r_data, - ViewContext *vc, const bool select, const int mval[2], const float rad) +static void view3d_userdata_circleselect_init(CircleSelectUserData *r_data, + ViewContext *vc, + const bool select, + const int mval[2], + const float rad) { - r_data->vc = vc; - r_data->select = select; - copy_v2_v2_int(r_data->mval, mval); - r_data->mval_fl[0] = mval[0]; - r_data->mval_fl[1] = mval[1]; + r_data->vc = vc; + r_data->select = select; + copy_v2_v2_int(r_data->mval, mval); + r_data->mval_fl[0] = mval[0]; + r_data->mval_fl[1] = mval[1]; - r_data->radius = rad; - r_data->radius_squared = rad * rad; + r_data->radius = rad; + r_data->radius_squared = rad * rad; - /* runtime */ - r_data->is_changed = false; + /* runtime */ + r_data->is_changed = false; } -static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index)) +static void mesh_circle_doSelectVert(void *userData, + BMVert *eve, + const float screen_co[2], + int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = userData; - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - BM_vert_select_set(data->vc->em->bm, eve, data->select); - data->is_changed = true; - } + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + BM_vert_select_set(data->vc->em->bm, eve, data->select); + data->is_changed = true; + } } -static void mesh_circle_doSelectEdge( - void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) +static void mesh_circle_doSelectEdge(void *userData, + BMEdge *eed, + const float screen_co_a[2], + const float screen_co_b[2], + int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = userData; - 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 (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; + } } -static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) +static void mesh_circle_doSelectFace(void *userData, + BMFace *efa, + const float screen_co[2], + int UNUSED(index)) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = userData; - 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 (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; + } } static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad) { - ToolSettings *ts = vc->scene->toolsettings; - int bbsel; - CircleSelectUserData data; - vc->em = BKE_editmesh_from_object(vc->obedit); - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - if (vc->em->bm->totvertsel) { - EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); - changed = true; - } - } - const bool select = (sel_op != SEL_OP_SUB); - - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - - if (ts->selectmode & SCE_SELECT_VERTEX) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); - } - else { - mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - - if (ts->selectmode & SCE_SELECT_EDGE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); - } - else { - mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); - } - } - - if (ts->selectmode & SCE_SELECT_FACE) { - if (bbsel) { - changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); - } - else { - mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } - } - - changed |= data.is_changed; - - EDBM_backbuf_free(); - - if (changed) { - EDBM_selectmode_flush(vc->em); - } - return changed; -} - -static bool paint_facesel_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); - Object *ob = vc->obact; - Mesh *me = ob->data; - bool bbsel; - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - /* flush selection at the end */ - changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); - } - - bm_vertoffs = me->totpoly + 1; /* max index array */ - - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); - EDBM_backbuf_free(); - } - if (changed) { - paintface_flush_flags(vc->C, ob, SELECT); - } - return changed; -} - -static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index)) -{ - CircleSelectUserData *data = userData; - - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); - data->is_changed = true; - } -} -static bool paint_vertsel_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); - const bool use_zbuf = !XRAY_ENABLED(vc->v3d); - Object *ob = vc->obact; - Mesh *me = ob->data; - bool bbsel; - /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */ - } - - const bool select = (sel_op != SEL_OP_SUB); - - if (use_zbuf) { - bm_vertoffs = me->totvert + 1; /* max index array */ - - bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); - if (bbsel) { - changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); - EDBM_backbuf_free(); - } - } - else { - CircleSelectUserData data; - - ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - changed |= data.is_changed; - } - - if (changed) { - if (sel_op == SEL_OP_SUB) { - BKE_mesh_mselect_validate(me); - } - paintvert_flush_flags(ob); - paintvert_tag_select_update(vc->C, ob); - } - return changed; -} - - -static void nurbscurve_circle_doSelect( - void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) -{ - CircleSelectUserData *data = userData; - - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - if (bp) { - bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); - } - else { - if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { - /* can only be (beztindex == 0) here since handles are hidden */ - bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT); - } - else { - if (beztindex == 0) { - bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT); - } - else if (beztindex == 1) { - bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT); - } - else { - bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT); - } - } - } - data->is_changed = true; - } -} -static bool nurbscurve_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - CircleSelectUserData data; - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - Curve *curve = vc->obedit->data; - changed |= ED_curve_deselect_all(curve->editnurb); - } - const bool select = (sel_op != SEL_OP_SUB); - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - BKE_curve_nurb_vert_active_validate(vc->obedit->data); - - return changed || data.is_changed; + ToolSettings *ts = vc->scene->toolsettings; + int bbsel; + CircleSelectUserData data; + vc->em = BKE_editmesh_from_object(vc->obedit); + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + if (vc->em->bm->totvertsel) { + EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT); + changed = true; + } + } + const bool select = (sel_op != SEL_OP_SUB); + + bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + + if (ts->selectmode & SCE_SELECT_VERTEX) { + if (bbsel) { + changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } + else { + mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + + if (ts->selectmode & SCE_SELECT_EDGE) { + if (bbsel) { + changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } + else { + mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR); + } + } + + if (ts->selectmode & SCE_SELECT_FACE) { + if (bbsel) { + changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB); + } + else { + mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + } + } + + changed |= data.is_changed; + + EDBM_backbuf_free(); + + if (changed) { + EDBM_selectmode_flush(vc->em); + } + return changed; +} + +static bool paint_facesel_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + Object *ob = vc->obact; + Mesh *me = ob->data; + bool bbsel; + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + /* flush selection at the end */ + changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); + } + + bm_vertoffs = me->totpoly + 1; /* max index array */ + + bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + if (bbsel) { + changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op); + EDBM_backbuf_free(); + } + if (changed) { + paintface_flush_flags(vc->C, ob, SELECT); + } + return changed; +} + +static void paint_vertsel_circle_select_doSelectVert(void *userData, + MVert *mv, + const float screen_co[2], + int UNUSED(index)) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT); + data->is_changed = true; + } +} +static bool paint_vertsel_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + const bool use_zbuf = !XRAY_ENABLED(vc->v3d); + Object *ob = vc->obact; + Mesh *me = ob->data; + bool bbsel; + /* CircleSelectUserData data = {NULL}; */ /* UNUSED */ + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= paintvert_deselect_all_visible( + ob, SEL_DESELECT, false); /* flush selection at the end */ + } + + const bool select = (sel_op != SEL_OP_SUB); + + if (use_zbuf) { + bm_vertoffs = me->totvert + 1; /* max index array */ + + bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f)); + if (bbsel) { + changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op); + EDBM_backbuf_free(); + } + } + else { + CircleSelectUserData data; + + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + meshobject_foreachScreenVert( + vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + changed |= data.is_changed; + } + + if (changed) { + if (sel_op == SEL_OP_SUB) { + BKE_mesh_mselect_validate(me); + } + paintvert_flush_flags(ob); + paintvert_tag_select_update(vc->C, ob); + } + return changed; +} + +static void nurbscurve_circle_doSelect(void *userData, + Nurb *UNUSED(nu), + BPoint *bp, + BezTriple *bezt, + int beztindex, + const float screen_co[2]) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + if (bp) { + bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); + } + else { + if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) { + /* can only be (beztindex == 0) here since handles are hidden */ + bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT); + } + else { + if (beztindex == 0) { + bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT); + } + else if (beztindex == 1) { + bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT); + } + else { + bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT); + } + } + } + data->is_changed = true; + } +} +static bool nurbscurve_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + CircleSelectUserData data; + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + Curve *curve = vc->obedit->data; + changed |= ED_curve_deselect_all(curve->editnurb); + } + const bool select = (sel_op != SEL_OP_SUB); + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + BKE_curve_nurb_vert_active_validate(vc->obedit->data); + + return changed || data.is_changed; } - static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2]) { - CircleSelectUserData *data = userData; + CircleSelectUserData *data = userData; - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); - data->is_changed = true; - } + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT); + data->is_changed = true; + } } -static bool lattice_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) +static bool lattice_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) { - CircleSelectUserData data; - const bool select = (sel_op != SEL_OP_SUB); + 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); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); - } - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); + } + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return data.is_changed; + return data.is_changed; } - /* NOTE: pose-bone case is copied from editbone case... */ -static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2]) -{ - CircleSelectUserData *data = userData; - - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - if (data->select) { - pchan->bone->flag |= BONE_SELECTED; - } - else { - pchan->bone->flag &= ~BONE_SELECTED; - } - return 1; - } - return 0; -} -static void do_circle_select_pose__doSelectBone( - void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2]) -{ - CircleSelectUserData *data = userData; - bArmature *arm = data->vc->obact->data; - - if (PBONE_SELECTABLE(arm, pchan->bone)) { - bool is_point_done = false; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { - is_point_done = true; - } - } - - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) { - is_point_done = true; - } - } - - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ - - /* only if the endpoints didn't get selected, deal with the middle of the bone too - * It works nicer to only do this if the head or tail are not in the circle, - * otherwise there is no way to circle select joints alone */ - if ((is_point_done == false) && (points_proj_tot == 2) && - edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) - { - if (data->select) { - pchan->bone->flag |= BONE_SELECTED; - } - else { - pchan->bone->flag &= ~BONE_SELECTED; - } - data->is_changed = true; - } - - data->is_changed |= is_point_done; - } -} -static bool pose_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); - CircleSelectUserData data; - const bool select = (sel_op != SEL_OP_SUB); - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); - } - - ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ - - pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - - if (data.is_changed) { - ED_pose_bone_select_tag_update(vc->obact); - } - return data.is_changed; -} - -static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head) -{ - CircleSelectUserData *data = userData; - - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - if (head) { - if (data->select) { - ebone->flag |= BONE_ROOTSEL; - } - else { - ebone->flag &= ~BONE_ROOTSEL; - } - } - else { - if (data->select) { - ebone->flag |= BONE_TIPSEL; - } - else { - ebone->flag &= ~BONE_TIPSEL; - } - } - return 1; - } - return 0; -} -static void do_circle_select_armature__doSelectBone( - void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2]) -{ - CircleSelectUserData *data = userData; - bArmature *arm = data->vc->obedit->data; - - if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) { - bool is_point_done = false; - int points_proj_tot = 0; - - /* project head location to screenspace */ - if (screen_co_a[0] != IS_CLIPPED) { - points_proj_tot++; - if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) { - is_point_done = true; - } - } - - /* project tail location to screenspace */ - if (screen_co_b[0] != IS_CLIPPED) { - points_proj_tot++; - if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) { - is_point_done = true; - } - } - - /* check if the head and/or tail is in the circle - * - the call to check also does the selection already - */ - - /* only if the endpoints didn't get selected, deal with the middle of the bone too - * It works nicer to only do this if the head or tail are not in the circle, - * otherwise there is no way to circle select joints alone */ - if ((is_point_done == false) && (points_proj_tot == 2) && - edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) - { - if (data->select) { - ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - data->is_changed = true; - } - - data->is_changed |= is_point_done; - } -} -static bool armature_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) +static bool pchan_circle_doSelectJoint(void *userData, + bPoseChannel *pchan, + const float screen_co[2]) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + if (data->select) { + pchan->bone->flag |= BONE_SELECTED; + } + else { + pchan->bone->flag &= ~BONE_SELECTED; + } + return 1; + } + return 0; +} +static void do_circle_select_pose__doSelectBone(void *userData, + struct bPoseChannel *pchan, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + CircleSelectUserData *data = userData; + bArmature *arm = data->vc->obact->data; + + if (PBONE_SELECTABLE(arm, pchan->bone)) { + bool is_point_done = false; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) { + is_point_done = true; + } + } + + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) { + is_point_done = true; + } + } + + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ + + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == false) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + if (data->select) { + pchan->bone->flag |= BONE_SELECTED; + } + else { + pchan->bone->flag &= ~BONE_SELECTED; + } + data->is_changed = true; + } + + data->is_changed |= is_point_done; + } +} +static bool pose_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + CircleSelectUserData data; + const bool select = (sel_op != SEL_OP_SUB); + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_pose_deselect_all(vc->obact, SEL_DESELECT, false); + } + + ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */ + + pose_foreachScreenBone( + vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_changed) { + ED_pose_bone_select_tag_update(vc->obact); + } + return data.is_changed; +} + +static bool armature_circle_doSelectJoint(void *userData, + EditBone *ebone, + const float screen_co[2], + bool head) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + if (head) { + if (data->select) { + ebone->flag |= BONE_ROOTSEL; + } + else { + ebone->flag &= ~BONE_ROOTSEL; + } + } + else { + if (data->select) { + ebone->flag |= BONE_TIPSEL; + } + else { + ebone->flag &= ~BONE_TIPSEL; + } + } + return 1; + } + return 0; +} +static void do_circle_select_armature__doSelectBone(void *userData, + struct EditBone *ebone, + const float screen_co_a[2], + const float screen_co_b[2]) +{ + CircleSelectUserData *data = userData; + bArmature *arm = data->vc->obedit->data; + + if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) { + bool is_point_done = false; + int points_proj_tot = 0; + + /* project head location to screenspace */ + if (screen_co_a[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) { + is_point_done = true; + } + } + + /* project tail location to screenspace */ + if (screen_co_b[0] != IS_CLIPPED) { + points_proj_tot++; + if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) { + is_point_done = true; + } + } + + /* check if the head and/or tail is in the circle + * - the call to check also does the selection already + */ + + /* only if the endpoints didn't get selected, deal with the middle of the bone too + * It works nicer to only do this if the head or tail are not in the circle, + * otherwise there is no way to circle select joints alone */ + if ((is_point_done == false) && (points_proj_tot == 2) && + edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) { + if (data->select) { + ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + data->is_changed = true; + } + + data->is_changed |= is_point_done; + } +} +static bool armature_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + CircleSelectUserData data; + bArmature *arm = vc->obedit->data; + + const bool select = (sel_op != SEL_OP_SUB); + + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); + } + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + armature_foreachScreenBone( + vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (data.is_changed) { + ED_armature_edit_sync_selection(arm->edbo); + ED_armature_edit_validate_active(arm); + WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); + } + return data.is_changed; +} + +static void do_circle_select_mball__doSelectElem(void *userData, + struct MetaElem *ml, + const float screen_co[2]) +{ + CircleSelectUserData *data = userData; + + if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { + if (data->select) { + ml->flag |= SELECT; + } + else { + ml->flag &= ~SELECT; + } + data->is_changed = true; + } +} +static bool mball_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) { - CircleSelectUserData data; - bArmature *arm = vc->obedit->data; - - const bool select = (sel_op != SEL_OP_SUB); - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); - } - - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - - armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - - if (data.is_changed) { - ED_armature_edit_sync_selection(arm->edbo); - ED_armature_edit_validate_active(arm); - WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit); - } - return data.is_changed; -} - -static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2]) -{ - CircleSelectUserData *data = userData; - - if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) { - if (data->select) { - ml->flag |= SELECT; - } - else { - ml->flag &= ~SELECT; - } - data->is_changed = true; - } -} -static bool mball_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - CircleSelectUserData data; - - const bool select = (sel_op != SEL_OP_SUB); - - view3d_userdata_circleselect_init(&data, vc, select, mval, rad); + CircleSelectUserData data; + + const bool select = (sel_op != SEL_OP_SUB); - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - data.is_changed |= BKE_mball_deselect_all(vc->obedit->data); - } + view3d_userdata_circleselect_init(&data, vc, select, mval, rad); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + data.is_changed |= BKE_mball_deselect_all(vc->obedit->data); + } + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - return data.is_changed; + mball_foreachScreenElem( + vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + return data.is_changed; } /** Callbacks for circle selection in Editmode */ -static bool obedit_circle_select( - ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); - switch (vc->obedit->type) { - case OB_MESH: - return mesh_circle_select(vc, sel_op, mval, rad); - case OB_CURVE: - case OB_SURF: - return nurbscurve_circle_select(vc, sel_op, mval, rad); - case OB_LATTICE: - return lattice_circle_select(vc, sel_op, mval, rad); - case OB_ARMATURE: - return armature_circle_select(vc, sel_op, mval, rad); - case OB_MBALL: - return mball_circle_select(vc, sel_op, mval, rad); - default: - BLI_assert(0); - return false; - } -} - -static bool object_circle_select(ViewContext *vc, const eSelectOp sel_op, const int mval[2], float rad) -{ - BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); - ViewLayer *view_layer = vc->view_layer; - View3D *v3d = vc->v3d; - - const float radius_squared = rad * rad; - const float mval_fl[2] = {mval[0], mval[1]}; - - bool changed = false; - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { - changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); - } - const bool select = (sel_op != SEL_OP_SUB); - const int select_flag = select ? BASE_SELECTED : 0; - - Base *base; - for (base = FIRSTBASE(view_layer); base; base = base->next) { - if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { - float screen_co[2]; - if (ED_view3d_project_float_global( - vc->ar, base->object->obmat[3], screen_co, - V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == 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; - } - } - } - } - - return changed; +static bool obedit_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + switch (vc->obedit->type) { + case OB_MESH: + return mesh_circle_select(vc, sel_op, mval, rad); + case OB_CURVE: + case OB_SURF: + return nurbscurve_circle_select(vc, sel_op, mval, rad); + case OB_LATTICE: + return lattice_circle_select(vc, sel_op, mval, rad); + case OB_ARMATURE: + return armature_circle_select(vc, sel_op, mval, rad); + case OB_MBALL: + return mball_circle_select(vc, sel_op, mval, rad); + default: + BLI_assert(0); + return false; + } +} + +static bool object_circle_select(ViewContext *vc, + const eSelectOp sel_op, + const int mval[2], + float rad) +{ + BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB)); + ViewLayer *view_layer = vc->view_layer; + View3D *v3d = vc->v3d; + + const float radius_squared = rad * rad; + const float mval_fl[2] = {mval[0], mval[1]}; + + bool changed = false; + if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + changed |= object_deselect_all_visible(vc->view_layer, vc->v3d); + } + const bool select = (sel_op != SEL_OP_SUB); + const int select_flag = select ? BASE_SELECTED : 0; + + Base *base; + for (base = FIRSTBASE(view_layer); base; base = base->next) { + if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) { + float screen_co[2]; + if (ED_view3d_project_float_global(vc->ar, + base->object->obmat[3], + screen_co, + V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | + V3D_PROJ_TEST_CLIP_NEAR) == 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; + } + } + } + } + + return changed; } /* not a real operator, only for circle test */ static int view3d_circle_select_exec(bContext *C, wmOperator *op) { - ViewContext vc; - const int radius = RNA_int_get(op->ptr, "radius"); - const int mval[2] = {RNA_int_get(op->ptr, "x"), - RNA_int_get(op->ptr, "y")}; - - const eSelectOp sel_op = ED_select_op_modal( - RNA_enum_get(op->ptr, "mode"), WM_gesture_is_modal_first(op->customdata)); - - ED_view3d_viewcontext_init(C, &vc); - - Object *obact = vc.obact; - Object *obedit = vc.obedit; - - if (obedit || BKE_paint_select_elem_test(obact) || - (obact && (obact->mode & OB_MODE_POSE))) - { - view3d_operator_needs_opengl(C); - - FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { - ED_view3d_viewcontext_init_object(&vc, ob_iter); - - obact = vc.obact; - obedit = vc.obedit; - - if (obedit) { - if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) { - DEG_id_tag_update(obact->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); - } - } - else if (BKE_paint_select_face_test(obact)) { - paint_facesel_circle_select(&vc, sel_op, mval, (float)radius); - } - else if (BKE_paint_select_vert_test(obact)) { - paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius); - } - else if (obact->mode & OB_MODE_POSE) { - pose_circle_select(&vc, sel_op, mval, (float)radius); - } - else { - BLI_assert(0); - } - } - FOREACH_OBJECT_IN_MODE_END; - } - else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) { - if (PE_circle_select(C, sel_op, mval, (float)radius)) { - return OPERATOR_FINISHED; - } - return OPERATOR_CANCELLED; - } - else if (obact && obact->mode & OB_MODE_SCULPT) { - return OPERATOR_CANCELLED; - } - 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); - } - } - - return OPERATOR_FINISHED; + ViewContext vc; + const int radius = RNA_int_get(op->ptr, "radius"); + const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")}; + + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), + WM_gesture_is_modal_first(op->customdata)); + + ED_view3d_viewcontext_init(C, &vc); + + Object *obact = vc.obact; + Object *obedit = vc.obedit; + + if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) { + view3d_operator_needs_opengl(C); + + FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) { + ED_view3d_viewcontext_init_object(&vc, ob_iter); + + obact = vc.obact; + obedit = vc.obedit; + + if (obedit) { + if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) { + DEG_id_tag_update(obact->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data); + } + } + else if (BKE_paint_select_face_test(obact)) { + paint_facesel_circle_select(&vc, sel_op, mval, (float)radius); + } + else if (BKE_paint_select_vert_test(obact)) { + paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius); + } + else if (obact->mode & OB_MODE_POSE) { + pose_circle_select(&vc, sel_op, mval, (float)radius); + } + else { + BLI_assert(0); + } + } + FOREACH_OBJECT_IN_MODE_END; + } + else if (obact && (obact->mode & OB_MODE_PARTICLE_EDIT)) { + if (PE_circle_select(C, sel_op, mval, (float)radius)) { + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; + } + else if (obact && obact->mode & OB_MODE_SCULPT) { + return OPERATOR_CANCELLED; + } + 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); + } + } + + return OPERATOR_FINISHED; } void VIEW3D_OT_select_circle(wmOperatorType *ot) { - ot->name = "Circle Select"; - ot->description = "Select items using circle selection"; - ot->idname = "VIEW3D_OT_select_circle"; + ot->name = "Circle Select"; + ot->description = "Select items using circle selection"; + ot->idname = "VIEW3D_OT_select_circle"; - ot->invoke = WM_gesture_circle_invoke; - ot->modal = WM_gesture_circle_modal; - ot->exec = view3d_circle_select_exec; - ot->poll = view3d_selectable_data; - ot->cancel = WM_gesture_circle_cancel; + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = view3d_circle_select_exec; + ot->poll = view3d_selectable_data; + ot->cancel = WM_gesture_circle_cancel; - /* flags */ - ot->flag = OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_UNDO; - /* properties */ - WM_operator_properties_gesture_circle(ot); - WM_operator_properties_select_operation_simple(ot); + /* properties */ + WM_operator_properties_gesture_circle(ot); + WM_operator_properties_select_operation_simple(ot); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 711e084f2ac..5aa19cc8a51 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -21,7 +21,6 @@ * \ingroup spview3d */ - #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" @@ -62,172 +61,172 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]); static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]); - /* *********************** operators ******************** */ /** Snaps every individual object center to its nearest point on the grid. */ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); - RegionView3D *rv3d = CTX_wm_region_data(C); - View3D *v3d = CTX_wm_view3d(C); - TransVertStore tvs = {NULL}; - TransVert *tv; - float gridf, imat[3][3], bmat[3][3], vec[3]; - int a; - - gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); - - if (obedit) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - obedit = objects[ob_index]; - - if (obedit->type == OB_MESH) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (em->bm->totvertsel == 0) { - continue; - } - } - - if (ED_transverts_check_obedit(obedit)) { - ED_transverts_create_from_obedit(&tvs, obedit, 0); - } - - if (tvs.transverts_tot != 0) { - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(imat, bmat); - - tv = tvs.transverts; - for (a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(vec, tv->loc); - mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit->obmat[3]); - vec[0] = gridf * floorf(0.5f + vec[0] / gridf); - vec[1] = gridf * floorf(0.5f + vec[1] / gridf); - vec[2] = gridf * floorf(0.5f + vec[2] / gridf); - sub_v3_v3(vec, obedit->obmat[3]); - - mul_m3_v3(imat, vec); - copy_v3_v3(tv->loc, vec); - } - ED_transverts_update_obedit(&tvs, obedit); - } - ED_transverts_free(&tvs); - } - MEM_freeN(objects); - } - else { - struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); - - FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(view_layer_eval, v3d, ob_eval) - { - Object *ob = DEG_get_original_object(ob_eval); - if (ob->mode & OB_MODE_POSE) { - bPoseChannel *pchan_eval; - bArmature *arm_eval = ob_eval->data; - - invert_m4_m4(ob_eval->imat, ob_eval->obmat); - - for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; pchan_eval = pchan_eval->next) { - if (pchan_eval->bone->flag & BONE_SELECTED) { - if (pchan_eval->bone->layer & arm_eval->layer) { - if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) { - float nLoc[3]; - - /* get nearest grid point to snap to */ - copy_v3_v3(nLoc, pchan_eval->pose_mat[3]); - /* We must operate in world space! */ - mul_m4_v3(ob_eval->obmat, nLoc); - vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf); - vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); - vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); - /* Back in object space... */ - mul_m4_v3(ob_eval->imat, vec); - - /* Get location of grid point in pose space. */ - BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec); - - /* adjust location on the original pchan*/ - bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name); - if ((pchan->protectflag & OB_LOCK_LOCX) == 0) { - pchan->loc[0] = vec[0]; - } - if ((pchan->protectflag & OB_LOCK_LOCY) == 0) { - pchan->loc[1] = vec[1]; - } - if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) { - pchan->loc[2] = vec[2]; - } - - /* auto-keyframing */ - ED_autokeyframe_pchan(C, scene, ob, pchan, ks); - } - /* if the bone has a parent and is connected to the parent, - * don't do anything - will break chain unless we do auto-ik. - */ - } - } - } - ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } - else { - vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf); - vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf); - vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf); - - if (ob->parent) { - float originmat[3][3]; - BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat); - - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, vec); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] = ob_eval->loc[0] + vec[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] = ob_eval->loc[1] + vec[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] = ob_eval->loc[2] + vec[2]; - } - - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); - - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } - } - FOREACH_SELECTED_EDITABLE_OBJECT_END; - } - - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); + Object *obedit = CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = CTX_wm_region_data(C); + View3D *v3d = CTX_wm_view3d(C); + TransVertStore tvs = {NULL}; + TransVert *tv; + float gridf, imat[3][3], bmat[3][3], vec[3]; + int a; + + gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); + + if (obedit) { + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + obedit = objects[ob_index]; + + if (obedit->type == OB_MESH) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + if (em->bm->totvertsel == 0) { + continue; + } + } + + if (ED_transverts_check_obedit(obedit)) { + ED_transverts_create_from_obedit(&tvs, obedit, 0); + } + + if (tvs.transverts_tot != 0) { + copy_m3_m4(bmat, obedit->obmat); + invert_m3_m3(imat, bmat); + + tv = tvs.transverts; + for (a = 0; a < tvs.transverts_tot; a++, tv++) { + copy_v3_v3(vec, tv->loc); + mul_m3_v3(bmat, vec); + add_v3_v3(vec, obedit->obmat[3]); + vec[0] = gridf * floorf(0.5f + vec[0] / gridf); + vec[1] = gridf * floorf(0.5f + vec[1] / gridf); + vec[2] = gridf * floorf(0.5f + vec[2] / gridf); + sub_v3_v3(vec, obedit->obmat[3]); + + mul_m3_v3(imat, vec); + copy_v3_v3(tv->loc, vec); + } + ED_transverts_update_obedit(&tvs, obedit); + } + ED_transverts_free(&tvs); + } + MEM_freeN(objects); + } + else { + struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); + + FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) { + Object *ob = DEG_get_original_object(ob_eval); + if (ob->mode & OB_MODE_POSE) { + bPoseChannel *pchan_eval; + bArmature *arm_eval = ob_eval->data; + + invert_m4_m4(ob_eval->imat, ob_eval->obmat); + + for (pchan_eval = ob_eval->pose->chanbase.first; pchan_eval; + pchan_eval = pchan_eval->next) { + if (pchan_eval->bone->flag & BONE_SELECTED) { + if (pchan_eval->bone->layer & arm_eval->layer) { + if ((pchan_eval->bone->flag & BONE_CONNECTED) == 0) { + float nLoc[3]; + + /* get nearest grid point to snap to */ + copy_v3_v3(nLoc, pchan_eval->pose_mat[3]); + /* We must operate in world space! */ + mul_m4_v3(ob_eval->obmat, nLoc); + vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf); + vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); + vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); + /* Back in object space... */ + mul_m4_v3(ob_eval->imat, vec); + + /* Get location of grid point in pose space. */ + BKE_armature_loc_pose_to_bone(pchan_eval, vec, vec); + + /* adjust location on the original pchan*/ + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, pchan_eval->name); + if ((pchan->protectflag & OB_LOCK_LOCX) == 0) { + pchan->loc[0] = vec[0]; + } + if ((pchan->protectflag & OB_LOCK_LOCY) == 0) { + pchan->loc[1] = vec[1]; + } + if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) { + pchan->loc[2] = vec[2]; + } + + /* auto-keyframing */ + ED_autokeyframe_pchan(C, scene, ob, pchan, ks); + } + /* if the bone has a parent and is connected to the parent, + * don't do anything - will break chain unless we do auto-ik. + */ + } + } + } + ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + else { + vec[0] = -ob_eval->obmat[3][0] + gridf * floorf(0.5f + ob_eval->obmat[3][0] / gridf); + vec[1] = -ob_eval->obmat[3][1] + gridf * floorf(0.5f + ob_eval->obmat[3][1] / gridf); + vec[2] = -ob_eval->obmat[3][2] + gridf * floorf(0.5f + ob_eval->obmat[3][2] / gridf); + + if (ob->parent) { + float originmat[3][3]; + BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat); + + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, vec); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] = ob_eval->loc[0] + vec[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] = ob_eval->loc[1] + vec[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] = ob_eval->loc[2] + vec[2]; + } + + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); + + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + } + } + FOREACH_SELECTED_EDITABLE_OBJECT_END; + } + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + + return OPERATOR_FINISHED; } void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Selection to Grid"; - ot->description = "Snap selected item(s) to their nearest grid division"; - ot->idname = "VIEW3D_OT_snap_selected_to_grid"; + /* identifiers */ + ot->name = "Snap Selection to Grid"; + ot->description = "Snap selected item(s) to their nearest grid division"; + ot->idname = "VIEW3D_OT_snap_selected_to_grid"; - /* api callbacks */ - ot->exec = snap_sel_to_grid_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = snap_sel_to_grid_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; } /* *************************************************** */ @@ -238,256 +237,257 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) * \param use_offset: if the selected objects should maintain their relative offsets and be snapped by the selection * pivot point (median, active), or if every object origin should be snapped to the given location. */ -static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset) +static int snap_selected_to_location(bContext *C, + const float snap_target_global[3], + const bool use_offset) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - Object *obedit = CTX_data_edit_object(C); - Object *obact = CTX_data_active_object(C); - View3D *v3d = CTX_wm_view3d(C); - TransVertStore tvs = {NULL}; - TransVert *tv; - float imat[3][3], bmat[3][3]; - float center_global[3]; - float offset_global[3]; - int a; - - if (use_offset) { - if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) && - snap_calc_active_center(C, true, center_global)) - { - /* pass */ - } - else { - snap_curs_to_sel_ex(C, center_global); - } - sub_v3_v3v3(offset_global, snap_target_global, center_global); - } - - if (obedit) { - float snap_target_local[3]; - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - obedit = objects[ob_index]; - - if (obedit->type == OB_MESH) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (em->bm->totvertsel == 0) { - continue; - } - } - - if (ED_transverts_check_obedit(obedit)) { - ED_transverts_create_from_obedit(&tvs, obedit, 0); - } - - if (tvs.transverts_tot != 0) { - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(imat, bmat); - - /* get the cursor in object space */ - sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); - mul_m3_v3(imat, snap_target_local); - - if (use_offset) { - float offset_local[3]; - - mul_v3_m3v3(offset_local, imat, offset_global); - - tv = tvs.transverts; - for (a = 0; a < tvs.transverts_tot; a++, tv++) { - add_v3_v3(tv->loc, offset_local); - } - } - else { - tv = tvs.transverts; - for (a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(tv->loc, snap_target_local); - } - } - ED_transverts_update_obedit(&tvs, obedit); - } - ED_transverts_free(&tvs); - } - MEM_freeN(objects); - } - else if (obact && (obact->mode & OB_MODE_POSE)) { - struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(view_layer, CTX_wm_view3d(C), - &objects_len, OB_MODE_POSE); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob = objects[ob_index]; - bPoseChannel *pchan; - bArmature *arm = ob->data; - float snap_target_local[3]; - - invert_m4_m4(ob->imat, ob->obmat); - mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global); - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if ((pchan->bone->flag & BONE_SELECTED) && - (PBONE_VISIBLE(arm, pchan->bone)) && - /* if the bone has a parent and is connected to the parent, - * don't do anything - will break chain unless we do auto-ik. - */ - (pchan->bone->flag & BONE_CONNECTED) == 0) - { - pchan->bone->flag |= BONE_TRANSFORM; - } - else { - pchan->bone->flag &= ~BONE_TRANSFORM; - } - } - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if ((pchan->bone->flag & BONE_TRANSFORM) && - /* check that our parents not transformed (if we have one) */ - ((pchan->bone->parent && - BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0)) - { - /* Get position in pchan (pose) space. */ - float cursor_pose[3]; - - if (use_offset) { - mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]); - add_v3_v3(cursor_pose, offset_global); - - mul_m4_v3(ob->imat, cursor_pose); - BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); - } - else { - BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose); - } - - /* copy new position */ - if ((pchan->protectflag & OB_LOCK_LOCX) == 0) { - pchan->loc[0] = cursor_pose[0]; - } - if ((pchan->protectflag & OB_LOCK_LOCY) == 0) { - pchan->loc[1] = cursor_pose[1]; - } - if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) { - pchan->loc[2] = cursor_pose[2]; - } - - /* auto-keyframing */ - ED_autokeyframe_pchan(C, scene, ob, pchan, ks); - } - } - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - pchan->bone->flag &= ~BONE_TRANSFORM; - } - - ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); - - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } - MEM_freeN(objects); - } - else { - struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); - Main *bmain = CTX_data_main(C); - - ListBase ctx_data_list; - CollectionPointerLink *ctx_ob; - Object *ob; - - CTX_data_selected_editable_objects(C, &ctx_data_list); - - /* reset flags */ - for (ob = bmain->objects.first; ob; ob = ob->id.next) { - ob->flag &= ~OB_DONE; - } - - /* tag objects we're transforming */ - for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { - ob = ctx_ob->ptr.data; - ob->flag |= OB_DONE; - } - - for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { - ob = ctx_ob->ptr.data; - - if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { - - float cursor_parent[3]; /* parent-relative */ - - if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); - } - else { - copy_v3_v3(cursor_parent, snap_target_global); - } - - sub_v3_v3(cursor_parent, ob->obmat[3]); - - if (ob->parent) { - float originmat[3][3]; - BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat); - - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, cursor_parent); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] += cursor_parent[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] += cursor_parent[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] += cursor_parent[2]; - } - - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); - - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } - } - - BLI_freelistN(&ctx_data_list); - } - - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + Object *obedit = CTX_data_edit_object(C); + Object *obact = CTX_data_active_object(C); + View3D *v3d = CTX_wm_view3d(C); + TransVertStore tvs = {NULL}; + TransVert *tv; + float imat[3][3], bmat[3][3]; + float center_global[3]; + float offset_global[3]; + int a; + + if (use_offset) { + if ((v3d && scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) && + snap_calc_active_center(C, true, center_global)) { + /* pass */ + } + else { + snap_curs_to_sel_ex(C, center_global); + } + sub_v3_v3v3(offset_global, snap_target_global, center_global); + } + + if (obedit) { + float snap_target_local[3]; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + obedit = objects[ob_index]; + + if (obedit->type == OB_MESH) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + if (em->bm->totvertsel == 0) { + continue; + } + } + + if (ED_transverts_check_obedit(obedit)) { + ED_transverts_create_from_obedit(&tvs, obedit, 0); + } + + if (tvs.transverts_tot != 0) { + copy_m3_m4(bmat, obedit->obmat); + invert_m3_m3(imat, bmat); + + /* get the cursor in object space */ + sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); + mul_m3_v3(imat, snap_target_local); + + if (use_offset) { + float offset_local[3]; + + mul_v3_m3v3(offset_local, imat, offset_global); + + tv = tvs.transverts; + for (a = 0; a < tvs.transverts_tot; a++, tv++) { + add_v3_v3(tv->loc, offset_local); + } + } + else { + tv = tvs.transverts; + for (a = 0; a < tvs.transverts_tot; a++, tv++) { + copy_v3_v3(tv->loc, snap_target_local); + } + } + ED_transverts_update_obedit(&tvs, obedit); + } + ED_transverts_free(&tvs); + } + MEM_freeN(objects); + } + else if (obact && (obact->mode & OB_MODE_POSE)) { + struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len, OB_MODE_POSE); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + bPoseChannel *pchan; + bArmature *arm = ob->data; + float snap_target_local[3]; + + invert_m4_m4(ob->imat, ob->obmat); + mul_v3_m4v3(snap_target_local, ob->imat, snap_target_global); + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if ((pchan->bone->flag & BONE_SELECTED) && (PBONE_VISIBLE(arm, pchan->bone)) && + /* if the bone has a parent and is connected to the parent, + * don't do anything - will break chain unless we do auto-ik. + */ + (pchan->bone->flag & BONE_CONNECTED) == 0) { + pchan->bone->flag |= BONE_TRANSFORM; + } + else { + pchan->bone->flag &= ~BONE_TRANSFORM; + } + } + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if ((pchan->bone->flag & BONE_TRANSFORM) && + /* check that our parents not transformed (if we have one) */ + ((pchan->bone->parent && + BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0)) { + /* Get position in pchan (pose) space. */ + float cursor_pose[3]; + + if (use_offset) { + mul_v3_m4v3(cursor_pose, ob->obmat, pchan->pose_mat[3]); + add_v3_v3(cursor_pose, offset_global); + + mul_m4_v3(ob->imat, cursor_pose); + BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); + } + else { + BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose); + } + + /* copy new position */ + if ((pchan->protectflag & OB_LOCK_LOCX) == 0) { + pchan->loc[0] = cursor_pose[0]; + } + if ((pchan->protectflag & OB_LOCK_LOCY) == 0) { + pchan->loc[1] = cursor_pose[1]; + } + if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) { + pchan->loc[2] = cursor_pose[2]; + } + + /* auto-keyframing */ + ED_autokeyframe_pchan(C, scene, ob, pchan, ks); + } + } + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + pchan->bone->flag &= ~BONE_TRANSFORM; + } + + ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + MEM_freeN(objects); + } + else { + struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); + Main *bmain = CTX_data_main(C); + + ListBase ctx_data_list; + CollectionPointerLink *ctx_ob; + Object *ob; + + CTX_data_selected_editable_objects(C, &ctx_data_list); + + /* reset flags */ + for (ob = bmain->objects.first; ob; ob = ob->id.next) { + ob->flag &= ~OB_DONE; + } + + /* tag objects we're transforming */ + for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { + ob = ctx_ob->ptr.data; + ob->flag |= OB_DONE; + } + + for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { + ob = ctx_ob->ptr.data; + + if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { + + float cursor_parent[3]; /* parent-relative */ + + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, snap_target_global); + } + + sub_v3_v3(cursor_parent, ob->obmat[3]); + + if (ob->parent) { + float originmat[3][3]; + BKE_object_where_is_calc_ex(depsgraph, scene, NULL, ob, originmat); + + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, cursor_parent); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] += cursor_parent[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] += cursor_parent[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] += cursor_parent[2]; + } + + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); + + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + } + } + + BLI_freelistN(&ctx_data_list); + } + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + + return OPERATOR_FINISHED; } static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op) { - const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); - Scene *scene = CTX_data_scene(C); + Scene *scene = CTX_data_scene(C); - const float *snap_target_global = scene->cursor.location; + const float *snap_target_global = scene->cursor.location; - return snap_selected_to_location(C, snap_target_global, use_offset); + return snap_selected_to_location(C, snap_target_global, use_offset); } void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Selection to Cursor"; - ot->description = "Snap selected item(s) to the 3D cursor"; - ot->idname = "VIEW3D_OT_snap_selected_to_cursor"; - - /* api callbacks */ - ot->exec = snap_selected_to_cursor_exec; - ot->poll = ED_operator_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; - - /* rna */ - RNA_def_boolean( - ot->srna, "use_offset", 1, "Offset", - "If the selection should be snapped as a whole or by each object center"); + /* identifiers */ + ot->name = "Snap Selection to Cursor"; + ot->description = "Snap selected item(s) to the 3D cursor"; + ot->idname = "VIEW3D_OT_snap_selected_to_cursor"; + + /* api callbacks */ + ot->exec = snap_selected_to_cursor_exec; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + + /* rna */ + RNA_def_boolean(ot->srna, + "use_offset", + 1, + "Offset", + "If the selection should be snapped as a whole or by each object center"); } /* *************************************************** */ @@ -495,68 +495,67 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) /** Snaps each selected object to the location of the active selected object. */ static int snap_selected_to_active_exec(bContext *C, wmOperator *op) { - float snap_target_global[3]; + float snap_target_global[3]; - if (snap_calc_active_center(C, false, snap_target_global) == false) { - BKE_report(op->reports, RPT_ERROR, "No active element found!"); - return OPERATOR_CANCELLED; - } + if (snap_calc_active_center(C, false, snap_target_global) == false) { + BKE_report(op->reports, RPT_ERROR, "No active element found!"); + return OPERATOR_CANCELLED; + } - return snap_selected_to_location(C, snap_target_global, false); + return snap_selected_to_location(C, snap_target_global, false); } void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Selection to Active"; - ot->description = "Snap selected item(s) to the active item"; - ot->idname = "VIEW3D_OT_snap_selected_to_active"; + /* identifiers */ + ot->name = "Snap Selection to Active"; + ot->description = "Snap selected item(s) to the active item"; + ot->idname = "VIEW3D_OT_snap_selected_to_active"; - /* api callbacks */ - ot->exec = snap_selected_to_active_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = snap_selected_to_active_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; } - /* *************************************************** */ /** Snaps the 3D cursor location to its nearest point on the grid. */ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - RegionView3D *rv3d = CTX_wm_region_data(C); - View3D *v3d = CTX_wm_view3d(C); - float gridf, *curs; + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = CTX_wm_region_data(C); + View3D *v3d = CTX_wm_view3d(C); + float gridf, *curs; - gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); - curs = scene->cursor.location; + gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); + curs = scene->cursor.location; - curs[0] = gridf * floorf(0.5f + curs[0] / gridf); - curs[1] = gridf * floorf(0.5f + curs[1] / gridf); - curs[2] = gridf * floorf(0.5f + curs[2] / gridf); + curs[0] = gridf * floorf(0.5f + curs[0] / gridf); + curs[1] = gridf * floorf(0.5f + curs[1] / gridf); + curs[2] = gridf * floorf(0.5f + curs[2] / gridf); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */ - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); /* hrm */ + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Cursor to Grid"; - ot->description = "Snap 3D cursor to the nearest grid division"; - ot->idname = "VIEW3D_OT_snap_cursor_to_grid"; + /* identifiers */ + ot->name = "Snap Cursor to Grid"; + ot->description = "Snap 3D cursor to the nearest grid division"; + ot->idname = "VIEW3D_OT_snap_cursor_to_grid"; - /* api callbacks */ - ot->exec = snap_curs_to_grid_exec; - ot->poll = ED_operator_region_view3d_active; + /* api callbacks */ + ot->exec = snap_curs_to_grid_exec; + ot->poll = ED_operator_region_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* **************************************************** */ @@ -567,202 +566,202 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot) */ static void bundle_midpoint(Scene *scene, Object *ob, float r_vec[3]) { - MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); - MovieTracking *tracking; - MovieTrackingObject *object; - bool ok = false; - float min[3], max[3], mat[4][4], pos[3], cammat[4][4]; + MovieClip *clip = BKE_object_movieclip_get(scene, ob, false); + MovieTracking *tracking; + MovieTrackingObject *object; + bool ok = false; + float min[3], max[3], mat[4][4], pos[3], cammat[4][4]; - if (!clip) { - return; - } + if (!clip) { + return; + } - tracking = &clip->tracking; + tracking = &clip->tracking; - copy_m4_m4(cammat, ob->obmat); + copy_m4_m4(cammat, ob->obmat); - BKE_tracking_get_camera_object_matrix(scene, ob, mat); + BKE_tracking_get_camera_object_matrix(scene, ob, mat); - INIT_MINMAX(min, max); + INIT_MINMAX(min, max); - for (object = tracking->objects.first; object; object = object->next) { - ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); - MovieTrackingTrack *track = tracksbase->first; - float obmat[4][4]; + for (object = tracking->objects.first; object; object = object->next) { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); + MovieTrackingTrack *track = tracksbase->first; + float obmat[4][4]; - if (object->flag & TRACKING_OBJECT_CAMERA) { - copy_m4_m4(obmat, mat); - } - else { - float imat[4][4]; + if (object->flag & TRACKING_OBJECT_CAMERA) { + copy_m4_m4(obmat, mat); + } + else { + float imat[4][4]; - BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, scene->r.cfra, imat); - invert_m4(imat); + BKE_tracking_camera_get_reconstructed_interpolate(tracking, object, scene->r.cfra, imat); + invert_m4(imat); - mul_m4_m4m4(obmat, cammat, imat); - } + mul_m4_m4m4(obmat, cammat, imat); + } - while (track) { - if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) { - ok = 1; - mul_v3_m4v3(pos, obmat, track->bundle_pos); - minmax_v3v3_v3(min, max, pos); - } + while (track) { + if ((track->flag & TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) { + ok = 1; + mul_v3_m4v3(pos, obmat, track->bundle_pos); + minmax_v3v3_v3(min, max, pos); + } - track = track->next; - } - } + track = track->next; + } + } - if (ok) { - mid_v3_v3v3(r_vec, min, max); - } + if (ok) { + mid_v3_v3v3(r_vec, min, max); + } } /** Snaps the 3D cursor location to the median point of the selection. */ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); - Object *obedit = CTX_data_edit_object(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - TransVertStore tvs = {NULL}; - TransVert *tv; - float bmat[3][3], vec[3], min[3], max[3], centroid[3]; - int count, a; - - count = 0; - INIT_MINMAX(min, max); - zero_v3(centroid); - - if (obedit) { - int global_transverts_tot = 0; - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - obedit = objects[ob_index]; - - /* We can do that quick check for meshes only... */ - if (obedit->type == OB_MESH) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (em->bm->totvertsel == 0) { - continue; - } - } - - if (ED_transverts_check_obedit(obedit)) { - ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES); - } - - global_transverts_tot += tvs.transverts_tot; - if (tvs.transverts_tot != 0) { - Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - copy_m3_m4(bmat, obedit_eval->obmat); - - tv = tvs.transverts; - for (a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(vec, tv->loc); - mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit_eval->obmat[3]); - add_v3_v3(centroid, vec); - minmax_v3v3_v3(min, max, vec); - } - } - ED_transverts_free(&tvs); - } - MEM_freeN(objects); - - if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) { - mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot); - copy_v3_v3(cursor, centroid); - } - else { - mid_v3_v3v3(cursor, min, max); - } - } - else { - Object *obact = CTX_data_active_object(C); - - if (obact && (obact->mode & OB_MODE_POSE)) { - Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); - bArmature *arm = obact_eval->data; - bPoseChannel *pchan; - for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) { - if (arm->layer & pchan->bone->layer) { - if (pchan->bone->flag & BONE_SELECTED) { - copy_v3_v3(vec, pchan->pose_head); - mul_m4_v3(obact_eval->obmat, vec); - add_v3_v3(centroid, vec); - minmax_v3v3_v3(min, max, vec); - count++; - } - } - } - } - else { - FOREACH_SELECTED_OBJECT_BEGIN(view_layer_eval, v3d, ob_eval) - { - copy_v3_v3(vec, ob_eval->obmat[3]); - - /* special case for camera -- snap to bundles */ - if (ob_eval->type == OB_CAMERA) { - /* snap to bundles should happen only when bundles are visible */ - if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) { - bundle_midpoint(scene, DEG_get_original_object(ob_eval), vec); - } - } - - add_v3_v3(centroid, vec); - minmax_v3v3_v3(min, max, vec); - count++; - } - FOREACH_SELECTED_OBJECT_END; - } - - if (count == 0) { - return false; - } - - if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) { - mul_v3_fl(centroid, 1.0f / (float)count); - copy_v3_v3(cursor, centroid); - } - else { - mid_v3_v3v3(cursor, min, max); - } - } - return true; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); + Object *obedit = CTX_data_edit_object(C); + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + TransVertStore tvs = {NULL}; + TransVert *tv; + float bmat[3][3], vec[3], min[3], max[3], centroid[3]; + int count, a; + + count = 0; + INIT_MINMAX(min, max); + zero_v3(centroid); + + if (obedit) { + int global_transverts_tot = 0; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + obedit = objects[ob_index]; + + /* We can do that quick check for meshes only... */ + if (obedit->type == OB_MESH) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + if (em->bm->totvertsel == 0) { + continue; + } + } + + if (ED_transverts_check_obedit(obedit)) { + ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES); + } + + global_transverts_tot += tvs.transverts_tot; + if (tvs.transverts_tot != 0) { + Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); + copy_m3_m4(bmat, obedit_eval->obmat); + + tv = tvs.transverts; + for (a = 0; a < tvs.transverts_tot; a++, tv++) { + copy_v3_v3(vec, tv->loc); + mul_m3_v3(bmat, vec); + add_v3_v3(vec, obedit_eval->obmat[3]); + add_v3_v3(centroid, vec); + minmax_v3v3_v3(min, max, vec); + } + } + ED_transverts_free(&tvs); + } + MEM_freeN(objects); + + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) { + mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot); + copy_v3_v3(cursor, centroid); + } + else { + mid_v3_v3v3(cursor, min, max); + } + } + else { + Object *obact = CTX_data_active_object(C); + + if (obact && (obact->mode & OB_MODE_POSE)) { + Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact); + bArmature *arm = obact_eval->data; + bPoseChannel *pchan; + for (pchan = obact_eval->pose->chanbase.first; pchan; pchan = pchan->next) { + if (arm->layer & pchan->bone->layer) { + if (pchan->bone->flag & BONE_SELECTED) { + copy_v3_v3(vec, pchan->pose_head); + mul_m4_v3(obact_eval->obmat, vec); + add_v3_v3(centroid, vec); + minmax_v3v3_v3(min, max, vec); + count++; + } + } + } + } + else { + FOREACH_SELECTED_OBJECT_BEGIN (view_layer_eval, v3d, ob_eval) { + copy_v3_v3(vec, ob_eval->obmat[3]); + + /* special case for camera -- snap to bundles */ + if (ob_eval->type == OB_CAMERA) { + /* snap to bundles should happen only when bundles are visible */ + if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) { + bundle_midpoint(scene, DEG_get_original_object(ob_eval), vec); + } + } + + add_v3_v3(centroid, vec); + minmax_v3v3_v3(min, max, vec); + count++; + } + FOREACH_SELECTED_OBJECT_END; + } + + if (count == 0) { + return false; + } + + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) { + mul_v3_fl(centroid, 1.0f / (float)count); + copy_v3_v3(cursor, centroid); + } + else { + mid_v3_v3v3(cursor, min, max); + } + } + return true; } static int snap_curs_to_sel_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - if (snap_curs_to_sel_ex(C, scene->cursor.location)) { - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + Scene *scene = CTX_data_scene(C); + if (snap_curs_to_sel_ex(C, scene->cursor.location)) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Cursor to Selected"; - ot->description = "Snap 3D cursor to the middle of the selected item(s)"; - ot->idname = "VIEW3D_OT_snap_cursor_to_selected"; + /* identifiers */ + ot->name = "Snap Cursor to Selected"; + ot->description = "Snap 3D cursor to the middle of the selected item(s)"; + ot->idname = "VIEW3D_OT_snap_cursor_to_selected"; - /* api callbacks */ - ot->exec = snap_curs_to_sel_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = snap_curs_to_sel_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; } /* ********************************************** */ @@ -774,42 +773,42 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot) */ static bool snap_calc_active_center(bContext *C, const bool select_only, float r_center[3]) { - Object *ob = CTX_data_active_object(C); - if (ob == NULL) { - return false; - } - return ED_object_calc_active_center(ob, select_only, r_center); + Object *ob = CTX_data_active_object(C); + if (ob == NULL) { + return false; + } + return ED_object_calc_active_center(ob, select_only, r_center); } static int snap_curs_to_active_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - - if (snap_calc_active_center(C, false, scene->cursor.location)) { - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + if (snap_calc_active_center(C, false, scene->cursor.location)) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Cursor to Active"; - ot->description = "Snap 3D cursor to the active item"; - ot->idname = "VIEW3D_OT_snap_cursor_to_active"; + /* identifiers */ + ot->name = "Snap Cursor to Active"; + ot->description = "Snap 3D cursor to the active item"; + ot->idname = "VIEW3D_OT_snap_cursor_to_active"; - /* api callbacks */ - ot->exec = snap_curs_to_active_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = snap_curs_to_active_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA; } /* **************************************************** */ @@ -817,32 +816,32 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot) /** Snaps the 3D cursor location to the origin and clears cursor rotation. */ static int snap_curs_to_center_exec(bContext *C, wmOperator *UNUSED(op)) { - Scene *scene = CTX_data_scene(C); - float mat3[3][3]; - unit_m3(mat3); + Scene *scene = CTX_data_scene(C); + float mat3[3][3]; + unit_m3(mat3); - zero_v3(scene->cursor.location); - BKE_scene_cursor_mat3_to_rot(&scene->cursor, mat3, false); + zero_v3(scene->cursor.location); + BKE_scene_cursor_mat3_to_rot(&scene->cursor, mat3, false); - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - return OPERATOR_FINISHED; + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + return OPERATOR_FINISHED; } void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Snap Cursor to World Origin"; - ot->description = "Snap 3D cursor to the world origin"; - ot->idname = "VIEW3D_OT_snap_cursor_to_center"; + /* identifiers */ + ot->name = "Snap Cursor to World Origin"; + ot->description = "Snap 3D cursor to the world origin"; + ot->idname = "VIEW3D_OT_snap_cursor_to_center"; - /* api callbacks */ - ot->exec = snap_curs_to_center_exec; - ot->poll = ED_operator_view3d_active; + /* api callbacks */ + ot->exec = snap_curs_to_center_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* **************************************************** */ @@ -853,43 +852,43 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot) */ bool ED_view3d_minmax_verts(Object *obedit, float r_min[3], float r_max[3]) { - TransVertStore tvs = {NULL}; - TransVert *tv; - float centroid[3], vec[3], bmat[3][3]; - - /* Metaballs are an exception. */ - if (obedit->type == OB_MBALL) { - float ob_min[3], ob_max[3]; - bool changed; - - changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT); - if (changed) { - minmax_v3v3_v3(r_min, r_max, ob_min); - minmax_v3v3_v3(r_min, r_max, ob_max); - } - return changed; - } - - if (ED_transverts_check_obedit(obedit)) { - ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS); - } - - if (tvs.transverts_tot == 0) { - return false; - } - - copy_m3_m4(bmat, obedit->obmat); - - tv = tvs.transverts; - for (int a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc); - mul_m3_v3(bmat, vec); - add_v3_v3(vec, obedit->obmat[3]); - add_v3_v3(centroid, vec); - minmax_v3v3_v3(r_min, r_max, vec); - } - - ED_transverts_free(&tvs); - - return true; + TransVertStore tvs = {NULL}; + TransVert *tv; + float centroid[3], vec[3], bmat[3][3]; + + /* Metaballs are an exception. */ + if (obedit->type == OB_MBALL) { + float ob_min[3], ob_max[3]; + bool changed; + + changed = BKE_mball_minmax_ex(obedit->data, ob_min, ob_max, obedit->obmat, SELECT); + if (changed) { + minmax_v3v3_v3(r_min, r_max, ob_min); + minmax_v3v3_v3(r_min, r_max, ob_max); + } + return changed; + } + + if (ED_transverts_check_obedit(obedit)) { + ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS); + } + + if (tvs.transverts_tot == 0) { + return false; + } + + copy_m3_m4(bmat, obedit->obmat); + + tv = tvs.transverts; + for (int a = 0; a < tvs.transverts_tot; a++, tv++) { + copy_v3_v3(vec, (tv->flag & TX_VERT_USE_MAPLOC) ? tv->maploc : tv->loc); + mul_m3_v3(bmat, vec); + add_v3_v3(vec, obedit->obmat[3]); + add_v3_v3(centroid, vec); + minmax_v3v3_v3(r_min, r_max, vec); + } + + ED_transverts_free(&tvs); + + return true; } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index c96e524ec2b..9357d3e05ee 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -37,31 +37,31 @@ #include "ED_screen.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* ********** operator to open/close toolshelf region */ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { - ScrArea *sa = CTX_wm_area(C); - ARegion *ar = view3d_has_tools_region(sa); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = view3d_has_tools_region(sa); - if (ar) { - ED_region_toggle_hidden(C, ar); - } + if (ar) { + ED_region_toggle_hidden(C, ar); + } - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void VIEW3D_OT_toolshelf(wmOperatorType *ot) { - ot->name = "Toggle Toolbar"; - ot->description = "Toggles tool shelf display"; - ot->idname = "VIEW3D_OT_toolshelf"; + ot->name = "Toggle Toolbar"; + ot->description = "Toggles tool shelf display"; + ot->idname = "VIEW3D_OT_toolshelf"; - ot->exec = view3d_toolshelf_toggle_exec; - ot->poll = ED_operator_view3d_active; + ot->exec = view3d_toolshelf_toggle_exec; + ot->poll = ED_operator_view3d_active; - /* flags */ - ot->flag = 0; + /* flags */ + ot->flag = 0; } diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 0639bdaa71c..3f078e35046 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -63,7 +63,7 @@ #include "UI_resources.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name View Data Access Utilities @@ -72,115 +72,118 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float r_color[3]) { - if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { - if (scene->world) { - copy_v3_v3(r_color, &scene->world->horr); - return; - } - } - else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) { - copy_v3_v3(r_color, v3d->shading.background_color); - return; - } - - UI_GetThemeColor3fv(TH_BACK, r_color); + if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) { + if (scene->world) { + copy_v3_v3(r_color, &scene->world->horr); + return; + } + } + else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) { + copy_v3_v3(r_color, v3d->shading.background_color); + return; + } + + UI_GetThemeColor3fv(TH_BACK, r_color); } void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3]) { - const View3DCursor *cursor = &scene->cursor; - BKE_scene_cursor_rot_to_mat3(cursor, mat); + const View3DCursor *cursor = &scene->cursor; + BKE_scene_cursor_rot_to_mat3(cursor, mat); } void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4]) { - const View3DCursor *cursor = &scene->cursor; - float mat3[3][3]; - BKE_scene_cursor_rot_to_mat3(cursor, mat3); - copy_m4_m3(mat, mat3); - copy_v3_v3(mat[3], cursor->location); + const View3DCursor *cursor = &scene->cursor; + float mat3[3][3]; + BKE_scene_cursor_rot_to_mat3(cursor, mat3); + copy_m4_m3(mat, mat3); + copy_v3_v3(mat[3], cursor->location); } Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d) { - /* establish the camera object, - * so we can default to view mapping if anything is wrong with it */ - if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { - return v3d->camera->data; - } - else { - return NULL; - } + /* establish the camera object, + * so we can default to view mapping if anything is wrong with it */ + if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) { + return v3d->camera->data; + } + else { + return NULL; + } } -void ED_view3d_dist_range_get( - const View3D *v3d, - float r_dist_range[2]) +void ED_view3d_dist_range_get(const View3D *v3d, float r_dist_range[2]) { - r_dist_range[0] = v3d->grid * 0.001f; - r_dist_range[1] = v3d->clip_end * 10.0f; + r_dist_range[0] = v3d->grid * 0.001f; + r_dist_range[1] = v3d->clip_end * 10.0f; } /** * \note copies logic of #ED_view3d_viewplane_get(), keep in sync. */ -bool ED_view3d_clip_range_get( - Depsgraph *depsgraph, - const View3D *v3d, const RegionView3D *rv3d, - float *r_clipsta, float *r_clipend, - const bool use_ortho_factor) +bool ED_view3d_clip_range_get(Depsgraph *depsgraph, + const View3D *v3d, + const RegionView3D *rv3d, + float *r_clipsta, + float *r_clipend, + const bool use_ortho_factor) { - CameraParams params; + CameraParams params; - BKE_camera_params_init(¶ms); - BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); + BKE_camera_params_init(¶ms); + BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); - if (use_ortho_factor && params.is_ortho) { - const float fac = 2.0f / (params.clip_end - params.clip_start); - params.clip_start *= fac; - params.clip_end *= fac; - } + if (use_ortho_factor && params.is_ortho) { + const float fac = 2.0f / (params.clip_end - params.clip_start); + params.clip_start *= fac; + params.clip_end *= fac; + } - if (r_clipsta) { - *r_clipsta = params.clip_start; - } - if (r_clipend) { - *r_clipend = params.clip_end; - } + if (r_clipsta) { + *r_clipsta = params.clip_start; + } + if (r_clipend) { + *r_clipend = params.clip_end; + } - return params.is_ortho; + return params.is_ortho; } -bool ED_view3d_viewplane_get( - Depsgraph *depsgraph, - const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, - rctf *r_viewplane, float *r_clip_start, float *r_clip_end, float *r_pixsize) +bool ED_view3d_viewplane_get(Depsgraph *depsgraph, + const View3D *v3d, + const RegionView3D *rv3d, + int winx, + int winy, + rctf *r_viewplane, + float *r_clip_start, + float *r_clip_end, + float *r_pixsize) { - CameraParams params; - - BKE_camera_params_init(¶ms); - BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); - BKE_camera_params_compute_viewplane(¶ms, winx, winy, 1.0f, 1.0f); - - if (r_viewplane) { - *r_viewplane = params.viewplane; - } - if (r_clip_start) { - *r_clip_start = params.clip_start; - } - if (r_clip_end) { - *r_clip_end = params.clip_end; - } - if (r_pixsize) { - *r_pixsize = params.viewdx; - } - - return params.is_ortho; + CameraParams params; + + BKE_camera_params_init(¶ms); + BKE_camera_params_from_view3d(¶ms, depsgraph, v3d, rv3d); + BKE_camera_params_compute_viewplane(¶ms, winx, winy, 1.0f, 1.0f); + + if (r_viewplane) { + *r_viewplane = params.viewplane; + } + if (r_clip_start) { + *r_clip_start = params.clip_start; + } + if (r_clip_end) { + *r_clip_end = params.clip_end; + } + if (r_pixsize) { + *r_pixsize = params.viewdx; + } + + return params.is_ortho; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name View State/Context Utilities * @@ -192,25 +195,25 @@ bool ED_view3d_viewplane_get( */ void view3d_operator_needs_opengl(const bContext *C) { - wmWindow *win = CTX_wm_window(C); - ARegion *ar = CTX_wm_region(C); + wmWindow *win = CTX_wm_window(C); + ARegion *ar = CTX_wm_region(C); - view3d_region_operator_needs_opengl(win, ar); + view3d_region_operator_needs_opengl(win, ar); } void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar) { - /* for debugging purpose, context should always be OK */ - if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) { - printf("view3d_region_operator_needs_opengl error, wrong region\n"); - } - else { - RegionView3D *rv3d = ar->regiondata; - - wmViewport(&ar->winrct); // TODO: bad - GPU_matrix_projection_set(rv3d->winmat); - GPU_matrix_set(rv3d->viewmat); - } + /* for debugging purpose, context should always be OK */ + if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) { + printf("view3d_region_operator_needs_opengl error, wrong region\n"); + } + else { + RegionView3D *rv3d = ar->regiondata; + + wmViewport(&ar->winrct); // TODO: bad + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); + } } /** @@ -218,51 +221,51 @@ void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *ar) */ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) { - float viewdist; + float viewdist; - if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { - return; - } + if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { + return; + } - viewdist = rv3d->dist; + viewdist = rv3d->dist; - /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ - if (dist != 0.0f) { - if (rv3d->persp == RV3D_CAMOB) { - if (rv3d->is_persp == false) { - viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); - } - } - } + /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ + if (dist != 0.0f) { + if (rv3d->persp == RV3D_CAMOB) { + if (rv3d->is_persp == false) { + viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1])); + } + } + } - bglPolygonOffset(viewdist, dist); + bglPolygonOffset(viewdist, dist); } bool ED_view3d_context_activate(bContext *C) { - bScreen *sc = CTX_wm_screen(C); - ScrArea *sa = CTX_wm_area(C); - ARegion *ar; + bScreen *sc = CTX_wm_screen(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar; - /* sa can be NULL when called from python */ - if (sa == NULL || sa->spacetype != SPACE_VIEW3D) { - sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0); - } + /* sa can be NULL when called from python */ + if (sa == NULL || sa->spacetype != SPACE_VIEW3D) { + sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0); + } - if (sa == NULL) { - return false; - } + if (sa == NULL) { + return false; + } - ar = BKE_area_find_region_active_win(sa); - if (ar == NULL) { - return false; - } + ar = BKE_area_find_region_active_win(sa); + if (ar == NULL) { + return false; + } - /* bad context switch .. */ - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); + /* bad context switch .. */ + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); - return true; + return true; } /** \} */ @@ -272,51 +275,54 @@ bool ED_view3d_context_activate(bContext *C) * * \{ */ -void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) +void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], + const BoundBox *bb, + const bool is_flip) { - int val; + int val; - for (val = 0; val < 4; val++) { - normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); - if (UNLIKELY(is_flip)) { - negate_v3(clip[val]); - } + for (val = 0; val < 4; val++) { + normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); + if (UNLIKELY(is_flip)) { + negate_v3(clip[val]); + } - clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]); - } + clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]); + } } -void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect) +void ED_view3d_clipping_calc( + BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect) { - /* init in case unproject fails */ - memset(bb->vec, 0, sizeof(bb->vec)); - - /* four clipping planes and bounding volume */ - /* first do the bounding volume */ - for (int val = 0; val < 4; val++) { - float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; - float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; - - ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]); - ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]); - } - - /* optionally transform to object space */ - if (ob) { - float imat[4][4]; - invert_m4_m4(imat, ob->obmat); - - for (int val = 0; val < 8; val++) { - mul_m4_v3(imat, bb->vec[val]); - } - } - - /* verify if we have negative scale. doing the transform before cross - * product flips the sign of the vector compared to doing cross product - * before transform then, so we correct for that. */ - int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false; - - ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); + /* init in case unproject fails */ + memset(bb->vec, 0, sizeof(bb->vec)); + + /* four clipping planes and bounding volume */ + /* first do the bounding volume */ + for (int val = 0; val < 4; val++) { + float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax; + float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax; + + ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]); + ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]); + } + + /* optionally transform to object space */ + if (ob) { + float imat[4][4]; + invert_m4_m4(imat, ob->obmat); + + for (int val = 0; val < 8; val++) { + mul_m4_v3(imat, bb->vec[val]); + } + } + + /* verify if we have negative scale. doing the transform before cross + * product flips the sign of the vector compared to doing cross product + * before transform then, so we correct for that. */ + int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false; + + ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign); } /** \} */ @@ -328,73 +334,73 @@ void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4]) { - int a, flag = -1, fl; - - for (a = 0; a < 8; a++) { - float vec[4], min, max; - copy_v3_v3(vec, bb->vec[a]); - vec[3] = 1.0; - mul_m4_v4(persmatob, vec); - max = vec[3]; - min = -vec[3]; - - fl = 0; - if (vec[0] < min) { - fl += 1; - } - if (vec[0] > max) { - fl += 2; - } - if (vec[1] < min) { - fl += 4; - } - if (vec[1] > max) { - fl += 8; - } - if (vec[2] < min) { - fl += 16; - } - if (vec[2] > max) { - fl += 32; - } - - flag &= fl; - if (flag == 0) { - return true; - } - } - - return false; + int a, flag = -1, fl; + + for (a = 0; a < 8; a++) { + float vec[4], min, max; + copy_v3_v3(vec, bb->vec[a]); + vec[3] = 1.0; + mul_m4_v4(persmatob, vec); + max = vec[3]; + min = -vec[3]; + + fl = 0; + if (vec[0] < min) { + fl += 1; + } + if (vec[0] > max) { + fl += 2; + } + if (vec[1] < min) { + fl += 4; + } + if (vec[1] > max) { + fl += 8; + } + if (vec[2] < min) { + fl += 16; + } + if (vec[2] > max) { + fl += 32; + } + + flag &= fl; + if (flag == 0) { + return true; + } + } + + return false; } bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) { - /* return 1: draw */ + /* return 1: draw */ - float persmatob[4][4]; + float persmatob[4][4]; - if (bb == NULL) { - return true; - } - if (bb->flag & BOUNDBOX_DISABLED) { - return true; - } + if (bb == NULL) { + return true; + } + if (bb->flag & BOUNDBOX_DISABLED) { + return true; + } - mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); + mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); - return view3d_boundbox_clip_m4(bb, persmatob); + return view3d_boundbox_clip_m4(bb, persmatob); } bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb) { - if (bb == NULL) { - return true; - } - if (bb->flag & BOUNDBOX_DISABLED) { - return true; - } - - return view3d_boundbox_clip_m4(bb, rv3d->persmatob); + if (bb == NULL) { + return true; + } + if (bb->flag & BOUNDBOX_DISABLED) { + return true; + } + + return view3d_boundbox_clip_m4(bb, rv3d->persmatob); } /** \} */ @@ -405,9 +411,9 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb) * Misc view utility functions. * \{ */ -bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) +bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) { - return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); + return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); } /** @@ -415,19 +421,19 @@ bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) */ void ED_view3d_lastview_store(RegionView3D *rv3d) { - copy_qt_qt(rv3d->lviewquat, rv3d->viewquat); - rv3d->lview = rv3d->view; - if (rv3d->persp != RV3D_CAMOB) { - rv3d->lpersp = rv3d->persp; - } + copy_qt_qt(rv3d->lviewquat, rv3d->viewquat); + rv3d->lview = rv3d->view; + if (rv3d->persp != RV3D_CAMOB) { + rv3d->lpersp = rv3d->persp; + } } void ED_view3d_lock_clear(View3D *v3d) { - v3d->ob_centre = NULL; - v3d->ob_centre_bone[0] = '\0'; - v3d->ob_centre_cursor = false; - v3d->flag2 &= ~V3D_LOCK_CAMERA; + v3d->ob_centre = NULL; + v3d->ob_centre_bone[0] = '\0'; + v3d->ob_centre_cursor = false; + v3d->flag2 &= ~V3D_LOCK_CAMERA; } /** @@ -437,20 +443,23 @@ void ED_view3d_lock_clear(View3D *v3d) * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera, * otherwise switching out of camera view may jump to a different part of the scene. */ -void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const char persp) +void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, + View3D *v3d, + RegionView3D *rv3d, + const char persp) { - BLI_assert(rv3d->persp == RV3D_CAMOB); - BLI_assert(persp != RV3D_CAMOB); - - if (v3d->camera) { - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); - ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); - } - - if (!ED_view3d_camera_lock_check(v3d, rv3d)) { - rv3d->persp = persp; - } + BLI_assert(rv3d->persp == RV3D_CAMOB); + BLI_assert(persp != RV3D_CAMOB); + + if (v3d->camera) { + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); + } + + if (!ED_view3d_camera_lock_check(v3d, rv3d)) { + rv3d->persp = persp; + } } /** * Action to take when rotating the view, @@ -460,29 +469,29 @@ void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, */ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; - const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0; - - BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); - - if (ED_view3d_camera_lock_check(v3d, rv3d)) { - return false; - } - - if (rv3d->persp != RV3D_PERSP) { - if (rv3d->persp == RV3D_CAMOB) { - /* If autopersp and previous view was an axis one, - * switch back to PERSP mode, else reuse previous mode. */ - char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp; - ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp); - } - else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) { - rv3d->persp = RV3D_PERSP; - } - return true; - } - - return false; + RegionView3D *rv3d = ar->regiondata; + const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0; + + BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); + + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + return false; + } + + if (rv3d->persp != RV3D_PERSP) { + if (rv3d->persp == RV3D_CAMOB) { + /* If autopersp and previous view was an axis one, + * switch back to PERSP mode, else reuse previous mode. */ + char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp; + ED_view3d_persp_switch_from_camera(depsgraph, v3d, rv3d, persp); + } + else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) { + rv3d->persp = RV3D_PERSP; + } + return true; + } + + return false; } /** \} */ @@ -498,31 +507,33 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *ar */ bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d) { - return ((v3d->camera) && - (!ID_IS_LINKED(v3d->camera)) && - (v3d->flag2 & V3D_LOCK_CAMERA) && - (rv3d->persp == RV3D_CAMOB)); + return ((v3d->camera) && (!ID_IS_LINKED(v3d->camera)) && (v3d->flag2 & V3D_LOCK_CAMERA) && + (rv3d->persp == RV3D_CAMOB)); } /** * Apply the camera object transformation to the view-port. * (needed so we can use regular view-port manipulation operators, that sync back to the camera). */ -void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, const bool calc_dist) +void ED_view3d_camera_lock_init_ex(const Depsgraph *depsgraph, + View3D *v3d, + RegionView3D *rv3d, + const bool calc_dist) { - if (ED_view3d_camera_lock_check(v3d, rv3d)) { - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - if (calc_dist) { - /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */ - rv3d->dist = ED_view3d_offset_distance(ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); - } - ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); - } + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + if (calc_dist) { + /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */ + rv3d->dist = ED_view3d_offset_distance( + ob_camera_eval->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + } + ED_view3d_from_object(ob_camera_eval, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); + } } void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d) { - ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true); + ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, true); } /** @@ -532,95 +543,95 @@ void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionV */ bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d) { - if (ED_view3d_camera_lock_check(v3d, rv3d)) { - ObjectTfmProtectedChannels obtfm; - Object *root_parent; - - if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) { - Object *ob_update; - float tmat[4][4]; - float imat[4][4]; - float view_mat[4][4]; - float diff_mat[4][4]; - float parent_mat[4][4]; - - while (root_parent->parent) { - root_parent = root_parent->parent; - } - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent); - - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - - normalize_m4_m4(tmat, ob_camera_eval->obmat); - - invert_m4_m4(imat, tmat); - mul_m4_m4m4(diff_mat, view_mat, imat); - - mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat); - - BKE_object_tfm_protected_backup(root_parent, &obtfm); - BKE_object_apply_mat4(root_parent, parent_mat, true, false); - BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag); - - ob_update = v3d->camera; - while (ob_update) { - DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM); - WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update); - ob_update = ob_update->parent; - } - } - else { - /* always maintain the same scale */ - const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ); - BKE_object_tfm_protected_backup(v3d->camera, &obtfm); - ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); - BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all); - - DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); - WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera); - } - - return true; - } - else { - return false; - } + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + ObjectTfmProtectedChannels obtfm; + Object *root_parent; + + if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) { + Object *ob_update; + float tmat[4][4]; + float imat[4][4]; + float view_mat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; + + while (root_parent->parent) { + root_parent = root_parent->parent; + } + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + Object *root_parent_eval = DEG_get_evaluated_object(depsgraph, root_parent); + + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + + normalize_m4_m4(tmat, ob_camera_eval->obmat); + + invert_m4_m4(imat, tmat); + mul_m4_m4m4(diff_mat, view_mat, imat); + + mul_m4_m4m4(parent_mat, diff_mat, root_parent_eval->obmat); + + BKE_object_tfm_protected_backup(root_parent, &obtfm); + BKE_object_apply_mat4(root_parent, parent_mat, true, false); + BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag); + + ob_update = v3d->camera; + while (ob_update) { + DEG_id_tag_update(&ob_update->id, ID_RECALC_TRANSFORM); + WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update); + ob_update = ob_update->parent; + } + } + else { + /* always maintain the same scale */ + const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ); + BKE_object_tfm_protected_backup(v3d->camera, &obtfm); + ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); + BKE_object_tfm_protected_restore( + v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all); + + DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); + WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera); + } + + return true; + } + else { + return false; + } } bool ED_view3d_camera_autokey( - Scene *scene, ID *id_key, - struct bContext *C, const bool do_rotate, const bool do_translate) + Scene *scene, ID *id_key, struct bContext *C, const bool do_rotate, const bool do_translate) { - if (autokeyframe_cfra_can_key(scene, id_key)) { - const float cfra = (float)CFRA; - ListBase dsources = {NULL, NULL}; - - /* add data-source override for the camera object */ - ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); - - /* insert keyframes - * 1) on the first frame - * 2) on each subsequent frame - * TODO: need to check in future that frame changed before doing this - */ - if (do_rotate) { - struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); - } - if (do_translate) { - struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); - } - - /* free temp data */ - BLI_freelistN(&dsources); - - return true; - } - else { - return false; - } + if (autokeyframe_cfra_can_key(scene, id_key)) { + const float cfra = (float)CFRA; + ListBase dsources = {NULL, NULL}; + + /* add data-source override for the camera object */ + ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); + + /* insert keyframes + * 1) on the first frame + * 2) on each subsequent frame + * TODO: need to check in future that frame changed before doing this + */ + if (do_rotate) { + struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + if (do_translate) { + struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + + /* free temp data */ + BLI_freelistN(&dsources); + + return true; + } + else { + return false; + } } /** @@ -629,36 +640,36 @@ bool ED_view3d_camera_autokey( * \note Not every view edit currently auto-keys (numpad for eg), * this is complicated because of smoothview. */ -bool ED_view3d_camera_lock_autokey( - View3D *v3d, RegionView3D *rv3d, - struct bContext *C, const bool do_rotate, const bool do_translate) +bool ED_view3d_camera_lock_autokey(View3D *v3d, + RegionView3D *rv3d, + struct bContext *C, + const bool do_rotate, + const bool do_translate) { - /* similar to ED_view3d_cameracontrol_update */ - if (ED_view3d_camera_lock_check(v3d, rv3d)) { - Scene *scene = CTX_data_scene(C); - ID *id_key; - Object *root_parent; - if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) { - while (root_parent->parent) { - root_parent = root_parent->parent; - } - id_key = &root_parent->id; - } - else { - id_key = &v3d->camera->id; - } - - return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate); - } - else { - return false; - } + /* similar to ED_view3d_cameracontrol_update */ + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + Scene *scene = CTX_data_scene(C); + ID *id_key; + Object *root_parent; + if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) { + while (root_parent->parent) { + root_parent = root_parent->parent; + } + id_key = &root_parent->id; + } + else { + id_key = &v3d->camera->id; + } + + return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate); + } + else { + return false; + } } /** \} */ - - /* -------------------------------------------------------------------- */ /** \name Box View Support * @@ -667,100 +678,100 @@ bool ED_view3d_camera_lock_autokey( static void view3d_boxview_clip(ScrArea *sa) { - ARegion *ar; - BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); - float clip[6][4]; - float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; - int val; - - /* create bounding box */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->viewlock & RV3D_BOXCLIP) { - if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { - if (ar->winx > ar->winy) { - x1 = rv3d->dist; - } - else { - x1 = ar->winx * rv3d->dist / ar->winy; - } - - if (ar->winx > ar->winy) { - y1 = ar->winy * rv3d->dist / ar->winx; - } - else { - y1 = rv3d->dist; - } - copy_v2_v2(ofs, rv3d->ofs); - } - else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { - ofs[2] = rv3d->ofs[2]; - - if (ar->winx > ar->winy) { - z1 = ar->winy * rv3d->dist / ar->winx; - } - else { - z1 = rv3d->dist; - } - } - } - } - } - - for (val = 0; val < 8; val++) { - if (ELEM(val, 0, 3, 4, 7)) { - bb->vec[val][0] = -x1 - ofs[0]; - } - else { - bb->vec[val][0] = x1 - ofs[0]; - } - - if (ELEM(val, 0, 1, 4, 5)) { - bb->vec[val][1] = -y1 - ofs[1]; - } - else { - bb->vec[val][1] = y1 - ofs[1]; - } - - if (val > 3) { - bb->vec[val][2] = -z1 - ofs[2]; - } - else { - bb->vec[val][2] = z1 - ofs[2]; - } - } - - /* normals for plane equations */ - normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]); - normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]); - normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]); - normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]); - normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]); - normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]); - - /* then plane equations */ - for (val = 0; val < 6; val++) { - clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]); - } - - /* create bounding box */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->viewlock & RV3D_BOXCLIP) { - rv3d->rflag |= RV3D_CLIPPING; - memcpy(rv3d->clip, clip, sizeof(clip)); - if (rv3d->clipbb) { - MEM_freeN(rv3d->clipbb); - } - rv3d->clipbb = MEM_dupallocN(bb); - } - } - } - MEM_freeN(bb); + ARegion *ar; + BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); + float clip[6][4]; + float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; + int val; + + /* create bounding box */ + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->viewlock & RV3D_BOXCLIP) { + if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) { + if (ar->winx > ar->winy) { + x1 = rv3d->dist; + } + else { + x1 = ar->winx * rv3d->dist / ar->winy; + } + + if (ar->winx > ar->winy) { + y1 = ar->winy * rv3d->dist / ar->winx; + } + else { + y1 = rv3d->dist; + } + copy_v2_v2(ofs, rv3d->ofs); + } + else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) { + ofs[2] = rv3d->ofs[2]; + + if (ar->winx > ar->winy) { + z1 = ar->winy * rv3d->dist / ar->winx; + } + else { + z1 = rv3d->dist; + } + } + } + } + } + + for (val = 0; val < 8; val++) { + if (ELEM(val, 0, 3, 4, 7)) { + bb->vec[val][0] = -x1 - ofs[0]; + } + else { + bb->vec[val][0] = x1 - ofs[0]; + } + + if (ELEM(val, 0, 1, 4, 5)) { + bb->vec[val][1] = -y1 - ofs[1]; + } + else { + bb->vec[val][1] = y1 - ofs[1]; + } + + if (val > 3) { + bb->vec[val][2] = -z1 - ofs[2]; + } + else { + bb->vec[val][2] = z1 - ofs[2]; + } + } + + /* normals for plane equations */ + normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]); + normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]); + normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]); + normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]); + normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]); + normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]); + + /* then plane equations */ + for (val = 0; val < 6; val++) { + clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]); + } + + /* create bounding box */ + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->viewlock & RV3D_BOXCLIP) { + rv3d->rflag |= RV3D_CLIPPING; + memcpy(rv3d->clip, clip, sizeof(clip)); + if (rv3d->clipbb) { + MEM_freeN(rv3d->clipbb); + } + rv3d->clipbb = MEM_dupallocN(bb); + } + } + } + MEM_freeN(bb); } /** @@ -769,161 +780,156 @@ static void view3d_boxview_clip(ScrArea *sa) */ static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src) { - /* absolute axis values above this are considered to be set (will be ~1.0f) */ - const float axis_eps = 0.5f; - float viewinv[4]; - - /* use the view rotation to identify which axis to sync on */ - float view_axis_all[4][3] = { - {1.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}, - {1.0f, 0.0f, 0.0f}, - {0.0f, 1.0f, 0.0f}}; - - float *view_src_x = &view_axis_all[0][0]; - float *view_src_y = &view_axis_all[1][0]; - - float *view_dst_x = &view_axis_all[2][0]; - float *view_dst_y = &view_axis_all[3][0]; - int i; - - - /* we could use rv3d->viewinv, but better not depend on view matrix being updated */ - if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) { - return; - } - invert_qt_normalized(viewinv); - mul_qt_v3(viewinv, view_src_x); - mul_qt_v3(viewinv, view_src_y); - - if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) { - return; - } - invert_qt_normalized(viewinv); - mul_qt_v3(viewinv, view_dst_x); - mul_qt_v3(viewinv, view_dst_y); - - /* check source and dest have a matching axis */ - for (i = 0; i < 3; i++) { - if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) && - ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps))) - { - rv3d_dst->ofs[i] = rv3d_src->ofs[i]; - } - } + /* absolute axis values above this are considered to be set (will be ~1.0f) */ + const float axis_eps = 0.5f; + float viewinv[4]; + + /* use the view rotation to identify which axis to sync on */ + float view_axis_all[4][3] = { + {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}}; + + float *view_src_x = &view_axis_all[0][0]; + float *view_src_y = &view_axis_all[1][0]; + + float *view_dst_x = &view_axis_all[2][0]; + float *view_dst_y = &view_axis_all[3][0]; + int i; + + /* we could use rv3d->viewinv, but better not depend on view matrix being updated */ + if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) { + return; + } + invert_qt_normalized(viewinv); + mul_qt_v3(viewinv, view_src_x); + mul_qt_v3(viewinv, view_src_y); + + if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) { + return; + } + invert_qt_normalized(viewinv); + mul_qt_v3(viewinv, view_dst_x); + mul_qt_v3(viewinv, view_dst_y); + + /* check source and dest have a matching axis */ + for (i = 0; i < 3; i++) { + if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) && + ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps))) { + rv3d_dst->ofs[i] = rv3d_src->ofs[i]; + } + } } /* sync center/zoom view of region to others, for view transforms */ void view3d_boxview_sync(ScrArea *sa, ARegion *ar) { - ARegion *artest; - RegionView3D *rv3d = ar->regiondata; - short clip = 0; - - for (artest = sa->regionbase.first; artest; artest = artest->next) { - if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3dtest = artest->regiondata; - - if (rv3dtest->viewlock & RV3D_LOCKED) { - rv3dtest->dist = rv3d->dist; - view3d_boxview_sync_axis(rv3dtest, rv3d); - clip |= rv3dtest->viewlock & RV3D_BOXCLIP; - - ED_region_tag_redraw(artest); - } - } - } - - if (clip) { - view3d_boxview_clip(sa); - } + ARegion *artest; + RegionView3D *rv3d = ar->regiondata; + short clip = 0; + + for (artest = sa->regionbase.first; artest; artest = artest->next) { + if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3dtest = artest->regiondata; + + if (rv3dtest->viewlock & RV3D_LOCKED) { + rv3dtest->dist = rv3d->dist; + view3d_boxview_sync_axis(rv3dtest, rv3d); + clip |= rv3dtest->viewlock & RV3D_BOXCLIP; + + ED_region_tag_redraw(artest); + } + } + } + + if (clip) { + view3d_boxview_clip(sa); + } } /* for home, center etc */ void view3d_boxview_copy(ScrArea *sa, ARegion *ar) { - ARegion *artest; - RegionView3D *rv3d = ar->regiondata; - bool clip = false; - - for (artest = sa->regionbase.first; artest; artest = artest->next) { - if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3dtest = artest->regiondata; - - if (rv3dtest->viewlock) { - rv3dtest->dist = rv3d->dist; - copy_v3_v3(rv3dtest->ofs, rv3d->ofs); - ED_region_tag_redraw(artest); - - clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0); - } - } - } - - if (clip) { - view3d_boxview_clip(sa); - } + ARegion *artest; + RegionView3D *rv3d = ar->regiondata; + bool clip = false; + + for (artest = sa->regionbase.first; artest; artest = artest->next) { + if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3dtest = artest->regiondata; + + if (rv3dtest->viewlock) { + rv3dtest->dist = rv3d->dist; + copy_v3_v3(rv3dtest->ofs, rv3d->ofs); + ED_region_tag_redraw(artest); + + clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0); + } + } + } + + if (clip) { + view3d_boxview_clip(sa); + } } /* 'clip' is used to know if our clip setting has changed */ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) { - ARegion *ar_sync = NULL; - RegionView3D *rv3d = ar->regiondata; - short viewlock; - /* this function copies flags from the first of the 3 other quadview - * regions to the 2 other, so it assumes this is the region whose - * properties are always being edited, weak */ - viewlock = rv3d->viewlock; - - if ((viewlock & RV3D_LOCKED) == 0) { - do_clip = (viewlock & RV3D_BOXCLIP) != 0; - viewlock = 0; - } - else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) { - do_clip = true; - viewlock &= ~RV3D_BOXCLIP; - } - - for (; ar; ar = ar->prev) { - if (ar->alignment == RGN_ALIGN_QSPLIT) { - rv3d = ar->regiondata; - rv3d->viewlock = viewlock; - - if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) { - rv3d->rflag &= ~RV3D_BOXCLIP; - } - - /* use ar_sync so we sync with one of the aligned views below - * else the view jumps on changing view settings like 'clip' - * since it copies from the perspective view */ - ar_sync = ar; - } - } - - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last); - } - - /* ensure locked regions have an axis, locked user views don't make much sense */ - if (viewlock & RV3D_LOCKED) { - int index_qsplit = 0; - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->alignment == RGN_ALIGN_QSPLIT) { - rv3d = ar->regiondata; - if (rv3d->viewlock) { - if (!RV3D_VIEW_IS_AXIS(rv3d->view)) { - rv3d->view = ED_view3d_lock_view_from_index(index_qsplit); - rv3d->persp = RV3D_ORTHO; - ED_view3d_lock(rv3d); - } - } - index_qsplit++; - } - } - } - - ED_area_tag_redraw(sa); + ARegion *ar_sync = NULL; + RegionView3D *rv3d = ar->regiondata; + short viewlock; + /* this function copies flags from the first of the 3 other quadview + * regions to the 2 other, so it assumes this is the region whose + * properties are always being edited, weak */ + viewlock = rv3d->viewlock; + + if ((viewlock & RV3D_LOCKED) == 0) { + do_clip = (viewlock & RV3D_BOXCLIP) != 0; + viewlock = 0; + } + else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) { + do_clip = true; + viewlock &= ~RV3D_BOXCLIP; + } + + for (; ar; ar = ar->prev) { + if (ar->alignment == RGN_ALIGN_QSPLIT) { + rv3d = ar->regiondata; + rv3d->viewlock = viewlock; + + if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) { + rv3d->rflag &= ~RV3D_BOXCLIP; + } + + /* use ar_sync so we sync with one of the aligned views below + * else the view jumps on changing view settings like 'clip' + * since it copies from the perspective view */ + ar_sync = ar; + } + } + + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last); + } + + /* ensure locked regions have an axis, locked user views don't make much sense */ + if (viewlock & RV3D_LOCKED) { + int index_qsplit = 0; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->alignment == RGN_ALIGN_QSPLIT) { + rv3d = ar->regiondata; + if (rv3d->viewlock) { + if (!RV3D_VIEW_IS_AXIS(rv3d->view)) { + rv3d->view = ED_view3d_lock_view_from_index(index_qsplit); + rv3d->persp = RV3D_ORTHO; + ED_view3d_lock(rv3d); + } + } + index_qsplit++; + } + } + } + + ED_area_tag_redraw(sa); } /** \} */ @@ -934,25 +940,25 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin) { - ViewDepths depth_temp = {0}; - rcti rect; - float depth_close; - - if (margin == 0) { - /* Get Z Depths, needed for perspective, nice for ortho */ - rect.xmin = mval[0]; - rect.ymin = mval[1]; - rect.xmax = mval[0] + 1; - rect.ymax = mval[1] + 1; - } - else { - BLI_rcti_init_pt_radius(&rect, mval, margin); - } - - view3d_update_depths_rect(ar, &depth_temp, &rect); - depth_close = view3d_depth_near(&depth_temp); - MEM_SAFE_FREE(depth_temp.depths); - return depth_close; + ViewDepths depth_temp = {0}; + rcti rect; + float depth_close; + + if (margin == 0) { + /* Get Z Depths, needed for perspective, nice for ortho */ + rect.xmin = mval[0]; + rect.ymin = mval[1]; + rect.xmax = mval[0] + 1; + rect.ymax = mval[1] + 1; + } + else { + BLI_rcti_init_pt_radius(&rect, mval, margin); + } + + view3d_update_depths_rect(ar, &depth_temp, &rect); + depth_close = view3d_depth_near(&depth_temp); + MEM_SAFE_FREE(depth_temp.depths); + return depth_close; } /** @@ -962,131 +968,139 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg * \param mouse_worldloc: Output world-space location. * \param fallback_depth_pt: Use this points depth when no depth can be found. */ -bool ED_view3d_autodist( - Depsgraph *depsgraph, ARegion *ar, View3D *v3d, - const int mval[2], float mouse_worldloc[3], - const bool alphaoverride, const float fallback_depth_pt[3]) +bool ED_view3d_autodist(Depsgraph *depsgraph, + ARegion *ar, + View3D *v3d, + const int mval[2], + float mouse_worldloc[3], + const bool alphaoverride, + const float fallback_depth_pt[3]) { - float depth_close; - int margin_arr[] = {0, 2, 4}; - int i; - bool depth_ok = false; - - /* Get Z Depths, needed for perspective, nice for ortho */ - ED_view3d_draw_depth(depsgraph, ar, v3d, alphaoverride); - - /* Attempt with low margin's first */ - i = 0; - do { - depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize); - depth_ok = (depth_close != FLT_MAX); - } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); - - if (depth_ok) { - float centx = (float)mval[0] + 0.5f; - float centy = (float)mval[1] + 0.5f; - - if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) { - return true; - } - } - - if (fallback_depth_pt) { - ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc); - return true; - } - else { - return false; - } + float depth_close; + int margin_arr[] = {0, 2, 4}; + int i; + bool depth_ok = false; + + /* Get Z Depths, needed for perspective, nice for ortho */ + ED_view3d_draw_depth(depsgraph, ar, v3d, alphaoverride); + + /* Attempt with low margin's first */ + i = 0; + do { + depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize); + depth_ok = (depth_close != FLT_MAX); + } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr))); + + if (depth_ok) { + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + + if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) { + return true; + } + } + + if (fallback_depth_pt) { + ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc); + return true; + } + else { + return false; + } } -void ED_view3d_autodist_init(Depsgraph *depsgraph, - ARegion *ar, View3D *v3d, int mode) +void ED_view3d_autodist_init(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, int mode) { - /* Get Z Depths, needed for perspective, nice for ortho */ - switch (mode) { - case 0: - ED_view3d_draw_depth(depsgraph, ar, v3d, true); - break; - case 1: - { - Scene *scene = DEG_get_evaluated_scene(depsgraph); - ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d); - break; - } - } + /* Get Z Depths, needed for perspective, nice for ortho */ + switch (mode) { + case 0: + ED_view3d_draw_depth(depsgraph, ar, v3d, true); + break; + case 1: { + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ED_view3d_draw_depth_gpencil(depsgraph, scene, ar, v3d); + break; + } + } } /* no 4x4 sampling, run #ED_view3d_autodist_init first */ -bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3], - int margin, float *force_depth) +bool ED_view3d_autodist_simple( + ARegion *ar, const int mval[2], float mouse_worldloc[3], int margin, float *force_depth) { - float depth; - - /* Get Z Depths, needed for perspective, nice for ortho */ - if (force_depth) { - depth = *force_depth; - } - else { - depth = view_autodist_depth_margin(ar, mval, margin); - } - - if (depth == FLT_MAX) { - return false; - } - - float centx = (float)mval[0] + 0.5f; - float centy = (float)mval[1] + 0.5f; - return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc); + float depth; + + /* Get Z Depths, needed for perspective, nice for ortho */ + if (force_depth) { + depth = *force_depth; + } + else { + depth = view_autodist_depth_margin(ar, mval, margin); + } + + if (depth == FLT_MAX) { + return false; + } + + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc); } bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth) { - *depth = view_autodist_depth_margin(ar, mval, margin); + *depth = view_autodist_depth_margin(ar, mval, margin); - return (*depth != FLT_MAX); + return (*depth != FLT_MAX); } static bool depth_segment_cb(int x, int y, void *userData) { - struct { ARegion *ar; int margin; float depth; } *data = userData; - int mval[2]; - float depth; - - mval[0] = x; - mval[1] = y; - - depth = view_autodist_depth_margin(data->ar, mval, data->margin); - - if (depth != FLT_MAX) { - data->depth = depth; - return 0; - } - else { - return 1; - } + struct { + ARegion *ar; + int margin; + float depth; + } *data = userData; + int mval[2]; + float depth; + + mval[0] = x; + mval[1] = y; + + depth = view_autodist_depth_margin(data->ar, mval, data->margin); + + if (depth != FLT_MAX) { + data->depth = depth; + return 0; + } + else { + return 1; + } } bool ED_view3d_autodist_depth_seg( - ARegion *ar, const int mval_sta[2], const int mval_end[2], - int margin, float *depth) + ARegion *ar, const int mval_sta[2], const int mval_end[2], int margin, float *depth) { - struct { ARegion *ar; int margin; float depth; } data = {NULL}; - int p1[2]; - int p2[2]; + struct { + ARegion *ar; + int margin; + float depth; + } data = {NULL}; + int p1[2]; + int p2[2]; - data.ar = ar; - data.margin = margin; - data.depth = FLT_MAX; + data.ar = ar; + data.margin = margin; + data.depth = FLT_MAX; - copy_v2_v2_int(p1, mval_sta); - copy_v2_v2_int(p2, mval_end); + copy_v2_v2_int(p1, mval_sta); + copy_v2_v2_int(p2, mval_end); - BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data); + BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data); - *depth = data.depth; + *depth = data.depth; - return (*depth != FLT_MAX); + return (*depth != FLT_MAX); } /** \} */ @@ -1099,12 +1113,12 @@ bool ED_view3d_autodist_depth_seg( float ED_view3d_radius_to_dist_persp(const float angle, const float radius) { - return radius * (1.0f / tanf(angle / 2.0f)); + return radius * (1.0f / tanf(angle / 2.0f)); } float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) { - return radius / (DEFAULT_SENSOR_WIDTH / lens); + return radius / (DEFAULT_SENSOR_WIDTH / lens); } /** @@ -1131,78 +1145,79 @@ float ED_view3d_radius_to_dist_ortho(const float lens, const float radius) * \param use_aspect: Increase the distance to account for non 1:1 view aspect. * \param radius: The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN). */ -float ED_view3d_radius_to_dist( - const View3D *v3d, const ARegion *ar, - const struct Depsgraph *depsgraph, - const char persp, const bool use_aspect, - const float radius) +float ED_view3d_radius_to_dist(const View3D *v3d, + const ARegion *ar, + const struct Depsgraph *depsgraph, + const char persp, + const bool use_aspect, + const float radius) { - float dist; - - BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB)); - BLI_assert((persp != RV3D_CAMOB) || v3d->camera); - - if (persp == RV3D_ORTHO) { - dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius); - } - else { - float lens, sensor_size, zoom; - float angle; - - if (persp == RV3D_CAMOB) { - CameraParams params; - BKE_camera_params_init(¶ms); - params.clip_start = v3d->clip_start; - params.clip_end = v3d->clip_end; - Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - BKE_camera_params_from_object(¶ms, camera_eval); - - lens = params.lens; - sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); - - /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */ - zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB; - } - else { - lens = v3d->lens; - sensor_size = DEFAULT_SENSOR_WIDTH; - zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; - } - - angle = focallength_to_fov(lens, sensor_size); - - /* zoom influences lens, correct this by scaling the angle as a distance - * (by the zoom-level) */ - angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f; - - dist = ED_view3d_radius_to_dist_persp(angle, radius); - } - - if (use_aspect) { - const RegionView3D *rv3d = ar->regiondata; - - float winx, winy; - - if (persp == RV3D_CAMOB) { - /* camera frame x/y in pixels */ - winx = ar->winx / rv3d->viewcamtexcofac[0]; - winy = ar->winy / rv3d->viewcamtexcofac[1]; - } - else { - winx = ar->winx; - winy = ar->winy; - } - - if (winx && winy) { - float aspect = winx / winy; - if (aspect < 1.0f) { - aspect = 1.0f / aspect; - } - dist *= aspect; - } - } - - return dist; + float dist; + + BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB)); + BLI_assert((persp != RV3D_CAMOB) || v3d->camera); + + if (persp == RV3D_ORTHO) { + dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius); + } + else { + float lens, sensor_size, zoom; + float angle; + + if (persp == RV3D_CAMOB) { + CameraParams params; + BKE_camera_params_init(¶ms); + params.clip_start = v3d->clip_start; + params.clip_end = v3d->clip_end; + Object *camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + BKE_camera_params_from_object(¶ms, camera_eval); + + lens = params.lens; + sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y); + + /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */ + zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB; + } + else { + lens = v3d->lens; + sensor_size = DEFAULT_SENSOR_WIDTH; + zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; + } + + angle = focallength_to_fov(lens, sensor_size); + + /* zoom influences lens, correct this by scaling the angle as a distance + * (by the zoom-level) */ + angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f; + + dist = ED_view3d_radius_to_dist_persp(angle, radius); + } + + if (use_aspect) { + const RegionView3D *rv3d = ar->regiondata; + + float winx, winy; + + if (persp == RV3D_CAMOB) { + /* camera frame x/y in pixels */ + winx = ar->winx / rv3d->viewcamtexcofac[0]; + winy = ar->winy / rv3d->viewcamtexcofac[1]; + } + else { + winx = ar->winx; + winy = ar->winy; + } + + if (winx && winy) { + float aspect = winx / winy; + if (aspect < 1.0f) { + aspect = 1.0f / aspect; + } + dist *= aspect; + } + } + + return dist; } /** \} */ @@ -1217,22 +1232,22 @@ float ED_view3d_radius_to_dist( */ float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist) { - float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f}; - float dist; + float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f}; + float dist; - mul_m4_v4(mat, pos); - add_v3_v3(pos, ofs); - mul_m4_v4(mat, dir); - normalize_v3(dir); + mul_m4_v4(mat, pos); + add_v3_v3(pos, ofs); + mul_m4_v4(mat, dir); + normalize_v3(dir); - dist = dot_v3v3(pos, dir); + dist = dot_v3v3(pos, dir); - if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { - dist = fallback_dist; - } + if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { + dist = fallback_dist; + } - return dist; + return dist; } /** @@ -1242,22 +1257,22 @@ float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float */ void ED_view3d_distance_set(RegionView3D *rv3d, const float dist) { - float viewinv[4]; - float tvec[3]; + float viewinv[4]; + float tvec[3]; - BLI_assert(dist >= 0.0f); + BLI_assert(dist >= 0.0f); - copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist); - /* rv3d->viewinv isn't always valid */ + copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist); + /* rv3d->viewinv isn't always valid */ #if 0 - mul_mat3_m4_v3(rv3d->viewinv, tvec); + mul_mat3_m4_v3(rv3d->viewinv, tvec); #else - invert_qt_qt_normalized(viewinv, rv3d->viewquat); - mul_qt_v3(viewinv, tvec); + invert_qt_qt_normalized(viewinv, rv3d->viewquat); + mul_qt_v3(viewinv, tvec); #endif - sub_v3_v3(rv3d->ofs, tvec); + sub_v3_v3(rv3d->ofs, tvec); - rv3d->dist = dist; + rv3d->dist = dist; } /** \} */ @@ -1266,70 +1281,77 @@ void ED_view3d_distance_set(RegionView3D *rv3d, const float dist) /** \name View Axis Utilities * \{ */ static float view3d_quat_axis[6][4] = { - {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */ - {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */ - {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */ - {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */ - {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */ - {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */ + {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */ + {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */ + {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */ + {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */ + {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */ + {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */ }; - bool ED_view3d_quat_from_axis_view(const char view, float quat[4]) { - if (RV3D_VIEW_IS_AXIS(view)) { - copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]); - return true; - } - else { - return false; - } + if (RV3D_VIEW_IS_AXIS(view)) { + copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]); + return true; + } + else { + return false; + } } char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon) { - /* quat values are all unit length */ + /* quat values are all unit length */ - char view; + char view; - for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { - if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) { - return view; - } - } + for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) { + if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) { + return view; + } + } - return RV3D_VIEW_USER; + return RV3D_VIEW_USER; } char ED_view3d_lock_view_from_index(int index) { - switch (index) { - case 0: return RV3D_VIEW_FRONT; - case 1: return RV3D_VIEW_TOP; - case 2: return RV3D_VIEW_RIGHT; - default: return RV3D_VIEW_USER; - } - + switch (index) { + case 0: + return RV3D_VIEW_FRONT; + case 1: + return RV3D_VIEW_TOP; + case 2: + return RV3D_VIEW_RIGHT; + default: + return RV3D_VIEW_USER; + } } char ED_view3d_axis_view_opposite(char view) { - switch (view) { - case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK; - case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT; - case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT; - case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT; - case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM; - case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP; - } - - return RV3D_VIEW_USER; + switch (view) { + case RV3D_VIEW_FRONT: + return RV3D_VIEW_BACK; + case RV3D_VIEW_BACK: + return RV3D_VIEW_FRONT; + case RV3D_VIEW_LEFT: + return RV3D_VIEW_RIGHT; + case RV3D_VIEW_RIGHT: + return RV3D_VIEW_LEFT; + case RV3D_VIEW_TOP: + return RV3D_VIEW_BOTTOM; + case RV3D_VIEW_BOTTOM: + return RV3D_VIEW_TOP; + } + + return RV3D_VIEW_USER; } - bool ED_view3d_lock(RegionView3D *rv3d) { - return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); + return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); } /** \} */ @@ -1348,28 +1370,28 @@ bool ED_view3d_lock(RegionView3D *rv3d) */ void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float *dist) { - float nmat[3][3]; + float nmat[3][3]; - /* dist depends on offset */ - BLI_assert(dist == NULL || ofs != NULL); + /* dist depends on offset */ + BLI_assert(dist == NULL || ofs != NULL); - copy_m3_m4(nmat, mat); - normalize_m3(nmat); + copy_m3_m4(nmat, mat); + normalize_m3(nmat); - /* Offset */ - if (ofs) { - negate_v3_v3(ofs, mat[3]); - } + /* Offset */ + if (ofs) { + negate_v3_v3(ofs, mat[3]); + } - /* Quat */ - if (quat) { - mat3_normalized_to_quat(quat, nmat); - invert_qt_normalized(quat); - } + /* Quat */ + if (quat) { + mat3_normalized_to_quat(quat, nmat); + invert_qt_normalized(quat); + } - if (ofs && dist) { - madd_v3_v3fl(ofs, nmat[2], *dist); - } + if (ofs && dist) { + madd_v3_v3fl(ofs, nmat[2], *dist); + } } /** @@ -1382,12 +1404,12 @@ void ED_view3d_from_m4(const float mat[4][4], float ofs[3], float quat[4], float */ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist) { - float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]}; - float dvec[3] = {0.0f, 0.0f, dist}; + float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]}; + float dvec[3] = {0.0f, 0.0f, dist}; - quat_to_mat4(mat, iviewquat); - mul_mat3_m4_v3(mat, dvec); - sub_v3_v3v3(mat[3], dvec, ofs); + quat_to_mat4(mat, iviewquat); + mul_mat3_m4_v3(mat, dvec); + sub_v3_v3v3(mat[3], dvec, ofs); } /** @@ -1400,15 +1422,15 @@ void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], c */ void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float *dist, float *lens) { - ED_view3d_from_m4(ob->obmat, ofs, quat, dist); + ED_view3d_from_m4(ob->obmat, ofs, quat, dist); - if (lens) { - CameraParams params; + if (lens) { + CameraParams params; - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, ob); - *lens = params.lens; - } + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, ob); + *lens = params.lens; + } } /** @@ -1419,13 +1441,17 @@ void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], float * \param quat: The view rotation, quaternion normally from RegionView3D.viewquat. * \param dist: The view distance from ofs, normally from RegionView3D.dist. */ -void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs[3], const float quat[4], const float dist) +void ED_view3d_to_object(const Depsgraph *depsgraph, + Object *ob, + const float ofs[3], + const float quat[4], + const float dist) { - float mat[4][4]; - ED_view3d_to_m4(mat, ofs, quat, dist); + float mat[4][4]; + ED_view3d_to_m4(mat, ofs, quat, dist); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_apply_mat4_ex(ob, mat, ob_eval->parent, ob_eval->parentinv, true); } /** \} */ @@ -1436,96 +1462,92 @@ void ED_view3d_to_object(const Depsgraph *depsgraph, Object *ob, const float ofs float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2]) { - ViewDepths *vd = vc->rv3d->depths; - - int x = mval[0]; - int y = mval[1]; - - if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) { - return vd->depths[y * vd->w + x]; - } - else { - BLI_assert(1.0 <= vd->depth_range[1]); - return 1.0f; - } + ViewDepths *vd = vc->rv3d->depths; + + int x = mval[0]; + int y = mval[1]; + + if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) { + return vd->depths[y * vd->w + x]; + } + else { + BLI_assert(1.0 <= vd->depth_range[1]); + return 1.0f; + } } -bool ED_view3d_depth_read_cached_normal( - const ViewContext *vc, const int mval[2], - float r_normal[3]) +bool ED_view3d_depth_read_cached_normal(const ViewContext *vc, + const int mval[2], + float r_normal[3]) { - /* Note: we could support passing in a radius. - * For now just read 9 pixels. */ - - /* pixels surrounding */ - bool depths_valid[9] = {false}; - float coords[9][3] = {{0}}; - - ARegion *ar = vc->ar; - const ViewDepths *depths = vc->rv3d->depths; - - for (int x = 0, i = 0; x < 2; x++) { - for (int y = 0; y < 2; y++) { - const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)}; - - const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs); - if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) { - depths_valid[i] = true; - } - } - i++; - } - } - - const int edges[2][6][2] = { - /* x edges */ - {{0, 1}, {1, 2}, - {3, 4}, {4, 5}, - {6, 7}, {7, 8}}, - /* y edges */ - {{0, 3}, {3, 6}, - {1, 4}, {4, 7}, - {2, 5}, {5, 8}}, - }; - - float cross[2][3] = {{0.0f}}; - - for (int i = 0; i < 6; i++) { - for (int axis = 0; axis < 2; axis++) { - if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) { - float delta[3]; - sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]); - add_v3_v3(cross[axis], delta); - } - } - } - - cross_v3_v3v3(r_normal, cross[0], cross[1]); - - if (normalize_v3(r_normal) != 0.0f) { - return true; - } - else { - return false; - } + /* Note: we could support passing in a radius. + * For now just read 9 pixels. */ + + /* pixels surrounding */ + bool depths_valid[9] = {false}; + float coords[9][3] = {{0}}; + + ARegion *ar = vc->ar; + const ViewDepths *depths = vc->rv3d->depths; + + for (int x = 0, i = 0; x < 2; x++) { + for (int y = 0; y < 2; y++) { + const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)}; + + const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs); + if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { + if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) { + depths_valid[i] = true; + } + } + i++; + } + } + + const int edges[2][6][2] = { + /* x edges */ + {{0, 1}, {1, 2}, {3, 4}, {4, 5}, {6, 7}, {7, 8}}, + /* y edges */ + {{0, 3}, {3, 6}, {1, 4}, {4, 7}, {2, 5}, {5, 8}}, + }; + + float cross[2][3] = {{0.0f}}; + + for (int i = 0; i < 6; i++) { + for (int axis = 0; axis < 2; axis++) { + if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) { + float delta[3]; + sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]); + add_v3_v3(cross[axis], delta); + } + } + } + + cross_v3_v3v3(r_normal, cross[0], cross[1]); + + if (normalize_v3(r_normal) != 0.0f) { + return true; + } + else { + return false; + } } -bool ED_view3d_depth_unproject( - const ARegion *ar, - const int mval[2], const double depth, - float r_location_world[3]) +bool ED_view3d_depth_unproject(const ARegion *ar, + const int mval[2], + const double depth, + float r_location_world[3]) { - float centx = (float)mval[0] + 0.5f; - float centy = (float)mval[1] + 0.5f; - return ED_view3d_unproject(ar, centx, centy, depth, r_location_world); + float centx = (float)mval[0] + 0.5f; + float centy = (float)mval[1] + 0.5f; + return ED_view3d_unproject(ar, centx, centy, depth, r_location_world); } void ED_view3d_depth_tag_update(RegionView3D *rv3d) { - if (rv3d->depths) { - rv3d->depths->damaged = true; - } + if (rv3d->depths) { + rv3d->depths->damaged = true; + } } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 4e5dddf4742..e313ed39c49 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -62,7 +62,7 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ /* -------------------------------------------------------------------- */ /** \name Smooth View Operator & Utilities @@ -73,371 +73,378 @@ /* This operator is one of the 'timer refresh' ones like animation playback */ struct SmoothView3DState { - float dist; - float lens; - float quat[4]; - float ofs[3]; + float dist; + float lens; + float quat[4]; + float ofs[3]; }; struct SmoothView3DStore { - /* source*/ - struct SmoothView3DState src; /* source */ - struct SmoothView3DState dst; /* destination */ - struct SmoothView3DState org; /* original */ + /* source*/ + struct SmoothView3DState src; /* source */ + struct SmoothView3DState dst; /* destination */ + struct SmoothView3DState org; /* original */ - bool to_camera; + bool to_camera; - bool use_dyn_ofs; - float dyn_ofs[3]; + bool use_dyn_ofs; + float dyn_ofs[3]; - /* When smooth-view is enabled, store the 'rv3d->view' here, - * assign back when the view motion is completed. */ - char org_view; + /* When smooth-view is enabled, store the 'rv3d->view' here, + * assign back when the view motion is completed. */ + char org_view; - double time_allowed; + double time_allowed; }; static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state, - const View3D *v3d, const RegionView3D *rv3d) + const View3D *v3d, + const RegionView3D *rv3d) { - copy_v3_v3(sms_state->ofs, rv3d->ofs); - copy_qt_qt(sms_state->quat, rv3d->viewquat); - sms_state->dist = rv3d->dist; - sms_state->lens = v3d->lens; + copy_v3_v3(sms_state->ofs, rv3d->ofs); + copy_qt_qt(sms_state->quat, rv3d->viewquat); + sms_state->dist = rv3d->dist; + sms_state->lens = v3d->lens; } static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state, - View3D *v3d, RegionView3D *rv3d) + View3D *v3d, + RegionView3D *rv3d) { - copy_v3_v3(rv3d->ofs, sms_state->ofs); - copy_qt_qt(rv3d->viewquat, sms_state->quat); - rv3d->dist = sms_state->dist; - v3d->lens = sms_state->lens; + copy_v3_v3(rv3d->ofs, sms_state->ofs); + copy_qt_qt(rv3d->viewquat, sms_state->quat); + rv3d->dist = sms_state->dist; + v3d->lens = sms_state->lens; } /* will start timer if appropriate */ /* the arguments are the desired situation */ void ED_view3d_smooth_view_ex( - /* avoid passing in the context */ - const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *sa, - View3D *v3d, ARegion *ar, const int smooth_viewtx, - const V3D_SmoothParams *sview) + /* avoid passing in the context */ + const Depsgraph *depsgraph, + wmWindowManager *wm, + wmWindow *win, + ScrArea *sa, + View3D *v3d, + ARegion *ar, + const int smooth_viewtx, + const V3D_SmoothParams *sview) { - RegionView3D *rv3d = ar->regiondata; - struct SmoothView3DStore sms = {{0}}; - bool ok = false; - - /* initialize sms */ - view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); - view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); - /* if smoothview runs multiple times... */ - if (rv3d->sms == NULL) { - view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); - } - else { - sms.org = rv3d->sms->org; - } - sms.org_view = rv3d->view; - - /* sms.to_camera = false; */ /* initizlized to zero anyway */ - - /* note on camera locking, this is a little confusing but works ok. - * we may be changing the view 'as if' there is no active camera, but in fact - * there is an active camera which is locked to the view. - * - * In the case where smooth view is moving _to_ a camera we don't want that - * camera to be moved or changed, so only when the camera is not being set should - * we allow camera option locking to initialize the view settings from the camera. - */ - if (sview->camera == NULL && sview->camera_old == NULL) { - ED_view3d_camera_lock_init(depsgraph, v3d, rv3d); - } - - /* store the options we want to end with */ - if (sview->ofs) { - copy_v3_v3(sms.dst.ofs, sview->ofs); - } - if (sview->quat) { - copy_qt_qt(sms.dst.quat, sview->quat); - } - if (sview->dist) { - sms.dst.dist = *sview->dist; - } - if (sview->lens) { - sms.dst.lens = *sview->lens; - } - - if (sview->dyn_ofs) { - BLI_assert(sview->ofs == NULL); - BLI_assert(sview->quat != NULL); - - copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs); - sms.use_dyn_ofs = true; - - /* calculate the final destination offset */ - view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs); - } - - if (sview->camera) { - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera); - sms.dst.dist = ED_view3d_offset_distance(ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK); - ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens); - sms.to_camera = true; /* restore view3d values in end */ - } - - /* skip smooth viewing for render engine draw */ - if (smooth_viewtx && v3d->shading.type != OB_RENDER) { - bool changed = false; /* zero means no difference */ - - if (sview->camera_old != sview->camera) { - changed = true; - } - else if (sms.dst.dist != rv3d->dist) { - changed = true; - } - else if (sms.dst.lens != v3d->lens) { - changed = true; - } - else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) { - changed = true; - } - else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) { - changed = true; - } - - /* The new view is different from the old one - * so animate the view */ - if (changed) { - /* original values */ - if (sview->camera_old) { - Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old); - sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f); - /* this */ - ED_view3d_from_object(ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens); - } - /* grid draw as floor */ - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - /* use existing if exists, means multiple calls to smooth view - * wont loose the original 'view' setting */ - rv3d->view = RV3D_VIEW_USER; - } - - sms.time_allowed = (double)smooth_viewtx / 1000.0; - - /* if this is view rotation only - * we can decrease the time allowed by - * the angle between quats - * this means small rotations wont lag */ - if (sview->quat && !sview->ofs && !sview->dist) { - /* scale the time allowed by the rotation */ - /* 180deg == 1.0 */ - sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) / M_PI; - } - - /* ensure it shows correct */ - if (sms.to_camera) { - /* use ortho if we move from an ortho view to an ortho camera */ - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera); - rv3d->persp = (((rv3d->is_persp == false) && - (ob_camera_eval->type == OB_CAMERA) && - (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ? - RV3D_ORTHO : RV3D_PERSP); - } - - rv3d->rflag |= RV3D_NAVIGATING; - - /* not essential but in some cases the caller will tag the area for redraw, and in that - * case we can get a flicker of the 'org' user view but we want to see 'src' */ - view3d_smooth_view_state_restore(&sms.src, v3d, rv3d); - - /* keep track of running timer! */ - if (rv3d->sms == NULL) { - rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d"); - } - *rv3d->sms = sms; - if (rv3d->smooth_timer) { - WM_event_remove_timer(wm, win, rv3d->smooth_timer); - } - /* TIMER1 is hardcoded in keymap */ - /* max 30 frs/sec */ - rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0); - - ok = true; - } - } - - /* if we get here nothing happens */ - if (ok == false) { - if (sms.to_camera == false) { - copy_v3_v3(rv3d->ofs, sms.dst.ofs); - copy_qt_qt(rv3d->viewquat, sms.dst.quat); - rv3d->dist = sms.dst.dist; - v3d->lens = sms.dst.lens; - - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - } - - if (rv3d->viewlock & RV3D_BOXVIEW) { - view3d_boxview_copy(sa, ar); - } - - ED_region_tag_redraw(ar); - } + RegionView3D *rv3d = ar->regiondata; + struct SmoothView3DStore sms = {{0}}; + bool ok = false; + + /* initialize sms */ + view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); + view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); + /* if smoothview runs multiple times... */ + if (rv3d->sms == NULL) { + view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); + } + else { + sms.org = rv3d->sms->org; + } + sms.org_view = rv3d->view; + + /* sms.to_camera = false; */ /* initizlized to zero anyway */ + + /* note on camera locking, this is a little confusing but works ok. + * we may be changing the view 'as if' there is no active camera, but in fact + * there is an active camera which is locked to the view. + * + * In the case where smooth view is moving _to_ a camera we don't want that + * camera to be moved or changed, so only when the camera is not being set should + * we allow camera option locking to initialize the view settings from the camera. + */ + if (sview->camera == NULL && sview->camera_old == NULL) { + ED_view3d_camera_lock_init(depsgraph, v3d, rv3d); + } + + /* store the options we want to end with */ + if (sview->ofs) { + copy_v3_v3(sms.dst.ofs, sview->ofs); + } + if (sview->quat) { + copy_qt_qt(sms.dst.quat, sview->quat); + } + if (sview->dist) { + sms.dst.dist = *sview->dist; + } + if (sview->lens) { + sms.dst.lens = *sview->lens; + } + + if (sview->dyn_ofs) { + BLI_assert(sview->ofs == NULL); + BLI_assert(sview->quat != NULL); + + copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs); + sms.use_dyn_ofs = true; + + /* calculate the final destination offset */ + view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs); + } + + if (sview->camera) { + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera); + sms.dst.dist = ED_view3d_offset_distance( + ob_camera_eval->obmat, sview->ofs, VIEW3D_DIST_FALLBACK); + ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens); + sms.to_camera = true; /* restore view3d values in end */ + } + + /* skip smooth viewing for render engine draw */ + if (smooth_viewtx && v3d->shading.type != OB_RENDER) { + bool changed = false; /* zero means no difference */ + + if (sview->camera_old != sview->camera) { + changed = true; + } + else if (sms.dst.dist != rv3d->dist) { + changed = true; + } + else if (sms.dst.lens != v3d->lens) { + changed = true; + } + else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) { + changed = true; + } + else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) { + changed = true; + } + + /* The new view is different from the old one + * so animate the view */ + if (changed) { + /* original values */ + if (sview->camera_old) { + Object *ob_camera_old_eval = DEG_get_evaluated_object(depsgraph, sview->camera_old); + sms.src.dist = ED_view3d_offset_distance(ob_camera_old_eval->obmat, rv3d->ofs, 0.0f); + /* this */ + ED_view3d_from_object( + ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens); + } + /* grid draw as floor */ + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + /* use existing if exists, means multiple calls to smooth view + * wont loose the original 'view' setting */ + rv3d->view = RV3D_VIEW_USER; + } + + sms.time_allowed = (double)smooth_viewtx / 1000.0; + + /* if this is view rotation only + * we can decrease the time allowed by + * the angle between quats + * this means small rotations wont lag */ + if (sview->quat && !sview->ofs && !sview->dist) { + /* scale the time allowed by the rotation */ + /* 180deg == 1.0 */ + sms.time_allowed *= (double)fabsf( + angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) / + M_PI; + } + + /* ensure it shows correct */ + if (sms.to_camera) { + /* use ortho if we move from an ortho view to an ortho camera */ + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, sview->camera); + rv3d->persp = (((rv3d->is_persp == false) && (ob_camera_eval->type == OB_CAMERA) && + (((Camera *)ob_camera_eval->data)->type == CAM_ORTHO)) ? + RV3D_ORTHO : + RV3D_PERSP); + } + + rv3d->rflag |= RV3D_NAVIGATING; + + /* not essential but in some cases the caller will tag the area for redraw, and in that + * case we can get a flicker of the 'org' user view but we want to see 'src' */ + view3d_smooth_view_state_restore(&sms.src, v3d, rv3d); + + /* keep track of running timer! */ + if (rv3d->sms == NULL) { + rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d"); + } + *rv3d->sms = sms; + if (rv3d->smooth_timer) { + WM_event_remove_timer(wm, win, rv3d->smooth_timer); + } + /* TIMER1 is hardcoded in keymap */ + /* max 30 frs/sec */ + rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0); + + ok = true; + } + } + + /* if we get here nothing happens */ + if (ok == false) { + if (sms.to_camera == false) { + copy_v3_v3(rv3d->ofs, sms.dst.ofs); + copy_qt_qt(rv3d->viewquat, sms.dst.quat); + rv3d->dist = sms.dst.dist; + v3d->lens = sms.dst.lens; + + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + } + + if (rv3d->viewlock & RV3D_BOXVIEW) { + view3d_boxview_copy(sa, ar); + } + + ED_region_tag_redraw(ar); + } } -void ED_view3d_smooth_view( - bContext *C, - View3D *v3d, ARegion *ar, const int smooth_viewtx, - const struct V3D_SmoothParams *sview) +void ED_view3d_smooth_view(bContext *C, + View3D *v3d, + ARegion *ar, + const int smooth_viewtx, + const struct V3D_SmoothParams *sview) { - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - ScrArea *sa = CTX_wm_area(C); - - ED_view3d_smooth_view_ex( - depsgraph, - wm, win, sa, - v3d, ar, smooth_viewtx, - sview); + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + + ED_view3d_smooth_view_ex(depsgraph, wm, win, sa, v3d, ar, smooth_viewtx, sview); } /* only meant for timer usage */ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool sync_boxview) { - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - RegionView3D *rv3d = ar->regiondata; - struct SmoothView3DStore *sms = rv3d->sms; - float step, step_inv; - - if (sms->time_allowed != 0.0) { - step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed); - } - else { - step = 1.0f; - } - - /* end timer */ - if (step >= 1.0f) { - - /* if we went to camera, store the original */ - if (sms->to_camera) { - rv3d->persp = RV3D_CAMOB; - view3d_smooth_view_state_restore(&sms->org, v3d, rv3d); - } - else { - view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d); - - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true); - } - - if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - rv3d->view = sms->org_view; - } - - MEM_freeN(rv3d->sms); - rv3d->sms = NULL; - - WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer); - rv3d->smooth_timer = NULL; - rv3d->rflag &= ~RV3D_NAVIGATING; - } - else { - /* ease in/out */ - step = (3.0f * step * step - 2.0f * step * step * step); - - step_inv = 1.0f - step; - - interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step); - - if (sms->use_dyn_ofs) { - view3d_orbit_apply_dyn_ofs(rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs); - } - else { - interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step); - } - - rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv; - v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv; - - ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); - if (ED_screen_animation_playing(CTX_wm_manager(C))) { - ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true); - } - - /* Event handling won't know if a UI item has been moved under the pointer. */ - WM_event_add_mousemove(C); - } - - if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) { - view3d_boxview_copy(CTX_wm_area(C), ar); - } - - /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, - * when switching camera in quad-view the other ortho views would zoom & reset. - * - * For now only redraw all regions when smoothview finishes. - */ - if (step >= 1.0f) { - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); - } - else { - ED_region_tag_redraw(ar); - } + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + RegionView3D *rv3d = ar->regiondata; + struct SmoothView3DStore *sms = rv3d->sms; + float step, step_inv; + + if (sms->time_allowed != 0.0) { + step = (float)((rv3d->smooth_timer->duration) / sms->time_allowed); + } + else { + step = 1.0f; + } + + /* end timer */ + if (step >= 1.0f) { + + /* if we went to camera, store the original */ + if (sms->to_camera) { + rv3d->persp = RV3D_CAMOB; + view3d_smooth_view_state_restore(&sms->org, v3d, rv3d); + } + else { + view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d); + + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true); + } + + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + rv3d->view = sms->org_view; + } + + MEM_freeN(rv3d->sms); + rv3d->sms = NULL; + + WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rv3d->smooth_timer); + rv3d->smooth_timer = NULL; + rv3d->rflag &= ~RV3D_NAVIGATING; + } + else { + /* ease in/out */ + step = (3.0f * step * step - 2.0f * step * step * step); + + step_inv = 1.0f - step; + + interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step); + + if (sms->use_dyn_ofs) { + view3d_orbit_apply_dyn_ofs( + rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs); + } + else { + interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step); + } + + rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv; + v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv; + + ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); + if (ED_screen_animation_playing(CTX_wm_manager(C))) { + ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true); + } + + /* Event handling won't know if a UI item has been moved under the pointer. */ + WM_event_add_mousemove(C); + } + + if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) { + view3d_boxview_copy(CTX_wm_area(C), ar); + } + + /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, + * when switching camera in quad-view the other ortho views would zoom & reset. + * + * For now only redraw all regions when smoothview finishes. + */ + if (step >= 1.0f) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + } + else { + ED_region_tag_redraw(ar); + } } static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; - /* escape if not our timer */ - if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) { - return OPERATOR_PASS_THROUGH; - } + /* escape if not our timer */ + if (rv3d->smooth_timer == NULL || rv3d->smooth_timer != event->customdata) { + return OPERATOR_PASS_THROUGH; + } - view3d_smoothview_apply(C, v3d, ar, true); + view3d_smoothview_apply(C, v3d, ar, true); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } /** * Apply the smoothview immediately, use when we need to start a new view operation. * (so we don't end up half-applying a view operation when pressing keys quickly). */ -void ED_view3d_smooth_view_force_finish( - bContext *C, - View3D *v3d, ARegion *ar) +void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d && rv3d->sms) { - rv3d->sms->time_allowed = 0.0; /* force finishing */ - view3d_smoothview_apply(C, v3d, ar, false); - - /* force update of view matrix so tools that run immediately after - * can use them without redrawing first */ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL); - } + RegionView3D *rv3d = ar->regiondata; + + if (rv3d && rv3d->sms) { + rv3d->sms->time_allowed = 0.0; /* force finishing */ + view3d_smoothview_apply(C, v3d, ar, false); + + /* force update of view matrix so tools that run immediately after + * can use them without redrawing first */ + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL); + } } void VIEW3D_OT_smoothview(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth View"; - ot->idname = "VIEW3D_OT_smoothview"; + /* identifiers */ + ot->name = "Smooth View"; + ot->idname = "VIEW3D_OT_smoothview"; - /* api callbacks */ - ot->invoke = view3d_smoothview_invoke; + /* api callbacks */ + ot->invoke = view3d_smoothview_invoke; - /* flags */ - ot->flag = OPTYPE_INTERNAL; + /* flags */ + ot->flag = OPTYPE_INTERNAL; - ot->poll = ED_operator_view3d_active; + ot->poll = ED_operator_view3d_active; } /** \} */ @@ -448,65 +455,64 @@ void VIEW3D_OT_smoothview(wmOperatorType *ot) static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op)) { - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; - - ObjectTfmProtectedChannels obtfm; + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; + ObjectTfmProtectedChannels obtfm; - ED_view3d_lastview_store(rv3d); + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; - BKE_object_tfm_protected_backup(v3d->camera, &obtfm); + ED_view3d_lastview_store(rv3d); - ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); + BKE_object_tfm_protected_backup(v3d->camera, &obtfm); - BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); + ED_view3d_to_object(depsgraph, v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); - DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); - rv3d->persp = RV3D_CAMOB; + BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera); + DEG_id_tag_update(&v3d->camera->id, ID_RECALC_TRANSFORM); + rv3d->persp = RV3D_CAMOB; - return OPERATOR_FINISHED; + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, v3d->camera); + return OPERATOR_FINISHED; } static bool view3d_camera_to_view_poll(bContext *C) { - View3D *v3d; - ARegion *ar; - - if (ED_view3d_context_user_region(C, &v3d, &ar)) { - RegionView3D *rv3d = ar->regiondata; - if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) { - if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) { - if (rv3d->persp != RV3D_CAMOB) { - return 1; - } - } - } - } - - return 0; + View3D *v3d; + ARegion *ar; + + if (ED_view3d_context_user_region(C, &v3d, &ar)) { + RegionView3D *rv3d = ar->regiondata; + if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) { + if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) { + if (rv3d->persp != RV3D_CAMOB) { + return 1; + } + } + } + } + + return 0; } void VIEW3D_OT_camera_to_view(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Align Camera To View"; - ot->description = "Set camera view to active view"; - ot->idname = "VIEW3D_OT_camera_to_view"; + /* identifiers */ + ot->name = "Align Camera To View"; + ot->description = "Set camera view to active view"; + ot->idname = "VIEW3D_OT_camera_to_view"; - /* api callbacks */ - ot->exec = view3d_camera_to_view_exec; - ot->poll = view3d_camera_to_view_poll; + /* api callbacks */ + ot->exec = view3d_camera_to_view_exec; + ot->poll = view3d_camera_to_view_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -519,60 +525,61 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot) * meant to take into account vertex/bone selection for eg. */ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ - Object *camera_ob = v3d ? v3d->camera : scene->camera; - Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); - - float r_co[3]; /* the new location to apply */ - float r_scale; /* only for ortho cameras */ - - if (camera_ob_eval == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active camera"); - return OPERATOR_CANCELLED; - } - - /* this function does all the important stuff */ - if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) { - ObjectTfmProtectedChannels obtfm; - float obmat_new[4][4]; - - if ((camera_ob_eval->type == OB_CAMERA) && (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { - ((Camera *)camera_ob->data)->ortho_scale = r_scale; - } - - copy_m4_m4(obmat_new, camera_ob_eval->obmat); - copy_v3_v3(obmat_new[3], r_co); - - /* only touch location */ - BKE_object_tfm_protected_backup(camera_ob, &obtfm); - BKE_object_apply_mat4(camera_ob, obmat_new, true, true); - BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); - - /* notifiers */ - DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); /* can be NULL */ + Object *camera_ob = v3d ? v3d->camera : scene->camera; + Object *camera_ob_eval = DEG_get_evaluated_object(depsgraph, camera_ob); + + float r_co[3]; /* the new location to apply */ + float r_scale; /* only for ortho cameras */ + + if (camera_ob_eval == NULL) { + BKE_report(op->reports, RPT_ERROR, "No active camera"); + return OPERATOR_CANCELLED; + } + + /* this function does all the important stuff */ + if (BKE_camera_view_frame_fit_to_scene(depsgraph, scene, camera_ob_eval, r_co, &r_scale)) { + ObjectTfmProtectedChannels obtfm; + float obmat_new[4][4]; + + if ((camera_ob_eval->type == OB_CAMERA) && + (((Camera *)camera_ob_eval->data)->type == CAM_ORTHO)) { + ((Camera *)camera_ob->data)->ortho_scale = r_scale; + } + + copy_m4_m4(obmat_new, camera_ob_eval->obmat); + copy_v3_v3(obmat_new[3], r_co); + + /* only touch location */ + BKE_object_tfm_protected_backup(camera_ob, &obtfm); + BKE_object_apply_mat4(camera_ob, obmat_new, true, true); + BKE_object_tfm_protected_restore(camera_ob, &obtfm, OB_LOCK_SCALE | OB_LOCK_ROT4D); + + /* notifiers */ + DEG_id_tag_update(&camera_ob->id, ID_RECALC_TRANSFORM); + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, camera_ob); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Camera Fit Frame to Selected"; - ot->description = "Move the camera so selected objects are framed"; - ot->idname = "VIEW3D_OT_camera_to_view_selected"; + /* identifiers */ + ot->name = "Camera Fit Frame to Selected"; + ot->description = "Move the camera so selected objects are framed"; + ot->idname = "VIEW3D_OT_camera_to_view_selected"; - /* api callbacks */ - ot->exec = view3d_camera_to_view_selected_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = view3d_camera_to_view_selected_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -581,124 +588,134 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot) /** \name Object as Camera Operator * \{ */ -static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx) +static void sync_viewport_camera_smoothview(bContext *C, + View3D *v3d, + Object *ob, + const int smooth_viewtx) { - Main *bmain = CTX_data_main(C); - for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) { - for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) { - for (SpaceLink *space_link = area->spacedata.first; space_link != NULL; space_link = space_link->next) { - if (space_link->spacetype == SPACE_VIEW3D) { - View3D *other_v3d = (View3D *)space_link; - if (other_v3d == v3d) { - continue; - } - if (other_v3d->camera == ob) { - continue; - } - if (v3d->scenelock) { - ListBase *lb = (space_link == area->spacedata.first) - ? &area->regionbase - : &space_link->regionbase; - for (ARegion *other_ar = lb->first; other_ar != NULL; other_ar = other_ar->next) { - if (other_ar->regiontype == RGN_TYPE_WINDOW) { - if (other_ar->regiondata) { - RegionView3D *other_rv3d = other_ar->regiondata; - if (other_rv3d->persp == RV3D_CAMOB) { - Object *other_camera_old = other_v3d->camera; - other_v3d->camera = ob; - ED_view3d_lastview_store(other_rv3d); - ED_view3d_smooth_view( - C, other_v3d, other_ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = other_camera_old, - .camera = other_v3d->camera, - .ofs = other_rv3d->ofs, - .quat = other_rv3d->viewquat, - .dist = &other_rv3d->dist, - .lens = &other_v3d->lens, - }); - } - else { - other_v3d->camera = ob; - } - } - } - } - } - } - } - } - } + Main *bmain = CTX_data_main(C); + for (bScreen *screen = bmain->screens.first; screen != NULL; screen = screen->id.next) { + for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) { + for (SpaceLink *space_link = area->spacedata.first; space_link != NULL; + space_link = space_link->next) { + if (space_link->spacetype == SPACE_VIEW3D) { + View3D *other_v3d = (View3D *)space_link; + if (other_v3d == v3d) { + continue; + } + if (other_v3d->camera == ob) { + continue; + } + if (v3d->scenelock) { + ListBase *lb = (space_link == area->spacedata.first) ? &area->regionbase : + &space_link->regionbase; + for (ARegion *other_ar = lb->first; other_ar != NULL; other_ar = other_ar->next) { + if (other_ar->regiontype == RGN_TYPE_WINDOW) { + if (other_ar->regiondata) { + RegionView3D *other_rv3d = other_ar->regiondata; + if (other_rv3d->persp == RV3D_CAMOB) { + Object *other_camera_old = other_v3d->camera; + other_v3d->camera = ob; + ED_view3d_lastview_store(other_rv3d); + ED_view3d_smooth_view(C, + other_v3d, + other_ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = other_camera_old, + .camera = other_v3d->camera, + .ofs = other_rv3d->ofs, + .quat = other_rv3d->viewquat, + .dist = &other_rv3d->dist, + .lens = &other_v3d->lens, + }); + } + else { + other_v3d->camera = ob; + } + } + } + } + } + } + } + } + } } static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op) { - View3D *v3d; - ARegion *ar; - RegionView3D *rv3d; - - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - - /* no NULL check is needed, poll checks */ - ED_view3d_context_user_region(C, &v3d, &ar); - rv3d = ar->regiondata; - - if (ob) { - Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL; - rv3d->persp = RV3D_CAMOB; - v3d->camera = ob; - if (v3d->scenelock && scene->camera != ob) { - scene->camera = ob; - DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); - } - - /* unlikely but looks like a glitch when set to the same */ - if (camera_old != ob) { - ED_view3d_lastview_store(rv3d); - - ED_view3d_smooth_view( - C, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old, .camera = v3d->camera, - .ofs = rv3d->ofs, .quat = rv3d->viewquat, - .dist = &rv3d->dist, .lens = &v3d->lens, - }); - } - - if (v3d->scenelock) { - sync_viewport_camera_smoothview(C, v3d, ob, smooth_viewtx); - WM_event_add_notifier(C, NC_SCENE, scene); - } - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); - } - - return OPERATOR_FINISHED; + View3D *v3d; + ARegion *ar; + RegionView3D *rv3d; + + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + + /* no NULL check is needed, poll checks */ + ED_view3d_context_user_region(C, &v3d, &ar); + rv3d = ar->regiondata; + + if (ob) { + Object *camera_old = (rv3d->persp == RV3D_CAMOB) ? V3D_CAMERA_SCENE(scene, v3d) : NULL; + rv3d->persp = RV3D_CAMOB; + v3d->camera = ob; + if (v3d->scenelock && scene->camera != ob) { + scene->camera = ob; + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + } + + /* unlikely but looks like a glitch when set to the same */ + if (camera_old != ob) { + ED_view3d_lastview_store(rv3d); + + ED_view3d_smooth_view(C, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = camera_old, + .camera = v3d->camera, + .ofs = rv3d->ofs, + .quat = rv3d->viewquat, + .dist = &rv3d->dist, + .lens = &v3d->lens, + }); + } + + if (v3d->scenelock) { + sync_viewport_camera_smoothview(C, v3d, ob, smooth_viewtx); + WM_event_add_notifier(C, NC_SCENE, scene); + } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene); + } + + return OPERATOR_FINISHED; } bool ED_operator_rv3d_user_region_poll(bContext *C) { - View3D *v3d_dummy; - ARegion *ar_dummy; + View3D *v3d_dummy; + ARegion *ar_dummy; - return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy); + return ED_view3d_context_user_region(C, &v3d_dummy, &ar_dummy); } void VIEW3D_OT_object_as_camera(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Active Object as Camera"; - ot->description = "Set the active object as the active camera for this view or scene"; - ot->idname = "VIEW3D_OT_object_as_camera"; + /* identifiers */ + ot->name = "Set Active Object as Camera"; + ot->description = "Set the active object as the active camera for this view or scene"; + ot->idname = "VIEW3D_OT_object_as_camera"; - /* api callbacks */ - ot->exec = view3d_setobjectascamera_exec; - ot->poll = ED_operator_rv3d_user_region_poll; + /* api callbacks */ + ot->exec = view3d_setobjectascamera_exec; + ot->poll = ED_operator_rv3d_user_region_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ @@ -712,51 +729,54 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot) */ void view3d_winmatrix_set(Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect) { - RegionView3D *rv3d = ar->regiondata; - rctf viewplane; - float clipsta, clipend; - bool is_ortho; + RegionView3D *rv3d = ar->regiondata; + rctf viewplane; + float clipsta, clipend; + bool is_ortho; - is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL); - rv3d->is_persp = !is_ortho; + is_ortho = ED_view3d_viewplane_get( + depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL); + rv3d->is_persp = !is_ortho; #if 0 - printf("%s: %d %d %f %f %f %f %f %f\n", __func__, winx, winy, - viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, - clipsta, clipend); + printf("%s: %d %d %f %f %f %f %f %f\n", __func__, winx, winy, + viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, + clipsta, clipend); #endif - if (rect) { /* picking */ - rctf r; - r.xmin = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmin / (float)ar->winx)); - r.ymin = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymin / (float)ar->winy)); - r.xmax = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmax / (float)ar->winx)); - r.ymax = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymax / (float)ar->winy)); - viewplane = r; - } - - if (is_ortho) { - GPU_matrix_ortho_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); - } - else { - GPU_matrix_frustum_set(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); - } - - /* update matrix in 3d view region */ - GPU_matrix_projection_get(rv3d->winmat); + if (rect) { /* picking */ + rctf r; + r.xmin = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmin / (float)ar->winx)); + r.ymin = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymin / (float)ar->winy)); + r.xmax = viewplane.xmin + (BLI_rctf_size_x(&viewplane) * (rect->xmax / (float)ar->winx)); + r.ymax = viewplane.ymin + (BLI_rctf_size_y(&viewplane) * (rect->ymax / (float)ar->winy)); + viewplane = r; + } + + if (is_ortho) { + GPU_matrix_ortho_set( + viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + } + else { + GPU_matrix_frustum_set( + viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); + } + + /* update matrix in 3d view region */ + GPU_matrix_projection_get(rv3d->winmat); } static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) { - float bmat[4][4]; + float bmat[4][4]; - rv3d->view = RV3D_VIEW_USER; /* don't show the grid */ + rv3d->view = RV3D_VIEW_USER; /* don't show the grid */ - normalize_m4_m4(bmat, ob->obmat); - invert_m4_m4(rv3d->viewmat, bmat); + normalize_m4_m4(bmat, ob->obmat); + invert_m4_m4(rv3d->viewmat, bmat); - /* view quat calculation, needed for add object */ - mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat); + /* view quat calculation, needed for add object */ + mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat); } /** @@ -771,86 +791,87 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) * * \note don't set windows active in here, is used by renderwin too. */ -void view3d_viewmatrix_set( - Depsgraph *depsgraph, Scene *scene, - const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]) +void view3d_viewmatrix_set(Depsgraph *depsgraph, + Scene *scene, + const View3D *v3d, + RegionView3D *rv3d, + const float rect_scale[2]) { - if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ - if (v3d->camera) { - Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); - obmat_to_viewmat(rv3d, ob_camera_eval); - } - else { - quat_to_mat4(rv3d->viewmat, rv3d->viewquat); - rv3d->viewmat[3][2] -= rv3d->dist; - } - } - else { - bool use_lock_ofs = false; - - - /* should be moved to better initialize later on XXX */ - if (rv3d->viewlock & RV3D_LOCKED) { - ED_view3d_lock(rv3d); - } - - quat_to_mat4(rv3d->viewmat, rv3d->viewquat); - if (rv3d->persp == RV3D_PERSP) { - rv3d->viewmat[3][2] -= rv3d->dist; - } - if (v3d->ob_centre) { - Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre); - float vec[3]; - - copy_v3_v3(vec, ob_eval->obmat[3]); - if (ob_eval->type == OB_ARMATURE && v3d->ob_centre_bone[0]) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_centre_bone); - if (pchan) { - copy_v3_v3(vec, pchan->pose_mat[3]); - mul_m4_v3(ob_eval->obmat, vec); - } - } - translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); - use_lock_ofs = true; - } - else if (v3d->ob_centre_cursor) { - float vec[3]; - copy_v3_v3(vec, scene->cursor.location); - translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); - use_lock_ofs = true; - } - else { - translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); - } - - /* lock offset */ - if (use_lock_ofs) { - float persmat[4][4], persinv[4][4]; - float vec[3]; - - /* we could calculate the real persmat/persinv here - * but it would be unreliable so better to later */ - mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat); - invert_m4_m4(persinv, persmat); - - mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f); - vec[2] = 0.0f; - - if (rect_scale) { - /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion' - * we don't know about the region size. - * Use 'rect_scale' when drawing a sub-region to apply 2D offset, - * scaled by the difference between the sub-region and the region size. - */ - vec[0] /= rect_scale[0]; - vec[1] /= rect_scale[1]; - } - - mul_mat3_m4_v3(persinv, vec); - translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]); - } - /* end lock offset */ - } + if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ + if (v3d->camera) { + Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, v3d->camera); + obmat_to_viewmat(rv3d, ob_camera_eval); + } + else { + quat_to_mat4(rv3d->viewmat, rv3d->viewquat); + rv3d->viewmat[3][2] -= rv3d->dist; + } + } + else { + bool use_lock_ofs = false; + + /* should be moved to better initialize later on XXX */ + if (rv3d->viewlock & RV3D_LOCKED) { + ED_view3d_lock(rv3d); + } + + quat_to_mat4(rv3d->viewmat, rv3d->viewquat); + if (rv3d->persp == RV3D_PERSP) { + rv3d->viewmat[3][2] -= rv3d->dist; + } + if (v3d->ob_centre) { + Object *ob_eval = DEG_get_evaluated_object(depsgraph, v3d->ob_centre); + float vec[3]; + + copy_v3_v3(vec, ob_eval->obmat[3]); + if (ob_eval->type == OB_ARMATURE && v3d->ob_centre_bone[0]) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_eval->pose, v3d->ob_centre_bone); + if (pchan) { + copy_v3_v3(vec, pchan->pose_mat[3]); + mul_m4_v3(ob_eval->obmat, vec); + } + } + translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); + use_lock_ofs = true; + } + else if (v3d->ob_centre_cursor) { + float vec[3]; + copy_v3_v3(vec, scene->cursor.location); + translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); + use_lock_ofs = true; + } + else { + translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); + } + + /* lock offset */ + if (use_lock_ofs) { + float persmat[4][4], persinv[4][4]; + float vec[3]; + + /* we could calculate the real persmat/persinv here + * but it would be unreliable so better to later */ + mul_m4_m4m4(persmat, rv3d->winmat, rv3d->viewmat); + invert_m4_m4(persinv, persmat); + + mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f); + vec[2] = 0.0f; + + if (rect_scale) { + /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion' + * we don't know about the region size. + * Use 'rect_scale' when drawing a sub-region to apply 2D offset, + * scaled by the difference between the sub-region and the region size. + */ + vec[0] /= rect_scale[0]; + vec[1] /= rect_scale[1]; + } + + mul_mat3_m4_v3(persinv, vec); + translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]); + } + /* end lock offset */ + } } /** \} */ @@ -866,77 +887,76 @@ void view3d_viewmatrix_set( */ void view3d_opengl_select_cache_begin(void) { - GPU_select_cache_begin(); + GPU_select_cache_begin(); } void view3d_opengl_select_cache_end(void) { - GPU_select_cache_end(); + GPU_select_cache_end(); } struct DrawSelectLoopUserData { - uint pass; - uint hits; - uint *buffer; - uint buffer_len; - const rcti *rect; - char gpu_select_mode; + uint pass; + uint hits; + uint *buffer; + uint buffer_len; + const rcti *rect; + char gpu_select_mode; }; static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data) { - bool continue_pass = false; - struct DrawSelectLoopUserData *data = user_data; - if (stage == DRW_SELECT_PASS_PRE) { - GPU_select_begin(data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits); - /* always run POST after PRE. */ - continue_pass = true; - } - else if (stage == DRW_SELECT_PASS_POST) { - int hits = GPU_select_end(); - if (data->pass == 0) { - /* quirk of GPU_select_end, only take hits value from first call. */ - data->hits = hits; - } - if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) { - data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS; - continue_pass = (hits > 0); - } - data->pass += 1; - } - else { - BLI_assert(0); - } - return continue_pass; - + bool continue_pass = false; + struct DrawSelectLoopUserData *data = user_data; + if (stage == DRW_SELECT_PASS_PRE) { + GPU_select_begin( + data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits); + /* always run POST after PRE. */ + continue_pass = true; + } + else if (stage == DRW_SELECT_PASS_POST) { + int hits = GPU_select_end(); + if (data->pass == 0) { + /* quirk of GPU_select_end, only take hits value from first call. */ + data->hits = hits; + } + if (data->gpu_select_mode == GPU_SELECT_NEAREST_FIRST_PASS) { + data->gpu_select_mode = GPU_SELECT_NEAREST_SECOND_PASS; + continue_pass = (hits > 0); + } + data->pass += 1; + } + else { + BLI_assert(0); + } + return continue_pass; } eV3DSelectObjectFilter ED_view3d_select_filter_from_mode(const Scene *scene, const Object *obact) { - if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { - if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && - BKE_object_pose_armature_get((Object *)obact)) - { - return VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK; - } - return VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK; - } - return VIEW3D_SELECT_FILTER_NOP; + if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) { + if (obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && + BKE_object_pose_armature_get((Object *)obact)) { + return VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK; + } + return VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK; + } + return VIEW3D_SELECT_FILTER_NOP; } /** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */ static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data) { - const Object *obact = user_data; - return BKE_object_is_mode_compat(ob, obact->mode); + const Object *obact = user_data; + return BKE_object_is_mode_compat(ob, obact->mode); } /** Implement #VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK for special case when * we want to select pose bones (this doesn't switch modes). */ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data) { - const Object *ob_pose = user_data; - return (DEG_get_original_object(ob) == ob_pose); + const Object *ob_pose = user_data; + return (DEG_get_original_object(ob) == ob_pose); } /** @@ -946,184 +966,196 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void * * \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection. */ -int view3d_opengl_select( - ViewContext *vc, uint *buffer, uint bufsize, const rcti *input, - eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter) +int view3d_opengl_select(ViewContext *vc, + uint *buffer, + uint bufsize, + const rcti *input, + eV3DSelectMode select_mode, + eV3DSelectObjectFilter select_filter) { - struct bThemeState theme_state; - Depsgraph *depsgraph = vc->depsgraph; - Scene *scene = vc->scene; - View3D *v3d = vc->v3d; - ARegion *ar = vc->ar; - rcti rect; - int hits = 0; - const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && (vc->obedit == NULL); - const bool is_pick_select = (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0; - const bool do_passes = ( - (is_pick_select == false) && - (select_mode == VIEW3D_SELECT_PICK_NEAREST)); - const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST); - bool draw_surface = true; - - char gpu_select_mode; - - /* case not a box select */ - if (input->xmin == input->xmax) { - /* seems to be default value for bones only now */ - BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12); - } - else { - rect = *input; - } - - if (is_pick_select) { - if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) { - gpu_select_mode = GPU_SELECT_PICK_NEAREST; - } - else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) { - gpu_select_mode = GPU_SELECT_PICK_ALL; - } - else { - gpu_select_mode = GPU_SELECT_ALL; - } - } - else { - if (do_passes) { - gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS; - } - else { - gpu_select_mode = GPU_SELECT_ALL; - } - } - - /* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below, - * so it will be NULL when hidden. */ - struct { - DRW_ObjectFilterFn fn; - void *user_data; - } object_filter = {NULL, NULL}; - switch (select_filter) { - case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK: - { - Object *obact = vc->obact; - if (obact && obact->mode != OB_MODE_OBJECT) { - object_filter.fn = drw_select_filter_object_mode_lock; - object_filter.user_data = obact; - } - break; - } - case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK: - { - Object *obact = vc->obact; - BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT)); - Object *ob_pose = BKE_object_pose_armature_get(obact); - - object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint; - object_filter.user_data = ob_pose; - break; - } - case VIEW3D_SELECT_FILTER_NOP: - break; - - } - - /* Tools may request depth outside of regular drawing code. */ - UI_Theme_Store(&theme_state); - UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); - - /* Re-use cache (rect must be smaller then the cached) - * other context is assumed to be unchanged */ - if (GPU_select_is_cached()) { - GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); - GPU_select_cache_load_id(); - hits = GPU_select_end(); - goto finally; - } - - /* All of the queries need to be perform on the drawing context. */ - DRW_opengl_context_enable(); - - G.f |= G_FLAG_PICKSEL; - - /* Important we use the 'viewmat' and don't re-calculate since - * the object & bone view locking takes 'rect' into account, see: T51629. */ - ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); - - if (!XRAY_ACTIVE(v3d)) { - GPU_depth_test(true); - } - - if (vc->rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_set(vc->rv3d); - } - - /* If in xray mode, we select the wires in priority. */ - if (XRAY_ACTIVE(v3d) && use_nearest) { - /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop - * because the OpenGL context created & destroyed inside this function. */ - struct DrawSelectLoopUserData drw_select_loop_user_data = { - .pass = 0, - .hits = 0, - .buffer = buffer, - .buffer_len = bufsize, - .rect = &rect, - .gpu_select_mode = gpu_select_mode, - }; - draw_surface = false; - DRW_draw_select_loop( - depsgraph, ar, v3d, - use_obedit_skip, draw_surface, use_nearest, &rect, - drw_select_loop_pass, &drw_select_loop_user_data, - object_filter.fn, object_filter.user_data); - hits = drw_select_loop_user_data.hits; - /* FIX: This cleanup the state before doing another selection pass. - * (see T56695) */ - GPU_select_cache_end(); - } - - if (hits == 0) { - /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop - * because the OpenGL context created & destroyed inside this function. */ - struct DrawSelectLoopUserData drw_select_loop_user_data = { - .pass = 0, - .hits = 0, - .buffer = buffer, - .buffer_len = bufsize, - .rect = &rect, - .gpu_select_mode = gpu_select_mode, - }; - /* If are not in wireframe mode, we need to use the mesh surfaces to check for hits */ - draw_surface = (v3d->shading.type > OB_WIRE) || !XRAY_ENABLED(v3d); - DRW_draw_select_loop( - depsgraph, ar, v3d, - use_obedit_skip, draw_surface, use_nearest, &rect, - drw_select_loop_pass, &drw_select_loop_user_data, - object_filter.fn, object_filter.user_data); - hits = drw_select_loop_user_data.hits; - } - - G.f &= ~G_FLAG_PICKSEL; - ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); - - if (!XRAY_ACTIVE(v3d)) { - GPU_depth_test(false); - } - - if (vc->rv3d->rflag & RV3D_CLIPPING) { - ED_view3d_clipping_disable(); - } - - DRW_opengl_context_disable(); + struct bThemeState theme_state; + Depsgraph *depsgraph = vc->depsgraph; + Scene *scene = vc->scene; + View3D *v3d = vc->v3d; + ARegion *ar = vc->ar; + rcti rect; + int hits = 0; + const bool use_obedit_skip = (OBEDIT_FROM_VIEW_LAYER(vc->view_layer) != NULL) && + (vc->obedit == NULL); + const bool is_pick_select = (U.gpu_flag & USER_GPU_FLAG_NO_DEPT_PICK) == 0; + const bool do_passes = ((is_pick_select == false) && + (select_mode == VIEW3D_SELECT_PICK_NEAREST)); + const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST); + bool draw_surface = true; + + char gpu_select_mode; + + /* case not a box select */ + if (input->xmin == input->xmax) { + /* seems to be default value for bones only now */ + BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12); + } + else { + rect = *input; + } + + if (is_pick_select) { + if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) { + gpu_select_mode = GPU_SELECT_PICK_NEAREST; + } + else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) { + gpu_select_mode = GPU_SELECT_PICK_ALL; + } + else { + gpu_select_mode = GPU_SELECT_ALL; + } + } + else { + if (do_passes) { + gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS; + } + else { + gpu_select_mode = GPU_SELECT_ALL; + } + } + + /* Important to use 'vc->obact', not 'OBACT(vc->view_layer)' below, + * so it will be NULL when hidden. */ + struct { + DRW_ObjectFilterFn fn; + void *user_data; + } object_filter = {NULL, NULL}; + switch (select_filter) { + case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK: { + Object *obact = vc->obact; + if (obact && obact->mode != OB_MODE_OBJECT) { + object_filter.fn = drw_select_filter_object_mode_lock; + object_filter.user_data = obact; + } + break; + } + case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK: { + Object *obact = vc->obact; + BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT)); + Object *ob_pose = BKE_object_pose_armature_get(obact); + + object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint; + object_filter.user_data = ob_pose; + break; + } + case VIEW3D_SELECT_FILTER_NOP: + break; + } + + /* Tools may request depth outside of regular drawing code. */ + UI_Theme_Store(&theme_state); + UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW); + + /* Re-use cache (rect must be smaller then the cached) + * other context is assumed to be unchanged */ + if (GPU_select_is_cached()) { + GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0); + GPU_select_cache_load_id(); + hits = GPU_select_end(); + goto finally; + } + + /* All of the queries need to be perform on the drawing context. */ + DRW_opengl_context_enable(); + + G.f |= G_FLAG_PICKSEL; + + /* Important we use the 'viewmat' and don't re-calculate since + * the object & bone view locking takes 'rect' into account, see: T51629. */ + ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, &rect); + + if (!XRAY_ACTIVE(v3d)) { + GPU_depth_test(true); + } + + if (vc->rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_set(vc->rv3d); + } + + /* If in xray mode, we select the wires in priority. */ + if (XRAY_ACTIVE(v3d) && use_nearest) { + /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop + * because the OpenGL context created & destroyed inside this function. */ + struct DrawSelectLoopUserData drw_select_loop_user_data = { + .pass = 0, + .hits = 0, + .buffer = buffer, + .buffer_len = bufsize, + .rect = &rect, + .gpu_select_mode = gpu_select_mode, + }; + draw_surface = false; + DRW_draw_select_loop(depsgraph, + ar, + v3d, + use_obedit_skip, + draw_surface, + use_nearest, + &rect, + drw_select_loop_pass, + &drw_select_loop_user_data, + object_filter.fn, + object_filter.user_data); + hits = drw_select_loop_user_data.hits; + /* FIX: This cleanup the state before doing another selection pass. + * (see T56695) */ + GPU_select_cache_end(); + } + + if (hits == 0) { + /* We need to call "GPU_select_*" API's inside DRW_draw_select_loop + * because the OpenGL context created & destroyed inside this function. */ + struct DrawSelectLoopUserData drw_select_loop_user_data = { + .pass = 0, + .hits = 0, + .buffer = buffer, + .buffer_len = bufsize, + .rect = &rect, + .gpu_select_mode = gpu_select_mode, + }; + /* If are not in wireframe mode, we need to use the mesh surfaces to check for hits */ + draw_surface = (v3d->shading.type > OB_WIRE) || !XRAY_ENABLED(v3d); + DRW_draw_select_loop(depsgraph, + ar, + v3d, + use_obedit_skip, + draw_surface, + use_nearest, + &rect, + drw_select_loop_pass, + &drw_select_loop_user_data, + object_filter.fn, + object_filter.user_data); + hits = drw_select_loop_user_data.hits; + } + + G.f &= ~G_FLAG_PICKSEL; + ED_view3d_draw_setup_view(vc->win, depsgraph, scene, ar, v3d, vc->rv3d->viewmat, NULL, NULL); + + if (!XRAY_ACTIVE(v3d)) { + GPU_depth_test(false); + } + + if (vc->rv3d->rflag & RV3D_CLIPPING) { + ED_view3d_clipping_disable(); + } + + DRW_opengl_context_disable(); finally: - if (hits < 0) { - printf("Too many objects in select buffer\n"); /* XXX make error message */ - } + if (hits < 0) { + printf("Too many objects in select buffer\n"); /* XXX make error message */ + } - UI_Theme_Restore(&theme_state); + UI_Theme_Restore(&theme_state); - return hits; + return hits; } /** \} */ @@ -1134,332 +1166,348 @@ finally: static uint free_localbit(Main *bmain) { - ScrArea *sa; - bScreen *sc; - - ushort local_view_bits = 0; - - /* sometimes we loose a localview: when an area is closed */ - /* check all areas: which localviews are in use? */ - for (sc = bmain->screens.first; sc; sc = sc->id.next) { - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl = sa->spacedata.first; - for (; sl; sl = sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *) sl; - if (v3d->localvd) { - local_view_bits |= v3d->local_view_uuid; - } - } - } - } - } - - for (int i = 0; i < 16; i++) { - if ((local_view_bits & (1 << i)) == 0) { - return (1 << i); - } - } - - return 0; + ScrArea *sa; + bScreen *sc; + + ushort local_view_bits = 0; + + /* sometimes we loose a localview: when an area is closed */ + /* check all areas: which localviews are in use? */ + for (sc = bmain->screens.first; sc; sc = sc->id.next) { + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl = sa->spacedata.first; + for (; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + if (v3d->localvd) { + local_view_bits |= v3d->local_view_uuid; + } + } + } + } + } + + for (int i = 0; i < 16; i++) { + if ((local_view_bits & (1 << i)) == 0) { + return (1 << i); + } + } + + return 0; } -static bool view3d_localview_init( - const Depsgraph *depsgraph, - wmWindowManager *wm, - wmWindow *win, - Main *bmain, - ViewLayer *view_layer, - ScrArea *sa, - const bool frame_selected, - const int smooth_viewtx, - ReportList *reports) +static bool view3d_localview_init(const Depsgraph *depsgraph, + wmWindowManager *wm, + wmWindow *win, + Main *bmain, + ViewLayer *view_layer, + ScrArea *sa, + const bool frame_selected, + const int smooth_viewtx, + ReportList *reports) { - View3D *v3d = sa->spacedata.first; - Base *base; - float min[3], max[3], box[3]; - float size = 0.0f; - uint local_view_bit; - bool ok = false; - - if (v3d->localvd) { - return ok; - } - - INIT_MINMAX(min, max); - - local_view_bit = free_localbit(bmain); - - if (local_view_bit == 0) { - /* TODO(dfelinto): We can kick one of the other 3D views out of local view - specially if it is not being used. */ - BKE_report(reports, RPT_ERROR, "No more than 16 local views"); - ok = false; - } - else { - Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); - if (obedit) { - FOREACH_BASE_IN_EDIT_MODE_BEGIN(view_layer, v3d, base_iter) { - BKE_object_minmax(base_iter->object, min, max, false); - base_iter->local_view_bits |= local_view_bit; - ok = true; - } FOREACH_BASE_IN_EDIT_MODE_END; - } - else { - for (base = FIRSTBASE(view_layer); base; base = base->next) { - if (BASE_SELECTED(v3d, base)) { - BKE_object_minmax(base->object, min, max, false); - base->local_view_bits |= local_view_bit; - ok = true; - } - } - } - - sub_v3_v3v3(box, max, min); - size = max_fff(box[0], box[1], box[2]); - } - - if (ok == false) { - return false; - } - - ARegion *ar; - - v3d->localvd = MEM_mallocN(sizeof(View3D), "localview"); - - memcpy(v3d->localvd, v3d, sizeof(View3D)); - v3d->local_view_uuid = local_view_bit; - - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - bool ok_dist = true; - - /* New view values. */ - Object *camera_old = NULL; - float dist_new, ofs_new[3]; - - rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); - memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); - - if (frame_selected) { - float mid[3]; - mid_v3_v3v3(mid, min, max); - negate_v3_v3(ofs_new, mid); - - if (rv3d->persp == RV3D_CAMOB) { - rv3d->persp = RV3D_PERSP; - camera_old = v3d->camera; - } - - if (rv3d->persp == RV3D_ORTHO) { - if (size < 0.0001f) { - ok_dist = false; - } - } - - if (ok_dist) { - dist_new = ED_view3d_radius_to_dist(v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); - - if (rv3d->persp == RV3D_PERSP) { - /* Don't zoom closer than the near clipping plane. */ - dist_new = max_ff(dist_new, v3d->clip_start * 1.5f); - } - } - - ED_view3d_smooth_view_ex( - depsgraph, - wm, win, sa, v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old, - .ofs = ofs_new, .quat = rv3d->viewquat, - .dist = ok_dist ? &dist_new : NULL, .lens = &v3d->lens, - }); - } - } - } - - return ok; + View3D *v3d = sa->spacedata.first; + Base *base; + float min[3], max[3], box[3]; + float size = 0.0f; + uint local_view_bit; + bool ok = false; + + if (v3d->localvd) { + return ok; + } + + INIT_MINMAX(min, max); + + local_view_bit = free_localbit(bmain); + + if (local_view_bit == 0) { + /* TODO(dfelinto): We can kick one of the other 3D views out of local view + specially if it is not being used. */ + BKE_report(reports, RPT_ERROR, "No more than 16 local views"); + ok = false; + } + else { + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); + if (obedit) { + FOREACH_BASE_IN_EDIT_MODE_BEGIN (view_layer, v3d, base_iter) { + BKE_object_minmax(base_iter->object, min, max, false); + base_iter->local_view_bits |= local_view_bit; + ok = true; + } + FOREACH_BASE_IN_EDIT_MODE_END; + } + else { + for (base = FIRSTBASE(view_layer); base; base = base->next) { + if (BASE_SELECTED(v3d, base)) { + BKE_object_minmax(base->object, min, max, false); + base->local_view_bits |= local_view_bit; + ok = true; + } + } + } + + sub_v3_v3v3(box, max, min); + size = max_fff(box[0], box[1], box[2]); + } + + if (ok == false) { + return false; + } + + ARegion *ar; + + v3d->localvd = MEM_mallocN(sizeof(View3D), "localview"); + + memcpy(v3d->localvd, v3d, sizeof(View3D)); + v3d->local_view_uuid = local_view_bit; + + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + bool ok_dist = true; + + /* New view values. */ + Object *camera_old = NULL; + float dist_new, ofs_new[3]; + + rv3d->localvd = MEM_mallocN(sizeof(RegionView3D), "localview region"); + memcpy(rv3d->localvd, rv3d, sizeof(RegionView3D)); + + if (frame_selected) { + float mid[3]; + mid_v3_v3v3(mid, min, max); + negate_v3_v3(ofs_new, mid); + + if (rv3d->persp == RV3D_CAMOB) { + rv3d->persp = RV3D_PERSP; + camera_old = v3d->camera; + } + + if (rv3d->persp == RV3D_ORTHO) { + if (size < 0.0001f) { + ok_dist = false; + } + } + + if (ok_dist) { + dist_new = ED_view3d_radius_to_dist( + v3d, ar, depsgraph, rv3d->persp, true, (size / 2) * VIEW3D_MARGIN); + + if (rv3d->persp == RV3D_PERSP) { + /* Don't zoom closer than the near clipping plane. */ + dist_new = max_ff(dist_new, v3d->clip_start * 1.5f); + } + } + + ED_view3d_smooth_view_ex(depsgraph, + wm, + win, + sa, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = camera_old, + .ofs = ofs_new, + .quat = rv3d->viewquat, + .dist = ok_dist ? &dist_new : NULL, + .lens = &v3d->lens, + }); + } + } + } + + return ok; } -static void view3d_localview_exit( - const Depsgraph *depsgraph, - wmWindowManager *wm, - wmWindow *win, - ViewLayer *view_layer, - ScrArea *sa, - const bool frame_selected, - const int smooth_viewtx) +static void view3d_localview_exit(const Depsgraph *depsgraph, + wmWindowManager *wm, + wmWindow *win, + ViewLayer *view_layer, + ScrArea *sa, + const bool frame_selected, + const int smooth_viewtx) { - View3D *v3d = sa->spacedata.first; - - if (v3d->localvd == NULL) { - return; - } - - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { - if (base->local_view_bits & v3d->local_view_uuid) { - base->local_view_bits &= ~v3d->local_view_uuid; - } - } - - Object *camera_old = v3d->camera; - Object *camera_new = v3d->localvd->camera; - - v3d->local_view_uuid = 0; - v3d->camera = v3d->localvd->camera; - - MEM_freeN(v3d->localvd); - v3d->localvd = NULL; - - for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = ar->regiondata; - - if (rv3d->localvd == NULL) { - continue; - } - - if (frame_selected) { - Object *camera_old_rv3d, *camera_new_rv3d; - - camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL; - camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL; - - rv3d->view = rv3d->localvd->view; - rv3d->persp = rv3d->localvd->persp; - rv3d->camzoom = rv3d->localvd->camzoom; - - ED_view3d_smooth_view_ex( - depsgraph, - wm, win, sa, - v3d, ar, smooth_viewtx, - &(const V3D_SmoothParams) { - .camera_old = camera_old_rv3d, .camera = camera_new_rv3d, - .ofs = rv3d->localvd->ofs, .quat = rv3d->localvd->viewquat, - .dist = &rv3d->localvd->dist, - }); - } - - MEM_freeN(rv3d->localvd); - rv3d->localvd = NULL; - } - } + View3D *v3d = sa->spacedata.first; + + if (v3d->localvd == NULL) { + return; + } + + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + if (base->local_view_bits & v3d->local_view_uuid) { + base->local_view_bits &= ~v3d->local_view_uuid; + } + } + + Object *camera_old = v3d->camera; + Object *camera_new = v3d->localvd->camera; + + v3d->local_view_uuid = 0; + v3d->camera = v3d->localvd->camera; + + MEM_freeN(v3d->localvd); + v3d->localvd = NULL; + + for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->localvd == NULL) { + continue; + } + + if (frame_selected) { + Object *camera_old_rv3d, *camera_new_rv3d; + + camera_old_rv3d = (rv3d->persp == RV3D_CAMOB) ? camera_old : NULL; + camera_new_rv3d = (rv3d->localvd->persp == RV3D_CAMOB) ? camera_new : NULL; + + rv3d->view = rv3d->localvd->view; + rv3d->persp = rv3d->localvd->persp; + rv3d->camzoom = rv3d->localvd->camzoom; + + ED_view3d_smooth_view_ex(depsgraph, + wm, + win, + sa, + v3d, + ar, + smooth_viewtx, + &(const V3D_SmoothParams){ + .camera_old = camera_old_rv3d, + .camera = camera_new_rv3d, + .ofs = rv3d->localvd->ofs, + .quat = rv3d->localvd->viewquat, + .dist = &rv3d->localvd->dist, + }); + } + + MEM_freeN(rv3d->localvd); + rv3d->localvd = NULL; + } + } } static int localview_exec(bContext *C, wmOperator *op) { - const Depsgraph *depsgraph = CTX_data_depsgraph(C); - const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); - wmWindowManager *wm = CTX_wm_manager(C); - wmWindow *win = CTX_wm_window(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = CTX_wm_view3d(C); - bool frame_selected = RNA_boolean_get(op->ptr, "frame_selected"); - bool changed; - - if (v3d->localvd) { - view3d_localview_exit(depsgraph, wm, win, view_layer, sa, frame_selected, smooth_viewtx); - changed = true; - } - else { - changed = view3d_localview_init(depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports); - } - - if (changed) { - DEG_id_type_tag(bmain, ID_OB); - ED_area_tag_redraw(sa); - - /* Unselected objects become selected when exiting. */ - if (v3d->localvd == NULL) { - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else { - DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); - } - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + const Depsgraph *depsgraph = CTX_data_depsgraph(C); + const int smooth_viewtx = WM_operator_smooth_viewtx_get(op); + wmWindowManager *wm = CTX_wm_manager(C); + wmWindow *win = CTX_wm_window(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + ScrArea *sa = CTX_wm_area(C); + View3D *v3d = CTX_wm_view3d(C); + bool frame_selected = RNA_boolean_get(op->ptr, "frame_selected"); + bool changed; + + if (v3d->localvd) { + view3d_localview_exit(depsgraph, wm, win, view_layer, sa, frame_selected, smooth_viewtx); + changed = true; + } + else { + changed = view3d_localview_init( + depsgraph, wm, win, bmain, view_layer, sa, frame_selected, smooth_viewtx, op->reports); + } + + if (changed) { + DEG_id_type_tag(bmain, ID_OB); + ED_area_tag_redraw(sa); + + /* Unselected objects become selected when exiting. */ + if (v3d->localvd == NULL) { + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + } + else { + DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); + } + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void VIEW3D_OT_localview(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Local View"; - ot->description = "Toggle display of selected object(s) separately and centered in view"; - ot->idname = "VIEW3D_OT_localview"; - - /* api callbacks */ - ot->exec = localview_exec; - ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */ - - ot->poll = ED_operator_view3d_active; - - RNA_def_boolean(ot->srna, "frame_selected", true, "Frame Selected", "Move the view to frame the selected objects"); + /* identifiers */ + ot->name = "Local View"; + ot->description = "Toggle display of selected object(s) separately and centered in view"; + ot->idname = "VIEW3D_OT_localview"; + + /* api callbacks */ + ot->exec = localview_exec; + ot->flag = OPTYPE_UNDO; /* localview changes object layer bitflags */ + + ot->poll = ED_operator_view3d_active; + + RNA_def_boolean(ot->srna, + "frame_selected", + true, + "Frame Selected", + "Move the view to frame the selected objects"); } static int localview_remove_from_exec(bContext *C, wmOperator *op) { - View3D *v3d = CTX_wm_view3d(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - bool changed = false; - - for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { - if (BASE_SELECTED(v3d, base)) { - base->local_view_bits &= ~v3d->local_view_uuid; - ED_object_base_select(base, BA_DESELECT); - - if (base == BASACT(view_layer)) { - view_layer->basact = NULL; - } - changed = true; - } - } - - if (changed) { - DEG_on_visible_update(bmain, false); - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - return OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "No object selected"); - return OPERATOR_CANCELLED; - } + View3D *v3d = CTX_wm_view3d(C); + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + bool changed = false; + + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + if (BASE_SELECTED(v3d, base)) { + base->local_view_bits &= ~v3d->local_view_uuid; + ED_object_base_select(base, BA_DESELECT); + + if (base == BASACT(view_layer)) { + view_layer->basact = NULL; + } + changed = true; + } + } + + if (changed) { + DEG_on_visible_update(bmain, false); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "No object selected"); + return OPERATOR_CANCELLED; + } } static bool localview_remove_from_poll(bContext *C) { - if (CTX_data_edit_object(C) != NULL) { - return false; - } + if (CTX_data_edit_object(C) != NULL) { + return false; + } - View3D *v3d = CTX_wm_view3d(C); - return v3d && v3d->localvd; + View3D *v3d = CTX_wm_view3d(C); + return v3d && v3d->localvd; } void VIEW3D_OT_localview_remove_from(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove from Local View"; - ot->description = "Move selected objects out of local view"; - ot->idname = "VIEW3D_OT_localview_remove_from"; - - /* api callbacks */ - ot->exec = localview_remove_from_exec; - ot->invoke = WM_operator_confirm; - ot->poll = localview_remove_from_poll; - ot->flag = OPTYPE_UNDO; + /* identifiers */ + ot->name = "Remove from Local View"; + ot->description = "Move selected objects out of local view"; + ot->idname = "VIEW3D_OT_localview_remove_from"; + + /* api callbacks */ + ot->exec = localview_remove_from_exec; + ot->invoke = WM_operator_confirm; + ot->poll = localview_remove_from_poll; + ot->flag = OPTYPE_UNDO; } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index a015b7f9945..a0613d3b76f 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -52,7 +52,7 @@ #include "DEG_depsgraph.h" -#include "view3d_intern.h" /* own include */ +#include "view3d_intern.h" /* own include */ #ifdef WITH_INPUT_NDOF //# define NDOF_WALK_DEBUG @@ -71,330 +71,344 @@ static float getVelocityZeroTime(const float gravity, const float velocity); /* NOTE: these defines are saved in keymap files, * do not change values but just add new ones */ enum { - WALK_MODAL_CANCEL = 1, - WALK_MODAL_CONFIRM, - WALK_MODAL_DIR_FORWARD, - WALK_MODAL_DIR_FORWARD_STOP, - WALK_MODAL_DIR_BACKWARD, - WALK_MODAL_DIR_BACKWARD_STOP, - WALK_MODAL_DIR_LEFT, - WALK_MODAL_DIR_LEFT_STOP, - WALK_MODAL_DIR_RIGHT, - WALK_MODAL_DIR_RIGHT_STOP, - WALK_MODAL_DIR_UP, - WALK_MODAL_DIR_UP_STOP, - WALK_MODAL_DIR_DOWN, - WALK_MODAL_DIR_DOWN_STOP, - WALK_MODAL_FAST_ENABLE, - WALK_MODAL_FAST_DISABLE, - WALK_MODAL_SLOW_ENABLE, - WALK_MODAL_SLOW_DISABLE, - WALK_MODAL_JUMP, - WALK_MODAL_JUMP_STOP, - WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, - WALK_MODAL_ACCELERATE, - WALK_MODAL_DECELERATE, + WALK_MODAL_CANCEL = 1, + WALK_MODAL_CONFIRM, + WALK_MODAL_DIR_FORWARD, + WALK_MODAL_DIR_FORWARD_STOP, + WALK_MODAL_DIR_BACKWARD, + WALK_MODAL_DIR_BACKWARD_STOP, + WALK_MODAL_DIR_LEFT, + WALK_MODAL_DIR_LEFT_STOP, + WALK_MODAL_DIR_RIGHT, + WALK_MODAL_DIR_RIGHT_STOP, + WALK_MODAL_DIR_UP, + WALK_MODAL_DIR_UP_STOP, + WALK_MODAL_DIR_DOWN, + WALK_MODAL_DIR_DOWN_STOP, + WALK_MODAL_FAST_ENABLE, + WALK_MODAL_FAST_DISABLE, + WALK_MODAL_SLOW_ENABLE, + WALK_MODAL_SLOW_DISABLE, + WALK_MODAL_JUMP, + WALK_MODAL_JUMP_STOP, + WALK_MODAL_TELEPORT, + WALK_MODAL_TOGGLE, + WALK_MODAL_ACCELERATE, + WALK_MODAL_DECELERATE, }; enum { - WALK_BIT_FORWARD = 1 << 0, - WALK_BIT_BACKWARD = 1 << 1, - WALK_BIT_LEFT = 1 << 2, - WALK_BIT_RIGHT = 1 << 3, - WALK_BIT_UP = 1 << 4, - WALK_BIT_DOWN = 1 << 5, + WALK_BIT_FORWARD = 1 << 0, + WALK_BIT_BACKWARD = 1 << 1, + WALK_BIT_LEFT = 1 << 2, + WALK_BIT_RIGHT = 1 << 3, + WALK_BIT_UP = 1 << 4, + WALK_BIT_DOWN = 1 << 5, }; typedef enum eWalkTeleportState { - WALK_TELEPORT_STATE_OFF = 0, - WALK_TELEPORT_STATE_ON, + WALK_TELEPORT_STATE_OFF = 0, + WALK_TELEPORT_STATE_ON, } eWalkTeleportState; typedef enum eWalkMethod { - WALK_MODE_FREE = 0, - WALK_MODE_GRAVITY, + WALK_MODE_FREE = 0, + WALK_MODE_GRAVITY, } eWalkMethod; typedef enum eWalkGravityState { - WALK_GRAVITY_STATE_OFF = 0, - WALK_GRAVITY_STATE_JUMP, - WALK_GRAVITY_STATE_START, - WALK_GRAVITY_STATE_ON, + WALK_GRAVITY_STATE_OFF = 0, + WALK_GRAVITY_STATE_JUMP, + WALK_GRAVITY_STATE_START, + WALK_GRAVITY_STATE_ON, } eWalkGravityState; /* called in transform_ops.c, on each regeneration of keymaps */ void walk_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + static const EnumPropertyItem modal_items[] = { + {WALK_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {WALK_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, - {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, - {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""}, - {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""}, - {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""}, - {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, + {WALK_MODAL_DIR_FORWARD, "FORWARD", 0, "Forward", ""}, + {WALK_MODAL_DIR_BACKWARD, "BACKWARD", 0, "Backward", ""}, + {WALK_MODAL_DIR_LEFT, "LEFT", 0, "Left (Strafe)", ""}, + {WALK_MODAL_DIR_RIGHT, "RIGHT", 0, "Right (Strafe)", ""}, + {WALK_MODAL_DIR_UP, "UP", 0, "Up", ""}, + {WALK_MODAL_DIR_DOWN, "DOWN", 0, "Down", ""}, - {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""}, - {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""}, - {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""}, - {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""}, - {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""}, - {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""}, + {WALK_MODAL_DIR_FORWARD_STOP, "FORWARD_STOP", 0, "Stop Move Forward", ""}, + {WALK_MODAL_DIR_BACKWARD_STOP, "BACKWARD_STOP", 0, "Stop Mode Backward", ""}, + {WALK_MODAL_DIR_LEFT_STOP, "LEFT_STOP", 0, "Stop Move Left", ""}, + {WALK_MODAL_DIR_RIGHT_STOP, "RIGHT_STOP", 0, "Stop Mode Right", ""}, + {WALK_MODAL_DIR_UP_STOP, "UP_STOP", 0, "Stop Move Up", ""}, + {WALK_MODAL_DIR_DOWN_STOP, "DOWN_STOP", 0, "Stop Mode Down", ""}, - {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"}, + {WALK_MODAL_TELEPORT, "TELEPORT", 0, "Teleport", "Move forward a few units at once"}, - {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, - {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, + {WALK_MODAL_ACCELERATE, "ACCELERATE", 0, "Accelerate", ""}, + {WALK_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, - {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"}, - {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"}, + {WALK_MODAL_FAST_ENABLE, "FAST_ENABLE", 0, "Fast", "Move faster (walk or fly)"}, + {WALK_MODAL_FAST_DISABLE, "FAST_DISABLE", 0, "Fast (Off)", "Resume regular speed"}, - {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"}, - {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"}, + {WALK_MODAL_SLOW_ENABLE, "SLOW_ENABLE", 0, "Slow", "Move slower (walk or fly)"}, + {WALK_MODAL_SLOW_DISABLE, "SLOW_DISABLE", 0, "Slow (Off)", "Resume regular speed"}, - {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, - {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, + {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, + {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, - {0, NULL, 0, NULL, NULL}, - }; + {0, NULL, 0, NULL, NULL}, + }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal"); + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) { - return; - } + /* this function is called for each spacetype, only needs to add map once */ + if (keymap && keymap->modal_items) { + return; + } - keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items); + keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items); - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); } - typedef struct WalkTeleport { - eWalkTeleportState state; - float duration; /* from user preferences */ - float origin[3]; - float direction[3]; - double initial_time; - eWalkMethod navigation_mode; /* teleport always set FREE mode on */ + eWalkTeleportState state; + float duration; /* from user preferences */ + float origin[3]; + float direction[3]; + double initial_time; + eWalkMethod navigation_mode; /* teleport always set FREE mode on */ } WalkTeleport; typedef struct WalkInfo { - /* context stuff */ - RegionView3D *rv3d; - View3D *v3d; - ARegion *ar; - struct Depsgraph *depsgraph; - Scene *scene; + /* context stuff */ + RegionView3D *rv3d; + View3D *v3d; + ARegion *ar; + struct Depsgraph *depsgraph; + Scene *scene; - wmTimer *timer; /* needed for redraws */ + wmTimer *timer; /* needed for redraws */ - short state; - bool redraw; + short state; + bool redraw; - int prev_mval[2]; /* previous 2D mouse values */ - int center_mval[2]; /* center mouse values */ - int moffset[2]; + int prev_mval[2]; /* previous 2D mouse values */ + int center_mval[2]; /* center mouse values */ + int moffset[2]; #ifdef WITH_INPUT_NDOF - wmNDOFMotionData *ndof; /* latest 3D mouse values */ + wmNDOFMotionData *ndof; /* latest 3D mouse values */ #endif - /* walk state state */ - float base_speed; /* the base speed without run/slow down modifications */ - float speed; /* the speed the view is moving per redraw */ - float grid; /* world scale 1.0 default */ + /* walk state state */ + float base_speed; /* the base speed without run/slow down modifications */ + float speed; /* the speed the view is moving per redraw */ + float grid; /* world scale 1.0 default */ - /* compare between last state */ - double time_lastdraw; /* time between draws */ + /* compare between last state */ + double time_lastdraw; /* time between draws */ - void *draw_handle_pixel; + void *draw_handle_pixel; - /* use for some lag */ - float dvec_prev[3]; /* old for some lag */ + /* use for some lag */ + float dvec_prev[3]; /* old for some lag */ - /* walk/fly */ - eWalkMethod navigation_mode; + /* walk/fly */ + eWalkMethod navigation_mode; - /* teleport */ - WalkTeleport teleport; + /* teleport */ + WalkTeleport teleport; - /* look speed factor - user preferences */ - float mouse_speed; + /* look speed factor - user preferences */ + float mouse_speed; - /* speed adjustments */ - bool is_fast; - bool is_slow; + /* speed adjustments */ + bool is_fast; + bool is_slow; - /* mouse reverse */ - bool is_reversed; + /* mouse reverse */ + bool is_reversed; #ifdef USE_TABLET_SUPPORT - /* check if we had a cursor event before */ - bool is_cursor_first; + /* check if we had a cursor event before */ + bool is_cursor_first; - /* tablet devices (we can't relocate the cursor) */ - bool is_cursor_absolute; + /* tablet devices (we can't relocate the cursor) */ + bool is_cursor_absolute; #endif - /* gravity system */ - eWalkGravityState gravity_state; - float gravity; + /* gravity system */ + eWalkGravityState gravity_state; + float gravity; - /* height to use in walk mode */ - float view_height; + /* height to use in walk mode */ + float view_height; - /* counting system to allow movement to continue if a direction (WASD) key is still pressed */ - int active_directions; + /* counting system to allow movement to continue if a direction (WASD) key is still pressed */ + int active_directions; - float speed_jump; - float jump_height; /* maximum jump height */ - float speed_factor; /* to use for fast/slow speeds */ + float speed_jump; + float jump_height; /* maximum jump height */ + float speed_factor; /* to use for fast/slow speeds */ - struct SnapObjectContext *snap_context; + struct SnapObjectContext *snap_context; - struct View3DCameraControl *v3d_camera_control; + struct View3DCameraControl *v3d_camera_control; } WalkInfo; static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg) { - /* draws an aim/cross in the center */ - WalkInfo *walk = arg; + /* draws an aim/cross in the center */ + WalkInfo *walk = arg; - const int outter_length = 24; - const int inner_length = 14; - int xoff, yoff; - rctf viewborder; + const int outter_length = 24; + const int inner_length = 14; + int xoff, yoff; + rctf viewborder; - if (ED_view3d_cameracontrol_object_get(walk->v3d_camera_control)) { - ED_view3d_calc_camera_border(walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false); - xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f; - yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f; - } - else { - xoff = walk->ar->winx / 2; - yoff = walk->ar->winy / 2; - } + if (ED_view3d_cameracontrol_object_get(walk->v3d_camera_control)) { + ED_view3d_calc_camera_border( + walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false); + xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f; + yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f; + } + else { + xoff = walk->ar->winx / 2; + yoff = walk->ar->winy / 2; + } - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - immBegin(GPU_PRIM_LINES, 8); + immBegin(GPU_PRIM_LINES, 8); - /* North */ - immVertex2i(pos, xoff, yoff + inner_length); - immVertex2i(pos, xoff, yoff + outter_length); + /* North */ + immVertex2i(pos, xoff, yoff + inner_length); + immVertex2i(pos, xoff, yoff + outter_length); - /* East */ - immVertex2i(pos, xoff + inner_length, yoff); - immVertex2i(pos, xoff + outter_length, yoff); + /* East */ + immVertex2i(pos, xoff + inner_length, yoff); + immVertex2i(pos, xoff + outter_length, yoff); - /* South */ - immVertex2i(pos, xoff, yoff - inner_length); - immVertex2i(pos, xoff, yoff - outter_length); + /* South */ + immVertex2i(pos, xoff, yoff - inner_length); + immVertex2i(pos, xoff, yoff - outter_length); - /* West */ - immVertex2i(pos, xoff - inner_length, yoff); - immVertex2i(pos, xoff - outter_length, yoff); + /* West */ + immVertex2i(pos, xoff - inner_length, yoff); + immVertex2i(pos, xoff - outter_length, yoff); - immEnd(); - immUnbindProgram(); + immEnd(); + immUnbindProgram(); } static void walk_update_header(bContext *C, wmOperator *op, WalkInfo *walk) { - const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) || - ((walk->teleport.state == WALK_TELEPORT_STATE_ON) && - (walk->teleport.navigation_mode == WALK_MODE_GRAVITY)); - char header[UI_MAX_DRAW_STR]; - char buf[UI_MAX_DRAW_STR]; + const bool gravity = (walk->navigation_mode == WALK_MODE_GRAVITY) || + ((walk->teleport.state == WALK_TELEPORT_STATE_ON) && + (walk->teleport.navigation_mode == WALK_MODE_GRAVITY)); + char header[UI_MAX_DRAW_STR]; + char buf[UI_MAX_DRAW_STR]; - char *p = buf; - int available_len = sizeof(buf); + char *p = buf; + int available_len = sizeof(buf); #define WM_MODALKEY(_id) \ - WM_modalkeymap_operator_items_to_string_buf(op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) - - BLI_snprintf(header, sizeof(header), IFACE_("%s: confirm, %s: cancel, " - "%s: gravity (%s), " - "%s|%s|%s|%s: move around, " - "%s: fast, %s: slow, " - "%s|%s: up and down, " - "%s: teleport, %s: jump, " - "%s: increase speed, %s: decrease speed"), - WM_MODALKEY(WALK_MODAL_CONFIRM), WM_MODALKEY(WALK_MODAL_CANCEL), - WM_MODALKEY(WALK_MODAL_TOGGLE), WM_bool_as_string(gravity), - WM_MODALKEY(WALK_MODAL_DIR_FORWARD), WM_MODALKEY(WALK_MODAL_DIR_LEFT), - WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), WM_MODALKEY(WALK_MODAL_DIR_RIGHT), - WM_MODALKEY(WALK_MODAL_FAST_ENABLE), WM_MODALKEY(WALK_MODAL_SLOW_ENABLE), - WM_MODALKEY(WALK_MODAL_DIR_UP), WM_MODALKEY(WALK_MODAL_DIR_DOWN), - WM_MODALKEY(WALK_MODAL_TELEPORT), WM_MODALKEY(WALK_MODAL_JUMP), - WM_MODALKEY(WALK_MODAL_ACCELERATE), WM_MODALKEY(WALK_MODAL_DECELERATE)); + WM_modalkeymap_operator_items_to_string_buf( \ + op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) + + BLI_snprintf(header, + sizeof(header), + IFACE_("%s: confirm, %s: cancel, " + "%s: gravity (%s), " + "%s|%s|%s|%s: move around, " + "%s: fast, %s: slow, " + "%s|%s: up and down, " + "%s: teleport, %s: jump, " + "%s: increase speed, %s: decrease speed"), + WM_MODALKEY(WALK_MODAL_CONFIRM), + WM_MODALKEY(WALK_MODAL_CANCEL), + WM_MODALKEY(WALK_MODAL_TOGGLE), + WM_bool_as_string(gravity), + WM_MODALKEY(WALK_MODAL_DIR_FORWARD), + WM_MODALKEY(WALK_MODAL_DIR_LEFT), + WM_MODALKEY(WALK_MODAL_DIR_BACKWARD), + WM_MODALKEY(WALK_MODAL_DIR_RIGHT), + WM_MODALKEY(WALK_MODAL_FAST_ENABLE), + WM_MODALKEY(WALK_MODAL_SLOW_ENABLE), + WM_MODALKEY(WALK_MODAL_DIR_UP), + WM_MODALKEY(WALK_MODAL_DIR_DOWN), + WM_MODALKEY(WALK_MODAL_TELEPORT), + WM_MODALKEY(WALK_MODAL_JUMP), + WM_MODALKEY(WALK_MODAL_ACCELERATE), + WM_MODALKEY(WALK_MODAL_DECELERATE)); #undef WM_MODALKEY - ED_workspace_status_text(C, header); + ED_workspace_status_text(C, header); } static void walk_navigation_mode_set(bContext *C, wmOperator *op, WalkInfo *walk, eWalkMethod mode) { - if (mode == WALK_MODE_FREE) { - walk->navigation_mode = WALK_MODE_FREE; - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - } - else { /* WALK_MODE_GRAVITY */ - walk->navigation_mode = WALK_MODE_GRAVITY; - walk->gravity_state = WALK_GRAVITY_STATE_START; - } - - walk_update_header(C, op, walk); + if (mode == WALK_MODE_FREE) { + walk->navigation_mode = WALK_MODE_FREE; + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + } + else { /* WALK_MODE_GRAVITY */ + walk->navigation_mode = WALK_MODE_GRAVITY; + walk->gravity_state = WALK_GRAVITY_STATE_START; + } + + walk_update_header(C, op, walk); } /** * \param r_distance: Distance to the hit point */ -static bool walk_floor_distance_get( - RegionView3D *rv3d, WalkInfo *walk, const float dvec[3], - float *r_distance) +static bool walk_floor_distance_get(RegionView3D *rv3d, + WalkInfo *walk, + const float dvec[3], + float *r_distance) { - float ray_normal[3] = {0, 0, -1}; /* down */ - float ray_start[3]; - float r_location[3]; - float r_normal_dummy[3]; - float dvec_tmp[3]; - bool ret; - - *r_distance = BVH_RAYCAST_DIST_MAX; - - copy_v3_v3(ray_start, rv3d->viewinv[3]); - - mul_v3_v3fl(dvec_tmp, dvec, walk->grid); - add_v3_v3(ray_start, dvec_tmp); - - ret = ED_transform_snap_object_project_ray( - walk->snap_context, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - }, - ray_start, ray_normal, r_distance, - r_location, r_normal_dummy); - - /* artificially scale the distance to the scene size */ - *r_distance /= walk->grid; - return ret; + float ray_normal[3] = {0, 0, -1}; /* down */ + float ray_start[3]; + float r_location[3]; + float r_normal_dummy[3]; + float dvec_tmp[3]; + bool ret; + + *r_distance = BVH_RAYCAST_DIST_MAX; + + copy_v3_v3(ray_start, rv3d->viewinv[3]); + + mul_v3_v3fl(dvec_tmp, dvec, walk->grid); + add_v3_v3(ray_start, dvec_tmp); + + ret = ED_transform_snap_object_project_ray(walk->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + }, + ray_start, + ray_normal, + r_distance, + r_location, + r_normal_dummy); + + /* artificially scale the distance to the scene size */ + *r_distance /= walk->grid; + return ret; } /** @@ -402,46 +416,50 @@ static bool walk_floor_distance_get( * \param r_location: Location of the hit point * \param r_normal: Normal of the hit surface, transformed to always face the camera */ -static bool walk_ray_cast( - RegionView3D *rv3d, WalkInfo *walk, - float r_location[3], float r_normal[3], float *ray_distance) +static bool walk_ray_cast(RegionView3D *rv3d, + WalkInfo *walk, + float r_location[3], + float r_normal[3], + float *ray_distance) { - float ray_normal[3] = {0, 0, -1}; /* forward */ - float ray_start[3]; - bool ret; + float ray_normal[3] = {0, 0, -1}; /* forward */ + float ray_start[3]; + bool ret; - *ray_distance = BVH_RAYCAST_DIST_MAX; + *ray_distance = BVH_RAYCAST_DIST_MAX; - copy_v3_v3(ray_start, rv3d->viewinv[3]); + copy_v3_v3(ray_start, rv3d->viewinv[3]); - mul_mat3_m4_v3(rv3d->viewinv, ray_normal); + mul_mat3_m4_v3(rv3d->viewinv, ray_normal); - normalize_v3(ray_normal); + normalize_v3(ray_normal); - ret = ED_transform_snap_object_project_ray( - walk->snap_context, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - }, - ray_start, ray_normal, NULL, - r_location, r_normal); + ret = ED_transform_snap_object_project_ray(walk->snap_context, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + }, + ray_start, + ray_normal, + NULL, + r_location, + r_normal); - /* dot is positive if both rays are facing the same direction */ - if (dot_v3v3(ray_normal, r_normal) > 0) { - negate_v3(r_normal); - } + /* dot is positive if both rays are facing the same direction */ + if (dot_v3v3(ray_normal, r_normal) > 0) { + negate_v3(r_normal); + } - /* artificially scale the distance to the scene size */ - *ray_distance /= walk->grid; + /* artificially scale the distance to the scene size */ + *ray_distance /= walk->grid; - return ret; + return ret; } /* WalkInfo->state */ enum { - WALK_RUNNING = 0, - WALK_CANCEL = 1, - WALK_CONFIRM = 2, + WALK_RUNNING = 0, + WALK_CANCEL = 1, + WALK_CONFIRM = 2, }; /* keep the previous speed until user changes userpreferences */ @@ -450,484 +468,484 @@ static float userdef_speed = -1.f; static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) { - Main *bmain = CTX_data_main(C); - wmWindow *win = CTX_wm_window(C); + Main *bmain = CTX_data_main(C); + wmWindow *win = CTX_wm_window(C); - walk->rv3d = CTX_wm_region_view3d(C); - walk->v3d = CTX_wm_view3d(C); - walk->ar = CTX_wm_region(C); - walk->depsgraph = CTX_data_depsgraph(C); - walk->scene = CTX_data_scene(C); + walk->rv3d = CTX_wm_region_view3d(C); + walk->v3d = CTX_wm_view3d(C); + walk->ar = CTX_wm_region(C); + walk->depsgraph = CTX_data_depsgraph(C); + walk->scene = CTX_data_scene(C); #ifdef NDOF_WALK_DEBUG - puts("\n-- walk begin --"); + puts("\n-- walk begin --"); #endif - /* sanity check: for rare but possible case (if lib-linking the camera fails) */ - if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { - walk->rv3d->persp = RV3D_PERSP; - } - - if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); - return false; - } - - if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); - return false; - } - - if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { - BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); - return false; - } - - walk->state = WALK_RUNNING; - - if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { - base_speed = U.walk_navigation.walk_speed; - userdef_speed = U.walk_navigation.walk_speed; - } - - walk->speed = 0.0f; - walk->is_fast = false; - walk->is_slow = false; - walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : 1.f / walk->scene->unit.scale_length; - - /* user preference settings */ - walk->teleport.duration = U.walk_navigation.teleport_time; - walk->mouse_speed = U.walk_navigation.mouse_speed; - - if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { - walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); - } - else { - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - } - - walk->view_height = U.walk_navigation.view_height; - walk->jump_height = U.walk_navigation.jump_height; - walk->speed = U.walk_navigation.walk_speed; - walk->speed_factor = U.walk_navigation.walk_speed_factor; - - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - - if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { - walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); - } - else { - walk->gravity = 9.80668f; /* m/s2 */ - } - - walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); + /* sanity check: for rare but possible case (if lib-linking the camera fails) */ + if ((walk->rv3d->persp == RV3D_CAMOB) && (walk->v3d->camera == NULL)) { + walk->rv3d->persp = RV3D_PERSP; + } + + if (walk->rv3d->persp == RV3D_CAMOB && ID_IS_LINKED(walk->v3d->camera)) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate a camera from an external library"); + return false; + } + + if (ED_view3d_offset_lock_check(walk->v3d, walk->rv3d)) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate when the view offset is locked"); + return false; + } + + if (walk->rv3d->persp == RV3D_CAMOB && walk->v3d->camera->constraints.first) { + BKE_report(op->reports, RPT_ERROR, "Cannot navigate an object with constraints"); + return false; + } + + walk->state = WALK_RUNNING; + + if (fabsf(U.walk_navigation.walk_speed - userdef_speed) > 0.1f) { + base_speed = U.walk_navigation.walk_speed; + userdef_speed = U.walk_navigation.walk_speed; + } + + walk->speed = 0.0f; + walk->is_fast = false; + walk->is_slow = false; + walk->grid = (walk->scene->unit.system == USER_UNIT_NONE) ? 1.f : + 1.f / walk->scene->unit.scale_length; + + /* user preference settings */ + walk->teleport.duration = U.walk_navigation.teleport_time; + walk->mouse_speed = U.walk_navigation.mouse_speed; + + if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { + walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); + } + else { + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + } + + walk->view_height = U.walk_navigation.view_height; + walk->jump_height = U.walk_navigation.jump_height; + walk->speed = U.walk_navigation.walk_speed; + walk->speed_factor = U.walk_navigation.walk_speed_factor; + + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + + if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { + walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); + } + else { + walk->gravity = 9.80668f; /* m/s2 */ + } + + walk->is_reversed = ((U.walk_navigation.flag & USER_WALK_MOUSE_REVERSE) != 0); #ifdef USE_TABLET_SUPPORT - walk->is_cursor_first = true; + walk->is_cursor_first = true; - walk->is_cursor_absolute = false; + walk->is_cursor_absolute = false; #endif - walk->active_directions = 0; + walk->active_directions = 0; #ifdef NDOF_WALK_DRAW_TOOMUCH - walk->redraw = 1; + walk->redraw = 1; #endif - zero_v3(walk->dvec_prev); + zero_v3(walk->dvec_prev); - walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); + walk->timer = WM_event_add_timer(CTX_wm_manager(C), win, TIMER, 0.01f); #ifdef WITH_INPUT_NDOF - walk->ndof = NULL; + walk->ndof = NULL; #endif - walk->time_lastdraw = PIL_check_seconds_timer(); + walk->time_lastdraw = PIL_check_seconds_timer(); - walk->draw_handle_pixel = ED_region_draw_cb_activate(walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); + walk->draw_handle_pixel = ED_region_draw_cb_activate( + walk->ar->type, drawWalkPixel, walk, REGION_DRAW_POST_PIXEL); - walk->rv3d->rflag |= RV3D_NAVIGATING; + walk->rv3d->rflag |= RV3D_NAVIGATING; - walk->snap_context = ED_transform_snap_object_context_create_view3d( - bmain, walk->scene, CTX_data_depsgraph(C), 0, - walk->ar, walk->v3d); + walk->snap_context = ED_transform_snap_object_context_create_view3d( + bmain, walk->scene, CTX_data_depsgraph(C), 0, walk->ar, walk->v3d); - walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( - walk->depsgraph, walk->scene, walk->v3d, walk->rv3d, - (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); + walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( + walk->depsgraph, + walk->scene, + walk->v3d, + walk->rv3d, + (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); - /* center the mouse */ - walk->center_mval[0] = walk->ar->winx * 0.5f; - walk->center_mval[1] = walk->ar->winy * 0.5f; + /* center the mouse */ + walk->center_mval[0] = walk->ar->winx * 0.5f; + walk->center_mval[1] = walk->ar->winy * 0.5f; #ifdef USE_PIXELSIZE_NATIVE_SUPPORT - walk->center_mval[0] += walk->ar->winrct.xmin; - walk->center_mval[1] += walk->ar->winrct.ymin; + walk->center_mval[0] += walk->ar->winrct.xmin; + walk->center_mval[1] += walk->ar->winrct.ymin; - WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); + WM_cursor_compatible_xy(win, &walk->center_mval[0], &walk->center_mval[1]); - walk->center_mval[0] -= walk->ar->winrct.xmin; - walk->center_mval[1] -= walk->ar->winrct.ymin; + walk->center_mval[0] -= walk->ar->winrct.xmin; + walk->center_mval[1] -= walk->ar->winrct.ymin; #endif - copy_v2_v2_int(walk->prev_mval, walk->center_mval); + copy_v2_v2_int(walk->prev_mval, walk->center_mval); - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); - /* remove the mouse cursor temporarily */ - WM_cursor_modal_set(win, CURSOR_NONE); + /* remove the mouse cursor temporarily */ + WM_cursor_modal_set(win, CURSOR_NONE); - return 1; + return 1; } static int walkEnd(bContext *C, WalkInfo *walk) { - wmWindow *win; - RegionView3D *rv3d; + wmWindow *win; + RegionView3D *rv3d; - if (walk->state == WALK_RUNNING) { - return OPERATOR_RUNNING_MODAL; - } + if (walk->state == WALK_RUNNING) { + return OPERATOR_RUNNING_MODAL; + } #ifdef NDOF_WALK_DEBUG - puts("\n-- walk end --"); + puts("\n-- walk end --"); #endif - win = CTX_wm_window(C); - rv3d = walk->rv3d; + win = CTX_wm_window(C); + rv3d = walk->rv3d; - WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer); + WM_event_remove_timer(CTX_wm_manager(C), win, walk->timer); - ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel); + ED_region_draw_cb_exit(walk->ar->type, walk->draw_handle_pixel); - ED_transform_snap_object_context_destroy(walk->snap_context); + ED_transform_snap_object_context_destroy(walk->snap_context); - ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL); + ED_view3d_cameracontrol_release(walk->v3d_camera_control, walk->state == WALK_CANCEL); - rv3d->rflag &= ~RV3D_NAVIGATING; + rv3d->rflag &= ~RV3D_NAVIGATING; #ifdef WITH_INPUT_NDOF - if (walk->ndof) { - MEM_freeN(walk->ndof); - } + if (walk->ndof) { + MEM_freeN(walk->ndof); + } #endif - /* restore the cursor */ - WM_cursor_modal_restore(win); + /* restore the cursor */ + WM_cursor_modal_restore(win); #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_absolute == false) + if (walk->is_cursor_absolute == false) #endif - { - /* center the mouse */ - WM_cursor_warp( - win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - } - - if (walk->state == WALK_CONFIRM) { - MEM_freeN(walk); - return OPERATOR_FINISHED; - } - - MEM_freeN(walk); - return OPERATOR_CANCELLED; + { + /* center the mouse */ + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + } + + if (walk->state == WALK_CONFIRM) { + MEM_freeN(walk); + return OPERATOR_FINISHED; + } + + MEM_freeN(walk); + return OPERATOR_CANCELLED; } static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event) { - if (event->type == TIMER && event->customdata == walk->timer) { - walk->redraw = true; - } - else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + if (event->type == TIMER && event->customdata == walk->timer) { + walk->redraw = true; + } + else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_first) { - /* wait until we get the 'warp' event */ - if ((walk->center_mval[0] == event->mval[0]) && - (walk->center_mval[1] == event->mval[1])) - { - walk->is_cursor_first = false; - } - else { - /* note, its possible the system isn't giving us the warp event - * ideally we shouldn't have to worry about this, see: T45361 */ - wmWindow *win = CTX_wm_window(C); - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - } - return; - } - - if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) { - walk->is_cursor_absolute = true; - copy_v2_v2_int(walk->prev_mval, event->mval); - copy_v2_v2_int(walk->center_mval, event->mval); - /* without this we can't turn 180d */ - CLAMP_MIN(walk->mouse_speed, 4.0f); - } -#endif /* USE_TABLET_SUPPORT */ - - - walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; - walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; - - copy_v2_v2_int(walk->prev_mval, event->mval); - - if ((walk->center_mval[0] != event->mval[0]) || - (walk->center_mval[1] != event->mval[1])) - { - walk->redraw = true; + if (walk->is_cursor_first) { + /* wait until we get the 'warp' event */ + if ((walk->center_mval[0] == event->mval[0]) && (walk->center_mval[1] == event->mval[1])) { + walk->is_cursor_first = false; + } + else { + /* note, its possible the system isn't giving us the warp event + * ideally we shouldn't have to worry about this, see: T45361 */ + wmWindow *win = CTX_wm_window(C); + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + } + return; + } + + if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) { + walk->is_cursor_absolute = true; + copy_v2_v2_int(walk->prev_mval, event->mval); + copy_v2_v2_int(walk->center_mval, event->mval); + /* without this we can't turn 180d */ + CLAMP_MIN(walk->mouse_speed, 4.0f); + } +#endif /* USE_TABLET_SUPPORT */ + + walk->moffset[0] += event->mval[0] - walk->prev_mval[0]; + walk->moffset[1] += event->mval[1] - walk->prev_mval[1]; + + copy_v2_v2_int(walk->prev_mval, event->mval); + + if ((walk->center_mval[0] != event->mval[0]) || (walk->center_mval[1] != event->mval[1])) { + walk->redraw = true; #ifdef USE_TABLET_SUPPORT - if (walk->is_cursor_absolute) { - /* pass */ - } - else + if (walk->is_cursor_absolute) { + /* pass */ + } + else #endif - if (WM_event_is_last_mousemove(event)) { - wmWindow *win = CTX_wm_window(C); + if (WM_event_is_last_mousemove(event)) { + wmWindow *win = CTX_wm_window(C); #ifdef __APPLE__ - if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) || - (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2)) + if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) || + (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2)) #endif - { - WM_cursor_warp(win, - walk->ar->winrct.xmin + walk->center_mval[0], - walk->ar->winrct.ymin + walk->center_mval[1]); - copy_v2_v2_int(walk->prev_mval, walk->center_mval); - } - } - } - } + { + WM_cursor_warp(win, + walk->ar->winrct.xmin + walk->center_mval[0], + walk->ar->winrct.ymin + walk->center_mval[1]); + copy_v2_v2_int(walk->prev_mval, walk->center_mval); + } + } + } + } #ifdef WITH_INPUT_NDOF - else if (event->type == NDOF_MOTION) { - /* do these automagically get delivered? yes. */ - // puts("ndof motion detected in walk mode!"); - // static const char *tag_name = "3D mouse position"; - - const wmNDOFMotionData *incoming_ndof = event->customdata; - switch (incoming_ndof->progress) { - case P_STARTING: - /* start keeping track of 3D mouse position */ + else if (event->type == NDOF_MOTION) { + /* do these automagically get delivered? yes. */ + // puts("ndof motion detected in walk mode!"); + // static const char *tag_name = "3D mouse position"; + + const wmNDOFMotionData *incoming_ndof = event->customdata; + switch (incoming_ndof->progress) { + case P_STARTING: + /* start keeping track of 3D mouse position */ # ifdef NDOF_WALK_DEBUG - puts("start keeping track of 3D mouse position"); + puts("start keeping track of 3D mouse position"); # endif - /* fall-through */ - case P_IN_PROGRESS: - /* update 3D mouse position */ + /* fall-through */ + case P_IN_PROGRESS: + /* update 3D mouse position */ # ifdef NDOF_WALK_DEBUG - putchar('.'); fflush(stdout); + putchar('.'); + fflush(stdout); # endif - if (walk->ndof == NULL) { - // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); - walk->ndof = MEM_dupallocN(incoming_ndof); - // walk->ndof = malloc(sizeof(wmNDOFMotionData)); - } - else { - memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); - } - break; - case P_FINISHING: - /* stop keeping track of 3D mouse position */ + if (walk->ndof == NULL) { + // walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); + walk->ndof = MEM_dupallocN(incoming_ndof); + // walk->ndof = malloc(sizeof(wmNDOFMotionData)); + } + else { + memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + } + break; + case P_FINISHING: + /* stop keeping track of 3D mouse position */ # ifdef NDOF_WALK_DEBUG - puts("stop keeping track of 3D mouse position"); + puts("stop keeping track of 3D mouse position"); # endif - if (walk->ndof) { - MEM_freeN(walk->ndof); - // free(walk->ndof); - walk->ndof = NULL; - } - - /* update the time else the view will jump when 2D mouse/timer resume */ - walk->time_lastdraw = PIL_check_seconds_timer(); - - break; - default: - break; /* should always be one of the above 3 */ - } - } + if (walk->ndof) { + MEM_freeN(walk->ndof); + // free(walk->ndof); + walk->ndof = NULL; + } + + /* update the time else the view will jump when 2D mouse/timer resume */ + walk->time_lastdraw = PIL_check_seconds_timer(); + + break; + default: + break; /* should always be one of the above 3 */ + } + } #endif /* WITH_INPUT_NDOF */ - /* handle modal keymap first */ - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case WALK_MODAL_CANCEL: - walk->state = WALK_CANCEL; - break; - case WALK_MODAL_CONFIRM: - walk->state = WALK_CONFIRM; - break; - - case WALK_MODAL_ACCELERATE: - base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f); - break; - case WALK_MODAL_DECELERATE: - base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f); - break; - - /* implement WASD keys */ - case WALK_MODAL_DIR_FORWARD: - walk->active_directions |= WALK_BIT_FORWARD; - break; - case WALK_MODAL_DIR_BACKWARD: - walk->active_directions |= WALK_BIT_BACKWARD; - break; - case WALK_MODAL_DIR_LEFT: - walk->active_directions |= WALK_BIT_LEFT; - break; - case WALK_MODAL_DIR_RIGHT: - walk->active_directions |= WALK_BIT_RIGHT; - break; - case WALK_MODAL_DIR_UP: - walk->active_directions |= WALK_BIT_UP; - break; - case WALK_MODAL_DIR_DOWN: - walk->active_directions |= WALK_BIT_DOWN; - break; - - case WALK_MODAL_DIR_FORWARD_STOP: - walk->active_directions &= ~WALK_BIT_FORWARD; - break; - case WALK_MODAL_DIR_BACKWARD_STOP: - walk->active_directions &= ~WALK_BIT_BACKWARD; - break; - case WALK_MODAL_DIR_LEFT_STOP: - walk->active_directions &= ~WALK_BIT_LEFT; - break; - case WALK_MODAL_DIR_RIGHT_STOP: - walk->active_directions &= ~WALK_BIT_RIGHT; - break; - case WALK_MODAL_DIR_UP_STOP: - walk->active_directions &= ~WALK_BIT_UP; - break; - case WALK_MODAL_DIR_DOWN_STOP: - walk->active_directions &= ~WALK_BIT_DOWN; - break; - - case WALK_MODAL_FAST_ENABLE: - walk->is_fast = true; - break; - case WALK_MODAL_FAST_DISABLE: - walk->is_fast = false; - break; - case WALK_MODAL_SLOW_ENABLE: - walk->is_slow = true; - break; - case WALK_MODAL_SLOW_DISABLE: - walk->is_slow = false; - break; + /* handle modal keymap first */ + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case WALK_MODAL_CANCEL: + walk->state = WALK_CANCEL; + break; + case WALK_MODAL_CONFIRM: + walk->state = WALK_CONFIRM; + break; + + case WALK_MODAL_ACCELERATE: + base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f); + break; + case WALK_MODAL_DECELERATE: + base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f); + break; + + /* implement WASD keys */ + case WALK_MODAL_DIR_FORWARD: + walk->active_directions |= WALK_BIT_FORWARD; + break; + case WALK_MODAL_DIR_BACKWARD: + walk->active_directions |= WALK_BIT_BACKWARD; + break; + case WALK_MODAL_DIR_LEFT: + walk->active_directions |= WALK_BIT_LEFT; + break; + case WALK_MODAL_DIR_RIGHT: + walk->active_directions |= WALK_BIT_RIGHT; + break; + case WALK_MODAL_DIR_UP: + walk->active_directions |= WALK_BIT_UP; + break; + case WALK_MODAL_DIR_DOWN: + walk->active_directions |= WALK_BIT_DOWN; + break; + + case WALK_MODAL_DIR_FORWARD_STOP: + walk->active_directions &= ~WALK_BIT_FORWARD; + break; + case WALK_MODAL_DIR_BACKWARD_STOP: + walk->active_directions &= ~WALK_BIT_BACKWARD; + break; + case WALK_MODAL_DIR_LEFT_STOP: + walk->active_directions &= ~WALK_BIT_LEFT; + break; + case WALK_MODAL_DIR_RIGHT_STOP: + walk->active_directions &= ~WALK_BIT_RIGHT; + break; + case WALK_MODAL_DIR_UP_STOP: + walk->active_directions &= ~WALK_BIT_UP; + break; + case WALK_MODAL_DIR_DOWN_STOP: + walk->active_directions &= ~WALK_BIT_DOWN; + break; + + case WALK_MODAL_FAST_ENABLE: + walk->is_fast = true; + break; + case WALK_MODAL_FAST_DISABLE: + walk->is_fast = false; + break; + case WALK_MODAL_SLOW_ENABLE: + walk->is_slow = true; + break; + case WALK_MODAL_SLOW_DISABLE: + walk->is_slow = false; + break; #define JUMP_SPEED_MIN 1.0f #define JUMP_TIME_MAX 0.2f /* s */ #define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height) - case WALK_MODAL_JUMP_STOP: - if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) { - float t; - - /* delta time */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - - /* reduce the veolocity, if JUMP wasn't hold for long enough */ - t = min_ff(t, JUMP_TIME_MAX); - walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; - - /* when jumping, duration is how long it takes before we start going down */ - walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); - - /* no more increase of jump speed */ - walk->gravity_state = WALK_GRAVITY_STATE_ON; - } - break; - case WALK_MODAL_JUMP: - if ((walk->navigation_mode == WALK_MODE_GRAVITY) && - (walk->gravity_state == WALK_GRAVITY_STATE_OFF) && - (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) - { - /* no need to check for ground, - * walk->gravity wouldn't be off - * if we were over a hole */ - walk->gravity_state = WALK_GRAVITY_STATE_JUMP; - walk->speed_jump = JUMP_SPEED_MAX; - - walk->teleport.initial_time = PIL_check_seconds_timer(); - copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); - - /* using previous vec because WASD keys are not called when SPACE is */ - copy_v2_v2(walk->teleport.direction, walk->dvec_prev); - - /* when jumping, duration is how long it takes before we start going down */ - walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); - } - - break; - - case WALK_MODAL_TELEPORT: - { - float loc[3], nor[3]; - float distance; - bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance); - - /* in case we are teleporting middle way from a jump */ - walk->speed_jump = 0.0f; - - if (ret) { - WalkTeleport *teleport = &walk->teleport; - teleport->state = WALK_TELEPORT_STATE_ON; - teleport->initial_time = PIL_check_seconds_timer(); - teleport->duration = U.walk_navigation.teleport_time; - - teleport->navigation_mode = walk->navigation_mode; - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - - copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); - - /* stop the camera from a distance (camera height) */ - normalize_v3_length(nor, walk->view_height); - add_v3_v3(loc, nor); - - sub_v3_v3v3(teleport->direction, loc, teleport->origin); - } - else { - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - } - break; - } + case WALK_MODAL_JUMP_STOP: + if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) { + float t; + + /* delta time */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + + /* reduce the veolocity, if JUMP wasn't hold for long enough */ + t = min_ff(t, JUMP_TIME_MAX); + walk->speed_jump = JUMP_SPEED_MIN + + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; + + /* when jumping, duration is how long it takes before we start going down */ + walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); + + /* no more increase of jump speed */ + walk->gravity_state = WALK_GRAVITY_STATE_ON; + } + break; + case WALK_MODAL_JUMP: + if ((walk->navigation_mode == WALK_MODE_GRAVITY) && + (walk->gravity_state == WALK_GRAVITY_STATE_OFF) && + (walk->teleport.state == WALK_TELEPORT_STATE_OFF)) { + /* no need to check for ground, + * walk->gravity wouldn't be off + * if we were over a hole */ + walk->gravity_state = WALK_GRAVITY_STATE_JUMP; + walk->speed_jump = JUMP_SPEED_MAX; + + walk->teleport.initial_time = PIL_check_seconds_timer(); + copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); + + /* using previous vec because WASD keys are not called when SPACE is */ + copy_v2_v2(walk->teleport.direction, walk->dvec_prev); + + /* when jumping, duration is how long it takes before we start going down */ + walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump); + } + + break; + + case WALK_MODAL_TELEPORT: { + float loc[3], nor[3]; + float distance; + bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance); + + /* in case we are teleporting middle way from a jump */ + walk->speed_jump = 0.0f; + + if (ret) { + WalkTeleport *teleport = &walk->teleport; + teleport->state = WALK_TELEPORT_STATE_ON; + teleport->initial_time = PIL_check_seconds_timer(); + teleport->duration = U.walk_navigation.teleport_time; + + teleport->navigation_mode = walk->navigation_mode; + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + + copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]); + + /* stop the camera from a distance (camera height) */ + normalize_v3_length(nor, walk->view_height); + add_v3_v3(loc, nor); + + sub_v3_v3v3(teleport->direction, loc, teleport->origin); + } + else { + walk->teleport.state = WALK_TELEPORT_STATE_OFF; + } + break; + } #undef JUMP_SPEED_MAX #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: - if (walk->navigation_mode == WALK_MODE_GRAVITY) { - walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); - } - else { /* WALK_MODE_FREE */ - walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); - } - break; - } - } + case WALK_MODAL_TOGGLE: + if (walk->navigation_mode == WALK_MODE_GRAVITY) { + walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE); + } + else { /* WALK_MODE_FREE */ + walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY); + } + break; + } + } } -static void walkMoveCamera(bContext *C, WalkInfo *walk, - const bool do_rotate, const bool do_translate) +static void walkMoveCamera(bContext *C, + WalkInfo *walk, + const bool do_rotate, + const bool do_translate) { - ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate); + ED_view3d_cameracontrol_update(walk->v3d_camera_control, true, C, do_rotate, do_translate); } static float getFreeFallDistance(const float gravity, const float time) { - return gravity * (time * time) * 0.5f; + return gravity * (time * time) * 0.5f; } static float getVelocityZeroTime(const float gravity, const float velocity) { - return velocity / gravity; + return velocity / gravity; } static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) @@ -938,361 +956,347 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) - /* walk mode - Ctrl+Shift+F - * a walk loop where the user can move move the view as if they are in a walk game - */ - RegionView3D *rv3d = walk->rv3d; - ARegion *ar = walk->ar; + /* walk mode - Ctrl+Shift+F + * a walk loop where the user can move move the view as if they are in a walk game + */ + RegionView3D *rv3d = walk->rv3d; + ARegion *ar = walk->ar; - /* 3x3 copy of the view matrix so we can move along the view axis */ - float mat[3][3]; - /* this is the direction that's added to the view offset per redraw */ - float dvec[3] = {0.0f, 0.0f, 0.0f}; + /* 3x3 copy of the view matrix so we can move along the view axis */ + float mat[3][3]; + /* this is the direction that's added to the view offset per redraw */ + float dvec[3] = {0.0f, 0.0f, 0.0f}; - int moffset[2]; /* mouse offset from the views center */ - float tmp_quat[4]; /* used for rotating the view */ + int moffset[2]; /* mouse offset from the views center */ + float tmp_quat[4]; /* used for rotating the view */ #ifdef NDOF_WALK_DEBUG - { - static uint iteration = 1; - printf("walk timer %d\n", iteration++); - } + { + static uint iteration = 1; + printf("walk timer %d\n", iteration++); + } #endif - { - /* mouse offset from the center */ - copy_v2_v2_int(moffset, walk->moffset); - - /* apply moffset so we can re-accumulate */ - walk->moffset[0] = 0; - walk->moffset[1] = 0; - - /* revert mouse */ - if (walk->is_reversed) { - moffset[1] = -moffset[1]; - } - - /* Should we redraw? */ - if ((walk->active_directions) || - moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF) - { - float dvec_tmp[3]; - - /* time how fast it takes for us to redraw, - * this is so simple scenes don't walk too fast */ - double time_current; - float time_redraw; + { + /* mouse offset from the center */ + copy_v2_v2_int(moffset, walk->moffset); + + /* apply moffset so we can re-accumulate */ + walk->moffset[0] = 0; + walk->moffset[1] = 0; + + /* revert mouse */ + if (walk->is_reversed) { + moffset[1] = -moffset[1]; + } + + /* Should we redraw? */ + if ((walk->active_directions) || moffset[0] || moffset[1] || + walk->teleport.state == WALK_TELEPORT_STATE_ON || + walk->gravity_state != WALK_GRAVITY_STATE_OFF) { + float dvec_tmp[3]; + + /* time how fast it takes for us to redraw, + * this is so simple scenes don't walk too fast */ + double time_current; + float time_redraw; #ifdef NDOF_WALK_DRAW_TOOMUCH - walk->redraw = 1; + walk->redraw = 1; #endif - time_current = PIL_check_seconds_timer(); - time_redraw = (float)(time_current - walk->time_lastdraw); - - walk->time_lastdraw = time_current; - - /* base speed in m/s */ - walk->speed = WALK_MOVE_SPEED; - - if (walk->is_fast) { - walk->speed *= WALK_BOOST_FACTOR; - } - else if (walk->is_slow) { - walk->speed *= 1.0f / WALK_BOOST_FACTOR; - } - - copy_m3_m4(mat, rv3d->viewinv); + time_current = PIL_check_seconds_timer(); + time_redraw = (float)(time_current - walk->time_lastdraw); - { - /* rotate about the X axis- look up/down */ - if (moffset[1]) { - float upvec[3]; - float angle; - float y; + walk->time_lastdraw = time_current; - /* relative offset */ - y = (float) moffset[1] / ar->winy; + /* base speed in m/s */ + walk->speed = WALK_MOVE_SPEED; - /* speed factor */ - y *= WALK_ROTATE_FAC; + if (walk->is_fast) { + walk->speed *= WALK_BOOST_FACTOR; + } + else if (walk->is_slow) { + walk->speed *= 1.0f / WALK_BOOST_FACTOR; + } - /* user adjustment factor */ - y *= walk->mouse_speed; + copy_m3_m4(mat, rv3d->viewinv); - /* clamp the angle limits */ - /* it ranges from 90.0f to -90.0f */ - angle = -asinf(rv3d->viewmat[2][2]); + { + /* rotate about the X axis- look up/down */ + if (moffset[1]) { + float upvec[3]; + float angle; + float y; - if (angle > WALK_TOP_LIMIT && y > 0.0f) { - y = 0.0f; - } - else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) { - y = 0.0f; - } + /* relative offset */ + y = (float)moffset[1] / ar->winy; - copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); - mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat(tmp_quat, upvec, -y); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - } + /* speed factor */ + y *= WALK_ROTATE_FAC; - /* rotate about the Y axis- look left/right */ - if (moffset[0]) { - float upvec[3]; - float x; + /* user adjustment factor */ + y *= walk->mouse_speed; - /* if we're upside down invert the moffset */ - copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); - mul_m3_v3(mat, upvec); + /* clamp the angle limits */ + /* it ranges from 90.0f to -90.0f */ + angle = -asinf(rv3d->viewmat[2][2]); - if (upvec[2] < 0.0f) { - moffset[0] = -moffset[0]; - } + if (angle > WALK_TOP_LIMIT && y > 0.0f) { + y = 0.0f; + } + else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f) { + y = 0.0f; + } - /* relative offset */ - x = (float) moffset[0] / ar->winx; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, -y); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + } - /* speed factor */ - x *= WALK_ROTATE_FAC; + /* rotate about the Y axis- look left/right */ + if (moffset[0]) { + float upvec[3]; + float x; - /* user adjustment factor */ - x *= walk->mouse_speed; + /* if we're upside down invert the moffset */ + copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f); + mul_m3_v3(mat, upvec); - /* Rotate about the relative up vec */ - axis_angle_to_quat_single(tmp_quat, 'Z', x); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); - } - } + if (upvec[2] < 0.0f) { + moffset[0] = -moffset[0]; + } - /* WASD - 'move' translation code */ - if ((walk->active_directions) && - (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) - { + /* relative offset */ + x = (float)moffset[0] / ar->winx; - short direction; - zero_v3(dvec); + /* speed factor */ + x *= WALK_ROTATE_FAC; - if ((walk->active_directions & WALK_BIT_FORWARD) || - (walk->active_directions & WALK_BIT_BACKWARD)) - { + /* user adjustment factor */ + x *= walk->mouse_speed; - direction = 0; + /* Rotate about the relative up vec */ + axis_angle_to_quat_single(tmp_quat, 'Z', x); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + } + } - if ((walk->active_directions & WALK_BIT_FORWARD)) { - direction += 1; - } + /* WASD - 'move' translation code */ + if ((walk->active_directions) && (walk->gravity_state == WALK_GRAVITY_STATE_OFF)) { - if ((walk->active_directions & WALK_BIT_BACKWARD)) { - direction -= 1; - } + short direction; + zero_v3(dvec); - copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); - mul_m3_v3(mat, dvec_tmp); + if ((walk->active_directions & WALK_BIT_FORWARD) || + (walk->active_directions & WALK_BIT_BACKWARD)) { - if (walk->navigation_mode == WALK_MODE_GRAVITY) { - dvec_tmp[2] = 0.0f; - } + direction = 0; - normalize_v3(dvec_tmp); - add_v3_v3(dvec, dvec_tmp); + if ((walk->active_directions & WALK_BIT_FORWARD)) { + direction += 1; + } - } + if ((walk->active_directions & WALK_BIT_BACKWARD)) { + direction -= 1; + } - if ((walk->active_directions & WALK_BIT_LEFT) || - (walk->active_directions & WALK_BIT_RIGHT)) - { + copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); + mul_m3_v3(mat, dvec_tmp); - direction = 0; + if (walk->navigation_mode == WALK_MODE_GRAVITY) { + dvec_tmp[2] = 0.0f; + } - if ((walk->active_directions & WALK_BIT_LEFT)) { - direction += 1; - } + normalize_v3(dvec_tmp); + add_v3_v3(dvec, dvec_tmp); + } - if ((walk->active_directions & WALK_BIT_RIGHT)) { - direction -= 1; - } + if ((walk->active_directions & WALK_BIT_LEFT) || + (walk->active_directions & WALK_BIT_RIGHT)) { - dvec_tmp[0] = direction * rv3d->viewinv[0][0]; - dvec_tmp[1] = direction * rv3d->viewinv[0][1]; - dvec_tmp[2] = 0.0f; + direction = 0; - normalize_v3(dvec_tmp); - add_v3_v3(dvec, dvec_tmp); + if ((walk->active_directions & WALK_BIT_LEFT)) { + direction += 1; + } - } + if ((walk->active_directions & WALK_BIT_RIGHT)) { + direction -= 1; + } - if ((walk->active_directions & WALK_BIT_UP) || - (walk->active_directions & WALK_BIT_DOWN)) - { + dvec_tmp[0] = direction * rv3d->viewinv[0][0]; + dvec_tmp[1] = direction * rv3d->viewinv[0][1]; + dvec_tmp[2] = 0.0f; - if (walk->navigation_mode == WALK_MODE_FREE) { + normalize_v3(dvec_tmp); + add_v3_v3(dvec, dvec_tmp); + } - direction = 0; - - if ((walk->active_directions & WALK_BIT_UP)) { - direction -= 1; - } - - if ((walk->active_directions & WALK_BIT_DOWN)) { - direction = 1; - } - - copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); - add_v3_v3(dvec, dvec_tmp); - } - } - - /* apply movement */ - mul_v3_fl(dvec, walk->speed * time_redraw); - } - - /* stick to the floor */ - if (walk->navigation_mode == WALK_MODE_GRAVITY && - ELEM(walk->gravity_state, - WALK_GRAVITY_STATE_OFF, - WALK_GRAVITY_STATE_START)) - { - - bool ret; - float ray_distance; - float difference = -100.0f; - float fall_distance; - - ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); - - if (ret) { - difference = walk->view_height - ray_distance; - } - - /* the distance we would fall naturally smoothly enough that we - * can manually drop the object without activating gravity */ - fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR; - - if (fabsf(difference) < fall_distance) { - /* slope/stairs */ - dvec[2] -= difference; - - /* in case we switched from FREE to GRAVITY too close to the ground */ - if (walk->gravity_state == WALK_GRAVITY_STATE_START) { - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - } - } - else { - /* hijack the teleport variables */ - walk->teleport.initial_time = PIL_check_seconds_timer(); - walk->gravity_state = WALK_GRAVITY_STATE_ON; - walk->teleport.duration = 0.0f; - - copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); - copy_v2_v2(walk->teleport.direction, dvec); - - } - } - - /* Falling or jumping) */ - if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) { - float t; - float z_cur, z_new; - bool ret; - float ray_distance, difference = -100.0f; - - /* delta time */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - - /* keep moving if we were moving */ - copy_v2_v2(dvec, walk->teleport.direction); - - z_cur = walk->rv3d->viewinv[3][2]; - z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; - - /* jump */ - z_new += t * walk->speed_jump * walk->grid; - - /* duration is the jump duration */ - if (t > walk->teleport.duration) { - - /* check to see if we are landing */ - ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); - - if (ret) { - difference = walk->view_height - ray_distance; - } - - if (difference > 0.0f) { - /* quit falling, lands at "view_height" from the floor */ - dvec[2] -= difference; - walk->gravity_state = WALK_GRAVITY_STATE_OFF; - walk->speed_jump = 0.0f; - } - else { - /* keep falling */ - dvec[2] = z_cur - z_new; - } - } - else { - /* keep going up (jump) */ - dvec[2] = z_cur - z_new; - } - } - - /* Teleport */ - else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) { - float t; /* factor */ - float new_loc[3]; - float cur_loc[3]; - - /* linear interpolation */ - t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - t /= walk->teleport.duration; - - /* clamp so we don't go past our limit */ - if (t >= 1.0f) { - t = 1.0f; - walk->teleport.state = WALK_TELEPORT_STATE_OFF; - walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode); - } - - mul_v3_v3fl(new_loc, walk->teleport.direction, t); - add_v3_v3(new_loc, walk->teleport.origin); - - copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]); - sub_v3_v3v3(dvec, cur_loc, new_loc); - } - - if (rv3d->persp == RV3D_CAMOB) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - if (lock_ob->protectflag & OB_LOCK_LOCX) { - dvec[0] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCY) { - dvec[1] = 0.0f; - } - if (lock_ob->protectflag & OB_LOCK_LOCZ) { - dvec[2] = 0.0f; - } - } - - /* scale the movement to the scene size */ - mul_v3_v3fl(dvec_tmp, dvec, walk->grid); - add_v3_v3(rv3d->ofs, dvec_tmp); - - if (rv3d->persp == RV3D_CAMOB) { - const bool do_rotate = (moffset[0] || moffset[1]); - const bool do_translate = (walk->speed != 0.0f); - walkMoveCamera(C, walk, do_rotate, do_translate); - } - } - else { - /* we're not redrawing but we need to update the time else the view will jump */ - walk->time_lastdraw = PIL_check_seconds_timer(); - } - /* end drawing */ - copy_v3_v3(walk->dvec_prev, dvec); - } - - return OPERATOR_FINISHED; + if ((walk->active_directions & WALK_BIT_UP) || (walk->active_directions & WALK_BIT_DOWN)) { + + if (walk->navigation_mode == WALK_MODE_FREE) { + + direction = 0; + + if ((walk->active_directions & WALK_BIT_UP)) { + direction -= 1; + } + + if ((walk->active_directions & WALK_BIT_DOWN)) { + direction = 1; + } + + copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction); + add_v3_v3(dvec, dvec_tmp); + } + } + + /* apply movement */ + mul_v3_fl(dvec, walk->speed * time_redraw); + } + + /* stick to the floor */ + if (walk->navigation_mode == WALK_MODE_GRAVITY && + ELEM(walk->gravity_state, WALK_GRAVITY_STATE_OFF, WALK_GRAVITY_STATE_START)) { + + bool ret; + float ray_distance; + float difference = -100.0f; + float fall_distance; + + ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); + + if (ret) { + difference = walk->view_height - ray_distance; + } + + /* the distance we would fall naturally smoothly enough that we + * can manually drop the object without activating gravity */ + fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR; + + if (fabsf(difference) < fall_distance) { + /* slope/stairs */ + dvec[2] -= difference; + + /* in case we switched from FREE to GRAVITY too close to the ground */ + if (walk->gravity_state == WALK_GRAVITY_STATE_START) { + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + } + } + else { + /* hijack the teleport variables */ + walk->teleport.initial_time = PIL_check_seconds_timer(); + walk->gravity_state = WALK_GRAVITY_STATE_ON; + walk->teleport.duration = 0.0f; + + copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]); + copy_v2_v2(walk->teleport.direction, dvec); + } + } + + /* Falling or jumping) */ + if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) { + float t; + float z_cur, z_new; + bool ret; + float ray_distance, difference = -100.0f; + + /* delta time */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + + /* keep moving if we were moving */ + copy_v2_v2(dvec, walk->teleport.direction); + + z_cur = walk->rv3d->viewinv[3][2]; + z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid; + + /* jump */ + z_new += t * walk->speed_jump * walk->grid; + + /* duration is the jump duration */ + if (t > walk->teleport.duration) { + + /* check to see if we are landing */ + ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance); + + if (ret) { + difference = walk->view_height - ray_distance; + } + + if (difference > 0.0f) { + /* quit falling, lands at "view_height" from the floor */ + dvec[2] -= difference; + walk->gravity_state = WALK_GRAVITY_STATE_OFF; + walk->speed_jump = 0.0f; + } + else { + /* keep falling */ + dvec[2] = z_cur - z_new; + } + } + else { + /* keep going up (jump) */ + dvec[2] = z_cur - z_new; + } + } + + /* Teleport */ + else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) { + float t; /* factor */ + float new_loc[3]; + float cur_loc[3]; + + /* linear interpolation */ + t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); + t /= walk->teleport.duration; + + /* clamp so we don't go past our limit */ + if (t >= 1.0f) { + t = 1.0f; + walk->teleport.state = WALK_TELEPORT_STATE_OFF; + walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode); + } + + mul_v3_v3fl(new_loc, walk->teleport.direction, t); + add_v3_v3(new_loc, walk->teleport.origin); + + copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]); + sub_v3_v3v3(dvec, cur_loc, new_loc); + } + + if (rv3d->persp == RV3D_CAMOB) { + Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + if (lock_ob->protectflag & OB_LOCK_LOCX) { + dvec[0] = 0.0f; + } + if (lock_ob->protectflag & OB_LOCK_LOCY) { + dvec[1] = 0.0f; + } + if (lock_ob->protectflag & OB_LOCK_LOCZ) { + dvec[2] = 0.0f; + } + } + + /* scale the movement to the scene size */ + mul_v3_v3fl(dvec_tmp, dvec, walk->grid); + add_v3_v3(rv3d->ofs, dvec_tmp); + + if (rv3d->persp == RV3D_CAMOB) { + const bool do_rotate = (moffset[0] || moffset[1]); + const bool do_translate = (walk->speed != 0.0f); + walkMoveCamera(C, walk, do_rotate, do_translate); + } + } + else { + /* we're not redrawing but we need to update the time else the view will jump */ + walk->time_lastdraw = PIL_check_seconds_timer(); + } + /* end drawing */ + copy_v3_v3(walk->dvec_prev, dvec); + } + + return OPERATOR_FINISHED; #undef WALK_ROTATE_FAC #undef WALK_ZUP_CORRECT_FAC #undef WALK_ZUP_CORRECT_ACCEL @@ -1306,121 +1310,124 @@ static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk) #ifdef WITH_INPUT_NDOF static void walkApply_ndof(bContext *C, WalkInfo *walk) { - Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - bool has_translate, has_rotate; - - view3d_ndof_fly(walk->ndof, - walk->v3d, walk->rv3d, - walk->is_slow, lock_ob ? lock_ob->protectflag : 0, - &has_translate, &has_rotate); - - if (has_translate || has_rotate) { - walk->redraw = true; - - if (walk->rv3d->persp == RV3D_CAMOB) { - walkMoveCamera(C, walk, has_rotate, has_translate); - } - } + Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + bool has_translate, has_rotate; + + view3d_ndof_fly(walk->ndof, + walk->v3d, + walk->rv3d, + walk->is_slow, + lock_ob ? lock_ob->protectflag : 0, + &has_translate, + &has_rotate); + + if (has_translate || has_rotate) { + walk->redraw = true; + + if (walk->rv3d->persp == RV3D_CAMOB) { + walkMoveCamera(C, walk, has_rotate, has_translate); + } + } } #endif /* WITH_INPUT_NDOF */ /****** walk operator ******/ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - WalkInfo *walk; + RegionView3D *rv3d = CTX_wm_region_view3d(C); + WalkInfo *walk; - if (rv3d->viewlock & RV3D_LOCKED) { - return OPERATOR_CANCELLED; - } + if (rv3d->viewlock & RV3D_LOCKED) { + return OPERATOR_CANCELLED; + } - walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation"); + walk = MEM_callocN(sizeof(WalkInfo), "NavigationWalkOperation"); - op->customdata = walk; + op->customdata = walk; - if (initWalkInfo(C, walk, op) == false) { - MEM_freeN(op->customdata); - return OPERATOR_CANCELLED; - } + if (initWalkInfo(C, walk, op) == false) { + MEM_freeN(op->customdata); + return OPERATOR_CANCELLED; + } - walkEvent(C, op, walk, event); + walkEvent(C, op, walk, event); - WM_event_add_modal_handler(C, op); + WM_event_add_modal_handler(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } static void walk_cancel(bContext *C, wmOperator *op) { - WalkInfo *walk = op->customdata; + WalkInfo *walk = op->customdata; - walk->state = WALK_CANCEL; - walkEnd(C, walk); - op->customdata = NULL; + walk->state = WALK_CANCEL; + walkEnd(C, walk); + op->customdata = NULL; } static int walk_modal(bContext *C, wmOperator *op, const wmEvent *event) { - int exit_code; - bool do_draw = false; - WalkInfo *walk = op->customdata; - RegionView3D *rv3d = walk->rv3d; - Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); + int exit_code; + bool do_draw = false; + WalkInfo *walk = op->customdata; + RegionView3D *rv3d = walk->rv3d; + Object *walk_object = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control); - walk->redraw = false; + walk->redraw = false; - walkEvent(C, op, walk, event); + walkEvent(C, op, walk, event); #ifdef WITH_INPUT_NDOF - if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ - if (event->type == NDOF_MOTION) { - walkApply_ndof(C, walk); - } - } - else + if (walk->ndof) { /* 3D mouse overrules [2D mouse + timer] */ + if (event->type == NDOF_MOTION) { + walkApply_ndof(C, walk); + } + } + else #endif /* WITH_INPUT_NDOF */ - if (event->type == TIMER && event->customdata == walk->timer) { - walkApply(C, op, walk); - } + if (event->type == TIMER && event->customdata == walk->timer) { + walkApply(C, op, walk); + } - do_draw |= walk->redraw; + do_draw |= walk->redraw; - exit_code = walkEnd(C, walk); + exit_code = walkEnd(C, walk); - if (exit_code != OPERATOR_RUNNING_MODAL) { - do_draw = true; - } + if (exit_code != OPERATOR_RUNNING_MODAL) { + do_draw = true; + } - if (do_draw) { - if (rv3d->persp == RV3D_CAMOB) { - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object); - } + if (do_draw) { + if (rv3d->persp == RV3D_CAMOB) { + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, walk_object); + } - // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now - // puts("redraw!"); - ED_region_tag_redraw(CTX_wm_region(C)); - } + // too frequent, commented with NDOF_WALK_DRAW_TOOMUCH for now + // puts("redraw!"); + ED_region_tag_redraw(CTX_wm_region(C)); + } - if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { - ED_workspace_status_text(C, NULL); - } + if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { + ED_workspace_status_text(C, NULL); + } - return exit_code; + return exit_code; } void VIEW3D_OT_walk(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Walk Navigation"; - ot->description = "Interactively walk around the scene"; - ot->idname = "VIEW3D_OT_walk"; - - /* api callbacks */ - ot->invoke = walk_invoke; - ot->cancel = walk_cancel; - ot->modal = walk_modal; - ot->poll = ED_operator_region_view3d_active; - - /* flags */ - ot->flag = OPTYPE_BLOCKING; + /* identifiers */ + ot->name = "Walk Navigation"; + ot->description = "Interactively walk around the scene"; + ot->idname = "VIEW3D_OT_walk"; + + /* api callbacks */ + ot->invoke = walk_invoke; + ot->cancel = walk_cancel; + ot->modal = walk_modal; + ot->poll = ED_operator_region_view3d_active; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; } |