Gizmo: optional custom orientations for transform
authorCampbell Barton <ideasman42@gmail.com>
Wed, 19 Dec 2018 09:51:04 +0000 (20:51 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 19 Dec 2018 09:57:51 +0000 (20:57 +1100)
This aims to resolve a conflict where some users want to keep keyboard
axis setting global, even when the orientation is set to something else.

Move/rotate/scale can optionally each have a separate orientation.

Some UI changes will be made next.

19 files changed:
release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/versioning_280.c
source/blender/editors/include/ED_transform.h
source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
source/blender/editors/mesh/editmesh_select.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_gizmo_3d.c
source/blender/editors/transform/transform_gizmo_extrude_3d.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_scene.c

index 68b487ffe4428af4d3499f7a4b1b259d3f30279d..590d429996810511493503c227cef4265ab7d698 100644 (file)
@@ -64,6 +64,17 @@ class _template_widget:
             props = tool.gizmo_group_properties("VIEW3D_GGT_xform_extrude")
             layout.prop(props, "axis_type", expand=True)
 
+    class TRANSFORM_GGT_gizmo:
+        @staticmethod
+        def draw_settings_with_index(context, layout, index):
+            row = layout.row(align=True)
+            scene = context.scene
+            orientation_slot = scene.transform_orientation_slots[index]
+            value = orientation_slot.use
+            row.prop(orientation_slot, "use", text="", icon='LINKED' if value else 'UNLINKED')
+            if not value:
+                row.prop(orientation_slot, "type", text="")
+
 
 class _defs_view3d_generic:
     @ToolDef.from_fn
@@ -202,6 +213,8 @@ class _defs_transform:
 
     @ToolDef.from_fn
     def translate():
+        def draw_settings(context, layout, tool):
+            _template_widget.TRANSFORM_GGT_gizmo.draw_settings_with_index(context, layout, 1)
         return dict(
             text="Move",
             # cursor='SCROLL_XY',
@@ -209,10 +222,13 @@ class _defs_transform:
             widget="TRANSFORM_GGT_gizmo",
             operator="transform.translate",
             keymap="3D View Tool: Move",
+            draw_settings=draw_settings,
         )
 
     @ToolDef.from_fn
     def rotate():
+        def draw_settings(context, layout, tool):
+            _template_widget.TRANSFORM_GGT_gizmo.draw_settings_with_index(context, layout, 2)
         return dict(
             text="Rotate",
             # cursor='SCROLL_XY',
@@ -220,10 +236,13 @@ class _defs_transform:
             widget="TRANSFORM_GGT_gizmo",
             operator="transform.rotate",
             keymap="3D View Tool: Rotate",
+            draw_settings=draw_settings,
         )
 
     @ToolDef.from_fn
     def scale():
+        def draw_settings(context, layout, tool):
+            _template_widget.TRANSFORM_GGT_gizmo.draw_settings_with_index(context, layout, 3)
         return dict(
             text="Scale",
             # cursor='SCROLL_XY',
@@ -231,15 +250,19 @@ class _defs_transform:
             widget="TRANSFORM_GGT_gizmo",
             operator="transform.resize",
             keymap="3D View Tool: Scale",
+            draw_settings=draw_settings,
         )
 
     @ToolDef.from_fn
     def scale_cage():
+        def draw_settings(context, layout, tool):
+            _template_widget.TRANSFORM_GGT_gizmo.draw_settings_with_index(context, layout, 3)
         return dict(
             text="Scale Cage",
             icon="ops.transform.resize.cage",
             widget="VIEW3D_GGT_xform_cage",
             operator="transform.resize",
+            draw_settings=draw_settings,
         )
 
     @ToolDef.from_fn
@@ -252,6 +275,8 @@ class _defs_transform:
             props = tool.gizmo_group_properties("TRANSFORM_GGT_gizmo")
             layout.prop(props, "drag_action")
 
+            _template_widget.TRANSFORM_GGT_gizmo.draw_settings_with_index(context, layout, 1)
+
         return dict(
             text="Transform",
             description=(
index 825fd5f2a001c028031491dc5a70c3d1396d5b1a..8f3132f690fbdad8497c3961f00101dec48730f6 100644 (file)
@@ -121,16 +121,16 @@ class VIEW3D_HT_header(Header):
 
         # Orientation
         if object_mode in {'OBJECT', 'EDIT', 'POSE', 'EDIT_GPENCIL'}:
-            orientation = scene.transform_orientation
-            current_orientation = scene.current_orientation
+            orient_slot = scene.transform_orientation_slots[0]
+            custom_orientation = orient_slot.custom_orientation
 
-            if not current_orientation:
-                trans_orientation = bpy.types.Scene.bl_rna.properties["transform_orientation"].enum_items[orientation]
-                trans_icon = getattr(trans_orientation, "icon", "BLANK1")
+            if custom_orientation is None:
+                trans_orientation = bpy.types.TransformOrientationSlot.bl_rna.properties["type"].enum_items[orient_slot.type]
+                trans_icon = getattr(trans_orientation, "icon", 'BLANK1')
                 trans_name = getattr(trans_orientation, "name", "Orientation")
             else:
                 trans_icon = 'OBJECT_ORIGIN'
-                trans_name = getattr(current_orientation, "name", "Orientation")
+                trans_name = getattr(custom_orientation, "name", "Orientation")
 
             row = layout.row(align=True)
 
@@ -5258,11 +5258,12 @@ class VIEW3D_PT_transform_orientations(Panel):
         layout.label(text="Transform Orientations")
 
         scene = context.scene
-        orientation = scene.current_orientation
+        orient_slot = scene.transform_orientation_slots[0]
+        orientation = orient_slot.custom_orientation
 
         row = layout.row()
         col = row.column()
-        col.prop(scene, "transform_orientation", expand=True)
+        col.prop(orient_slot, "type", expand=True)
         row.operator("transform.create_orientation", text="", icon='ADD', emboss=False).use = True
 
         if orientation:
index 6344d29a2a0c29094f69f9647954fa80e3841c66..fd1ba56fd8bf5ed7918c91897b63e1a5375d6144 100644 (file)
@@ -139,6 +139,10 @@ float BKE_scene_frame_get(const struct Scene *scene);
 float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float frame);
 void  BKE_scene_frame_set(struct Scene *scene, double cfra);
 
+struct TransformOrientationSlot *BKE_scene_orientation_slot_get(struct Scene *scene, int flag);
+void BKE_scene_orientation_slot_set_index(struct TransformOrientationSlot *orient_slot, int orientation);
+int BKE_scene_orientation_slot_get_index(const struct TransformOrientationSlot *orient_slot);
+
 /* **  Scene evaluation ** */
 
 void BKE_scene_graph_update_tagged(struct Depsgraph *depsgraph,
index 3de1ddb1e1e30c53842ce346c59c09056bce6074..05603efb2c34b8711f30a393dea2cc9fb2c0780f 100644 (file)
@@ -864,7 +864,9 @@ void BKE_scene_init(Scene *sce)
        sce->toolsettings->annotate_v3d_align = GP_PROJECT_VIEWSPACE | GP_PROJECT_CURSOR;
        sce->toolsettings->annotate_thickness = 3;
 
-       sce->orientation_index_custom = -1;
+       for (int i = 0; i < ARRAY_SIZE(sce->orientation_slots); i++) {
+               sce->orientation_slots[i].index_custom = -1;
+       }
 
        /* Master Collection */
        sce->master_collection = BKE_collection_master_add();
@@ -1321,7 +1323,6 @@ float BKE_scene_frame_get_from_ctime(const Scene *scene, const float frame)
 
        return ctime;
 }
-
 /**
  * Sets the frame int/float components.
  */
@@ -1332,6 +1333,52 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
        scene->r.cfra = (int)intpart;
 }
 
+
+/* -------------------------------------------------------------------- */
+/** \name Scene Orientation Slots
+ * \{ */
+
+TransformOrientationSlot *BKE_scene_orientation_slot_get(Scene *scene, int flag)
+{
+       BLI_assert(flag && !(flag & ~(SCE_GIZMO_SHOW_TRANSLATE | SCE_GIZMO_SHOW_ROTATE | SCE_GIZMO_SHOW_SCALE)));
+       int index = SCE_ORIENT_DEFAULT;
+       if (flag & SCE_GIZMO_SHOW_TRANSLATE) {
+               index = SCE_ORIENT_TRANSLATE;
+       }
+       else if (flag & SCE_GIZMO_SHOW_ROTATE) {
+               index = SCE_ORIENT_ROTATE;
+       }
+       else if (flag & SCE_GIZMO_SHOW_SCALE) {
+               index = SCE_ORIENT_SCALE;
+       }
+
+       if ((scene->orientation_slots[index].flag & SELECT) == 0) {
+               index = SCE_ORIENT_DEFAULT;
+       }
+       return &scene->orientation_slots[index];
+}
+
+/**
+ * Activate a transform orientation in a 3D view based on an enum value.
+ *
+ * \param orientation: If this is #V3D_MANIP_CUSTOM or greater, the custom transform orientation
+ * with index \a orientation - #V3D_MANIP_CUSTOM gets activated.
+ */
+void BKE_scene_orientation_slot_set_index(TransformOrientationSlot *orient_slot, int orientation)
+{
+       const bool is_custom = orientation >= V3D_MANIP_CUSTOM;
+       orient_slot->type = is_custom ? V3D_MANIP_CUSTOM : orientation;
+       orient_slot->index_custom = is_custom ? (orientation - V3D_MANIP_CUSTOM) : -1;
+}
+
+int BKE_scene_orientation_slot_get_index(const TransformOrientationSlot *orient_slot)
+{
+       return (orient_slot->type == V3D_MANIP_CUSTOM) ? (orient_slot->type + orient_slot->index_custom) : orient_slot->type;
+}
+
+/** \} */
+
+
 /* That's like really a bummer, because currently animation data for armatures
  * might want to use pose, and pose might be missing on the object.
  * This happens when changing visible layers, which leads to situations when
@@ -2166,11 +2213,16 @@ void BKE_scene_transform_orientation_remove(
         Scene *scene, TransformOrientation *orientation)
 {
        const int orientation_index = BKE_scene_transform_orientation_get_index(scene, orientation);
-       if (scene->orientation_index_custom == orientation_index) {
-               /* could also use orientation_index-- */
-               scene->orientation_type = V3D_MANIP_GLOBAL;
-               scene->orientation_index_custom = -1;
+
+       for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+               TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
+               if (orient_slot->index_custom == orientation_index) {
+                       /* could also use orientation_index-- */
+                       orient_slot->type = V3D_MANIP_GLOBAL;
+                       orient_slot->index_custom = -1;
+               }
        }
