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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-01-28 15:34:02 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-01-28 16:18:10 +0300
commit49c19ca679ea89209a18374d51377084f378f289 (patch)
tree7111a90a709920ed09386d0f1e8c00aaa8905ad7 /source/blender/editors
parente15dd419d43182f9b826210e9ae90803cb7626a4 (diff)
parentdfbe4153721b6764a41c2e8de8f41c6cdab6fe7e (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt500
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c6
-rw-r--r--source/blender/editors/include/ED_view3d.h9
-rw-r--r--source/blender/editors/include/UI_icons.h7
-rw-r--r--source/blender/editors/include/UI_interface.h4
-rw-r--r--source/blender/editors/interface/interface_handlers.c72
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c4
-rw-r--r--source/blender/editors/interface/view2d_ops.c3
-rw-r--r--source/blender/editors/io/io_collada.c3
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c12
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c5
-rw-r--r--source/blender/editors/object/object_add.c17
-rw-r--r--source/blender/editors/object/object_relations.c6
-rw-r--r--source/blender/editors/render/render_shading.c3
-rw-r--r--source/blender/editors/screen/screen_draw.c8
-rw-r--r--source/blender/editors/screen/screen_ops.c88
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c9
-rw-r--r--source/blender/editors/space_action/action_select.c6
-rw-r--r--source/blender/editors/space_graph/graph_edit.c3
-rw-r--r--source/blender/editors/space_graph/graph_select.c6
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/space_nla/nla_select.c3
-rw-r--r--source/blender/editors/space_node/drawnode.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c94
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h9
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c163
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c20
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawobject.c7
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c1139
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h11
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c94
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c1436
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c700
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c7
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c89
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(&params);
- BKE_camera_params_from_object(&params, 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(&params);
+ BKE_camera_params_from_view3d(&params, 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(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, 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(&params);
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+ BKE_camera_params_from_object(&params, 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(&params);
+ BKE_camera_params_from_object(&params, 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(&params);
- BKE_camera_params_from_view3d(&params, 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(&params);
- BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
- BKE_camera_params_compute_viewplane(&params, 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(&params);
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, 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);