diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2018-01-28 15:34:02 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2018-01-28 16:18:10 +0300 |
commit | 49c19ca679ea89209a18374d51377084f378f289 (patch) | |
tree | 7111a90a709920ed09386d0f1e8c00aaa8905ad7 /source/blender/editors | |
parent | e15dd419d43182f9b826210e9ae90803cb7626a4 (diff) | |
parent | dfbe4153721b6764a41c2e8de8f41c6cdab6fe7e (diff) |
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/editors')
44 files changed, 2782 insertions, 1825 deletions
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 2a84ca7f297..65c55b6cd22 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -31,6 +31,500 @@ set(SRC ) +# Order matches "UI_icons.h", final name will be formatted: "icons{size}_{name}.dat" +set(ICON_NAMES + question + error + cancel + tria_right + tria_down + tria_left + tria_up + arrow_leftright + plus + disclosure_tri_down + disclosure_tri_right + radiobut_off + radiobut_on + menu_panel + blender + grip + dot + collapsemenu + x + go_left + plug + ui + node + node_sel + fullscreen + splitscreen + rightarrow_thin + bordermove + viewzoom + zoomin + zoomout + panel_close + copy_id + eyedropper + link_area + auto + checkbox_dehlt + checkbox_hlt + unlocked + locked + unpinned + pinned + screen_back + rightarrow + downarrow_hlt + dotsup + dotsdown + link + inlink + plugin + help + ghost_enabled + color + linked + unlinked + hand + zoom_all + zoom_selected + zoom_previous + zoom_in + zoom_out + render_region + border_rect + border_lasso + freeze + stylus_pressure + ghost_disabled + new + file_tick + quit + url + recover_last + fullscreen_enter + fullscreen_exit + lamp + material + texture + anim + world + scene + edit + game + radio + script + particles + physics + speaker + texture_shaded + view3d + ipo + oops + buts + filesel + image_col + info + sequence + text + imasel + sound + action + nla + scriptwin + time + nodetree + logic + console + preferences + clip + asset_manager + object_datamode + editmode_hlt + facesel_hlt + vpaint_hlt + tpaint_hlt + wpaint_hlt + sculptmode_hlt + pose_hlt + particlemode + lightpaint + greasepencil_stroke_paint + scene_data + renderlayers + world_data + object_data + mesh_data + curve_data + meta_data + lattice_data + lamp_data + material_data + texture_data + anim_data + camera_data + particle_data + library_data_direct + group + armature_data + pose_data + bone_data + constraint + shapekey_data + constraint_bone + camera_stereo + package + uglypackage + brush_data + image_data + file + fcurve + font_data + render_result + surface_data + empty_data + settings + render_animation + render_still + library_data_broken + boids + strands + library_data_indirect + greasepencil + line_data + library_data_override + group_bone + group_vertex + group_vcol + group_uvs + rna + rna_add + outliner_ob_empty + outliner_ob_mesh + outliner_ob_curve + outliner_ob_lattice + outliner_ob_meta + outliner_ob_lamp + outliner_ob_camera + outliner_ob_armature + outliner_ob_font + outliner_ob_surface + outliner_ob_speaker + outliner_ob_force_field + outliner_ob_group_instance + outliner_ob_greasepencil + restrict_color_off + restrict_color_on + restrict_view_off + restrict_view_on + restrict_select_off + restrict_select_on + restrict_render_off + restrict_render_on + outliner_data_empty + outliner_data_mesh + outliner_data_curve + outliner_data_lattice + outliner_data_meta + outliner_data_lamp + outliner_data_camera + outliner_data_armature + outliner_data_font + outliner_data_surface + outliner_data_speaker + outliner_data_pose + outliner_data_greasepencil + mesh_plane + mesh_cube + mesh_circle + mesh_uvsphere + mesh_icosphere + mesh_grid + mesh_monkey + mesh_cylinder + mesh_torus + mesh_cone + mesh_capsule + lamp_point + lamp_sun + lamp_spot + lamp_hemi + lamp_area + meta_empty + meta_plane + meta_cube + meta_ball + meta_ellipsoid + meta_capsule + surface_ncurve + surface_ncircle + surface_nsurface + surface_ncylinder + surface_nsphere + surface_ntorus + curve_bezcurve + curve_bezcircle + curve_ncurve + curve_ncircle + curve_path + color_red + color_green + color_blue + tria_right_bar + tria_down_bar + tria_left_bar + tria_up_bar + force_force + force_wind + force_vortex + force_magnetic + force_harmonic + force_charge + force_lennardjones + force_texture + force_curve + force_boid + force_turbulence + force_drag + force_smokeflow + node_insert_on + node_insert_off + modifier + mod_wave + mod_build + mod_decim + mod_mirror + mod_soft + mod_subsurf + hook + mod_physics + mod_particles + mod_boolean + mod_edgesplit + mod_array + mod_uvproject + mod_displace + mod_curve + mod_lattice + constraint_data + mod_armature + mod_shrinkwrap + mod_cast + mod_meshdeform + mod_bevel + mod_smooth + mod_simpledeform + mod_mask + mod_cloth + mod_explode + mod_fluidsim + mod_multires + mod_smoke + mod_solidify + mod_screw + mod_vertex_weight + mod_dynamicpaint + mod_remesh + mod_ocean + mod_warp + mod_skin + mod_triangulate + mod_wireframe + mod_data_transfer + mod_normaledit + rec + play + ff + rew + pause + prev_keyframe + next_keyframe + play_audio + play_reverse + preview_range + action_tweak + pmarker_act + pmarker_sel + pmarker + marker_hlt + marker + space2 + space3 + keyingset + key_dehlt + key_hlt + mute_ipo_off + mute_ipo_on + visible_ipo_off + visible_ipo_on + driver + solo_off + solo_on + frame_prev + frame_next + nla_pushdown + ipo_constant + ipo_linear + ipo_bezier + ipo_sine + ipo_quad + ipo_cubic + ipo_quart + ipo_quint + ipo_expo + ipo_circ + ipo_bounce + ipo_elastic + ipo_back + ipo_ease_in + ipo_ease_out + ipo_ease_in_out + normalize_fcurves + vertexsel + edgesel + facesel + loopsel + rotate + cursor + rotatecollection + rotatecenter + rotactive + align + smoothcurve + spherecurve + rootcurve + sharpcurve + lincurve + nocurve + rndcurve + prop_off + prop_on + prop_con + particle_point + particle_tip + particle_path + man_trans + man_rot + man_scale + manipul + snap_off + snap_on + snap_normal + snap_grid + snap_vertex + snap_edge + snap_face + snap_volume + snap_increment + sticky_uvs_loc + sticky_uvs_disable + sticky_uvs_vert + clipuv_dehlt + clipuv_hlt + snap_peel_object + grid + object_origin + pastedown + copydown + pasteflipup + pasteflipdown + snap_surface + automerge_on + automerge_off + retopo + uv_vertexsel + uv_edgesel + uv_facesel + uv_islandsel + uv_sync_select + bbox + wire + solid + smooth + potato + ortho + lockview_off + lockview_on + axis_side + axis_front + axis_top + ndof_dom + ndof_turn + ndof_fly + ndof_trans + layer_used + layer_active + sortalpha + sortbyext + sorttime + sortsize + longdisplay + shortdisplay + ghost + imgdisplay + save_as + save_copy + bookmarks + fontpreview + filter + newfolder + open_recent + file_parent + file_refresh + file_folder + file_blend + file_image + file_movie + file_script + file_sound + file_font + file_text + recover_auto + save_prefs + link_blend + append_blend + import + export + external_data + load_factory + loop_back + loop_forwards + back + forward + file_hidden + file_backup + disk_drive + matplane + matsphere + matcube + monkey + hair + aliased + antialiased + mat_sphere_sky + wordwrap_off + wordwrap_on + syntax_off + syntax_on + linenumbers_off + linenumbers_on + scriptplugins + seq_sequencer + seq_preview + seq_luma_waveform + seq_chroma_scope + seq_histogram + seq_splitview + image_rgb + image_rgb_alpha + image_alpha + image_zdepth + imagefile +) + data_to_c_simple(../../../../release/datafiles/bfont.pfb SRC) data_to_c_simple(../../../../release/datafiles/bfont.ttf SRC) data_to_c_simple(../../../../release/datafiles/bmonofont.ttf SRC) @@ -53,12 +547,12 @@ if(WITH_BLENDER) #../../../../release/datafiles/blender_icons16.png #90 SRC) - data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 SRC) + data_to_c_simple_icons(../../../../release/datafiles/blender_icons16 "icon16_" "${ICON_NAMES}" SRC) #data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC) #svg_to_png(../../../../release/datafiles/blender_icons.svg #../../../../release/datafiles/blender_icons32.png #180 SRC) - data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 SRC) + data_to_c_simple_icons(../../../../release/datafiles/blender_icons32 "icon32_" "${ICON_NAMES}" SRC) #data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC) #svg_to_png(../../../../release/datafiles/prvicons.svg #../../../../release/datafiles/prvicons.png @@ -130,4 +624,6 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/startup.blend SRC) endif() +unset(ICON_NAMES) + blender_add_lib(bf_editor_datafiles "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index a82148788c8..22a3224e563 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -105,7 +105,8 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ED_gpencil_reset_layers_parent(gpd); } - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL); WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); return OPERATOR_FINISHED; @@ -153,7 +154,8 @@ static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op)) ts->gp_sculpt.alpha = 1.0f; } - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL); WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index e66e5e7462d..8201401296a 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -236,6 +236,8 @@ eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar, float perspm eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); +float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); + float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); bool ED_view3d_win_to_ray( @@ -308,8 +310,6 @@ void ED_view3d_clipping_set(struct RegionView3D *rv3d); void ED_view3d_clipping_enable(void); void ED_view3d_clipping_disable(void); -float ED_view3d_pixel_size(const struct RegionView3D *rv3d, const float co[3]); - float ED_view3d_radius_to_dist_persp(const float angle, const float radius); float ED_view3d_radius_to_dist_ortho(const float lens, const float radius); float ED_view3d_radius_to_dist( @@ -446,6 +446,9 @@ uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d) uint64_t ED_view3d_screen_datamask(const struct Scene *scene, const struct bScreen *screen); bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); +void ED_view3d_persp_switch_from_camera(struct View3D *v3d, struct RegionView3D *rv3d, const char persp); +bool ED_view3d_persp_ensure(struct View3D *v3d, struct ARegion *ar); + /* camera lock functions */ bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); @@ -462,7 +465,7 @@ bool ED_view3d_camera_lock_autokey( struct View3D *v3d, struct RegionView3D *rv3d, struct bContext *C, const bool do_rotate, const bool do_translate); -void ED_view3D_lock_clear(struct View3D *v3d); +void ED_view3d_lock_clear(struct View3D *v3d); #define VIEW3D_MARGIN 1.4f #define VIEW3D_DIST_FALLBACK 1.0f diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 0b846ad642f..b6714e80e80 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -190,8 +190,8 @@ DEF_ICON(SCULPTMODE_HLT) DEF_ICON(POSE_HLT) DEF_ICON(PARTICLEMODE) DEF_ICON(LIGHTPAINT) +DEF_ICON(GREASEPENCIL_STROKE_PAINT) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK063) DEF_ICON(BLANK064) DEF_ICON(BLANK065) DEF_ICON(BLANK066) @@ -313,6 +313,7 @@ DEF_ICON(OUTLINER_OB_SURFACE) DEF_ICON(OUTLINER_OB_SPEAKER) DEF_ICON(OUTLINER_OB_FORCE_FIELD) DEF_ICON(OUTLINER_OB_GROUP_INSTANCE) +DEF_ICON(OUTLINER_OB_GREASEPENCIL) DEF_ICON(OUTLINER_OB_GROOM) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK123) @@ -344,8 +345,8 @@ DEF_ICON(OUTLINER_DATA_FONT) DEF_ICON(OUTLINER_DATA_SURFACE) DEF_ICON(OUTLINER_DATA_SPEAKER) DEF_ICON(OUTLINER_DATA_POSE) +DEF_ICON(OUTLINER_DATA_GREASEPENCIL) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK130) DEF_ICON(BLANK131) DEF_ICON(BLANK132) DEF_ICON(BLANK133) @@ -713,8 +714,8 @@ DEF_ICON(CLIPUV_DEHLT) DEF_ICON(CLIPUV_HLT) DEF_ICON(SNAP_PEEL_OBJECT) DEF_ICON(GRID) +DEF_ICON(OBJECT_ORIGIN) #ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK221) DEF_ICON(BLANK222) DEF_ICON(BLANK224) DEF_ICON(BLANK225) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 5d7a45a7e48..6e09318314d 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1105,6 +1105,8 @@ void UI_context_active_but_prop_get_templateID( struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop); +uiBut *UI_region_active_but_get(struct ARegion *ar); + /* Styled text draw */ void UI_fontstyle_set(const struct uiFontStyle *fs); void UI_fontstyle_draw_ex(const struct uiFontStyle *fs, const struct rcti *rect, const char *str, @@ -1151,7 +1153,7 @@ void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p); /* ui_interface_region_tooltip.c */ struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but); struct ARegion *UI_tooltip_create_from_manipulator(struct bContext *C, struct wmManipulator *mpr); -void UI_tooltip_free(struct bContext *C, struct ARegion *ar); +void UI_tooltip_free(struct bContext *C, struct bScreen *sc, struct ARegion *ar); /* How long before a tool-tip shows. */ #define UI_TOOLTIP_DELAY 0.5 diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9c1cee915e4..3af64c8c5a6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -296,8 +296,6 @@ typedef struct uiHandleButtonData { ColorBand *coba; /* tooltip */ - ARegion *tooltip; - wmTimer *tooltiptimer; unsigned int tooltip_force : 1; /* auto open */ @@ -7701,12 +7699,12 @@ static bool button_modal_state(uiHandleButtonState state) */ void UI_but_tooltip_refresh(bContext *C, uiBut *but) { - uiHandleButtonData *data; - - data = but->active; - if (data && data->tooltip) { - UI_tooltip_free(C, data->tooltip); - data->tooltip = UI_tooltip_create_from_button(C, data->region, but); + uiHandleButtonData *data = but->active; + if (data) { + bScreen *sc = WM_window_get_active_screen(data->window); + if (sc->tool_tip && sc->tool_tip->region) { + WM_tooltip_refresh(C, data->window); + } } } @@ -7717,39 +7715,38 @@ void UI_but_tooltip_timer_remove(bContext *C, uiBut *but) data = but->active; if (data) { - - if (data->tooltiptimer) { - WM_event_remove_timer(data->wm, data->window, data->tooltiptimer); - data->tooltiptimer = NULL; - } - if (data->tooltip) { - UI_tooltip_free(C, data->tooltip); - data->tooltip = NULL; - } - if (data->autoopentimer) { WM_event_remove_timer(data->wm, data->window, data->autoopentimer); data->autoopentimer = NULL; } + + if (data->window) { + WM_tooltip_clear(C, data->window); + } + } +} + +static ARegion *ui_but_tooltip_init(bContext *C, ARegion *ar, bool *r_exit_on_event) +{ + uiBut *but = UI_region_active_but_get(ar); + *r_exit_on_event = false; + if (but) { + return UI_tooltip_create_from_button(C, ar, but); } + return NULL; } static void button_tooltip_timer_reset(bContext *C, uiBut *but) { wmWindowManager *wm = CTX_wm_manager(C); - uiHandleButtonData *data; - - data = but->active; + uiHandleButtonData *data = but->active; - if (data->tooltiptimer) { - WM_event_remove_timer(data->wm, data->window, data->tooltiptimer); - data->tooltiptimer = NULL; - } + WM_tooltip_timer_clear(C, data->window); if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) { if (!but->block->tooltipdisabled) { if (!wm->drags.first) { - data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, UI_TOOLTIP_DELAY); + WM_tooltip_timer_init(C, data->window, data->region, ui_but_tooltip_init); } } } @@ -8109,12 +8106,10 @@ void ui_but_active_free(const bContext *C, uiBut *but) } /* returns the active button with an optional checking function */ -static uiBut *ui_context_button_active(const bContext *C, bool (*but_check_cb)(uiBut *)) +static uiBut *ui_context_button_active(ARegion *ar, bool (*but_check_cb)(uiBut *)) { uiBut *but_found = NULL; - ARegion *ar = CTX_wm_region(C); - while (ar) { uiBlock *block; uiBut *but, *activebut = NULL; @@ -8157,12 +8152,17 @@ static bool ui_context_rna_button_active_test(uiBut *but) } static uiBut *ui_context_rna_button_active(const bContext *C) { - return ui_context_button_active(C, ui_context_rna_button_active_test); + return ui_context_button_active(CTX_wm_region(C), ui_context_rna_button_active_test); } uiBut *UI_context_active_but_get(const struct bContext *C) { - return ui_context_button_active(C, NULL); + return ui_context_button_active(CTX_wm_region(C), NULL); +} + +uiBut *UI_region_active_but_get(ARegion *ar) +{ + return ui_context_button_active(ar, NULL); } /** @@ -8445,16 +8445,8 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) } case TIMER: { - /* handle tooltip timer */ - if (event->customdata == data->tooltiptimer) { - WM_event_remove_timer(data->wm, data->window, data->tooltiptimer); - data->tooltiptimer = NULL; - - if (!data->tooltip) - data->tooltip = UI_tooltip_create_from_button(C, data->region, but); - } /* handle menu auto open timer */ - else if (event->customdata == data->autoopentimer) { + if (event->customdata == data->autoopentimer) { WM_event_remove_timer(data->wm, data->window, data->autoopentimer); data->autoopentimer = NULL; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index eeda0a25195..16525dfbc9e 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1485,7 +1485,7 @@ void ED_keymap_ui(wmKeyConfig *keyconf) * through until a suitable eyedropper for the active button is found */ WM_keymap_add_item(keymap, "UI_OT_eyedropper_color", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband", EKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS , KM_ALT, 0); + WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "UI_OT_eyedropper_id", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "UI_OT_eyedropper_depth", EKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 9a818efebee..07fbefa42e1 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -953,9 +953,9 @@ ARegion *UI_tooltip_create_from_manipulator(bContext *C, wmManipulator *mpr) return ui_tooltip_create_with_data(C, data, init_position, aspect); } -void UI_tooltip_free(bContext *C, ARegion *ar) +void UI_tooltip_free(bContext *C, bScreen *sc, ARegion *ar) { - ui_region_temp_remove(C, CTX_wm_screen(C), ar); + ui_region_temp_remove(C, sc, ar); } /** \} */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index b271b0b5bc6..dc68c8b58de 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1509,6 +1509,9 @@ static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), v2d->smooth_timer); v2d->smooth_timer = NULL; + + /* Event handling won't know if a UI item has been moved under the pointer. */ + WM_event_add_mousemove(C); } else { /* ease in/out */ diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index fc227a2aa75..1b7fd319da0 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -40,6 +40,8 @@ #include "BKE_main.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" + #include "ED_screen.h" #include "ED_object.h" @@ -447,6 +449,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op) min_chain_length, keep_bind_info) ) { + DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_BASE_FLAGS_UPDATE); return OPERATOR_FINISHED; } else { diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c index ce6992e7ad9..7e57b48c77c 100644 --- a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c +++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c @@ -133,7 +133,6 @@ static void button2d_draw_intern( if (select == false) { if (button->shape_batch[0] != NULL) { - glEnable(GL_POLYGON_SMOOTH); glEnable(GL_LINE_SMOOTH); glLineWidth(1.0f); for (uint i = 0; i < ARRAY_SIZE(button->shape_batch) && button->shape_batch[i]; i++) { @@ -146,7 +145,6 @@ static void button2d_draw_intern( GWN_batch_uniform_4f(button->shape_batch[i], "color", UNPACK4(color)); GWN_batch_draw(button->shape_batch[i]); } - glDisable(GL_POLYGON_SMOOTH); glDisable(GL_LINE_SMOOTH); gpuPopMatrix(); } @@ -206,9 +204,12 @@ static int manipulator_button2d_test_select( return -1; } -static int manipulator_button2d_cursor_get(wmManipulator *UNUSED(mpr)) +static int manipulator_button2d_cursor_get(wmManipulator *mpr) { - return BC_HANDCURSOR; + if (RNA_boolean_get(mpr->ptr, "show_drag")) { + return BC_NSEW_SCROLLCURSOR; + } + return CURSOR_STD; } static void manipulator_button2d_free(wmManipulator *mpr) @@ -248,6 +249,9 @@ static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt) /* Passed to 'GPU_batch_from_poly_2d_encoded' */ RNA_def_property(wt->srna, "shape", PROP_STRING, PROP_BYTESTRING); + + /* Currently only used for cursor display. */ + RNA_def_boolean(wt->srna, "show_drag", true, "Show Drag", ""); } void ED_manipulatortypes_button_2d(void) diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index d7e59a05772..bd2ad21d51c 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -75,7 +75,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, DerivedMesh *dm; Scene *scene = CTX_data_scene(C); EvaluationContext eval_ctx; - LinkNode *dms = NULL; + LinkNodePair dms_pair = {NULL, NULL}; int nverts, ntris, *tris; float *verts; @@ -90,7 +90,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, ob = (Object *) oblink->link; dm = mesh_create_derived_no_virtual(&eval_ctx, scene, ob, NULL, CD_MASK_MESH); DM_ensure_tessface(dm); - BLI_linklist_prepend(&dms, dm); + BLI_linklist_append(&dms_pair, dm); nverts += dm->getNumVerts(dm); nfaces = dm->getNumTessFaces(dm); @@ -106,6 +106,7 @@ static void createVertsTrisData(bContext *C, LinkNode *obs, *r_lay |= ob->lay; } + LinkNode *dms = dms_pair.list; /* create data */ verts = MEM_mallocN(sizeof(float) * 3 * nverts, "createVertsTrisData verts"); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index af131e270ef..89b131fa340 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -2123,7 +2123,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer #define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } #define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; } - Base *basen = NULL; + Base *base, *basen = NULL; Material ***matarar; Object *obn; ID *id; @@ -2136,7 +2136,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); DEG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - BKE_collection_object_add_from(scene, ob, obn); + base = BKE_view_layer_base_find(view_layer, ob); + if ((base != NULL) && (base->flag & BASE_VISIBLED)) { + BKE_collection_object_add_from(scene, ob, obn); + } + else { + LayerCollection *layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer); + BKE_collection_object_add(&scene->id, layer_collection->scene_collection, obn); + } basen = BKE_view_layer_base_find(view_layer, obn); /* 1) duplis should end up in same group as the original @@ -2486,13 +2493,13 @@ static int add_named_exec(bContext *C, wmOperator *op) clear_sca_new_poins(); /* BGE logic */ basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag); - BKE_scene_object_base_flag_sync_from_object(basen); if (basen == NULL) { BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); return OPERATOR_CANCELLED; } + BKE_scene_object_base_flag_sync_from_object(basen); basen->object->restrictflag &= ~OB_RESTRICT_VIEW; if (event) { @@ -2510,9 +2517,11 @@ static int add_named_exec(bContext *C, wmOperator *op) BKE_main_id_clear_newpoins(bmain); + /* TODO(sergey): Only update relations for the current scene. */ DEG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene); + 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; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index b351bc7f114..13cc53c04a7 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1679,9 +1679,6 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen } } - /* we reset filter objects because they should be regenerated after this */ - BLI_freelistN(&sc->filter_objects); - for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups); } @@ -1741,9 +1738,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in libblock_relink_scene_collection(msc); set_sca_new_poins(); - - /* TODO redo filter */ - TODO_LAYER_SYNC_FILTER } /* not an especially efficient function, only added so the single user diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 6fdbe5e88a2..270ba2a7947 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -427,7 +427,8 @@ static int material_slot_move_exec(bContext *C, wmOperator *op) MEM_freeN(slot_remap); DEG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 694770d088d..2e4e9127ed6 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -288,7 +288,7 @@ static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos } /** - * Only for edge lines between areas, and the blended join arrows. + * Only for edge lines between areas. */ void ED_screen_draw_edges(wmWindow *win) { @@ -326,6 +326,12 @@ void ED_screen_draw_edges(wmWindow *win) screen->do_draw = false; } +/** + * The blended join arrows. + * + * \param sa1: Area from which the resultant originates. + * \param sa2: Target area that will be replaced. + */ void ED_screen_draw_join_shape(ScrArea *sa1, ScrArea *sa2) { unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index b73174917f3..030c24b0061 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1479,8 +1479,6 @@ static void SCREEN_OT_area_move(wmOperatorType *ot) */ typedef struct sAreaSplitData { - int x, y; /* last used mouse position */ - int origval; /* for move areas */ int bigger, smaller; /* constraints for moving new edge */ int delta; /* delta move edge */ @@ -1727,9 +1725,6 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) sd = (sAreaSplitData *)op->customdata; - sd->x = event->x; - sd->y = event->y; - if (event->type == EVT_ACTIONZONE_AREA) { /* do the split */ @@ -1797,28 +1792,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) /* execute the events */ switch (event->type) { case MOUSEMOVE: - { - const int dir = RNA_property_enum_get(op->ptr, prop_dir); - - sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval; - if (sd->previewmode == 0) - area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, sd->do_snap); - else { - if (sd->sarea) { - ED_area_tag_redraw(sd->sarea); - } - /* area context not set */ - sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y); - - if (sd->sarea) { - ED_area_tag_redraw(sd->sarea); - update_factor = true; - } - - CTX_wm_screen(C)->do_draw = true; - } + update_factor = true; break; - } + case LEFTMOUSE: if (sd->previewmode) { area_split_apply(C, op); @@ -1845,8 +1821,6 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) RNA_property_enum_set(op->ptr, prop_dir, (dir == 'v') ? 'h' : 'v'); area_split_preview_update_cursor(C, op); update_factor = true; - - ED_area_tag_redraw(sd->sarea); } } } @@ -1866,31 +1840,53 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) if (update_factor) { const int dir = RNA_property_enum_get(op->ptr, prop_dir); - float fac; - if (dir == 'v') { - sd->origsize = sd->sarea->winx; - sd->origmin = sd->sarea->totrct.xmin; + sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval; + + if (sd->previewmode == 0) { + if (sd->do_snap) { + const int snap_loc = area_snap_calc_location( + CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->bigger, sd->smaller); + sd->delta = snap_loc - sd->origval; + } + area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, false); } else { - sd->origsize = sd->sarea->winy; - sd->origmin = sd->sarea->totrct.ymin; - } + if (sd->sarea) { + ED_area_tag_redraw(sd->sarea); + } + /* area context not set */ + sd->sarea = BKE_screen_find_area_xy(CTX_wm_screen(C), SPACE_TYPE_ANY, event->x, event->y); + + if (sd->sarea) { + ScrArea *sa = sd->sarea; + if (dir == 'v') { + sd->origsize = sa->winx; + sd->origmin = sa->totrct.xmin; + } + else { + sd->origsize = sa->winy; + sd->origmin = sa->totrct.ymin; + } - if (sd->do_snap) { - ScrArea *sa = sd->sarea; - sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1; + if (sd->do_snap) { + sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 1; - int snap_loc = area_snap_calc_location( - CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->origmin + sd->origsize, -sd->origmin); + const int snap_loc = area_snap_calc_location( + CTX_wm_screen(C), sd->delta, sd->origval, dir, sd->origmin + sd->origsize, -sd->origmin); - sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0; - fac = snap_loc - sd->origmin; - } - else { - fac = (dir == 'v') ? event->x - sd->origmin : event->y - sd->origmin; + sa->v1->editflag = sa->v2->editflag = sa->v3->editflag = sa->v4->editflag = 0; + sd->delta = snap_loc - sd->origval; + } + + ED_area_tag_redraw(sd->sarea); + } + + CTX_wm_screen(C)->do_draw = true; } - RNA_float_set(op->ptr, "factor", fac / (float)sd->origsize); + + float fac = (float)(sd->delta + sd->origval - sd->origmin) / sd->origsize; + RNA_float_set(op->ptr, "factor", fac); } return OPERATOR_RUNNING_MODAL; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 9dd51b289f4..3982c9a3c30 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -109,6 +109,8 @@ typedef struct PaintStroke { * e.g. in sculpt mode, stroke doesn't start until cursor * passes over the mesh */ bool stroke_started; + /* Set when enough motion was found for rake rotation */ + bool rake_started; /* event that started stroke, for modal() return */ int event_type; /* check if stroke variables have been initialized */ @@ -376,7 +378,12 @@ static bool paint_brush_update(bContext *C, else if (!(brush->flag & BRUSH_CURVE)) { if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) { /* Not enough motion to define an angle. */ - is_dry_run = true; + if (!stroke->rake_started) { + is_dry_run = true; + } + } + else { + stroke->rake_started = true; } } } diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 1c55a0d76cf..110c4d1789d 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -1127,7 +1127,8 @@ static int actkeys_select_leftright_exec(bContext *C, wmOperator *op) actkeys_select_leftright(&ac, leftright, selectmode); /* set notifier that keyframe selection (and channels too) have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); return OPERATOR_FINISHED; } @@ -1577,7 +1578,8 @@ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent mouse_action_keys(&ac, event->mval, selectmode, column, channel); /* set notifier that keyframe selection (and channels too) have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 0e5c5ddc0c7..ce6ce802a5b 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -2792,7 +2792,8 @@ static int graph_driver_delete_invalid_exec(bContext *C, wmOperator *op) DEG_relations_tag_update(CTX_data_main(C)); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_REMOVED, NULL); WM_reportf(RPT_INFO, "Deleted %u drivers", deleted); - } else { + } + else { WM_report(RPT_INFO, "No drivers deleted"); } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 1683fbdbdb9..392db4ef4b5 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -1003,7 +1003,8 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op) graphkeys_select_leftright(&ac, leftright, selectmode); /* set notifier that keyframe selection (and channels too) have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); return OPERATOR_FINISHED; } @@ -1517,7 +1518,8 @@ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEve } /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2cc5c7f8d68..6c0ab33dd2c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1858,7 +1858,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI scene = CTX_data_scene(C); rr = BKE_image_acquire_renderresult(scene, ima); bool is_mono = rr ? BLI_listbase_count_ex(&rr->views, 2) < 2 : BLI_listbase_count_ex(&ima->views, 2) < 2; - bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER); + bool is_exr_rr = rr && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER) && RE_HasFloatPixels(rr); /* error handling */ if (!rr) { diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 1179401f346..e09e4417d5d 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -444,7 +444,8 @@ static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op) nlaedit_select_leftright(C, &ac, leftright, selectmode); /* set notifier that keyframe selection (and channels too) have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0fdd52d3205..1bee2716e65 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -633,7 +633,8 @@ static void node_common_set_butfunc(bNodeType *ntype) /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr, - PointerRNA *imaptr, PointerRNA *iuserptr) + PointerRNA *imaptr, PointerRNA *iuserptr, + bool compositor) { uiLayout *col; int source; @@ -668,7 +669,8 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr, uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE); } - if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && + if (compositor && + RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && RNA_boolean_get(ptr, "has_layers")) { col = uiLayoutColumn(layout, false); @@ -792,7 +794,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. */ - node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr); + node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); } static void node_shader_buts_tex_image_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -811,7 +813,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL); - node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr); + node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE); uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); @@ -1261,7 +1263,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA * imaptr = RNA_pointer_get(ptr, "image"); - node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr); + node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr, true); node_buts_image_views(layout, C, ptr, &imaptr); } diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 1ffe62fbc00..8999555521a 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -58,9 +58,6 @@ static int collection_delete_exec(struct bContext *C, struct wmOperator *op); static LayerCollection *outliner_collection_active(bContext *C) { - TODO_LAYER_OPERATORS; - /* consider that we may have overrides or objects active - * leading to no active collections */ return CTX_data_layer_collection(C); } @@ -79,15 +76,6 @@ SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te) return NULL; } -#if 0 -static CollectionOverride *outliner_override_active(bContext *UNUSED(C)) -{ - TODO_LAYER_OPERATORS; - TODO_LAYER_OVERRIDE; - return NULL; -} -#endif - /* -------------------------------------------------------------------- */ /* Poll functions. */ @@ -250,7 +238,6 @@ void OUTLINER_OT_collection_link(wmOperatorType *ot) /* api callbacks */ ot->exec = collection_link_exec; ot->invoke = collection_link_invoke; - ot->poll = view_layer_editor_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -327,14 +314,12 @@ void OUTLINER_OT_collection_unlink(wmOperatorType *ot) static int collection_new_exec(bContext *C, wmOperator *UNUSED(op)) { - SpaceOops *soops = CTX_wm_space_outliner(C); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); BKE_collection_link(view_layer, scene_collection); - outliner_cleanup_tree(soops); DEG_relations_tag_update(bmain); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); return OPERATOR_FINISHED; @@ -572,46 +557,6 @@ void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/**********************************************************************************/ - -/** - * Returns true is selected element is a collection - */ -static int collection_override_new_poll(bContext *(C)) -{ -#ifdef TODO_LAYER_OVERRIDE - /* disable for now, since it's not implemented */ - (void) C; - return 0; -#else - return outliner_collection_active(C) ? 1 : 0; -#endif -} - -static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) -{ - TODO_LAYER_OPERATORS; - TODO_LAYER_OVERRIDE; - BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet"); - return OPERATOR_CANCELLED; -} - -/* in the middle of renames remove s */ -void OUTLINER_OT_collection_override_new(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "New Override"; - ot->idname = "OUTLINER_OT_collection_override_new"; - ot->description = "Add a new override to the active collection"; - - /* api callbacks */ - ot->invoke = collection_override_new_invoke; - ot->poll = collection_override_new_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - struct CollectionDeleteData { Scene *scene; SpaceOops *soops; @@ -666,8 +611,6 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op)) data.collections_to_delete = BLI_gset_ptr_new(__func__); - TODO_LAYER_OVERRIDE; /* handle overrides */ - /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data); @@ -814,40 +757,3 @@ void OUTLINER_OT_collection_toggle(wmOperatorType *ot) #undef ACTION_TOGGLE #undef ACTION_ENABLE #undef ACTION_DISABLE - -/* -------------------------------------------------------------------- */ - -static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event)) -{ - TODO_LAYER_OPERATORS; - BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet"); - return OPERATOR_CANCELLED; -} - -void OUTLINER_OT_collection_objects_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Objects"; - ot->idname = "OUTLINER_OT_collection_objects_select"; - ot->description = "Select collection objects"; - - /* api callbacks */ - ot->invoke = stubs_invoke; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Deselect Objects"; - ot->idname = "OUTLINER_OT_collection_objects_deselect"; - ot->description = "Deselect collection objects"; - - /* api callbacks */ - ot->invoke = stubs_invoke; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index feeade036d1..45459bdb030 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1427,11 +1427,7 @@ static void outliner_draw_tree_element( } else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) { /* open/close icon, only when sublevels, except for scene */ - int icon_x; - if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE)) - icon_x = startx; - else - icon_x = startx + 5 * ufac; + int icon_x = startx; // icons a bit higher if (TSELEM_OPEN(tselem, soops)) @@ -1819,7 +1815,7 @@ static void outliner_draw_tree( // gray hierarchy lines starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y / 2 - OL_Y_OFFSET; - startx = 6; + startx = UI_UNIT_X / 2 - 1.0f; outliner_draw_hierarchy_lines(soops, &soops->tree, startx, &starty); // items themselves diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index fb4c8cd7506..30ede0a5e55 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -48,6 +48,7 @@ struct ID; struct Object; struct bPoseChannel; struct EditBone; +struct wmEvent; struct wmKeyConfig; @@ -72,7 +73,9 @@ typedef enum TreeTraversalAction { typedef void (*TreeElementReinsertFunc)(struct Main *bmain, struct SpaceOops *soops, struct TreeElement *insert_element, - struct TreeElement *insert_handle, TreeElementInsertType action); + struct TreeElement *insert_handle, + TreeElementInsertType action, + const struct wmEvent *event); /** * Executed on (almost) each mouse move while dragging. It's supposed to give info * if reinserting insert_element before/after/into insert_handle would be allowed. @@ -104,6 +107,7 @@ typedef struct TreeElement { TreeElementInsertType insert_type; /* the element before/after/into which we may insert the dragged one (NULL to insert at top) */ struct TreeElement *insert_handle; + void *tooltip_draw_handle; } *drag_data; } TreeElement; @@ -340,10 +344,7 @@ void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot); void OUTLINER_OT_collection_link(struct wmOperatorType *ot); void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot); void OUTLINER_OT_collection_new(struct wmOperatorType *ot); -void OUTLINER_OT_collection_override_new(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot); -void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot); -void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot); void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 9022552c429..52f27b9708e 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -33,9 +33,13 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLT_translation.h" + #include "BKE_context.h" #include "BKE_main.h" +#include "GPU_immediate.h" + #include "RNA_access.h" #include "UI_interface.h" @@ -48,6 +52,11 @@ #include "outliner_intern.h" +typedef struct OutlinerDragDropTooltip { + TreeElement *te; + void *handle; +} OutlinerDragDropTooltip; + enum { OUTLINER_ITEM_DRAG_CANCEL, OUTLINER_ITEM_DRAG_CONFIRM, @@ -69,9 +78,15 @@ static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *a return outliner_find_item_at_y(soops, &soops->tree, my); } -static void outliner_item_drag_end(TreeElement *dragged_te) +static void outliner_item_drag_end(wmWindow *win, OutlinerDragDropTooltip *data) { - MEM_SAFE_FREE(dragged_te->drag_data); + MEM_SAFE_FREE(data->te->drag_data); + + if (data->handle) { + WM_draw_cb_exit(win, data->handle); + } + + MEM_SAFE_FREE(data); } static void outliner_item_drag_get_insert_data( @@ -164,8 +179,35 @@ static void outliner_item_drag_handle( te_dragged->drag_data->insert_handle = te_insert_handle; } -static bool outliner_item_drag_drop_apply(Main *bmain, SpaceOops *soops, TreeElement *dragged_te) +/** + * Returns true if it is a collection and empty. + */ +static bool is_empty_collection(TreeElement *te) { + if (!ELEM(TREESTORE(te)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) { + return false; + } + + SceneCollection *scene_collection; + if (TREESTORE(te)->type == TSE_SCENE_COLLECTION) { + scene_collection = (SceneCollection *)te->directdata; + } + else { + BLI_assert(TREESTORE(te)->type == TSE_LAYER_COLLECTION); + scene_collection = ((LayerCollection *)te->directdata)->scene_collection; + } + + return BLI_listbase_is_empty(&scene_collection->objects) && + BLI_listbase_is_empty(&scene_collection->scene_collections); +} + +static bool outliner_item_drag_drop_apply( + Main *bmain, + SpaceOops *soops, + OutlinerDragDropTooltip *data, + const wmEvent *event) +{ + TreeElement *dragged_te = data->te; TreeElement *insert_handle = dragged_te->drag_data->insert_handle; TreeElementInsertType insert_type = dragged_te->drag_data->insert_type; @@ -178,7 +220,16 @@ static bool outliner_item_drag_drop_apply(Main *bmain, SpaceOops *soops, TreeEle /* call of assert above should not have changed insert_handle and insert_type at this point */ BLI_assert(dragged_te->drag_data->insert_handle == insert_handle && dragged_te->drag_data->insert_type == insert_type); - dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type); + + /* If the collection was just created and you moved objects/collections inside it, + * it is strange to have it closed and we not see the newly dragged elements. */ + const bool should_open_collection = (insert_type == TE_INSERT_INTO) && is_empty_collection(insert_handle); + + dragged_te->reinsert(bmain, soops, dragged_te, insert_handle, insert_type, event); + + if (should_open_collection && !is_empty_collection(insert_handle)) { + TREESTORE(insert_handle)->flag &= ~TSE_CLOSED; + } return true; } @@ -190,7 +241,8 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv Main *bmain = CTX_data_main(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); - TreeElement *te_dragged = op->customdata; + OutlinerDragDropTooltip *data = op->customdata; + TreeElement *te_dragged = data->te; int retval = OPERATOR_RUNNING_MODAL; bool redraw = false; bool skip_rebuild = true; @@ -198,7 +250,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv switch (event->type) { case EVT_MODAL_MAP: if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) { - if (outliner_item_drag_drop_apply(bmain, soops, te_dragged)) { + if (outliner_item_drag_drop_apply(bmain, soops, data, event)) { skip_rebuild = false; } retval = OPERATOR_FINISHED; @@ -210,7 +262,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv BLI_assert(0); } WM_event_add_mousemove(C); /* update highlight */ - outliner_item_drag_end(te_dragged); + outliner_item_drag_end(CTX_wm_window(C), data); redraw = true; break; case MOUSEMOVE: @@ -229,6 +281,93 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv return retval; } +/** + * Check if the given TreeElement is a collection + * + * This test is mainly used to see if next/prev TreeElement is a collection. + * It will fail when there is no next/prev TreeElement, or when the + * element is an Override or something else in the future. + */ +static bool tree_element_is_collection_get(const TreeElement *te) { + if (te == NULL) { + return false; + } + + TreeStoreElem *tselem = TREESTORE(te); + return ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION); +} + +static const char *outliner_drag_drop_tooltip_get( + const TreeElement *te_float) +{ + const char *name = NULL; + + const TreeElement *te_insert = te_float->drag_data->insert_handle; + if (tree_element_is_collection_get(te_float)) { + if (te_insert == NULL) { + name = TIP_("Move collection"); + } + else { + switch (te_float->drag_data->insert_type) { + case TE_INSERT_BEFORE: + if (tree_element_is_collection_get(te_insert->prev)) { + name = TIP_("Move between collections"); + } + else { + name = TIP_("Move before collection"); + } + break; + case TE_INSERT_AFTER: + if (tree_element_is_collection_get(te_insert->next)) { + name = TIP_("Move between collections"); + } + else { + name = TIP_("Move after collection"); + } + break; + case TE_INSERT_INTO: + name = TIP_("Move inside collection"); + break; + } + } + } + else if ((TREESTORE(te_float)->type == 0) && (te_float->idcode == ID_OB)) { + name = TIP_("Move to collection (Ctrl to add)"); + } + + return name; +} + +static void outliner_drag_drop_tooltip_cb(const wmWindow *win, void *vdata) +{ + OutlinerDragDropTooltip *data = vdata; + const char *tooltip; + + int cursorx, cursory; + int x, y; + + tooltip = outliner_drag_drop_tooltip_get(data->te); + if (tooltip == NULL) { + return; + } + + cursorx = win->eventstate->x; + cursory = win->eventstate->y; + + x = cursorx + U.widget_unit; + y = cursory - U.widget_unit; + + /* Drawing. */ + const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; + + const float col_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + const float col_bg[4] = {0.0f, 0.0f, 0.0f, 0.2f}; + + glEnable(GL_BLEND); + UI_fontstyle_draw_simple_backdrop(fstyle, x, y, tooltip, col_fg, col_bg); + glDisable(GL_BLEND); +} + static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); @@ -239,7 +378,10 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); } - op->customdata = te_dragged; + OutlinerDragDropTooltip *data = MEM_mallocN(sizeof(OutlinerDragDropTooltip), __func__); + data->te = te_dragged; + + op->customdata = data; te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__); /* by default we don't change the item position */ te_dragged->drag_data->insert_handle = te_dragged; @@ -251,6 +393,8 @@ static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmE WM_event_add_modal_handler(C, op); + data->handle = WM_draw_cb_activate(CTX_wm_window(C), outliner_drag_drop_tooltip_cb, data); + return OPERATOR_RUNNING_MODAL; } @@ -330,9 +474,6 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_collection_link); WM_operatortype_append(OUTLINER_OT_collection_unlink); WM_operatortype_append(OUTLINER_OT_collection_new); - WM_operatortype_append(OUTLINER_OT_collection_override_new); - WM_operatortype_append(OUTLINER_OT_collection_objects_select); - WM_operatortype_append(OUTLINER_OT_collection_objects_deselect); WM_operatortype_append(OUTLINER_OT_collection_nested_new); WM_operatortype_append(OUTLINER_OT_collection_delete_selected); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index bf0dea06724..205f70e58dc 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -446,7 +446,8 @@ static TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void static void outliner_object_reorder( Main *bmain, SpaceOops *soops, TreeElement *insert_element, - TreeElement *insert_handle, TreeElementInsertType action) + TreeElement *insert_handle, TreeElementInsertType action, + const wmEvent *event) { SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle); SceneCollection *sc_ob_parent = NULL; @@ -459,12 +460,21 @@ static void outliner_object_reorder( .objects_selected_array = {NULL, NULL}, }; + const bool is_append = event->ctrl; + /* Make sure we include the originally inserted element as well. */ TREESTORE(insert_element)->flag |= TSE_SELECTED; outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data); BLI_LISTBASE_FOREACH (LinkData *, link, &data.objects_selected_array) { TreeElement *ten_selected = (TreeElement *)link->data; + Object *ob = (Object *)TREESTORE(ten_selected)->id; + + if (is_append) { + BKE_collection_object_add(id, sc, ob); + continue; + } + /* Find parent scene-collection of object. */ if (ten_selected->parent) { for (TreeElement *te_ob_parent = ten_selected->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) { @@ -477,7 +487,7 @@ static void outliner_object_reorder( else { sc_ob_parent = BKE_collection_master(id); } - Object *ob = (Object *)TREESTORE(ten_selected)->id; + BKE_collection_object_move(id, sc, sc_ob_parent, ob); } @@ -1443,7 +1453,8 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops) static void outliner_layer_collections_reorder( Main *bmain, SpaceOops *UNUSED(soops), - TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) + TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action, + const wmEvent *UNUSED(event)) { LayerCollection *lc_insert = insert_element->directdata; LayerCollection *lc_handle = insert_handle->directdata; @@ -1510,7 +1521,8 @@ static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElemen static void outliner_scene_collections_reorder( Main *bmain, SpaceOops *UNUSED(soops), - TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action) + TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action, + const wmEvent *UNUSED(event)) { SceneCollection *sc_insert = insert_element->directdata; SceneCollection *sc_handle = insert_handle->directdata; diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 11ef781b229..d148ef3c6fe 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -73,6 +73,7 @@ set(SRC view3d_select.c view3d_snap.c view3d_toolbar.c + view3d_utils.c view3d_view.c view3d_intern.h diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 3bc2481a608..51dc56bafaf 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1034,7 +1034,7 @@ static void drawcube_size(float size, unsigned pos) { size, size, size} }; - const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6}; + const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6}; #if 0 glEnableClientState(GL_VERTEX_ARRAY); @@ -8065,7 +8065,7 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos) if (solid) { /* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney * (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */ - static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5}; + static const GLubyte tris_strip_indices[14] = {0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5}; immBegin(GWN_PRIM_TRI_STRIP, 14); for (int i = 0; i < 14; ++i) { immVertex3fv(pos, vec[tris_strip_indices[i]]); @@ -8073,7 +8073,8 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos) immEnd(); } else { - static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7}; + static const GLubyte line_indices[24] = + {0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 4, 5, 5, 6, 6, 7, 7, 4, 1, 5, 2, 6, 3, 7}; immBegin(GWN_PRIM_LINES, 24); for (int i = 0; i < 24; ++i) { immVertex3fv(pos, vec[line_indices[i]]); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 64b607aa9f7..fb5b9386dde 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1128,10 +1128,12 @@ static void view3d_main_region_message_subscribe( extern StructRNA RNA_ViewLayerEngineSettingsEevee; WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw); } +#ifdef WITH_CLAY_ENGINE else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) { extern StructRNA RNA_ViewLayerEngineSettingsClay; WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw); } +#endif } /* concept is to retrieve cursor type context-less */ diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 9b07593e576..c39057431c2 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -138,13 +138,10 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl) * the view for first-person style navigation. */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, + const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root) { View3DCameraControl *vctrl; - EvaluationContext eval_ctx; - - CTX_data_eval_ctx(C, &eval_ctx); vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__); @@ -181,7 +178,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( /* store the original camera loc and rot */ vctrl->obtfm = BKE_object_tfm_backup(ob_back); - BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera); + BKE_object_where_is_calc(eval_ctx, scene, v3d->camera); negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]); rv3d->dist = 0.0; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index cf43d65b44a..f734bb085d0 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -133,11 +133,18 @@ void ED_view3d_update_viewmat( view3d_winmatrix_set(depsgraph, ar, v3d, rect); /* setup view matrix */ - if (viewmat) + if (viewmat) { copy_m4_m4(rv3d->viewmat, viewmat); - else - view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */ - + } + 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(eval_ctx, 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); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d286e608de4..1e368e2d171 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -26,6 +26,8 @@ /** \file blender/editors/space_view3d/view3d_edit.c * \ingroup spview3d + * + * 3D view manipulation/operators. */ #include <string.h> @@ -42,9 +44,7 @@ #include "MEM_guardedalloc.h" -#include "BLI_bitmap_draw_2d.h" #include "BLI_blenlib.h" -#include "BLI_kdopbvh.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -57,13 +57,11 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_report.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_action.h" #include "DEG_depsgraph.h" -#include "BIF_gl.h" #include "WM_api.h" #include "WM_types.h" @@ -73,14 +71,12 @@ #include "ED_armature.h" #include "ED_particle.h" -#include "ED_keyframing.h" #include "ED_screen.h" #include "ED_transform.h" #include "ED_mesh.h" #include "ED_gpencil.h" #include "ED_view3d.h" -#include "DEG_depsgraph_query.h" #include "UI_resources.h" @@ -88,440 +84,9 @@ #include "view3d_intern.h" /* own include */ -static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar); - -bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) -{ - return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); -} - -/* ********************** view3d_edit: view manipulations ********************* */ - -/** - * \return true when the view-port is locked to its camera. - */ -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)); -} - -/** - * 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(View3D *v3d, RegionView3D *rv3d, const bool calc_dist) -{ - if (ED_view3d_camera_lock_check(v3d, rv3d)) { - if (calc_dist) { - /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */ - rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); - } - ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); - } -} - -void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) -{ - ED_view3d_camera_lock_init_ex(v3d, rv3d, true); -} - -/** - * Apply the view-port transformation back to the camera object. - * - * \return true if the camera is moved. - */ -bool ED_view3d_camera_lock_sync(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; - } - - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - - normalize_m4_m4(tmat, v3d->camera->obmat); - - invert_m4_m4(imat, tmat); - mul_m4_m4m4(diff_mat, view_mat, imat); - - mul_m4_m4m4(parent_mat, diff_mat, root_parent->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, OB_RECALC_OB); - 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(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, OB_RECALC_OB); - 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) -{ - 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; - } -} - -/** - * Call after modifying a locked view. - * - * \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) -{ - /* 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; - } -} - -/** - * For viewport operators that exit camera persp. - * - * \note This differs from simply setting ``rv3d->persp = persp`` because it - * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera, - * otherwise switching out of camera view may jump to a different part of the scene. - */ -static void view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp) -{ - BLI_assert(rv3d->persp == RV3D_CAMOB); - BLI_assert(persp != RV3D_CAMOB); - - if (v3d->camera) { - rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); - ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); - } - - if (!ED_view3d_camera_lock_check(v3d, rv3d)) { - rv3d->persp = persp; - } -} - -/* ********************* box view support ***************** */ - -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); -} - -/** - * Find which axis values are shared between both views and copy to \a rv3d_dst - * taking axis flipping into account. - */ -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]; - } - } -} - -/* sync center/zoom view of region to others, for view transforms */ -static 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); - } -} - -/* 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); - } -} - -/* '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); -} - -/* ************************** init for view ops **********************************/ +/* -------------------------------------------------------------------- */ +/** \name Generic View Operator Custom-Data + * \{ */ typedef struct ViewOpsData { /* context pointers (assigned by viewops_data_alloc) */ @@ -581,13 +146,6 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3]) vec[2] = -z; /* yah yah! */ } - -/* -------------------------------------------------------------------- */ -/* ViewOpsData */ - -/** \name Generic View Operator Custom-Data. - * \{ */ - /** * Allocate and fill in context pointers for #ViewOpsData */ @@ -732,7 +290,7 @@ static enum eViewOpsOrbit viewops_orbit_mode(void) /** * Calculate the values for #ViewOpsData * - * \param use_ensure_persp: When enabled run #view3d_ensure_persp this may switch out of + * \param use_ensure_persp: 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). @@ -765,7 +323,7 @@ static void viewops_data_create_ex( } if (use_ensure_persp) { - if (view3d_ensure_persp(vod->v3d, vod->ar)) { + if (ED_view3d_persp_ensure(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. @@ -898,10 +456,12 @@ static void viewops_data_free(bContext *C, wmOperator *op) #endif ED_region_tag_redraw(ar); } -/** \} */ +/** \} */ -/* ************************** viewrotate **********************************/ +/* -------------------------------------------------------------------- */ +/** \name View Rotate Operator + * \{ */ enum { VIEW_PASS = 0, @@ -910,12 +470,14 @@ enum { }; /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ -#define VIEW_MODAL_CONFIRM 1 /* used for all view operations */ -#define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2 -#define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3 -#define VIEWROT_MODAL_SWITCH_ZOOM 4 -#define VIEWROT_MODAL_SWITCH_MOVE 5 -#define VIEWROT_MODAL_SWITCH_ROTATE 6 +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, +}; /* called in transform_ops.c, on each regeneration of keymaps */ void viewrotate_modal_keymap(wmKeyConfig *keyconf) @@ -1231,37 +793,6 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event) return ret; } -/** - * Action to take when rotating the view, - * handle auto-persp and logic for switching out of views. - * - * shared with NDOF. - */ -static bool view3d_ensure_persp(struct 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; - view3d_persp_switch_from_camera(v3d, rv3d, persp); - } - else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) { - rv3d->persp = RV3D_PERSP; - } - return true; - } - - return false; -} - static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod; @@ -1365,11 +896,13 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } -#ifdef WITH_INPUT_NDOF +/** \} */ +/* -------------------------------------------------------------------- */ /** \name NDOF Utility Functions * \{ */ +#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)) @@ -1419,8 +952,9 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d) * * \param has_zoom zoom, otherwise dolly, often `!rv3d->is_persp` since it doesnt 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]; @@ -1481,9 +1015,10 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, ScrArea *s } -static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, - /* optional, can be NULL*/ - ViewOpsData *vod) +static void view3d_ndof_orbit( + const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar, + /* optional, can be NULL*/ + ViewOpsData *vod) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; @@ -1492,7 +1027,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa, BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0); - view3d_ensure_persp(v3d, ar); + ED_view3d_persp_ensure(v3d, ar); rv3d->view = RV3D_VIEW_USER; @@ -1668,11 +1203,14 @@ void view3d_ndof_fly( /** \} */ +/* -------------------------------------------------------------------- */ +/** \name NDOF Operators + * + * - "orbit" navigation (trackball/turntable) + * - zooming + * - panning in rotationally-locked views + * \{ */ -/* -- "orbit" navigation (trackball/turntable) - * -- zooming - * -- panning in rotationally-locked views - */ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -1936,8 +1474,11 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot) #endif /* WITH_INPUT_NDOF */ -/* ************************ viewmove ******************************** */ +/** \} */ +/* -------------------------------------------------------------------- */ +/** \name View Move (Pan) Operator + * \{ */ /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ @@ -1999,8 +1540,9 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) add_v3_v3(vod->rv3d->ofs, dvec); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->ar); + } } vod->oldx = x; @@ -2117,7 +1659,11 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } -/* ************************ viewzoom ******************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Zoom Operator + * \{ */ /* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */ /* called in transform_ops.c, on each regeneration of keymaps */ @@ -2359,8 +1905,9 @@ static void viewzoom_apply_3d( /* these limits were in old code too */ CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->ar); + } ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); @@ -2497,8 +2044,9 @@ static int viewzoom_exec(bContext *C, wmOperator *op) } } - if (rv3d->viewlock & RV3D_BOXVIEW) + if (rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(sa, ar); + } ED_view3d_depth_tag_update(rv3d); @@ -2512,41 +2060,6 @@ static int viewzoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* this is an exact copy of viewzoom_modal_keymap */ -/* 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", ""}, - - {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} - }; - - 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; - - keymap = WM_modalkeymap_add(keyconf, "View3D Dolly 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); - - /* 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); -#endif - - /* assign map to operators */ - WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); -} - /* viewdolly_invoke() copied this function, changes here may apply there */ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -2634,8 +2147,50 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Dolly Operator + * + * Like zoom but translates the view offset along the view direction + * which avoids #RegionView3D.dist approaching zero. + * \{ */ + +/* this is an exact copy of viewzoom_modal_keymap */ +/* 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", ""}, + + {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} + }; + + 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; + + keymap = WM_modalkeymap_add(keyconf, "View3D Dolly 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); + + /* 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); +#endif + + /* assign map to operators */ + WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); +} -/* ************************ viewdolly ******************************** */ static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op) { View3D *v3d = CTX_wm_view3d(C); @@ -2679,8 +2234,9 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv if (zfac != 1.0f) view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac); - if (vod->rv3d->viewlock & RV3D_BOXVIEW) + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->ar); + } ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); @@ -2780,8 +2336,9 @@ static int viewdolly_exec(bContext *C, wmOperator *op) view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.8f); } - if (rv3d->viewlock & RV3D_BOXVIEW) + if (rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(sa, ar); + } ED_view3d_depth_tag_update(rv3d); @@ -2819,7 +2376,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (vod->rv3d->persp != RV3D_PERSP) { if (vod->rv3d->persp == RV3D_CAMOB) { /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */ - view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP); + ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP); } else { vod->rv3d->persp = RV3D_PERSP; @@ -2901,6 +2458,13 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View All Operator + * + * Move & Zoom the view to fit all of it's contents. + * \{ */ 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) @@ -2970,9 +2534,10 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar, } /* 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) +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; @@ -3072,6 +2637,14 @@ void VIEW3D_OT_view_all(wmOperatorType *ot) RNA_def_boolean(ot->srna, "center", 0, "Center", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Selected Operator + * + * Move & Zoom the view to fit selected contents. + * \{ */ + /* like a localview without local!, was centerview() in 2.4x */ static int viewselected_exec(bContext *C, wmOperator *op) { @@ -3202,12 +2775,18 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Lock Clear Operator + * \{ */ + static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); if (v3d) { - ED_view3D_lock_clear(v3d); + ED_view3d_lock_clear(v3d); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); @@ -3234,6 +2813,12 @@ void VIEW3D_OT_view_lock_clear(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Lock to Active Operator + * \{ */ + static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d = CTX_wm_view3d(C); @@ -3241,7 +2826,7 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op)) if (v3d) { - ED_view3D_lock_clear(v3d); + ED_view3d_lock_clear(v3d); v3d->ob_centre = obact; /* can be NULL */ @@ -3285,6 +2870,12 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Center Cursor Operator + * \{ */ + static int viewcenter_cursor_exec(bContext *C, wmOperator *op) { View3D *v3d = CTX_wm_view3d(C); @@ -3325,6 +2916,12 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Center Pick Operator + * \{ */ + static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); @@ -3375,6 +2972,12 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Camera Center Operator + * \{ */ + static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */ { const Depsgraph *depsgraph = CTX_data_depsgraph(C); @@ -3421,6 +3024,12 @@ void VIEW3D_OT_view_center_camera(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Lock Center Operator + * \{ */ + static int view3d_center_lock_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */ { RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -3447,7 +3056,11 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot) ot->flag = 0; } -/* ********************* Set render border operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Render Border Operator + * \{ */ static int render_border_exec(bContext *C, wmOperator *op) { @@ -3549,7 +3162,11 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); } -/* ********************* Clear render border operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Render Border Operator + * \{ */ static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -3596,7 +3213,11 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************* Border Zoom operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Border Zoom Operator + * \{ */ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) { @@ -3724,8 +3345,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) C, v3d, ar, smooth_viewtx, &(const V3D_SmoothParams) {.ofs = new_ofs, .dist = &new_dist}); - if (rv3d->viewlock & RV3D_BOXVIEW) + if (rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(CTX_wm_area(C), ar); + } return OPERATOR_FINISHED; } @@ -3764,7 +3386,14 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) WM_operator_properties_gesture_border_zoom(ot); } -/* sets the view to 1:1 camera/render-pixel */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Camera Zoom 1:1 Operator + * + * Sets the view to 1:1 camera/render-pixel. + * \{ */ + static void view3d_set_1_to_1_viewborder(Scene *scene, const Depsgraph *depsgraph, ARegion *ar, View3D *v3d) { RegionView3D *rv3d = ar->regiondata; @@ -3810,7 +3439,11 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot) ot->flag = 0; } -/* ********************* Changing view operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Axis/Type Operator + * \{ */ static const EnumPropertyItem prop_view_items[] = { {RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"}, @@ -3826,10 +3459,11 @@ static const EnumPropertyItem prop_view_items[] = { /* would like to make this a generic function - outside of transform */ -static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, - const float quat_[4], - short view, int perspo, bool align_active, - const int smooth_viewtx) +static void axis_set_view( + bContext *C, View3D *v3d, ARegion *ar, + const float quat_[4], + short view, int perspo, bool align_active, + const int smooth_viewtx) { RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */ float quat[4]; @@ -4049,6 +3683,12 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Orbit Operator + * \{ */ + 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"}, @@ -4092,7 +3732,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op) float quat_new[4]; if (view_opposite == RV3D_VIEW_USER) { - view3d_ensure_persp(v3d, ar); + ED_view3d_persp_ensure(v3d, ar); } if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) { @@ -4169,11 +3809,13 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot) 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"); - } +/** \} */ -/* ************************ viewroll ******************************** */ +/* -------------------------------------------------------------------- */ +/** \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) { @@ -4211,8 +3853,9 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y)) view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->ofs, vod->oldquat, vod->rv3d->viewquat, vod->dyn_ofs); } - if (vod->rv3d->viewlock & RV3D_BOXVIEW) + if (vod->rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_sync(vod->sa, vod->ar); + } ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); @@ -4415,6 +4058,14 @@ static const EnumPropertyItem prop_view_pan_items[] = { {0, NULL, 0, NULL, NULL} }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Pan Operator + * + * Move (pan) in incremental steps. + * \{ */ + static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int x = 0, y = 0; @@ -4455,6 +4106,12 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Toggle Perspective/Orthographic Operator + * \{ */ + static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d_dummy; @@ -4491,6 +4148,14 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Navigate Operator + * + * Wraps walk/fly modes. + * \{ */ + static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { eViewNavigation_Method mode = U.navigation_mode; @@ -4520,8 +4185,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot) ot->poll = ED_operator_view3d_active; } +/** \} */ -/* ******************** add background image operator **************** */ +/* -------------------------------------------------------------------- */ +/** \name Background Image Add Operator + * \{ */ static CameraBGImage *background_image_add(bContext *C) { @@ -4580,8 +4248,12 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Background Image Remove Operator + * \{ */ -/* ***** remove image operator ******* */ static int background_image_remove_exec(bContext *C, wmOperator *op) { Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data; @@ -4626,7 +4298,13 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot) RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX); } -/* ********************* set clipping operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Clipping Planes Operator + * + * Draw border or toggle off. + * \{ */ static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4]) { @@ -4707,7 +4385,11 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) WM_operator_properties_border(ot); } -/* ***************** 3d cursor cursor op ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Set Cursor Operator + * \{ */ /* cursor position in vec, result in vec, mval in region coords */ /* note: cannot use event->mval here (called by object_add() */ @@ -4819,7 +4501,11 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) } -/* ***************** manipulator op ******************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Enable Transform Manipulator Operator + * \{ */ static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { @@ -4861,7 +4547,11 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ************************* Toggle rendered shading *********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Render Shading Operator + * \{ */ static int toggle_render_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -4890,315 +4580,4 @@ void VIEW3D_OT_toggle_render(wmOperatorType *ot) ot->poll = ED_operator_view3d_active; } -/* ************************* below the line! *********************** */ - - -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; -} - -/** - * Get the world-space 3d location from a screen-space 2d point. - * - * \param mval: Input screen-space pixel location. - * \param mouse_worldloc: Output world-space location. - * \param fallback_depth_pt: Use this points depth when no depth can be found. - */ -bool ED_view3d_autodist( - const EvaluationContext *eval_ctx, struct Depsgraph *graph, 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(eval_ctx, graph, 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( - const EvaluationContext *eval_ctx, struct Depsgraph *graph, - ARegion *ar, View3D *v3d, int mode) -{ - /* Get Z Depths, needed for perspective, nice for ortho */ - switch (mode) { - case 0: - ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true); - break; - case 1: - { - Scene *scene = DEG_get_evaluated_scene(graph); - ED_view3d_draw_depth_gpencil(eval_ctx, 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) -{ - 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); - - 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; - } -} - -bool ED_view3d_autodist_depth_seg(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]; - - data.ar = ar; - data.margin = margin; - data.depth = FLT_MAX; - - 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); - - *depth = data.depth; - - return (*depth != FLT_MAX); -} - -/* problem - ofs[3] can be on same location as camera itself. - * Blender needs proper dist value for zoom. - * use fallback_dist to override small values - */ -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; - - mul_m4_v4(mat, pos); - add_v3_v3(pos, ofs); - mul_m4_v4(mat, dir); - normalize_v3(dir); - - dist = dot_v3v3(pos, dir); - - if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { - dist = fallback_dist; - } - - return dist; -} - -/** - * Set the dist without moving the view (compensate with #RegionView3D.ofs) - * - * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first. - */ -void ED_view3d_distance_set(RegionView3D *rv3d, const float dist) -{ - float viewinv[4]; - float tvec[3]; - - BLI_assert(dist >= 0.0f); - - 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); -#else - invert_qt_qt_normalized(viewinv, rv3d->viewquat); - mul_qt_v3(viewinv, tvec); -#endif - sub_v3_v3(rv3d->ofs, tvec); - - rv3d->dist = dist; -} - -/** - * Set the view transformation from a 4x4 matrix. - * - * \param mat The view 4x4 transformation matrix to assign. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ -void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) -{ - float nmat[3][3]; - - /* dist depends on offset */ - BLI_assert(dist == NULL || ofs != NULL); - - copy_m3_m4(nmat, mat); - normalize_m3(nmat); - - /* Offset */ - if (ofs) - negate_v3_v3(ofs, mat[3]); - - /* Quat */ - if (quat) { - mat3_normalized_to_quat(quat, nmat); - invert_qt_normalized(quat); - } - - if (ofs && dist) { - madd_v3_v3fl(ofs, nmat[2], *dist); - } -} - -/** - * Calculate the view transformation matrix from RegionView3D input. - * The resulting matrix is equivalent to RegionView3D.viewinv - * \param mat The view 4x4 transformation matrix to calculate. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ -void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float 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); -} - -/** - * Set the RegionView3D members from an objects transformation and optionally lens. - * \param ob The object to set the view to. - * \param ofs The view offset to be set, normally from RegionView3D.ofs. - * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. - * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. - */ -void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) -{ - ED_view3d_from_m4(ob->obmat, ofs, quat, dist); - - if (lens) { - CameraParams params; - - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, ob); - *lens = params.lens; - } -} - -/** - * Set the object transformation from RegionView3D members. - * \param ob The object which has the transformation assigned. - * \param ofs The view offset, normally from RegionView3D.ofs. - * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. - * \param dist The view distance from ofs, normally from RegionView3D.dist. - */ -void ED_view3d_to_object(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); - BKE_object_apply_mat4(ob, mat, true, true); -} - -/** - * Use to store the last view, before entering camera view. - */ -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; - } -} - -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; -} +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 8a48b1dc3aa..d2aa19509d7 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -58,6 +58,8 @@ #include "GPU_immediate.h" +#include "DEG_depsgraph.h" + #include "view3d_intern.h" /* own include */ /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ @@ -344,6 +346,10 @@ enum { static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); + rctf viewborder; float upvec[3]; /* tmp */ @@ -419,7 +425,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent } fly->v3d_camera_control = ED_view3d_cameracontrol_acquire( - C, fly->scene, fly->v3d, fly->rv3d, + &eval_ctx, fly->scene, fly->v3d, fly->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* calculate center */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index df2e5315c39..5e34bc188f0 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -111,6 +111,7 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot); void VIEW3D_OT_toggle_render(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); +void view3d_boxview_sync(ScrArea *sa, ARegion *ar); void view3d_orbit_apply_dyn_ofs( float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], @@ -276,8 +277,12 @@ void ED_view3d_smooth_view_force_finish( struct bContext *C, struct View3D *v3d, struct ARegion *ar); -void view3d_winmatrix_set(const struct Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect); -void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d); +void view3d_winmatrix_set( + const struct Depsgraph *depsgraph, + ARegion *ar, const View3D *v3d, const rcti *rect); +void view3d_viewmatrix_set( + const struct EvaluationContext *eval_ctx, 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); @@ -292,7 +297,7 @@ void view3d_buttons_register(struct ARegionType *art); /* view3d_camera_control.c */ struct View3DCameraControl *ED_view3d_cameracontrol_acquire( - const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d, + const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d, const bool use_parent_root); void ED_view3d_cameracontrol_update( struct View3DCameraControl *vctrl, diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c index 0f7df8fe6aa..9f655fff8a1 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c @@ -163,6 +163,16 @@ struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = { struct NavigateWidgetGroup { wmManipulator *mpr_array[MPR_TOTAL]; + /* Store the view state to check for changes. */ + struct { + struct { + short winx, winy; + } ar; + struct { + char is_persp; + char viewlock; + } rv3d; + } state; int region_size[2]; bool is_persp; }; @@ -200,8 +210,6 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG RNA_property_string_set_bytes( mpr->ptr, prop, (const char *)info->shape, info->shape_size); - /* don't fade icons so much */ - mpr->color[3] = 0.5f; } wmOperatorType *ot = WM_operatortype_find(info->opname, true); @@ -214,6 +222,15 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA); } + /* Click only buttons (not modal). */ + { + int mpr_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA}; + for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) { + wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]]; + RNA_boolean_set(mpr->ptr, "show_drag", false); + } + } + { wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE]; mpr->scale_basis = MANIPULATOR_SIZE / 2; @@ -248,16 +265,19 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]); } - if ((navgroup->region_size[0] == ar->winx) && - (navgroup->region_size[1] == ar->winy) && - (navgroup->is_persp == rv3d->is_persp)) + if ((navgroup->state.ar.winx == ar->winx) && + (navgroup->state.ar.winy == ar->winy) && + (navgroup->state.rv3d.is_persp == rv3d->is_persp) && + (navgroup->state.rv3d.viewlock == rv3d->viewlock)) { return; } - navgroup->region_size[0] = ar->winx; - navgroup->region_size[1] = ar->winy; - navgroup->is_persp = rv3d->is_persp; + + navgroup->state.ar.winx = ar->winx; + navgroup->state.ar.winy = ar->winy; + navgroup->state.rv3d.is_persp = rv3d->is_persp; + navgroup->state.rv3d.viewlock = rv3d->viewlock; const float icon_size = MANIPULATOR_SIZE; @@ -266,36 +286,50 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset}; wmManipulator *mpr; - mpr = navgroup->mpr_array[MPR_ROTATE]; - mpr->matrix_basis[3][0] = co[0]; - mpr->matrix_basis[3][1] = co[1]; - mpr = navgroup->mpr_array[MPR_MOVE]; - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + for (uint i = 0; i < ARRAY_SIZE(navgroup->mpr_array); i++) { + mpr = navgroup->mpr_array[i]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); + } - mpr = navgroup->mpr_array[MPR_ZOOM]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + if ((rv3d->viewlock & RV3D_LOCKED) == 0) { + mpr = navgroup->mpr_array[MPR_ROTATE]; + mpr->matrix_basis[3][0] = co[0]; + mpr->matrix_basis[3][1] = co[1]; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - if (rv3d->is_persp) { - mpr = navgroup->mpr_array[MPR_PERSP]; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); - mpr = navgroup->mpr_array[MPR_ORTHO]; + mpr = navgroup->mpr_array[MPR_MOVE]; + mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + mpr = navgroup->mpr_array[MPR_ZOOM]; + mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] - icon_offset_mini; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP]; + mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + + mpr = navgroup->mpr_array[MPR_CAMERA]; + mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); } else { - mpr = navgroup->mpr_array[MPR_ORTHO]; - WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true); - mpr = navgroup->mpr_array[MPR_PERSP]; + /* RV3D_LOCKED: only show supported buttons. */ + mpr = navgroup->mpr_array[MPR_MOVE]; + mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); - } - mpr->matrix_basis[3][0] = co[0] + icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; - mpr = navgroup->mpr_array[MPR_CAMERA]; - mpr->matrix_basis[3][0] = co[0] - icon_offset_mini; - mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + mpr = navgroup->mpr_array[MPR_ZOOM]; + mpr->matrix_basis[3][0] = co[0]; + mpr->matrix_basis[3][1] = co[1] + icon_offset_mini; + WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false); + } } void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt) diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c index bda692a0e5c..e8d540bcc9d 100644 --- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c +++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c @@ -1011,7 +1011,7 @@ void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt) wgt->name = "Ruler Widgets"; wgt->idname = view3d_wgt_ruler_id; - wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE; + wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE | WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL; wgt->mmap_params.spaceid = SPACE_VIEW3D; wgt->mmap_params.regionid = RGN_TYPE_WINDOW; diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index af44629a18e..ba3e78b25b9 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -277,6 +277,11 @@ eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[ /* 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; +} + /** * Calculate a depth value from \a co, use with #ED_view3d_win_to_delta */ diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c new file mode 100644 index 00000000000..7bb3f443ac6 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -0,0 +1,1436 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_utils.c + * \ingroup spview3d + * + * 3D View checks and manipulation (no operators). + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <float.h> + +#include "DNA_camera_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_bitmap_draw_2d.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_camera.h" +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_screen.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "GPU_matrix.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_keyframing.h" +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "view3d_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name View Data Access Utilities + * + * \{ */ + +float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d) +{ + if (v3d && v3d->localvd) return v3d->cursor; + else return scene->cursor; +} + +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; + } +} + +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->far * 10.0f; +} + +/** + * \note copies logic of #ED_view3d_viewplane_get(), keep in sync. + */ +bool ED_view3d_clip_range_get( + const Depsgraph *depsgraph, + const View3D *v3d, const RegionView3D *rv3d, + float *r_clipsta, float *r_clipend, + const bool use_ortho_factor) +{ + CameraParams params; + + 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.clipend - params.clipsta); + params.clipsta *= fac; + params.clipend *= fac; + } + + if (r_clipsta) *r_clipsta = params.clipsta; + if (r_clipend) *r_clipend = params.clipend; + + return params.is_ortho; +} + +bool ED_view3d_viewplane_get( + const Depsgraph *depsgraph, + const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, + rctf *r_viewplane, float *r_clipsta, float *r_clipend, 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_clipsta) *r_clipsta = params.clipsta; + if (r_clipend) *r_clipend = params.clipend; + if (r_pixsize) *r_pixsize = params.viewdx; + + return params.is_ortho; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/** \name View State/Context Utilities + * + * \{ */ + +/** + * Use this call when executing an operator, + * event system doesn't set for each event the OpenGL drawing context. + */ +void view3d_operator_needs_opengl(const bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + ARegion *ar = CTX_wm_region(C); + + view3d_region_operator_needs_opengl(win, ar); +} + +void view3d_region_operator_needs_opengl(wmWindow *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; + + wmSubWindowSet(win, ar->swinid); + gpuLoadProjectionMatrix(rv3d->winmat); + gpuLoadMatrix(rv3d->viewmat); + } +} + +/** + * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727] + */ +void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) +{ + float viewdist; + + if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { + return; + } + + 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])); + } + } + } + + bglPolygonOffset(viewdist, dist); +} + +bool ED_view3d_context_activate(bContext *C) +{ + 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); + } + + if (sa == 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); + + return true; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Clipping Utilities + * + * \{ */ + +void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) +{ + 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]); + } + + 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) +{ + /* 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); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Bound-Box Utilities + * + * \{ */ + +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; +} + +bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) +{ + /* return 1: draw */ + + float persmatob[4][4]; + + if (bb == NULL) return true; + if (bb->flag & BOUNDBOX_DISABLED) return true; + + mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); + + 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); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Perspective & Mode Switching + * + * Misc view utility functions. + * \{ */ + +bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d) +{ + return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre); +} + +/** + * Use to store the last view, before entering camera view. + */ +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; + } +} + +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; +} + +/** + * For viewport operators that exit camera perspective. + * + * \note This differs from simply setting ``rv3d->persp = persp`` because it + * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera, + * otherwise switching out of camera view may jump to a different part of the scene. + */ +void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp) +{ + BLI_assert(rv3d->persp == RV3D_CAMOB); + BLI_assert(persp != RV3D_CAMOB); + + if (v3d->camera) { + rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + ED_view3d_from_object(v3d->camera, 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, + * handle auto-persp and logic for switching out of views. + * + * shared with NDOF. + */ +bool ED_view3d_persp_ensure(struct 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(v3d, rv3d, persp); + } + else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) { + rv3d->persp = RV3D_PERSP; + } + return true; + } + + return false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Camera Lock API + * + * Lock the camera to the view-port, allowing view manipulation to transform the camera. + * \{ */ + +/** + * \return true when the view-port is locked to its camera. + */ +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)); +} + +/** + * 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(View3D *v3d, RegionView3D *rv3d, const bool calc_dist) +{ + if (ED_view3d_camera_lock_check(v3d, rv3d)) { + if (calc_dist) { + /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */ + rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK); + } + ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL); + } +} + +void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) +{ + ED_view3d_camera_lock_init_ex(v3d, rv3d, true); +} + +/** + * Apply the view-port transformation back to the camera object. + * + * \return true if the camera is moved. + */ +bool ED_view3d_camera_lock_sync(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; + } + + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + + normalize_m4_m4(tmat, v3d->camera->obmat); + + invert_m4_m4(imat, tmat); + mul_m4_m4m4(diff_mat, view_mat, imat); + + mul_m4_m4m4(parent_mat, diff_mat, root_parent->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, OB_RECALC_OB); + 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(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, OB_RECALC_OB); + 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) +{ + 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; + } +} + +/** + * Call after modifying a locked view. + * + * \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) +{ + /* 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 + * + * Use with quad-split so each view is clipped by the bounds of each view axis. + * \{ */ + +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); +} + +/** + * Find which axis values are shared between both views and copy to \a rv3d_dst + * taking axis flipping into account. + */ +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]; + } + } +} + +/* 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); + } +} + +/* 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); + } +} + +/* '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); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Auto-Depth Utilities + * \{ */ + +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; +} + +/** + * Get the world-space 3d location from a screen-space 2d point. + * + * \param mval: Input screen-space pixel location. + * \param mouse_worldloc: Output world-space location. + * \param fallback_depth_pt: Use this points depth when no depth can be found. + */ +bool ED_view3d_autodist( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, 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(eval_ctx, graph, 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( + const EvaluationContext *eval_ctx, struct Depsgraph *graph, + ARegion *ar, View3D *v3d, int mode) +{ + /* Get Z Depths, needed for perspective, nice for ortho */ + switch (mode) { + case 0: + ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true); + break; + case 1: + { + Scene *scene = DEG_get_evaluated_scene(graph); + ED_view3d_draw_depth_gpencil(eval_ctx, 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) +{ + 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); + + 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; + } +} + +bool ED_view3d_autodist_depth_seg( + 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]; + + data.ar = ar; + data.margin = margin; + data.depth = FLT_MAX; + + 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); + + *depth = data.depth; + + return (*depth != FLT_MAX); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Radius/Distance Utilities + * + * Use to calculate a distance to a point based on it's radius. + * \{ */ + +float ED_view3d_radius_to_dist_persp(const float angle, const float radius) +{ + 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 a new RegionView3D.dist value to fit the \a radius. + * + * \note Depth isn't taken into account, this will fit a flat plane exactly, + * but points towards the view (with a perspective projection), + * may be within the radius but outside the view. eg: + * + * <pre> + * + + * pt --> + /^ radius + * / | + * / | + * view + + + * \ | + * \ | + * \| + * + + * </pre> + * + * \param ar Can be NULL if \a use_aspect is false. + * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera) + * \param use_aspect Increase the distance to account for non 1:1 view aspect. + * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN). + */ +float ED_view3d_radius_to_dist( + const View3D *v3d, const ARegion *ar, + 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.clipsta = v3d->near; + params.clipend = v3d->far; + BKE_camera_params_from_object(¶ms, v3d->camera); + + 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; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Distance Utilities + * \{ */ + +/* problem - ofs[3] can be on same location as camera itself. + * Blender needs proper dist value for zoom. + * use fallback_dist to override small values + */ +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; + + mul_m4_v4(mat, pos); + add_v3_v3(pos, ofs); + mul_m4_v4(mat, dir); + normalize_v3(dir); + + dist = dot_v3v3(pos, dir); + + if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { + dist = fallback_dist; + } + + return dist; +} + +/** + * Set the dist without moving the view (compensate with #RegionView3D.ofs) + * + * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first. + */ +void ED_view3d_distance_set(RegionView3D *rv3d, const float dist) +{ + float viewinv[4]; + float tvec[3]; + + BLI_assert(dist >= 0.0f); + + 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); +#else + invert_qt_qt_normalized(viewinv, rv3d->viewquat); + mul_qt_v3(viewinv, tvec); +#endif + sub_v3_v3(rv3d->ofs, tvec); + + rv3d->dist = 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 */ +}; + + +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; + } +} + +char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon) +{ + /* quat values are all unit length */ + + 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; + } + } + + 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; + } + +} + +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; +} + + +bool ED_view3d_lock(RegionView3D *rv3d) +{ + return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Transform Utilities + * \{ */ + +/** + * Set the view transformation from a 4x4 matrix. + * + * \param mat The view 4x4 transformation matrix to assign. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. + */ +void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) +{ + float nmat[3][3]; + + /* dist depends on offset */ + BLI_assert(dist == NULL || ofs != NULL); + + copy_m3_m4(nmat, mat); + normalize_m3(nmat); + + /* Offset */ + if (ofs) + negate_v3_v3(ofs, mat[3]); + + /* Quat */ + if (quat) { + mat3_normalized_to_quat(quat, nmat); + invert_qt_normalized(quat); + } + + if (ofs && dist) { + madd_v3_v3fl(ofs, nmat[2], *dist); + } +} + +/** + * Calculate the view transformation matrix from RegionView3D input. + * The resulting matrix is equivalent to RegionView3D.viewinv + * \param mat The view 4x4 transformation matrix to calculate. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. + */ +void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float 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); +} + +/** + * Set the RegionView3D members from an objects transformation and optionally lens. + * \param ob The object to set the view to. + * \param ofs The view offset to be set, normally from RegionView3D.ofs. + * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs to be set, normally from RegionView3D.dist. + * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens. + */ +void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens) +{ + ED_view3d_from_m4(ob->obmat, ofs, quat, dist); + + if (lens) { + CameraParams params; + + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, ob); + *lens = params.lens; + } +} + +/** + * Set the object transformation from RegionView3D members. + * \param ob The object which has the transformation assigned. + * \param ofs The view offset, normally from RegionView3D.ofs. + * \param quat The view rotation, quaternion normally from RegionView3D.viewquat. + * \param dist The view distance from ofs, normally from RegionView3D.dist. + */ +void ED_view3d_to_object(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); + BKE_object_apply_mat4(ob, mat, true, true); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Depth Buffer Utilities + * \{ */ + +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; + } +} + +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; + } +} + +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); +} + +void ED_view3d_depth_tag_update(RegionView3D *rv3d) +{ + 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 72443a5a227..0597f2806b3 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -28,7 +28,6 @@ * \ingroup spview3d */ - #include "DNA_camera_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -39,7 +38,6 @@ #include "BLI_rect.h" #include "BLI_utildefines.h" -#include "BKE_anim.h" #include "BKE_action.h" #include "BKE_camera.h" #include "BKE_context.h" @@ -48,12 +46,9 @@ #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_screen.h" #include "DEG_depsgraph.h" -#include "BIF_glutil.h" - #include "UI_resources.h" #include "GPU_glew.h" @@ -64,7 +59,6 @@ #include "WM_types.h" #include "ED_screen.h" -#include "ED_armature.h" #include "DRW_engine.h" @@ -79,53 +73,14 @@ # include "BL_System.h" #endif - #include "view3d_intern.h" /* own include */ -/* use this call when executing an operator, - * event system doesn't set for each event the - * opengl drawing context */ -void view3d_operator_needs_opengl(const bContext *C) -{ - wmWindow *win = CTX_wm_window(C); - ARegion *ar = CTX_wm_region(C); - - view3d_region_operator_needs_opengl(win, ar); -} - -void view3d_region_operator_needs_opengl(wmWindow *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; - - wmSubWindowSet(win, ar->swinid); - gpuLoadProjectionMatrix(rv3d->winmat); - gpuLoadMatrix(rv3d->viewmat); - } -} - -float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d) -{ - if (v3d && v3d->localvd) return v3d->cursor; - else return scene->cursor; -} - -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; - } -} +/* -------------------------------------------------------------------- */ +/** \name Smooth View Operator & Utilities + * + * Use for view transitions to have smooth (animated) transitions. + * \{ */ -/* ****************** smooth view operator ****************** */ /* This operator is one of the 'timer refresh' ones like animation playback */ struct SmoothView3DState { @@ -402,6 +357,8 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool 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)) { @@ -463,22 +420,25 @@ void ED_view3d_smooth_view_force_finish( void VIEW3D_OT_smoothview(wmOperatorType *ot) { - /* identifiers */ ot->name = "Smooth View"; ot->description = ""; ot->idname = "VIEW3D_OT_smoothview"; - + /* api callbacks */ ot->invoke = view3d_smoothview_invoke; - + /* flags */ ot->flag = OPTYPE_INTERNAL; ot->poll = ED_operator_view3d_active; } -/* ****************** change view operators ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Camera to View Operator + * \{ */ static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -542,6 +502,12 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Camera Fit Frame to Selected Operator + * \{ */ + /* unlike VIEW3D_OT_view_selected this is for framing a render and not * meant to take into account vertex/bone selection for eg. */ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op) @@ -601,6 +567,12 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object as Camera Operator + * \{ */ + static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx) { Main *bmain = CTX_data_main(C); @@ -651,7 +623,7 @@ static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob } static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op) -{ +{ View3D *v3d; ARegion *ar; RegionView3D *rv3d; @@ -704,7 +676,6 @@ int ED_operator_rv3d_user_region_poll(bContext *C) 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"; @@ -718,280 +689,12 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************** */ - -void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) -{ - 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]); - } - - 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) -{ - /* 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); -} - -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; -} - -bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4]) -{ - /* return 1: draw */ - - float persmatob[4][4]; - - if (bb == NULL) return true; - if (bb->flag & BOUNDBOX_DISABLED) return true; - - mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat); - - 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); -} +/** \} */ /* -------------------------------------------------------------------- */ - -/** \name Depth Utilities +/** \name Window and View Matrix Calculation * \{ */ -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; - } -} - -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; - } -} - -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); -} - -/** \} */ - -void ED_view3d_depth_tag_update(RegionView3D *rv3d) -{ - if (rv3d->depths) - rv3d->depths->damaged = true; -} - -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->far * 10.0f; -} - -/* copies logic of get_view3d_viewplane(), keep in sync */ -bool ED_view3d_clip_range_get( - const Depsgraph *depsgraph, - const View3D *v3d, const RegionView3D *rv3d, - float *r_clipsta, float *r_clipend, - const bool use_ortho_factor) -{ - CameraParams params; - - 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.clipend - params.clipsta); - params.clipsta *= fac; - params.clipend *= fac; - } - - if (r_clipsta) *r_clipsta = params.clipsta; - if (r_clipend) *r_clipend = params.clipend; - - return params.is_ortho; -} - -bool ED_view3d_viewplane_get( - const Depsgraph *depsgraph, - const View3D *v3d, const RegionView3D *rv3d, int winx, int winy, - rctf *r_viewplane, float *r_clipsta, float *r_clipend, 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_clipsta) *r_clipsta = params.clipsta; - if (r_clipend) *r_clipend = params.clipend; - if (r_pixsize) *r_pixsize = params.viewdx; - - return params.is_ortho; -} - -/** - * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727] - */ -void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) -{ - float viewdist; - - if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { - return; - } - - 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])); - } - } - } - - bglPolygonOffset(viewdist, dist); -} - /** * \param rect optional for picking (can be NULL). */ @@ -1044,75 +747,21 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob) mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat); } -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 */ -}; - - -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; - } -} - -char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon) -{ - /* quat values are all unit length */ - - 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; - } - } - - 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; - } - -} - -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; -} - - -bool ED_view3d_lock(RegionView3D *rv3d) -{ - return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat); -} - -/* don't set windows active in here, is used by renderwin too */ -void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d) +/** + * Sets #RegionView3D.viewmat + * + * \param eval_ctx: Context. + * \param scene: Scene for camera and cursor location. + * \param v3d: View 3D space data. + * \param rv3d: 3D region which stores the final matrices. + * \param rect_scale: Optional 2D scale argument, + * Use when displaying a sub-region, eg: when #view3d_winmatrix_set takes a 'rect' argument. + * + * \note don't set windows active in here, is used by renderwin too. + */ +void view3d_viewmatrix_set( + const EvaluationContext *eval_ctx, Scene *scene, + const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { @@ -1173,6 +822,17 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons 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]); } @@ -1180,6 +840,12 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name OpenGL Select Utilities + * \{ */ + /** * Optionally cache data for multiple calls to #view3d_opengl_select * @@ -1331,6 +997,12 @@ finally: return hits; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Layer Utilities + * \{ */ + int ED_view3d_view_layer_set(int lay, const int *values, int *active) { int i, tot = 0; @@ -1369,43 +1041,43 @@ int ED_view3d_view_layer_set(int lay, const int *values, int *active) return lay; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Game Engine Operator + * + * Start the game engine (handles context switching). + * \{ */ + #ifdef WITH_GAMEENGINE static ListBase queue_back; -static void SaveState(bContext *C, wmWindow *win) +static void game_engine_save_state(bContext *C, wmWindow *win) { Object *obact = CTX_data_active_object(C); - + glPushAttrib(GL_ALL_ATTRIB_BITS); if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) GPU_paint_set_mipmap(1); - + queue_back = win->queue; - + BLI_listbase_clear(&win->queue); - - //XXX waitcursor(1); } -static void RestoreState(bContext *C, wmWindow *win) +static void game_engine_restore_state(bContext *C, wmWindow *win) { Object *obact = CTX_data_active_object(C); - + if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) GPU_paint_set_mipmap(0); - //XXX curarea->win_swap = 0; - //XXX curarea->head_swap = 0; - //XXX allqueue(REDRAWVIEW3D, 1); - //XXX allqueue(REDRAWBUTSALL, 0); - //XXX reset_slowparents(); - //XXX waitcursor(0); - //XXX G.qual = 0; - - if (win) /* check because closing win can set to NULL */ + /* check because closing win can set to NULL */ + if (win) { win->queue = queue_back; - + } + GPU_state_init(); glPopAttrib(); @@ -1476,33 +1148,6 @@ static int game_engine_poll(bContext *C) return 1; } -bool ED_view3d_context_activate(bContext *C) -{ - 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); - } - - if (sa == 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); - - return true; -} - static int game_engine_exec(bContext *C, wmOperator *op) { #ifdef WITH_GAMEENGINE @@ -1514,12 +1159,12 @@ static int game_engine_exec(bContext *C, wmOperator *op) RegionView3D *rv3d; rcti cam_frame; - (void)op; /* unused */ - + UNUSED_VARS(op); + /* bad context switch .. */ if (!ED_view3d_context_activate(C)) return OPERATOR_CANCELLED; - + /* redraw to hide any menus/popups, we don't go back to * the window manager until after this operator exits */ WM_redraw_windows(C); @@ -1531,7 +1176,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) ar = CTX_wm_region(C); view3d_operator_needs_opengl(C); - + game_set_commmandline_options(&startscene->gm); if ((rv3d->persp == RV3D_CAMOB) && @@ -1556,7 +1201,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) } - SaveState(C, prevwin); + game_engine_save_state(C, prevwin); StartKetsjiShell(C, ar, &cam_frame, 1); @@ -1565,7 +1210,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) prevwin = NULL; CTX_wm_window_set(C, NULL); } - + ED_area_tag_redraw(CTX_wm_area(C)); if (prevwin) { @@ -1576,7 +1221,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) CTX_wm_area_set(C, prevsa); } - RestoreState(C, prevwin); + game_engine_restore_state(C, prevwin); //XXX restore_all_scene_cfra(scene_cfra_store); BKE_scene_set_background(CTX_data_main(C), startscene); @@ -1586,7 +1231,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; #else - (void)C; /* unused */ + UNUSED_VARS(C); BKE_report(op->reports, RPT_ERROR, "Game engine is disabled in this build"); return OPERATOR_CANCELLED; #endif @@ -1594,168 +1239,15 @@ static int game_engine_exec(bContext *C, wmOperator *op) void VIEW3D_OT_game_start(wmOperatorType *ot) { - /* identifiers */ ot->name = "Start Game Engine"; ot->description = "Start game engine"; ot->idname = "VIEW3D_OT_game_start"; - + /* api callbacks */ ot->exec = game_engine_exec; - - ot->poll = game_engine_poll; -} - -/* ************************************** */ - -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; -} - -float ED_view3d_radius_to_dist_persp(const float angle, const float radius) -{ - 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 a new RegionView3D.dist value to fit the \a radius. - * - * \note Depth isn't taken into account, this will fit a flat plane exactly, - * but points towards the view (with a perspective projection), - * may be within the radius but outside the view. eg: - * - * <pre> - * + - * pt --> + /^ radius - * / | - * / | - * view + + - * \ | - * \ | - * \| - * + - * </pre> - * - * \param ar Can be NULL if \a use_aspect is false. - * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera) - * \param use_aspect Increase the distance to account for non 1:1 view aspect. - * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN). - */ -float ED_view3d_radius_to_dist( - const View3D *v3d, const ARegion *ar, - 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.clipsta = v3d->near; - params.clipend = v3d->far; - BKE_camera_params_from_object(¶ms, v3d->camera); - - 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; -} - -/* view matrix properties utilities */ - -/* unused */ -#if 0 -void ED_view3d_operator_properties_viewmat(wmOperatorType *ot) -{ - PropertyRNA *prop; - - prop = RNA_def_int(ot->srna, "region_width", 0, 0, INT_MAX, "Region Width", "", 0, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); - - prop = RNA_def_int(ot->srna, "region_height", 0, 0, INT_MAX, "Region height", "", 0, INT_MAX); - RNA_def_property_flag(prop, PROP_HIDDEN); - - prop = RNA_def_float_matrix(ot->srna, "perspective_matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Perspective Matrix", 0.0f, 0.0f); - RNA_def_property_flag(prop, PROP_HIDDEN); -} - -void ED_view3d_operator_properties_viewmat_set(bContext *C, wmOperator *op) -{ - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - - if (!RNA_struct_property_is_set(op->ptr, "region_width")) - RNA_int_set(op->ptr, "region_width", ar->winx); - - if (!RNA_struct_property_is_set(op->ptr, "region_height")) - RNA_int_set(op->ptr, "region_height", ar->winy); - - if (!RNA_struct_property_is_set(op->ptr, "perspective_matrix")) - RNA_float_set_array(op->ptr, "perspective_matrix", (float *)rv3d->persmat); + ot->poll = game_engine_poll; } -void ED_view3d_operator_properties_viewmat_get(wmOperator *op, int *winx, int *winy, float persmat[4][4]) -{ - *winx = RNA_int_get(op->ptr, "region_width"); - *winy = RNA_int_get(op->ptr, "region_height"); - - RNA_float_get_array(op->ptr, "perspective_matrix", (float *)persmat); -} -#endif +/** \} */ diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 724f60734f1..e65f9abae27 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -60,6 +60,8 @@ #include "RE_engine.h" +#include "DEG_depsgraph.h" + #include "view3d_intern.h" /* own include */ #ifdef WITH_INPUT_NDOF @@ -510,6 +512,9 @@ static float userdef_speed = -1.f; static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) { wmWindow *win = CTX_wm_window(C); + EvaluationContext eval_ctx; + + CTX_data_eval_ctx(C, &eval_ctx); walk->rv3d = CTX_wm_region_view3d(C); walk->v3d = CTX_wm_view3d(C); @@ -610,7 +615,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->ar, walk->v3d); walk->v3d_camera_control = ED_view3d_cameracontrol_acquire( - C, walk->scene, walk->v3d, walk->rv3d, + &eval_ctx, walk->scene, walk->v3d, walk->rv3d, (U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0); /* center the mouse */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index db6f2c27623..f882f3ecd65 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -622,7 +622,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - unsigned int pos; + unsigned int pos, color; efa_act = EDBM_uv_active_face_get(em, false, false); /* will be set to NULL if hidden */ ts = scene->toolsettings; @@ -671,58 +671,61 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje if (sima->flag & SI_DRAW_STRETCH) { draw_uvs_stretch(sima, scene, em, efa_act); } - else if (!(sima->flag & SI_NO_DRAWFACES)) { - /* draw transparent faces */ - UI_GetThemeColor4ubv(TH_FACE, col1); - UI_GetThemeColor4ubv(TH_FACE_SELECT, col2); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - - pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - for (unsigned int i = 0; i < em->tottri; i++) { - efa = em->looptris[i][0]->f; + else { + unsigned int tri_count = 0; + BM_ITER_MESH(efa, &iter, bm, BM_FACES_OF_MESH) { if (uvedit_face_visible_test(scene, ima, efa)) { - const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset); BM_elem_flag_enable(efa, BM_ELEM_TAG); - - if (efa == efa_act) { - /* only once */ - immUniformThemeColor(TH_EDITMESH_ACTIVE); - } - else { - immUniformColor4ubv(is_select ? col2 : col1); - } - - immBegin(GWN_PRIM_TRIS, (em->looptris[i][0]->f->len - 2) * 3); - draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos); - immEnd(); + tri_count += efa->len - 2; } else { BM_elem_flag_disable(efa, BM_ELEM_TAG); } } - immUnbindProgram(); + if (!(sima->flag & SI_NO_DRAWFACES)) { + /* draw transparent faces */ + UI_GetThemeColor4ubv(TH_FACE, col1); + UI_GetThemeColor4ubv(TH_FACE_SELECT, col2); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); - glDisable(GL_BLEND); - } - else { - /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, ima, efa)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); + Gwn_VertFormat *format = immVertexFormat(); + pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + + immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); + + immBegin(GWN_PRIM_TRIS, tri_count * 3); + for (unsigned int i = 0; i < em->tottri; i++) { + efa = em->looptris[i][0]->f; + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset); + + if (efa == efa_act) { + /* only once */ + unsigned char tmp_col[4]; + UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, tmp_col); + immAttrib4ubv(color, tmp_col); + } + else { + immAttrib4ubv(color, is_select ? col2 : col1); + } + + draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos); + } } - else { - if (efa == efa_act) - efa_act = NULL; - BM_elem_flag_disable(efa, BM_ELEM_TAG); + immEnd(); + + immUnbindProgram(); + + glDisable(GL_BLEND); + } + else { + if (efa_act && !uvedit_face_visible_test(scene, ima, efa_act)) { + efa_act = NULL; } } - } /* 3. draw active face stippled */ @@ -813,7 +816,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje Gwn_VertFormat *format = immVertexFormat(); pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); if (interpedges) { immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); @@ -900,7 +903,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje Gwn_VertFormat *format = immVertexFormat(); pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT); - unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); |