+
        BLI_freelinkN(&scene->transform_spaces, orientation);
 }
 
index 0c9b98064255117b949ff84c0f449c3feae3f05d..9b3add627226c2cc2b5ae20ff44e662d9479b77e 100644 (file)
@@ -1230,12 +1230,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
                        }
                }
 
-               if (!DNA_struct_elem_find(fd->filesdna, "Scene", "int", "orientation_index_custom")) {
-                       for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
-                               scene->orientation_index_custom = -1;
-                       }
-               }
-
                for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
                        for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
                                for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
@@ -2762,5 +2756,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
                                }
                        }
                }
+
+               if (!DNA_struct_find(fd->filesdna, "TransformOrientationSlot")) {
+                       for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+                               for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+                                       scene->orientation_slots[i].index_custom = -1;
+                               }
+                       }
+               }
        }
 }
index 718c8a48300495bb7da049c44aa95e99bcefde1a..ad39c1ccc8a3cac9a576a8ff9376c10015908cde 100644 (file)
@@ -132,7 +132,6 @@ void BIF_createTransformOrientation(struct bContext *C, struct ReportList *repor
                                     const char *name, const bool use_view,
                                     const bool activate, const bool overwrite);
 void BIF_selectTransformOrientation(struct bContext *C, struct TransformOrientation *ts);
