Manipulator: view3d navigation buttons
authorCampbell Barton <ideasman42@gmail.com>
Fri, 15 Dec 2017 16:57:20 +0000 (03:57 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 15 Dec 2017 17:21:30 +0000 (04:21 +1100)
Added for Blender101 template.
Disabled by default, enable as a preference.

Exposes rotate, pan, zoom, persp-ortho & camera toggle.

12 files changed:
release/scripts/startup/bl_ui/space_userpref.py
source/blender/editors/include/ED_manipulator_library.h
source/blender/editors/manipulator_library/CMakeLists.txt
source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c [new file with mode: 0644]
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_view3d/CMakeLists.txt
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_manipulator_navigate.c [new file with mode: 0644]
source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c [new file with mode: 0644]
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/intern/rna_userdef.c

index 31f0886e8b122a6a024ff70292e5f6de449d4ea3..0abb187679856953ef6ba291aff451f2823610d1 100644 (file)
@@ -287,6 +287,7 @@ class USERPREF_PT_interface(Panel):
         #col.prop(view, "open_left_mouse_delay", text="Hold LMB")
         #col.prop(view, "open_right_mouse_delay", text="Hold RMB")
         col.prop(view, "show_manipulator")
+        col.prop(view, "show_manipulator_navigate")
         ## Currently not working
         # col.prop(view, "show_manipulator_shaded")
         sub = col.column()
index 807033214906975b18176aaf500242b98e89eae3..7166292147ed1c072022c7765f5c33596e56aa57 100644 (file)
@@ -33,6 +33,7 @@
 /* initialize manipulators */
 void ED_manipulatortypes_arrow_2d(void);
 void ED_manipulatortypes_arrow_3d(void);
+void ED_manipulatortypes_button_2d(void);
 void ED_manipulatortypes_cage_2d(void);
 void ED_manipulatortypes_cage_3d(void);
 void ED_manipulatortypes_dial_3d(void);
index 9f7df8c642577929effd072803873a0ed96fc5a9..86e1bb3b6d7f9797dedc4b63234dbeb40df2fc43 100644 (file)
@@ -47,6 +47,7 @@ set(SRC
        geometry/geom_dial_manipulator.c
        manipulator_types/arrow2d_manipulator.c
        manipulator_types/arrow3d_manipulator.c
+       manipulator_types/button2d_manipulator.c
        manipulator_types/cage2d_manipulator.c
        manipulator_types/cage3d_manipulator.c
        manipulator_types/dial3d_manipulator.c
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
new file mode 100644 (file)
index 0000000..32c1dba
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file button2d_manipulator.c
+ *  \ingroup wm
+ *
+ * \name Button Manipulator
+ *
+ * 3D Manipulator, also works in 2D views.
+ *
+ * \brief Single click button action for use in manipulator groups.
+ *
+ * Note: currently only very basic icon buttons supported.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_interface_icons.h"
+#include "UI_resources.h"
+
+/* own includes */
+#include "../manipulator_geometry.h"
+#include "../manipulator_library_intern.h"
+
+typedef struct ButtonManipulator3D {
+       wmManipulator manipulator;
+       /* Added to 'matrix_basis' when calculating the matrix. */
+       float prop_co[3];
+} ButtonManipulator3D;
+
+#define DIAL_RESOLUTION 32
+
+/* -------------------------------------------------------------------- */
+
+static void button_geom_draw(
+        const wmManipulator *mpr, const float color[4], const bool select)
+{
+       glLineWidth(mpr->line_width);
+
+       Gwn_VertFormat *format = immVertexFormat();
+       uint pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+       immUniformColor4fv(color);
+
+       /* TODO, other draw styles */
+       imm_draw_circle_fill_2d(pos, 0, 0, 1.0f, DIAL_RESOLUTION);
+
+       immUnbindProgram();
+
+       UNUSED_VARS(select);
+}
+
+static void button3d_draw_intern(
+        const bContext *UNUSED(C), wmManipulator *mpr,
+        const bool select, const bool highlight)
+{
+       float color[4];
+       float matrix_final[4][4];
+
+       manipulator_color_get(mpr, highlight, color);
+       WM_manipulator_calc_matrix_final(mpr, matrix_final);
+
+       gpuPushMatrix();
+       gpuMultMatrix(matrix_final);
+
+       glEnable(GL_BLEND);
+       button_geom_draw(mpr, color, select);
+       gpuPopMatrix();
+
+
+       if (select == false) {
+               int icon = RNA_enum_get(mpr->ptr, "icon");
+               if (icon != ICON_NONE) {
+                       UI_icon_draw(
+                               mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * U.pixelsize,
+                               mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * U.pixelsize,
+                               icon);
+               }
+       }
+       glDisable(GL_BLEND);
+}
+
+static void manipulator_button_draw_select(const bContext *C, wmManipulator *mpr, int select_id)
+{
+       GPU_select_load_id(select_id);
+       button3d_draw_intern(C, mpr, true, false);
+}
+
+static void manipulator_button_draw(const bContext *C, wmManipulator *mpr)
+{
+       const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+       glEnable(GL_BLEND);
+       button3d_draw_intern(C, mpr, false, is_highlight);
+       glDisable(GL_BLEND);
+}
+
+static int manipulator_button_test_select(
+        bContext *C, wmManipulator *mpr, const wmEvent *event)
+{
+       float point_local[2];
+
+       if (0) {
+               /* correct, but unnecessarily slow. */
+               if (manipulator_window_project_2d(
+                       C, mpr, (const float[2]){UNPACK2(event->mval)}, 2, true, point_local) == false)
+               {
+                       return -1;
+               }
+       }
+       else {
+               copy_v2_v2(point_local, (float [2]){UNPACK2(event->mval)});
+               sub_v2_v2(point_local, mpr->matrix_basis[3]);
+               mul_v2_fl(point_local, 1.0f / mpr->scale_basis);
+       }
+
+       /* The 'mpr->scale_final' is already applied when projecting. */
+       if (len_squared_v2(point_local) < 1.0f) {
+               return 0;
+       }
+
+       return -1;
+}
+
+static int manipulator_button_cursor_get(wmManipulator *UNUSED(mpr))
+{
+       return BC_HANDCURSOR;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Button Manipulator API
+ *
+ * \{ */
+
+static void MANIPULATOR_WT_button_2d(wmManipulatorType *wt)
+{
+       /* identifiers */
+       wt->idname = "MANIPULATOR_WT_button_2d";
+
+       /* api callbacks */
+       wt->draw = manipulator_button_draw;
+       wt->draw_select = manipulator_button_draw_select;
+       wt->test_select = manipulator_button_test_select;
+       wt->cursor_get = manipulator_button_cursor_get;
+
+       wt->struct_size = sizeof(ButtonManipulator3D);
+
+       /* rna */
+       PropertyRNA *prop;
+       prop = RNA_def_property(wt->srna, "icon", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, rna_enum_icon_items);
+       RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item");
+}
+
+void ED_manipulatortypes_button_2d(void)
+{
+       WM_manipulatortype_append(MANIPULATOR_WT_button_2d);
+}
+
+/** \} */ // Button Manipulator API
index 32f6ac40d122f4287b888c9be7735e570b98834f..e417026640e14e55bcf5689bb27b7003155f611e 100644 (file)
@@ -127,6 +127,7 @@ void ED_spacetypes_init(void)
        ED_operatortypes_ui();
 
        /* manipulator types */
+       ED_manipulatortypes_button_2d();
        ED_manipulatortypes_dial_3d();
        ED_manipulatortypes_grab_3d();
        ED_manipulatortypes_arrow_2d();
index de8380aa8bbe8308dbfb564a8fce0bcc6f110069..11ef781b229da7799edb9f9de35ef080a4245108 100644 (file)
@@ -64,6 +64,8 @@ set(SRC
        view3d_manipulator_empty.c
        view3d_manipulator_forcefield.c
        view3d_manipulator_lamp.c
+       view3d_manipulator_navigate.c
+       view3d_manipulator_navigate_type.c
        view3d_manipulator_ruler.c
        view3d_ops.c
        view3d_project.c
index 984ab82ee607ccb47af34d754d80907448a069a7..3430351b7560d3b9c2c369e3189b415813b19361 100644 (file)
@@ -729,6 +729,9 @@ static void view3d_widgets(void)
 
        WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
        WM_manipulatortype_append(VIEW3D_WT_ruler_item);
+
+       WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
+       WM_manipulatortype_append(VIEW3D_WT_navigate_rotate);
 }
 
 
index a7368a84eb6bb4010bb00121ccc15e07105885fa..ee0b628fdadbc446e479b066e782feb68b2d59de 100644 (file)
@@ -153,7 +153,7 @@ void draw_object_select(
         const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, struct ARegion *ar, View3D *v3d,
         Base *base, const short dflag);
 
-void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
+void draw_mesh_object_outline(View3D *v3d, struct Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
 
 bool draw_glsl_material(Scene *scene, struct ViewLayer *view_layer, struct Object *ob, View3D *v3d, const char dt);
 void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]);
@@ -304,7 +304,7 @@ void ED_view3d_cameracontrol_update(
 void ED_view3d_cameracontrol_release(
         struct View3DCameraControl *vctrl,
         const bool restore);
-Object *ED_view3d_cameracontrol_object_get(
+struct Object *ED_view3d_cameracontrol_object_get(
         struct View3DCameraControl *vctrl);
 
 /* view3d_toolbar.c */
@@ -338,11 +338,14 @@ void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt);
 void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt);
 void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt);
 void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_navigate(struct wmManipulatorGroupType *wgt);
 
 void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt);
 void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt);
 void VIEW3D_OT_ruler_add(struct wmOperatorType *ot);
 
