diff options
author | Jacques Lucke <mail@jlucke.com> | 2018-10-09 15:36:15 +0300 |
---|---|---|
committer | Jacques Lucke <mail@jlucke.com> | 2018-10-09 15:36:15 +0300 |
commit | 85944a2d7e73d1ed070b19e50bc6927b47070091 (patch) | |
tree | 73c976ef37777b5569045fdb1e96ecd467ac6320 | |
parent | 3e2422a9471b7fccdd1de57ed06f3a0b95f5bb0a (diff) |
Image Empties: Usability improvements and fixes
- new "Align to View" option when loading a new image
- automatically align to view when dropping an image into a viewport
- larger default size for image empties
- fix image empty gizmo in orthographic view
- new "Align Objects to View" operator
Reviewer: brecht
Differential: https://developer.blender.org/D3778
6 files changed, 71 insertions, 17 deletions
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index f68ebfc4b94..d5175d31cf9 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -19,6 +19,7 @@ # <pep8-80 compliant> import bpy +from mathutils import Euler from bpy.types import Operator from bpy.props import ( BoolProperty, @@ -28,6 +29,8 @@ from bpy.props import ( StringProperty, ) +from math import radians + class SelectPattern(Operator): """Select objects matching a naming pattern""" @@ -874,7 +877,7 @@ class LoadImageAsEmpty(Operator): """Select an image file and create a new image empty with it""" bl_idname = "object.load_image_as_empty" bl_label = "Load Image as Empty" - bl_options = {'REGISTER'} + bl_options = {'REGISTER', 'UNDO'} filepath: StringProperty( subtype='FILE_PATH' @@ -883,6 +886,11 @@ class LoadImageAsEmpty(Operator): filter_image: BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) filter_folder: BoolProperty(default=True, options={'HIDDEN', 'SKIP_SAVE'}) + align_view: BoolProperty( + name="Align to view", + default=True + ) + def invoke(self, context, event): context.window_manager.fileselect_add(self) return {'RUNNING_MODAL'} @@ -899,10 +907,48 @@ class LoadImageAsEmpty(Operator): bpy.ops.object.empty_add(type='IMAGE', location=cursor) context.active_object.data = image + context.active_object.scale = (5, 5, 5) + if self.align_view: + bpy.ops.object.align_to_view() return {'FINISHED'} +class AlignObjectsToView(bpy.types.Operator): + bl_idname = "object.align_to_view" + bl_label = "Align Objects to View" + bl_options = {"REGISTER", "UNDO"} + + axis_data = { + "X": Euler((0, radians(-90), 0)), + "-X": Euler((0, radians(90), 0)), + "Y": Euler((radians(90), 0, 0)), + "-Y": Euler((radians(-90), 0, 0)), + "Z": Euler((0, 0, 0)), + "-Z": Euler((0, radians(180), 0)) + } + + front_axis: EnumProperty( + name="Front Axis", + default="Z", + items=[(name, name, "") for name in axis_data.keys()] + ) + + @classmethod + def poll(cls, context): + return context.space_data.type == "VIEW_3D" + + def execute(self, context): + base = self.axis_data[self.front_axis].to_matrix() + + view = context.space_data.region_3d.view_matrix + rotation = (view.to_3x3().inverted() @ base).to_euler() + for object in context.selected_objects: + object.rotation_euler = rotation + + return {"FINISHED"} + classes = ( + AlignObjectsToView, ClearAllRestrictRender, DupliOffsetFromCursor, IsolateTypeRender, diff --git a/source/blender/editors/gizmo_library/gizmo_library_utils.c b/source/blender/editors/gizmo_library/gizmo_library_utils.c index 350c9922179..25364652785 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_utils.c +++ b/source/blender/editors/gizmo_library/gizmo_library_utils.c @@ -190,7 +190,8 @@ bool gizmo_window_project_2d( float plane[4], co[3]; plane_from_point_normal_v3(plane, mat[3], mat[2]); - if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, true, co)) { + bool clip_ray = ((RegionView3D *)ar->regiondata)->is_persp; + if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, clip_ray, co)) { float imat[4][4]; invert_m4_m4(imat, mat); mul_m4_v3(imat, co); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 713cc21c8ec..560ed0cf0e0 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -469,6 +469,7 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple( struct GPUOffScreen *ofs, char err_out[256]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); +struct Object *ED_view3d_give_object_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip); void ED_view3d_update_viewmat( struct Depsgraph *depsgraph, struct Scene *scene, struct View3D *v3d, struct ARegion *ar, diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 3fccb5f6943..4963b304483 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -869,9 +869,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv { Scene *scene = CTX_data_scene(C); - Base *base = NULL; Image *ima = NULL; - Object *ob = NULL; ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM); if (!ima) { @@ -880,26 +878,24 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv /* handled below */ id_us_min((ID *)ima); - base = ED_view3d_give_base_under_cursor(C, event->mval); + Object *ob = NULL; + Object *ob_cursor = ED_view3d_give_object_under_cursor(C, event->mval); - /* if empty under cursor, then set object */ - if (base && base->object->type == OB_EMPTY) { - ob = base->object; - DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); + /* either change empty under cursor or create a new empty */ + if (ob_cursor && ob_cursor->type == OB_EMPTY) { WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + DEG_id_tag_update((ID *)ob_cursor, DEG_TAG_TRANSFORM); + ob = ob_cursor; } else { - /* add new empty */ - float rot[3]; - - if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, NULL)) - return OPERATOR_CANCELLED; - - ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false); + ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, NULL, false); - /* add under the mouse */ ED_object_location_from_view(C, ob->loc); ED_view3d_cursor3d_position(C, event->mval, false, ob->loc); + ED_object_rotation_from_view(C, ob->rot, 'Z'); + ob->size[0] = 5; + ob->size[1] = 5; + ob->size[2] = 5; } BKE_object_empty_draw_type_set(ob, OB_EMPTY_IMAGE); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_empty.c b/source/blender/editors/space_view3d/view3d_gizmo_empty.c index 2913ba245e7..8bbc9c8f553 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_empty.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_empty.c @@ -31,6 +31,8 @@ #include "BKE_object.h" #include "BKE_image.h" +#include "DEG_depsgraph.h" + #include "DNA_object_types.h" #include "DNA_lamp_types.h" @@ -94,6 +96,7 @@ static void gizmo_empty_image_prop_matrix_set( Object *ob = igzgroup->state.ob; ob->empty_drawsize = matrix[0][0]; + DEG_id_tag_update(ob, DEG_TAG_TRANSFORM); float dims[2]; RNA_float_get_array(gz->ptr, "dimensions", dims); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 26a9a8f24c1..47266c2584e 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1528,6 +1528,13 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2]) return basact; } +Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2]) +{ + Base *base = ED_view3d_give_base_under_cursor(C, mval); + if (base) return base->object; + return NULL; +} + static void deselect_all_tracks(MovieTracking *tracking) { MovieTrackingObject *object; |