-void BIF_selectTransformOrientationValue(struct Scene *scene, int orientation);
 
 void ED_getTransformOrientationMatrix(const struct bContext *C, float orientation_mat[3][3], const short around);
 
@@ -210,7 +209,8 @@ void ED_transform_calc_orientation_from_type(
          const struct bContext *C, float r_mat[3][3],
          /* extra args */
          struct Scene *scene, struct RegionView3D *rv3d, struct Object *ob, struct Object *obedit,
-         const short orientation_type, const int pivot_point);
+         const short orientation_type, int orientation_index_custom,
+         const int pivot_point);
 
 struct TransformBounds {
        float center[3];                /* Center for transform widget. */
@@ -226,6 +226,7 @@ struct TransformCalcParams {
        uint use_local_axis : 1;
        /* Use 'Scene.orientation_type' when zero, otherwise subtract one and use. */
        ushort orientation_type;
+       ushort orientation_index_custom;
 };
 int ED_transform_calc_gizmo_stats(
         const struct bContext *C,
index 92b655b6d8ddb0146d7dd48908cb93f0b81e4302..dd5f97cd010fa912b13f82a98dd1fe88be627a3a 100644 (file)
@@ -25,6 +25,7 @@
 #include "BLI_math.h"
 
 #include "BKE_context.h"
+#include "BKE_scene.h"
 
 #include "RNA_define.h"
 #include "RNA_access.h"
@@ -244,7 +245,8 @@ static void gizmo_mesh_spin_init_draw_prepare(
 
        {
                Scene *scene = CTX_data_scene(C);
-               switch (scene->orientation_type) {
+               const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_GIZMO_SHOW_ROTATE);
+               switch (orient_slot->type) {
                        case V3D_MANIP_VIEW:
                        {
                                if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
@@ -444,10 +446,8 @@ static void gizmo_mesh_spin_init_message_subscribe(
        RNA_id_pointer_create(&scene->id, &scene_ptr);
 
        {
-               extern PropertyRNA rna_Scene_transform_orientation;
                extern PropertyRNA rna_Scene_cursor_location;
                const PropertyRNA *props[] = {
-                       &rna_Scene_transform_orientation,
                        &rna_Scene_cursor_location,
                };
                for (int i = 0; i < ARRAY_SIZE(props); i++) {
index 4ab00dd59620e0d6c0273a40f726d59c168bfb65..fdd8a124652874d73725451761a4420051aa6e57 100644 (file)
@@ -4372,7 +4372,7 @@ static int edbm_select_axis_exec(bContext *C, wmOperator *op)
        ED_transform_calc_orientation_from_type_ex(
                C, axis_mat,
                scene, CTX_wm_region_view3d(C), obedit, obedit,
-               orientation, V3D_AROUND_ACTIVE);
+               orientation, 0, V3D_AROUND_ACTIVE);
 
        const float *axis_vector = axis_mat[axis];
 
index 0f555bcc5b7c374298395d2e1420ce9f00456825..7509b88ccff7f7d8fa2a936073cf39c34acf7434 100644 (file)
@@ -2147,10 +2147,11 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
                            !RNA_property_is_set(op->ptr, prop) &&
                            (t->orientation.user != V3D_MANIP_CUSTOM_MATRIX))
                        {
-                               t->scene->orientation_type = t->orientation.user;
-                               BLI_assert(((t->scene->orientation_index_custom == -1) && (t->orientation.custom == NULL)) ||
+                               TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+                               orient_slot->type = t->orientation.user;
+                               BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) ||
                                           (BKE_scene_transform_orientation_get_index(
-                                                   t->scene, t->orientation.custom) == t->scene->orientation_index_custom));
+                                                   t->scene, t->orientation.custom) == orient_slot->index_custom));
                        }
                }
        }
index 75044e77110eea8c0aa1875d0d5bc334f2c8cbde..3970261ac024bfd918348e7fe478d0627b029745 100644 (file)
@@ -509,7 +509,7 @@ typedef struct TransInfo {
                short           user_alt;
                short           index;
                short           *types[2];
-               /* this gets used when current_orientation is V3D_MANIP_CUSTOM */
+               /* this gets used when custom_orientation is V3D_MANIP_CUSTOM */
                TransformOrientation *custom;
        } orientation;
        short           gizmo_flag;                     /* backup from view3d, to restore on end */
index c1a2eb218cf4cbc8500c8ff7a3d988c5aa1d58b4..f1dc5525dbc5973346cbc479e233f5442846172f 100644 (file)
@@ -1401,9 +1401,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
                        t->around = V3D_AROUND_CURSOR;
                }
 