+void VIEW3D_WT_navigate_rotate(struct wmManipulatorType *wt);
+
 /* draw_volume.c */
 void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
                        const float min[3], const float max[3],
@@ -365,7 +368,7 @@ extern bool view3d_camera_border_hack_test;
 void VP_legacy_drawcursor(Scene *scene, struct ViewLayer *view_layer, ARegion *ar, View3D *v3d);
 void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect);
 void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect);
-void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect);
+void VP_legacy_draw_selected_name(Scene *scene, struct Object *ob, rcti *rect);
 void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
 void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
 void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
new file mode 100644 (file)
index 0000000..553d3b0
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_manipulator_navigate.c
+ *  \ingroup spview3d
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+
+#include "DNA_object_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h"  /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View3D Navigation Manipulator Group
+ * \{ */
+
+/* Offset from screen edge. */
+#define MANIPULATOR_OFFSET_FAC 2.5
+/* Size of main icon. */
+#define MANIPULATOR_SIZE 64
+/* Factor for size of smaller button. */
+#define MANIPULATOR_MINI_FAC 0.4
+/* How much mini buttons offset from the primary. */
+#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f
+
+
+enum {
+       MPR_MOVE = 0,
+       MPR_ROTATE = 1,
+       MPR_ZOOM = 2,
+       /* just buttons */
+       MPR_PERSP_ORTHO = 3,
+       MPR_CAMERA = 4,
+
+       MPR_TOTAL = 5,
+};
+
+struct NavigateManipulatorInfo {
+       const char *opname;
+       const char *manipulator;
+       int icon;
+};
+
+struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = {
+       {
+               .opname = "VIEW3D_OT_move",
+               .manipulator = "MANIPULATOR_WT_button_2d",
+               .icon = ICON_HAND,
+       }, {
+               .opname = "VIEW3D_OT_rotate",
+               .manipulator = "VIEW3D_WT_navigate_rotate",
+               .icon = ICON_NONE,
+       }, {
+               .opname = "VIEW3D_OT_zoom",
+               .manipulator = "MANIPULATOR_WT_button_2d",
+               .icon = ICON_VIEWZOOM,
+       }, {
+               .opname = "VIEW3D_OT_view_persportho",
+               .manipulator = "MANIPULATOR_WT_button_2d",
+               .icon = ICON_MESH_CUBE,
+       }, {
+               .opname = "VIEW3D_OT_viewnumpad",
+               .manipulator = "MANIPULATOR_WT_button_2d",
+               .icon = ICON_OUTLINER_OB_CAMERA,
+       },
+};
+
+struct NavigateWidgetGroup {
+       wmManipulator *mpr_array[MPR_TOTAL];
+       int region_size[2];
+};
+
+static bool WIDGETGROUP_navigate_poll(const bContext *UNUSED(C), wmManipulatorGroupType *UNUSED(wgt))
+{
+       if (U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) {
+               return true;
+       }
+       return false;
+
+}
+
+static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+       struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
+
+       navgroup->region_size[0] = -1;
+       navgroup->region_size[1] = -1;
+
+       wmOperatorType *ot_viewnumpad = WM_operatortype_find("VIEW3D_OT_viewnumpad", true);
+
+       for (int i = 0; i < MPR_TOTAL; i++) {
+               const struct NavigateManipulatorInfo *info = &g_navigate_params[i];
+               navgroup->mpr_array[i] = WM_manipulator_new(info->manipulator, mgroup, NULL);
+               wmManipulator *mpr = navgroup->mpr_array[i];
+               mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR;
+               RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_GRAB_DRAW_FLAG_FILL);
+               copy_v3_fl(mpr->color, 1.0f);
+               mpr->color[3] = 0.4f;
+
+               /* may be overwritten later */
+               mpr->scale_basis = (MANIPULATOR_SIZE * MANIPULATOR_MINI_FAC) / 2;
+               if (info->icon != ICON_NONE) {
+                       RNA_enum_set(mpr->ptr, "icon", info->icon);
+               }
+
+               wmOperatorType *ot = WM_operatortype_find(info->opname, true);
+               WM_manipulator_operator_set(mpr, 0, ot, NULL);
+       }
+
+       {
+               wmManipulator *mpr = navgroup->mpr_array[MPR_CAMERA];
+               PointerRNA *ptr = WM_manipulator_operator_set(mpr, 0, ot_viewnumpad, NULL);
+               RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA);
+       }
+
+       {
+               wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE];
+               mpr->scale_basis = MANIPULATOR_SIZE / 2;
+               char mapping[6] = {
+                       RV3D_VIEW_LEFT,
+                       RV3D_VIEW_RIGHT,
+                       RV3D_VIEW_FRONT,
+                       RV3D_VIEW_BACK,
+                       RV3D_VIEW_BOTTOM,
+                       RV3D_VIEW_TOP,
+               };
+
+               for (int part_index = 0; part_index < 6; part_index+= 1) {
+                       PointerRNA *ptr = WM_manipulator_operator_set(mpr, mapping[part_index], ot_viewnumpad, NULL);
+                       RNA_enum_set(ptr, "type", RV3D_VIEW_FRONT + part_index);
+               }
+       }
+
+       mgroup->customdata = navgroup;
+}
+
+static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+       struct NavigateWidgetGroup *navgroup = mgroup->customdata;
+       ARegion *ar = CTX_wm_region(C);
+       const RegionView3D *rv3d = ar->regiondata;
+
+       for (int i = 0; i < 3; i++) {
+               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))
+       {
+               return;
+       }
+
+       navgroup->region_size[0] = ar->winx;
+       navgroup->region_size[1] = ar->winy;
+
+       const float icon_size = MANIPULATOR_SIZE;
+       const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * U.pixelsize;
+       const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * U.pixelsize;
+       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;
+
+       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;
+
+       mpr = navgroup->mpr_array[MPR_PERSP_ORTHO];
+       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;
+}
+
+void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt)
+{
+       wgt->name = "View3D Navigate";
+       wgt->idname = "VIEW3D_WGT_navigate";
+
+       wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+                     WM_MANIPULATORGROUPTYPE_SCALE);
+
+       wgt->poll = WIDGETGROUP_navigate_poll;
+       wgt->setup = WIDGETGROUP_navigate_setup;
+       wgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
new file mode 100644 (file)
index 0000000..d57656c
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file view3d_manipulator_navigate_type.c
+ *  \ingroup wm
+ *
+ * \name Custom Orientation/Navigation Manipulator for the 3D View
+ *
+ * \brief Simple manipulator to axis and translate.
+ *
+ * matrix_offset is used to store the orientation.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_sort_utils.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_select.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_manipulator_library.h"
+
+#include "view3d_intern.h"
+
+#define DIAL_RESOLUTION 32
+
+#define HANDLE_SIZE 0.33
+
+static void axis_geom_draw(
+        const wmManipulator *mpr, const float color[4], const bool UNUSED(select))
+{
+       glLineWidth(mpr->line_width);
+
+       Gwn_VertFormat *format = immVertexFormat();
+       const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+       immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+       /* flip z for reverse */
+       const float cone_coords[5][3] = {
+               {-1, -1, 4},
+               {-1, +1, 4},
+               {+1, +1, 4},
+               {+1, -1, 4},
+               {0,   0, 2},
+       };
+
+       struct {
+               float depth;
+               char index;
+               char axis;
+               char is_pos;
+       } axis_order[6] = {
+               {-mpr->matrix_offset[0][2], 0, 0, false},
+               {+mpr->matrix_offset[0][2], 1, 0, true},
+               {-mpr->matrix_offset[1][2], 2, 1, false},
+               {+mpr->matrix_offset[1][2], 3, 1, true},
+               {-mpr->matrix_offset[2][2], 4, 2, false},
+               {+mpr->matrix_offset[2][2], 5, 2, true},
+       };
+       qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
+
+       const float scale_axis = 0.33f;
+       static const float axis_highlight[4] = {1, 1, 1, 1};
+       static const float axis_black[4] = {0, 0, 0, 1};
+       static float axis_color[3][4];
+       gpuPushMatrix();
+       gpuMultMatrix(mpr->matrix_offset);
+
+       bool draw_center_done = false;
+
+       for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
+               const int index = axis_order[axis_index].index;
+               const int axis = axis_order[axis_index].axis;
+               const bool is_pos = axis_order[axis_index].is_pos;
+
+               /* Draw slightly before, so axis aligned arrows draw ontop. */
+               if ((draw_center_done == false) && (axis_order[axis_index].depth > -0.01f)) {
+
+                       /* Circle defining active area (revert back to 2D space). */
+                       {
+                               gpuPopMatrix();
+                               immUniformColor4fv(color);
+                               imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
+                               gpuPushMatrix();
+                               gpuMultMatrix(mpr->matrix_offset);
+                       }
+
+                       /* Center cube. */
+                       {
+                               float center[3], size[3];
+
+                               zero_v3(center);
+                               copy_v3_fl(size, HANDLE_SIZE);
+
+                               glEnable(GL_DEPTH_TEST);
+                               glDepthMask(GL_TRUE);
+                               glDepthFunc(GL_LEQUAL);
+                               glBlendFunc(GL_ONE, GL_ZERO);
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                               glEnable(GL_LINE_SMOOTH);
+                               glEnable(GL_BLEND);
+                               glLineWidth(1.0f);
+                               immUniformColor4fv(axis_highlight);
+                               imm_draw_cube_fill_3d(pos_id, center, size);
+                               immUniformColor4fv(axis_black);
+                               madd_v3_v3fl(
+                                       center,
+                                       (float [3]){
+                                       mpr->matrix_offset[0][2],
+                                       mpr->matrix_offset[1][2],
+                                       mpr->matrix_offset[2][2]},
+                                       0.08f);
+                               imm_draw_cube_wire_3d(pos_id, center, size);
+                               glDisable(GL_BLEND);
+                               glDisable(GL_LINE_SMOOTH);
+                               glDisable(GL_DEPTH_TEST);
+                       }
+
+                       draw_center_done = true;
+               }
+               UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
+               axis_color[axis][3] = 1.0f;
+
+               const int index_z = axis;
+               const int index_y = (axis + 1) % 3;
+               const int index_x = (axis + 2) % 3;
+
+#define ROTATED_VERT(v_orig) \
+               { \
+                       float v[3]; \
+                       copy_v3_v3(v, v_orig); \
+                       if (is_pos == 0) { \
+                               v[2] *= -1.0f; \
+                       } \
+                       immVertex3f(pos_id, v[index_x] * scale_axis, v[index_y] * scale_axis, v[index_z] * scale_axis); \
+               } ((void)0)
+
+               bool ok = true;
+
+               /* skip view align axis */
+               if (len_squared_v2(mpr->matrix_offset[axis]) < 1e-6f && (mpr->matrix_offset[axis][2] > 0.0f) == is_pos) {
+                       ok = false;
+               }
+               if (ok) {
+                       immUniformColor4fv(index + 1 == mpr->highlight_part ? axis_highlight : axis_color[axis]);
+                       immBegin(GWN_PRIM_TRI_FAN, 6);
+                       ROTATED_VERT(cone_coords[4]);
+                       for (int j = 0; j <= 4; j++) {
+                               ROTATED_VERT(cone_coords[j % 4]);
+                       }
+                       immEnd();
+               }
+
+#undef ROTATED_VERT
+       }
+
+       gpuPopMatrix();
+       immUnbindProgram();
+}
+
+static void axis3d_draw_intern(
+        const bContext *UNUSED(C), wmManipulator *mpr,
+        const bool select, const bool highlight)
+{
+       const float *color = highlight ? mpr->color_hi : mpr->color;
+       float matrix_final[4][4];
+       float matrix_unit[4][4];
+
+       unit_m4(matrix_unit);
+
+       WM_manipulator_calc_matrix_final_params(
+               mpr,
+               &((struct WM_ManipulatorMatrixParams) {
+                   .matrix_offset = matrix_unit,
+               }), matrix_final);
+
+       gpuPushMatrix();
+       gpuMultMatrix(matrix_final);
+
+       glEnable(GL_BLEND);
+       axis_geom_draw(mpr, color, select);
+       glDisable(GL_BLEND);
+       gpuPopMatrix();
+}
+
+static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr)
+{
+       const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
+       const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0 && (mpr->highlight_part == 0);
+
+       (void)is_modal;
+
+       glEnable(GL_BLEND);
+       axis3d_draw_intern(C, mpr, false, is_highlight);
+       glDisable(GL_BLEND);
+}
+
+static int manipulator_axis_test_select(
+        bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+       float point_local[2] = {UNPACK2(event->mval)};
+       sub_v2_v2(point_local, mpr->matrix_basis[3]);
+       mul_v2_fl(point_local, 1.0f / mpr->scale_basis);
+
+       const float len_sq = len_squared_v2(point_local);
+       if (len_sq > SQUARE(1.0 + HANDLE_SIZE)) {
+               return -1;
+       }
+
+       int part_best = -1;
+       int part_index = 1;
+       float i_best_len_sq = SQUARE(HANDLE_SIZE);
+       for (int i = 0; i < 3; i++) {
+               for (int is_pos = 0; is_pos < 2; is_pos++) {
+                       float co[2] = {
+                               mpr->matrix_offset[i][0] * (is_pos ? 1 : -1),
+                               mpr->matrix_offset[i][1] * (is_pos ? 1 : -1),
+                       };
+
+                       bool ok = true;
+
+                       /* Check if we're viewing on an axis, there is no point to clicking on the current axis so show the reverse. */
+                       if (len_squared_v2(co) < 1e-6f && (mpr->matrix_offset[i][2] > 0.0f) == is_pos) {
+                               ok = false;
+                       }
+
+                       if (ok) {
+                               const float len_axis_sq = len_squared_v2v2(co, point_local);
+                               if (len_axis_sq < i_best_len_sq) {
+                                       part_best = part_index;
+                                       i_best_len_sq = len_axis_sq;
+                               }
+                       }
+                       part_index += 1;
+               }
+       }
+
+       if (part_best != -1) {
+               return part_best;
+       }
+
+       /* The 'mpr->scale_final' is already applied when projecting. */
+       if (len_sq < 1.0f) {
+               return 0;
+       }
+
+       return -1;
+}
+
+static int manipulator_axis_cursor_get(wmManipulator *mpr)
+{
+       if (mpr->highlight_part > 0) {
+               return BC_CROSSCURSOR;
+       }
+       return BC_NSEW_SCROLLCURSOR;
+}
+
+void VIEW3D_WT_navigate_rotate(wmManipulatorType *wt)
+{
+       /* identifiers */
+       wt->idname = "VIEW3D_WT_navigate_rotate";
+
+       /* api callbacks */
+       wt->draw = manipulator_axis_draw;
+       wt->test_select = manipulator_axis_test_select;
+       wt->cursor_get = manipulator_axis_cursor_get;
+
+       wt->struct_size = sizeof(wmManipulator);
+}
index 92ec93d8f2055cf55851fb1071f7ae59890a8e9a..e4747f733e5c296e81f41e24eccd27f6950efdf0 100644 (file)
@@ -817,8 +817,9 @@ typedef enum eGP_UserdefSettings {
 } eGP_UserdefSettings;
 
 enum {
-       USER_MANIPULATOR_DRAW        = (1 << 0),
-       USER_MANIPULATOR_SHADED      = (1 << 1),
+       USER_MANIPULATOR_DRAW            = (1 << 0),
+       USER_MANIPULATOR_DRAW_NAVIGATE   = (1 << 1),
+       USER_MANIPULATOR_SHADED          = (1 << 8),
 };
 
 /* Color Picker Types.
index 273f9fcf2802ffab4acfd138bdcd121c0e4f01d4..bff6cdcf1bdc9079a5e36cedb8ec3962c02abfc5 100644 (file)
@@ -3525,6 +3525,11 @@ static void rna_def_userdef_view(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Manipulator", "Use 3D transform manipulator");
        RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update");
 
+       prop = RNA_def_property(srna, "show_manipulator_navigate", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "manipulator_flag", USER_MANIPULATOR_DRAW_NAVIGATE);
+       RNA_def_property_ui_text(prop, "Navigate Manipulator", "Use 3D navigation manipulator");
+       RNA_def_property_update(prop, 0, "rna_userdef_show_manipulator_update");
+       
        /* TODO, expose once it's working. */
 #if 0
        prop = RNA_def_property(srna, "show_manipulator_shaded", PROP_BOOLEAN, PROP_NONE);