diff options
author | Hans Goudey <h.goudey@me.com> | 2019-05-15 17:56:22 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-05-15 19:10:58 +0300 |
commit | 06fe2a5e0c5d6202864701cf7fd800e4906057c9 (patch) | |
tree | 020910555116b6f002e87e52bb1f50a49e5967ef | |
parent | ddae9c92326486c5c95613bc0b7bb46e2d9bc261 (diff) |
Objects: new 3D cursor alignment option when adding objects
The choices are now World, View and 3D Cursor.
This breaks Python API compatibility, add-ons that add objects with this
parameter will need to be updated.
Differential Revision: https://developer.blender.org/D4706
-rw-r--r-- | release/scripts/modules/bpy_extras/object_utils.py | 59 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/add_mesh_torus.py | 2 | ||||
-rw-r--r-- | release/scripts/startup/bl_operators/object.py | 2 | ||||
-rw-r--r-- | release/scripts/templates_py/operator_mesh_add.py | 13 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 62 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_userdef.c | 7 | ||||
-rw-r--r-- | tests/python/bl_mesh_modifiers.py | 4 |
8 files changed, 98 insertions, 53 deletions
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index a5d80fd7810..48cdbb41c50 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -34,6 +34,7 @@ import bpy from bpy.props import ( BoolProperty, FloatVectorProperty, + EnumProperty, ) @@ -66,36 +67,32 @@ def add_object_align_init(context, operator): properties.location = location.to_translation() # rotation - view_align = (context.preferences.edit.object_align == 'VIEW') - view_align_force = False + add_align_preference = context.preferences.edit.object_align if operator: - if properties.is_property_set("view_align"): - view_align = view_align_force = operator.view_align + if not properties.is_property_set("rotation"): + # So one of "align" and "rotation" will be set + properties.align = add_align_preference + + if properties.align == 'WORLD': + rotation = properties.rotation.to_matrix().to_4x4() + elif properties.align == 'VIEW': + rotation = space_data.region_3d.view_matrix.to_3x3().inverted() + rotation.resize_4x4() + properties.rotation = rotation.to_euler() + elif properties.align == 'CURSOR': + rotation = context.scene.cursor.rotation_euler.to_matrix().to_4x4() + properties.rotation = rotation.to_euler() else: - if properties.is_property_set("rotation"): - # ugh, 'view_align' callback resets - value = properties.rotation[:] - properties.view_align = view_align - properties.rotation = value - del value - else: - properties.view_align = view_align - - if operator and (properties.is_property_set("rotation") and - not view_align_force): - - rotation = Euler(properties.rotation).to_matrix().to_4x4() + rotation = properties.rotation.to_matrix().to_4x4() else: - if view_align and space_data: + if (add_align_preference == 'VIEW') and space_data: rotation = space_data.region_3d.view_matrix.to_3x3().inverted() rotation.resize_4x4() + elif add_align_preference == 'CURSOR': + rotation = context.scene.cursor.rotation_euler.to_matrix().to_4x4() else: rotation = Matrix() - # set the operator properties - if operator: - properties.rotation = rotation.to_euler() - return location @ rotation @@ -168,14 +165,20 @@ def object_data_add(context, obdata, operator=None, name=None): class AddObjectHelper: - def view_align_update_callback(self, _context): - if not self.view_align: + def align_update_callback(self, _context): + if self.align == 'WORLD': self.rotation.zero() - view_align: BoolProperty( - name="Align to View", - default=False, - update=view_align_update_callback, + align_items = ( + ('WORLD', "World", "Align the new object to the world"), + ('VIEW', "View", "Align the new object to the view"), + ('CURSOR', "3D Cursor", "Use the 3D cursor orientation for the new object") + ) + align: EnumProperty( + name="Align", + items=align_items, + default='WORLD', + update=align_update_callback, ) location: FloatVectorProperty( name="Location", diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py index a22161fc1ae..bd727ec3e83 100644 --- a/release/scripts/startup/bl_operators/add_mesh_torus.py +++ b/release/scripts/startup/bl_operators/add_mesh_torus.py @@ -202,7 +202,7 @@ class AddTorus(Operator, object_utils.AddObjectHelper): col = layout.column(align=True) col.prop(self, "generate_uvs") col.separator() - col.prop(self, "view_align") + col.prop(self, "align") col = layout.column(align=True) col.label(text="Location") diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index f68b59192b8..28324891c53 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -912,7 +912,7 @@ class LoadImageAsEmpty: 'INVOKE_REGION_WIN', type='IMAGE', location=cursor, - view_align=self.view_align, + align=('VIEW' if self.view_align else 'WORLD'), ) obj = context.active_object diff --git a/release/scripts/templates_py/operator_mesh_add.py b/release/scripts/templates_py/operator_mesh_add.py index 5a9acce3026..39402ab1c6b 100644 --- a/release/scripts/templates_py/operator_mesh_add.py +++ b/release/scripts/templates_py/operator_mesh_add.py @@ -75,10 +75,17 @@ class AddBox(bpy.types.Operator): ) # generic transform props - view_align: BoolProperty( - name="Align to View", - default=False, + align_items = ( + ('WORLD', "World", "Align the new object to the world"), + ('VIEW', "View", "Align the new object to the view"), + ('CURSOR', "3D Cursor", "Use the 3D cursor orientation for the new object") ) + align: EnumProperty( + name="Align", + items=align_items, + default='WORLD', + update=AddObjectHelper.align_update_callback, + ) location: FloatVectorProperty( name="Location", subtype='TRANSLATION', diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 50a97e309fb..f8760f93f2f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -161,6 +161,18 @@ static EnumPropertyItem lightprobe_type_items[] = { {0, NULL, 0, NULL, NULL}, }; +enum ObjectAlign { + ALIGN_WORLD, + ALIGN_VIEW, + ALIGN_CURSOR, +} ALIGN_OPTIONS; + +static const EnumPropertyItem align_options[] = { + {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"}, + {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"}, + {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"}, + {0, NULL, 0, NULL, NULL}}; + /************************** Exported *****************************/ void ED_object_location_from_view(bContext *C, float loc[3]) @@ -291,16 +303,15 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode) { PropertyRNA *prop; - /* note: this property gets hidden for add-camera operator */ - prop = RNA_def_boolean( - ot->srna, "view_align", 0, "Align to View", "Align the new object to the view"); - RNA_def_property_update_runtime(prop, view_align_update); - if (do_editmode) { prop = RNA_def_boolean( ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } + /* note: this property gets hidden for add-camera operator */ + prop = RNA_def_enum( + ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object"); + RNA_def_property_update_runtime(prop, view_align_update); prop = RNA_def_float_vector_xyz(ot->srna, "location", @@ -392,23 +403,42 @@ bool ED_object_add_generic_get_opts(bContext *C, rot = _rot; } + prop = RNA_struct_find_property(op->ptr, "align"); + int alignment = RNA_property_enum_get(op->ptr, prop); + bool alignment_set = RNA_property_is_set(op->ptr, prop); + if (RNA_struct_property_is_set(op->ptr, "rotation")) { *is_view_aligned = false; } - else if (RNA_struct_property_is_set(op->ptr, "view_align")) { - *is_view_aligned = RNA_boolean_get(op->ptr, "view_align"); + else if (alignment_set) { + *is_view_aligned = alignment == ALIGN_VIEW; } else { *is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0; - RNA_boolean_set(op->ptr, "view_align", *is_view_aligned); + if (*is_view_aligned) { + RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW); + alignment = ALIGN_VIEW; + } + else if (U.flag & USER_ADD_CURSORALIGNED) { + RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR); + alignment = ALIGN_CURSOR; + } } - if (*is_view_aligned) { - ED_object_rotation_from_view(C, rot, view_align_axis); - RNA_float_set_array(op->ptr, "rotation", rot); - } - else { - RNA_float_get_array(op->ptr, "rotation", rot); + switch (alignment) { + case ALIGN_WORLD: + RNA_float_get_array(op->ptr, "rotation", rot); + break; + case ALIGN_VIEW: + ED_object_rotation_from_view(C, rot, view_align_axis); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + case ALIGN_CURSOR: { + const Scene *scene = CTX_data_scene(C); + copy_v3_v3(rot, scene->cursor.rotation_euler); + RNA_float_set_array(op->ptr, "rotation", rot); + break; + } } } @@ -690,7 +720,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) float loc[3], rot[3]; /* force view align for cameras */ - RNA_boolean_set(op->ptr, "view_align", true); + RNA_enum_set(op->ptr, "align", ALIGN_VIEW); if (!ED_object_add_generic_get_opts( C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) { @@ -732,7 +762,7 @@ void OBJECT_OT_camera_add(wmOperatorType *ot) ED_object_add_generic_props(ot, true); /* hide this for cameras, default */ - prop = RNA_struct_type_find_property(ot->srna, "view_align"); + prop = RNA_struct_type_find_property(ot->srna, "align"); RNA_def_property_flag(prop, PROP_HIDDEN); } diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index d42263660d2..2247ec2e6ee 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -833,7 +833,7 @@ typedef enum eUserPref_Flag { USER_TOOLTIPS = (1 << 11), USER_TWOBUTTONMOUSE = (1 << 12), USER_NONUMPAD = (1 << 13), - USER_FLAG_UNUSED_14 = (1 << 14), /* cleared */ + USER_ADD_CURSORALIGNED = (1 << 14), USER_FILECOMPRESS = (1 << 15), USER_SAVE_PREVIEWS = (1 << 16), USER_CUSTOM_RANGE = (1 << 17), diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 1e5d59c1491..38877ba6fdd 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4347,7 +4347,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna) "VIEW", 0, "View", - "Align newly added objects facing the active 3D View direction"}, + "Align newly added objects to the active 3D View direction"}, + {USER_ADD_CURSORALIGNED, + "CURSOR", + 0, + "3D Cursor", + "Align newly added objects to the 3D Cursor's rotation"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py index 74eaaeb7c68..80f810ffad8 100644 --- a/tests/python/bl_mesh_modifiers.py +++ b/tests/python/bl_mesh_modifiers.py @@ -582,7 +582,7 @@ cube_shell_face = ( def make_cube(scene): - bpy.ops.mesh.primitive_cube_add(view_align=False, + bpy.ops.mesh.primitive_cube_add(align='WORLD', enter_editmode=False, location=(0, 0, 0), rotation=(0, 0, 0), @@ -652,7 +652,7 @@ def make_cube_shell_extra(scene): def make_monkey(scene): - bpy.ops.mesh.primitive_monkey_add(view_align=False, + bpy.ops.mesh.primitive_monkey_add(align='WORLD', enter_editmode=False, location=(0, 0, 0), rotation=(0, 0, 0), |