-               t->orientation.user = t->scene->orientation_type;
-               t->orientation.custom = BKE_scene_transform_orientation_find(
-                       t->scene, t->scene->orientation_index_custom);
+               TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+               t->orientation.user = orient_slot->type;
+               t->orientation.custom = BKE_scene_transform_orientation_find(t->scene, orient_slot->index_custom);
 
                t->orientation.index = 0;
                ARRAY_SET_ITEMS(
index 5a26245c14d8f2475cb07b63681d78be774c01e0..b17a345ee097bc769c75315cb0a3726d8a03939e 100644 (file)
@@ -638,19 +638,21 @@ void ED_transform_calc_orientation_from_type(
        Object *obedit = CTX_data_edit_object(C);
        RegionView3D *rv3d = ar->regiondata;
        Object *ob = OBACT(view_layer);
-       const short orientation_type = scene->orientation_type;
+       const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+       const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
        const int pivot_point = scene->toolsettings->transform_pivot_point;
 
        ED_transform_calc_orientation_from_type_ex(
                C, r_mat,
-               scene, rv3d, ob, obedit, orientation_type, pivot_point);
+               scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
 }
 
 void ED_transform_calc_orientation_from_type_ex(
         const bContext *C, float r_mat[3][3],
         /* extra args (can be accessed from context) */
         Scene *scene, RegionView3D *rv3d, Object *ob, Object *obedit,
-        const short orientation_type, const int pivot_point)
+        const short orientation_type, int orientation_index_custom,
+        const int pivot_point)
 {
        bool ok = false;
 
@@ -712,7 +714,7 @@ void ED_transform_calc_orientation_from_type_ex(
                case V3D_MANIP_CUSTOM:
                {
                        TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
-                               scene, scene->orientation_index_custom);
+                               scene, orientation_index_custom);
                        if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
                                ok = true;
                        }
@@ -759,11 +761,14 @@ int ED_transform_calc_gizmo_stats(
        /* global, local or normal orientation?
         * if we could check 'totsel' now, this should be skipped with no selection. */
        if (ob) {
-               const short orientation_type = params->orientation_type ? (params->orientation_type - 1) : scene->orientation_type;
+               const short orientation_type = params->orientation_type ?
+                       (params->orientation_type - 1) : scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+               const short orientation_index_custom = params->orientation_type ?
+                       params->orientation_index_custom : scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
                float mat[3][3];
                ED_transform_calc_orientation_from_type_ex(
                        C, mat,
-                       scene, rv3d, ob, obedit, orientation_type, pivot_point);
+                       scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
                copy_m4_m3(rv3d->twmat, mat);
        }
 
@@ -1206,6 +1211,8 @@ static void gizmo_xform_message_subscribe(
         wmGizmoGroup *gzgroup, struct wmMsgBus *mbus,
         Scene *scene, bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar, const void *type_fn)
 {
+       GizmoGroup *ggd = gzgroup->customdata;
+
        /* Subscribe to view properties */
        wmMsgSubscribeValue msg_sub_value_gz_tag_refresh = {
                .owner = ar,
@@ -1217,10 +1224,10 @@ static void gizmo_xform_message_subscribe(
        RNA_id_pointer_create(&scene->id, &scene_ptr);
 
        {
-               extern PropertyRNA rna_Scene_transform_orientation;
+               extern PropertyRNA rna_Scene_transform_orientation_slots;
                extern PropertyRNA rna_Scene_cursor_location;
                const PropertyRNA *props[] = {
-                       &rna_Scene_transform_orientation,
+                       &rna_Scene_transform_orientation_slots,
                        (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) ? &rna_Scene_cursor_location : NULL,
                };
                for (int i = 0; i < ARRAY_SIZE(props); i++) {
@@ -1230,15 +1237,30 @@ static void gizmo_xform_message_subscribe(
                }
        }
 
+       TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, ggd->twtype_init);
+       PointerRNA orient_ref_ptr;
+       RNA_pointer_create(&scene->id, &RNA_TransformOrientationSlot, orient_slot, &orient_ref_ptr);
+       {
+               extern PropertyRNA rna_TransformOrientationSlot_type;
+               extern PropertyRNA rna_TransformOrientationSlot_use;
+               const PropertyRNA *props[] = {
+                       &rna_TransformOrientationSlot_type,
+                       &rna_TransformOrientationSlot_use,
+               };
+               for (int i = 0; i < ARRAY_SIZE(props); i++) {
+                       if (props[i]) {
+                               WM_msg_subscribe_rna(mbus, &orient_ref_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
+                       }
+               }
+       }
+
        PointerRNA toolsettings_ptr;
        RNA_pointer_create(&scene->id, &RNA_ToolSettings, scene->toolsettings, &toolsettings_ptr);
 
        if (type_fn == TRANSFORM_GGT_gizmo) {
                extern PropertyRNA rna_ToolSettings_transform_pivot_point;
-               extern PropertyRNA rna_ToolSettings_use_gizmo_mode;
                const PropertyRNA *props[] = {
                        &rna_ToolSettings_transform_pivot_point,
-                       &rna_ToolSettings_use_gizmo_mode,
                };
                for (int i = 0; i < ARRAY_SIZE(props); i++) {
                        WM_msg_subscribe_rna(mbus, &toolsettings_ptr, props[i], &msg_sub_value_gz_tag_refresh, __func__);
@@ -1610,12 +1632,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
 static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 {
        GizmoGroup *ggd = gzgroup->customdata;
+       Scene *scene = CTX_data_scene(C);
        ARegion *ar = CTX_wm_region(C);
        RegionView3D *rv3d = ar->regiondata;
        struct TransformBounds tbounds;
 
        if (ggd->use_twtype_refresh) {
-               Scene *scene = CTX_data_scene(C);
                ggd->twtype = scene->toolsettings->gizmo_flag & ggd->twtype_init;
                if (ggd->twtype != ggd->twtype_prev) {
                        ggd->twtype_prev = ggd->twtype;
@@ -1623,11 +1645,15 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
                }
        }
 
+       const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, ggd->twtype_init);
+
        /* skip, we don't draw anything anyway */
        if ((ggd->all_hidden =
             (ED_transform_calc_gizmo_stats(
                     C, &(struct TransformCalcParams){
                         .use_only_center = true,
+                        .orientation_type = orient_slot->type + 1,
+                        .orientation_index_custom = orient_slot->index_custom,
                     }, &tbounds) == 0)))
        {
                return;
@@ -1757,7 +1783,8 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr
        if (!equals_m3m3(viewinv_m3, ggd->prev.viewinv_m3)) {
                {
                        Scene *scene = CTX_data_scene(C);
-                       switch (scene->orientation_type) {
+                       const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, ggd->twtype_init);
+                       switch (orient_slot->type) {
                                case V3D_MANIP_VIEW:
                                {
                                        WIDGETGROUP_gizmo_refresh(C, gzgroup);
@@ -1774,8 +1801,26 @@ static void WIDGETGROUP_gizmo_invoke_prepare(
         const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
 {
 
-       /* Support shift click to constrain axis. */
        GizmoGroup *ggd = gzgroup->customdata;
+
+       /* Support gizmo spesific orientation. */
+       {
+               Scene *scene = CTX_data_scene(C);
+               wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
+               PointerRNA *ptr = &gzop->ptr;
+               PropertyRNA *prop_constraint_orientation = RNA_struct_find_property(ptr, "constraint_orientation");
+               const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, ggd->twtype_init);
+               if (orient_slot == &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
+                       RNA_property_unset(ptr, prop_constraint_orientation);
+               }
+               else {
+                       /* TODO: APIfunction */
+                       int index = BKE_scene_orientation_slot_get_index(orient_slot);
+                       RNA_property_enum_set(ptr, prop_constraint_orientation, index);
+               }
+       }
+
+       /* Support shift click to constrain axis. */
        const int axis_idx = BLI_array_findindex(ggd->gizmos, ARRAY_SIZE(ggd->gizmos), &gz);
        int axis = -1;
        switch (axis_idx) {
@@ -1932,15 +1977,20 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgr
 {
        ARegion *ar = CTX_wm_region(C);
        RegionView3D *rv3d = ar->regiondata;
+       Scene *scene = CTX_data_scene(C);
 
        struct XFormCageWidgetGroup *xgzgroup = gzgroup->customdata;
        wmGizmo *gz = xgzgroup->gizmo;
 
        struct TransformBounds tbounds;
 
+       const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_GIZMO_SHOW_SCALE);
+
        if ((ED_transform_calc_gizmo_stats(
                     C, &(struct TransformCalcParams) {
                         .use_local_axis = true,
+                        .orientation_type = orient_slot->type + 1,
+                        .orientation_index_custom = orient_slot->index_custom,
                     }, &tbounds) == 0) ||
            equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max))
        {
@@ -2016,7 +2066,8 @@ static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmGizmoGroup
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
        {
                Scene *scene = CTX_data_scene(C);
-               switch (scene->orientation_type) {
+               const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_GIZMO_SHOW_SCALE);
+               switch (orient_slot->type) {
                        case V3D_MANIP_VIEW:
                        {
                                float viewinv_m3[3][3];
@@ -2173,7 +2224,9 @@ static void WIDGETGROUP_xform_shear_draw_prepare(const bContext *C, wmGizmoGroup
        RegionView3D *rv3d = CTX_wm_region_view3d(C);
        {
                Scene *scene = CTX_data_scene(C);
-               switch (scene->orientation_type) {
+               /* Shear is like rotate, use the rotate setting. */
+               const TransformOrientationSlot *orient_slot = BKE_scene_orientation_slot_get(scene, SCE_GIZMO_SHOW_ROTATE);
+               switch (orient_slot->type) {
                        case V3D_MANIP_VIEW:
                        {
                                float viewinv_m3[3][3];
index 1dc50f476fa0149ccf3de934177febae151721b2..441141e97188271b31881b021062f846164e8d87 100644 (file)
@@ -233,7 +233,7 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
                axis_type = RNA_property_enum_get(&ptr, ggd->gzgt_axis_type_prop);
        }
 
-       ggd->data.orientation_type = scene->orientation_type;
+       ggd->data.orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
        const bool use_normal = (
                (ggd->data.orientation_type != V3D_MANIP_NORMAL) ||
                (axis_type == EXTRUDE_AXIS_NORMAL));
@@ -431,7 +431,7 @@ static void gizmo_mesh_extrude_message_subscribe(
        };
 
        {
-               WM_msg_subscribe_rna_anon_prop(mbus, Scene, transform_orientation, &msg_sub_value_gz_tag_refresh);
+               WM_msg_subscribe_rna_anon_prop(mbus, TransformOrientationSlot, type, &msg_sub_value_gz_tag_refresh);
        }
 
 
index d11cfa8d3d311a54a200d110dabb19229bc85b27..5a3575c04d98dccc79800998a82ae8d23033c8ff 100644 (file)
@@ -39,6 +39,7 @@
 #include "BKE_global.h"
 #include "BKE_report.h"
 #include "BKE_editmesh.h"
+#include "BKE_scene.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -168,12 +169,12 @@ static int select_orientation_exec(bContext *C, wmOperator *op)
        Scene *scene = CTX_data_scene(C);
        int orientation = RNA_enum_get(op->ptr, "orientation");
 
-       BIF_selectTransformOrientationValue(scene, orientation);
+       BKE_scene_orientation_slot_set_index(&scene->orientation_slots[SCE_ORIENT_DEFAULT], orientation);
 
        WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
 
        struct wmMsgBus *mbus = CTX_wm_message_bus(C);
-       WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation);
+       WM_msg_publish_rna_prop(mbus, &scene->id, scene, TransformOrientationSlot, type);
 
        return OPERATOR_FINISHED;
 }
@@ -215,7 +216,7 @@ static void TRANSFORM_OT_select_orientation(struct wmOperatorType *ot)
 static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Scene *scene = CTX_data_scene(C);
-       BIF_removeTransformOrientationIndex(C, scene->orientation_index_custom);
+       BIF_removeTransformOrientationIndex(C, scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom);
 
        WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene);
 
@@ -234,7 +235,8 @@ static bool delete_orientation_poll(bContext *C)
        if (ED_operator_areaactive(C) == 0)
                return 0;
 
-       return (scene->orientation_type >= V3D_MANIP_CUSTOM) && (scene->orientation_index_custom != -1);
+       return ((scene->orientation_slots[SCE_ORIENT_DEFAULT].type >= V3D_MANIP_CUSTOM) &&
+               (scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom != -1));
 }
 
 static void TRANSFORM_OT_delete_orientation(struct wmOperatorType *ot)
index a21882fc20661f1661eb8e8553acf13aa1a990a6..04999213c6312e338e18451fb8c57fd07de10b7b 100644 (file)
@@ -71,9 +71,12 @@ void BIF_clearTransformOrientation(bContext *C)
 
        BLI_freelistN(transform_orientations);
 
-       if (scene->orientation_type == V3D_MANIP_CUSTOM) {
-               scene->orientation_type = V3D_MANIP_GLOBAL; /* fallback to global */
-               scene->orientation_index_custom = -1;
+       for (int i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
+               TransformOrientationSlot *orient_slot = &scene->orientation_slots[i];
+               if (orient_slot->type == V3D_MANIP_CUSTOM) {
+                       orient_slot->type = V3D_MANIP_GLOBAL; /* fallback to global */
+                       orient_slot->index_custom = -1;
+               }
        }
 }
 
@@ -366,21 +369,8 @@ void BIF_selectTransformOrientation(bContext *C, TransformOrientation *target)
 
        BLI_assert(index != -1);
 
-       scene->orientation_type = V3D_MANIP_CUSTOM;
-       scene->orientation_index_custom = index;
-}
-
-/**
- * Activate a transform orientation in a 3D view based on an enum value.
- *
- * \param orientation: If this is #V3D_MANIP_CUSTOM or greater, the custom transform orientation
- *                     with index \a orientation - #V3D_MANIP_CUSTOM gets activated.
- */
-void BIF_selectTransformOrientationValue(Scene *scene, int orientation)
-{
-       const bool is_custom = orientation >= V3D_MANIP_CUSTOM;
-       scene->orientation_type = is_custom ? V3D_MANIP_CUSTOM : orientation;
-       scene->orientation_index_custom = is_custom ? (orientation - V3D_MANIP_CUSTOM) : -1;
+       scene->orientation_slots[SCE_ORIENT_DEFAULT].type = V3D_MANIP_CUSTOM;
+       scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom = index;
 }
 
 int BIF_countTransformOrientation(const bContext *C)
index d312566a4fda00d772fe9eb7863a3dff0d5a81ce..467d70ffd81923d3e387d4e5a7bd40213c4e1e4c 100644 (file)
@@ -1521,6 +1521,21 @@ typedef struct SceneEEVEE {
 /* *************************************************************** */
 /* Scene ID-Block */
 
+typedef struct TransformOrientationSlot {
+       int type;
+       int index_custom;
+       char flag;
+       char _pad0[7];
+} TransformOrientationSlot;
+
+/* Indices when used in Scene.orientation. */
+enum {
+       SCE_ORIENT_DEFAULT = 0,
+       SCE_ORIENT_TRANSLATE = 1,
+       SCE_ORIENT_ROTATE = 2,
+       SCE_ORIENT_SCALE = 3,
+};
+
 typedef struct Scene {
        ID id;
        struct AnimData *adt;   /* animation data (must be immediately after id for utilities to use it) */
@@ -1561,8 +1576,8 @@ typedef struct Scene {
        ListBase markers;
        ListBase transform_spaces;
 
-       int orientation_index_custom;
-       int orientation_type;
+       /* First is the [scene, translate, rotate, scale]. */
+       TransformOrientationSlot orientation_slots[4];
 
        void *sound_scene;
        void *playback_handle;
index 1fc143ed71fc462392753a4147275de6884737a1..336dbec214b70334ba24520adabd297914467aad 100644 (file)
@@ -514,7 +514,7 @@ enum {
 #define V3D_SHOW_Y              (1 << 2)
 #define V3D_SHOW_Z              (1 << 3)
 
-/* Scene.orientation_type */
+/** #TransformOrientationSlot.type */
 #define V3D_MANIP_GLOBAL               0
 #define V3D_MANIP_LOCAL                        1
 #define V3D_MANIP_NORMAL               2
index 86f0f2d85bfd839a0ce5efc7c8fb0b16e54ad44b..f6bfcb2bb3275c5e3ba2fcbbf9d456a103ac6b3c 100644 (file)
@@ -697,6 +697,7 @@ extern StructRNA RNA_TintGpencilModifier;
 extern StructRNA RNA_ToolSettings;
 extern StructRNA RNA_TrackToConstraint;
 extern StructRNA RNA_TransformConstraint;
+extern StructRNA RNA_TransformOrientationSlot;
 extern StructRNA RNA_TransformSequence;
 extern StructRNA RNA_UILayout;
 extern StructRNA RNA_UIList;
index 6719eaceaad62bbf223ef9c9a39e50db337ab939..58bde16344250e8875cd3b39b8f95ec5c7615a3d 100644 (file)
@@ -1567,6 +1567,20 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain), Scene *UNU
                RE_FreePersistentData();
 }
 
+/* Scene.orientation_slots */
+static void rna_Scene_transform_orientation_slots_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
+{
+       Scene *scene = (Scene *)ptr->id.data;
+       TransformOrientationSlot *orient_slot = &scene->orientation_slots[0];
+       rna_iterator_array_begin(iter, orient_slot, sizeof(*orient_slot), ARRAY_SIZE(scene->orientation_slots), 0, NULL);
+}
+
+static int rna_Scene_transform_orientation_slots_length(PointerRNA *ptr)
+{
+       Scene *scene = (Scene *)ptr->id.data;
+       return ARRAY_SIZE(scene->orientation_slots);
+}
+
 static bool rna_Scene_use_audio_get(PointerRNA *ptr)
 {
        Scene *scene = (Scene *)ptr->data;
@@ -1961,32 +1975,29 @@ static void rna_ViewLayer_remove(
        }
 }
 
-static int rna_Scene_transform_orientation_get(PointerRNA *ptr)
+static int rna_TransformOrientationSlot_type_get(PointerRNA *ptr)
 {
-       Scene *scene = ptr->data;
-       /* convert to enum value */
-       return (scene->orientation_type == V3D_MANIP_CUSTOM) ?
-                   (scene->orientation_type + scene->orientation_index_custom) : scene->orientation_type;
+       TransformOrientationSlot *orient_slot = ptr->data;
+       return BKE_scene_orientation_slot_get_index(orient_slot);
 }
 
-void rna_Scene_transform_orientation_set(PointerRNA *ptr, int value)
+void rna_TransformOrientationSlot_type_set(PointerRNA *ptr, int value)
 {
-       Scene *scene = ptr->data;
-       BIF_selectTransformOrientationValue(scene, value);
+       TransformOrientationSlot *orient_slot = ptr->data;
+       BKE_scene_orientation_slot_set_index(orient_slot, value);
 }
 
-static PointerRNA rna_Scene_current_orientation_get(PointerRNA *ptr)
+static PointerRNA rna_TransformOrientationSlot_get(PointerRNA *ptr)
 {
-       Scene *scene = ptr->data;
+       Scene *scene = ptr->id.data;
+       TransformOrientationSlot *orient_slot = ptr->data;
        TransformOrientation *orientation;
-
-       if (scene->orientation_type < V3D_MANIP_CUSTOM) {
+       if (orient_slot->type < V3D_MANIP_CUSTOM) {
                orientation = NULL;
        }
        else {
-               orientation = BKE_scene_transform_orientation_find(scene, scene->orientation_index_custom);
+               orientation = BKE_scene_transform_orientation_find(scene, orient_slot->index_custom);
        }
-
        return rna_pointer_inherit_refine(ptr, &RNA_TransformOrientation, orientation);
 }
 
@@ -2180,6 +2191,39 @@ static void rna_def_transform_orientation(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 }
 
+static void rna_def_transform_orientation_slot(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "TransformOrientationSlot", NULL);
+       RNA_def_struct_sdna(srna, "TransformOrientationSlot");
+       RNA_def_struct_ui_text(srna, "Orientation Slot", "");
+
+       /* Orientations */
+       prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, rna_enum_transform_orientation_items);
+       RNA_def_property_enum_funcs(
+               prop,
+               "rna_TransformOrientationSlot_type_get",
+               "rna_TransformOrientationSlot_type_set",
+               "rna_TransformOrientation_itemf");
+       RNA_def_property_ui_text(prop, "Transform Orientation", "Transformation orientation");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+       prop = RNA_def_property(srna, "custom_orientation", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "TransformOrientation");
+       RNA_def_property_pointer_funcs(prop, "rna_TransformOrientationSlot_get", NULL, NULL, NULL);
+       RNA_def_property_ui_text(prop, "Current Transform Orientation", "");
+
+       /* flag */
+       prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SELECT);
+       RNA_def_property_ui_text(prop, "Use", "Disable to unlink the orientation from the scene-setting");
+       RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
+
 static void rna_def_tool_settings(BlenderRNA  *brna)
 {
        StructRNA *srna;
@@ -6429,19 +6473,18 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Timeline Markers", "Markers used in all timelines for the current scene");
        rna_def_timeline_markers(brna, prop);
 
-       /* Orientations */
-       prop = RNA_def_property(srna, "transform_orientation", PROP_ENUM, PROP_NONE);
-       RNA_def_property_enum_sdna(prop, NULL, "orientation_type");
-       RNA_def_property_enum_items(prop, rna_enum_transform_orientation_items);
-       RNA_def_property_enum_funcs(prop, "rna_Scene_transform_orientation_get", "rna_Scene_transform_orientation_set",
-                                   "rna_TransformOrientation_itemf");
-       RNA_def_property_ui_text(prop, "Transform Orientation", "Transformation orientation");
-       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
-       prop = RNA_def_property(srna, "current_orientation", PROP_POINTER, PROP_NONE);
-       RNA_def_property_struct_type(prop, "TransformOrientation");
-       RNA_def_property_pointer_funcs(prop, "rna_Scene_current_orientation_get", NULL, NULL, NULL);
-       RNA_def_property_ui_text(prop, "Current Transform Orientation", "Current transformation orientation");
+       /* Transform Orientations */
+       prop = RNA_def_property(srna, "transform_orientation_slots", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_collection_funcs(
+               prop,
+               "rna_Scene_transform_orientation_slots_begin",
+               "rna_iterator_array_next",
+               "rna_iterator_array_end",
+               "rna_iterator_array_get",
+               "rna_Scene_transform_orientation_slots_length",
+               NULL, NULL, NULL);
+       RNA_def_property_struct_type(prop, "TransformOrientationSlot");
+       RNA_def_property_ui_text(prop, "Transform Orientation Slots", "");
 
        /* Audio Settings */
        prop = RNA_def_property(srna, "use_audio", PROP_BOOLEAN, PROP_NONE);
@@ -6566,6 +6609,7 @@ void RNA_def_scene(BlenderRNA *brna)
        rna_def_unit_settings(brna);
        rna_def_scene_image_format_data(brna);
        rna_def_transform_orientation(brna);
+       rna_def_transform_orientation_slot(brna);
        rna_def_selected_uv_element(brna);
        rna_def_display_safe_areas(brna);
        rna_def_scene_display(brna);