diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-06-16 23:13:44 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-06-16 23:14:29 +0300 |
commit | df017f7867ebb4a7a9c78f77d2b9deb2ffd54278 (patch) | |
tree | b14e7a239b0f5b91b5e2547445342d06266f60c1 | |
parent | 2b8d599b3a93c78661ff9a2c460b7144278409be (diff) |
Manipulator: New grab preset, use for bisect
6 files changed, 339 insertions, 1 deletions
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h index 1c3cbcf3294..692d6cbdcd8 100644 --- a/source/blender/editors/include/ED_manipulator_library.h +++ b/source/blender/editors/include/ED_manipulator_library.h @@ -35,6 +35,7 @@ void ED_manipulatortypes_arrow_2d(void); void ED_manipulatortypes_arrow_3d(void); void ED_manipulatortypes_cage_2d(void); void ED_manipulatortypes_dial_3d(void); +void ED_manipulatortypes_grab_3d(void); void ED_manipulatortypes_facemap_3d(void); void ED_manipulatortypes_primitive_3d(void); @@ -125,6 +126,14 @@ void ED_manipulator_dial3d_set_up_vector( /* -------------------------------------------------------------------- */ +/* Grab Manipulator */ + +struct wmManipulator *ED_manipulator_grab3d_new( + struct wmManipulatorGroup *mgroup, const char *name, const int style); +void ED_manipulator_grab3d_set_up_vector( + struct wmManipulator *mpr, const float direction[3]); + +/* -------------------------------------------------------------------- */ /* Facemap Manipulator */ struct wmManipulator *ED_manipulator_facemap_new( diff --git a/source/blender/editors/manipulator_library/CMakeLists.txt b/source/blender/editors/manipulator_library/CMakeLists.txt index cb31627e09a..6421cfddadf 100644 --- a/source/blender/editors/manipulator_library/CMakeLists.txt +++ b/source/blender/editors/manipulator_library/CMakeLists.txt @@ -41,6 +41,7 @@ set(SRC arrow3d_manipulator.c cage2d_manipulator.c dial3d_manipulator.c + grab3d_manipulator.c geom_arrow_manipulator.c geom_cube_manipulator.c geom_dial_manipulator.c diff --git a/source/blender/editors/manipulator_library/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/arrow3d_manipulator.c index c856374661f..431bccf379f 100644 --- a/source/blender/editors/manipulator_library/arrow3d_manipulator.c +++ b/source/blender/editors/manipulator_library/arrow3d_manipulator.c @@ -209,7 +209,6 @@ static void arrow_draw_intern(ArrowManipulator3D *arrow, const bool select, cons gpuPushMatrix(); gpuMultMatrix(mat); - gpuTranslate3fv(arrow->manipulator.offset); glEnable(GL_BLEND); diff --git a/source/blender/editors/manipulator_library/grab3d_manipulator.c b/source/blender/editors/manipulator_library/grab3d_manipulator.c new file mode 100644 index 00000000000..a089356a79d --- /dev/null +++ b/source/blender/editors/manipulator_library/grab3d_manipulator.c @@ -0,0 +1,285 @@ +/* + * ***** 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 grab3d_manipulator.c + * \ingroup wm + * + * \name Grab Manipulator + * + * 3D Manipulator + * + * \brief Simple manipulator to grab and translate. + */ + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "BKE_context.h" + +#include "BLI_math.h" + +#include "ED_screen.h" +#include "ED_view3d.h" +#include "ED_manipulator_library.h" + +#include "GPU_select.h" + +#include "GPU_matrix.h" + +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* own includes */ +#include "manipulator_geometry.h" +#include "manipulator_library_intern.h" + +static void manipulator_grab_modal(bContext *C, wmManipulator *mpr, const wmEvent *event, const int flag); + +typedef struct GrabManipulator { + wmManipulator manipulator; + int style; + float direction[3]; +} GrabManipulator; + +typedef struct GrabInteraction { + float init_mval[2]; + + /* only for when using properties */ + float init_prop_co[3]; + + /* final output values, used for drawing */ + struct { + float co_ofs[3]; + float co_final[3]; + } output; +} GrabInteraction; + +#define DIAL_WIDTH 1.0f +#define DIAL_RESOLUTION 32 + + +static void grab_calc_matrix(const GrabManipulator *grab, float mat[4][4]) +{ + float rot[3][3]; + const float up[3] = {0.0f, 0.0f, 1.0f}; + + rotation_between_vecs_to_mat3(rot, up, grab->direction); + copy_m4_m3(mat, rot); + copy_v3_v3(mat[3], grab->manipulator.origin); + mul_mat3_m4_fl(mat, grab->manipulator.scale); +} + +/* -------------------------------------------------------------------- */ + +static void grab_geom_draw( + const GrabManipulator *grab3d, const float col[4], const bool select) +{ +#ifdef USE_MANIPULATOR_CUSTOM_DIAL + UNUSED_VARS(grab3d, col, axis_modal_mat); + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_grab3d, select); +#else + const bool filled = (grab3d->style == ED_MANIPULATOR_DIAL_STYLE_RING_FILLED); + + glLineWidth(grab3d->manipulator.line_width); + + VertexFormat *format = immVertexFormat(); + unsigned int pos = VertexFormat_add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + immUniformColor4fv(col); + + if (filled) { + imm_draw_circle_fill(pos, 0, 0, 1.0, DIAL_RESOLUTION); + } + else { + imm_draw_circle_wire(pos, 0, 0, 1.0, DIAL_RESOLUTION); + } + + immUnbindProgram(); + + UNUSED_VARS(select); +#endif +} + +static void grab3d_get_translate( + const GrabManipulator *grab, const wmEvent *event, const ARegion *ar, + float co_delta[3]) +{ + GrabInteraction *inter = grab->manipulator.interaction_data; + const float mval_delta[2] = { + event->mval[0] - inter->init_mval[0], + event->mval[1] - inter->init_mval[1], + }; + + RegionView3D *rv3d = ar->regiondata; + const float *co_ref = inter->init_prop_co; + const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); + + ED_view3d_win_to_delta(ar, mval_delta, co_delta, zfac); +} + +static void grab3d_draw_intern( + const bContext *C, GrabManipulator *grab, + const bool select, const bool highlight) +{ + float mat[4][4]; + float col[4]; + + BLI_assert(CTX_wm_area(C)->spacetype == SPACE_VIEW3D); + + manipulator_color_get(&grab->manipulator, highlight, col); + + grab_calc_matrix(grab, mat); + + gpuPushMatrix(); + if (grab->manipulator.interaction_data) { + GrabInteraction *inter = grab->manipulator.interaction_data; + gpuTranslate3fv(inter->output.co_ofs); + } + gpuMultMatrix(mat); + gpuTranslate3fv(grab->manipulator.offset); + glEnable(GL_BLEND); + grab_geom_draw(grab, col, select); + glDisable(GL_BLEND); + gpuPopMatrix(); + + if (grab->manipulator.interaction_data) { + gpuPushMatrix(); + gpuMultMatrix(mat); + gpuTranslate3fv(grab->manipulator.offset); + glEnable(GL_BLEND); + grab_geom_draw(grab, (const float [4]){0.5f, 0.5f, 0.5f, 0.5f}, select); + glDisable(GL_BLEND); + gpuPopMatrix(); + } +} + +static void manipulator_grab_draw_select(const bContext *C, wmManipulator *mpr, int selectionbase) +{ + GrabManipulator *grab = (GrabManipulator *)mpr; + + GPU_select_load_id(selectionbase); + grab3d_draw_intern(C, grab, true, false); +} + +static void manipulator_grab_draw(const bContext *C, wmManipulator *mpr) +{ + GrabManipulator *grab = (GrabManipulator *)mpr; + const bool active = mpr->state & WM_MANIPULATOR_STATE_ACTIVE; + const bool highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0; + + (void)active; + + glEnable(GL_BLEND); + grab3d_draw_intern(C, grab, false, highlight); + glDisable(GL_BLEND); +} + +static void manipulator_grab_modal(bContext *C, wmManipulator *mpr, const wmEvent *event, const int UNUSED(flag)) +{ + GrabManipulator *grab = (GrabManipulator *)mpr; + + GrabInteraction *inter = grab->manipulator.interaction_data; + + grab3d_get_translate(grab, event, CTX_wm_region(C), inter->output.co_ofs); + + add_v3_v3v3(inter->output.co_final, inter->init_prop_co, inter->output.co_ofs); + + /* set the property for the operator and call its modal function */ + wmManipulatorProperty *mpr_prop = WM_manipulator_property_find(mpr, "offset"); + if (mpr_prop && WM_manipulator_property_is_valid(mpr_prop)) { + WM_manipulator_property_value_set_array(C, mpr, mpr_prop, inter->output.co_final, 3); + } +} + +static void manipulator_grab_invoke( + bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event) +{ + GrabInteraction *inter = MEM_callocN(sizeof(GrabInteraction), __func__); + + inter->init_mval[0] = event->mval[0]; + inter->init_mval[1] = event->mval[1]; + + wmManipulatorProperty *mpr_prop = WM_manipulator_property_find(mpr, "offset"); + if (mpr_prop && WM_manipulator_property_is_valid(mpr_prop)) { + WM_manipulator_property_value_get_array(mpr, mpr_prop, inter->init_prop_co, 3); + } + + mpr->interaction_data = inter; +} + + +/* -------------------------------------------------------------------- */ +/** \name Grab Manipulator API + * + * \{ */ + +wmManipulator *ED_manipulator_grab3d_new(wmManipulatorGroup *mgroup, const char *name, const int style) +{ + GrabManipulator *grab = (GrabManipulator *)WM_manipulator_new( + "MANIPULATOR_WT_grab3d", mgroup, name); + + const float dir_default[3] = {0.0f, 0.0f, 1.0f}; + + grab->style = style; + + /* defaults */ + copy_v3_v3(grab->direction, dir_default); + + return (wmManipulator *)grab; +} + +/** + * Define up-direction of the grab3d manipulator + */ +void ED_manipulator_grab3d_set_up_vector(wmManipulator *mpr, const float direction[3]) +{ + GrabManipulator *grab = (GrabManipulator *)mpr; + + copy_v3_v3(grab->direction, direction); + normalize_v3(grab->direction); +} + +static void MANIPULATOR_WT_grab_3d(wmManipulatorType *wt) +{ + /* identifiers */ + wt->idname = "MANIPULATOR_WT_grab3d"; + + /* api callbacks */ + wt->draw = manipulator_grab_draw; + wt->draw_select = manipulator_grab_draw_select; + wt->invoke = manipulator_grab_invoke; + wt->modal = manipulator_grab_modal; + + wt->struct_size = sizeof(GrabManipulator); +} + +void ED_manipulatortypes_grab_3d(void) +{ + WM_manipulatortype_append(MANIPULATOR_WT_grab_3d); +} + +/** \} */ // Grab Manipulator API diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c index 199ac050b5a..2ad457f1190 100644 --- a/source/blender/editors/mesh/editmesh_bisect.c +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -389,6 +389,8 @@ void MESH_OT_bisect(struct wmOperatorType *ot) typedef struct ManipulatorGroup { /* Arrow to change plane depth. */ struct wmManipulator *translate_z; + /* Translate XYZ */ + struct wmManipulator *translate_c; /* For grabbing the manipulator and moving freely. */ struct wmManipulator *rotate_c; @@ -427,10 +429,13 @@ static void manipulator_mesh_bisect_update_from_op(ManipulatorGroup *man) RNA_property_float_get_array(op->ptr, man->data.prop_plane_no, plane_no); WM_manipulator_set_origin(man->translate_z, plane_co); + WM_manipulator_set_origin(man->translate_c, plane_co); WM_manipulator_set_origin(man->rotate_c, plane_co); ED_manipulator_arrow3d_set_direction(man->translate_z, plane_no); + WM_manipulator_set_scale(man->translate_c, 0.2); + RegionView3D *rv3d = ED_view3d_context_rv3d(man->data.context); if (rv3d) { normalize_v3_v3(man->data.rotate_axis, rv3d->viewinv[2]); @@ -440,6 +445,7 @@ static void manipulator_mesh_bisect_update_from_op(ManipulatorGroup *man) project_plane_normalized_v3_v3v3(man->data.rotate_up, man->data.rotate_up, man->data.rotate_axis); normalize_v3(man->data.rotate_up); + ED_manipulator_grab3d_set_up_vector(man->translate_c, plane_no); ED_manipulator_dial3d_set_up_vector(man->rotate_c, man->data.rotate_axis); } } @@ -485,6 +491,32 @@ static void manipulator_bisect_prop_depth_set( manipulator_bisect_exec(man); } +/* translate callbacks */ +static void manipulator_bisect_prop_translate_get( + const wmManipulator *mpr, wmManipulatorProperty *UNUSED(mpr_prop), void *UNUSED(user_data), + float *value, uint value_len) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(value_len == 3); + RNA_property_float_get_array(op->ptr, man->data.prop_plane_co, value); +} + +static void manipulator_bisect_prop_translate_set( + const wmManipulator *mpr, wmManipulatorProperty *UNUSED(mpr_prop), void *UNUSED(user_data), + const float *value, uint value_len) +{ + ManipulatorGroup *man = mpr->parent_mgroup->customdata; + wmOperator *op = man->data.op; + + BLI_assert(value_len == 3); + RNA_property_float_set_array(op->ptr, man->data.prop_plane_co, value); + + manipulator_bisect_exec(man); +} + + /* angle callbacks */ static void manipulator_bisect_prop_angle_get( const wmManipulator *mpr, wmManipulatorProperty *UNUSED(mpr_prop), void *UNUSED(user_data), @@ -563,8 +595,10 @@ static void manipulator_mesh_bisect_setup(const bContext *C, wmManipulatorGroup mgroup->customdata = man; man->translate_z = ED_manipulator_arrow3d_new(mgroup, "translate_z", ED_MANIPULATOR_ARROW_STYLE_NORMAL); + man->translate_c = ED_manipulator_grab3d_new(mgroup, "translate_c", 0); man->rotate_c = ED_manipulator_dial3d_new(mgroup, "rotate_c", ED_MANIPULATOR_DIAL_STYLE_RING); + WM_manipulator_set_flag(man->translate_c, WM_MANIPULATOR_DRAW_VALUE, true); WM_manipulator_set_flag(man->rotate_c, WM_MANIPULATOR_DRAW_VALUE, true); { @@ -588,6 +622,15 @@ static void manipulator_mesh_bisect_setup(const bContext *C, wmManipulatorGroup }); WM_manipulator_property_def_func( + man->translate_c, "offset", + &(const struct wmManipulatorPropertyFnParams) { + .value_get_fn = manipulator_bisect_prop_translate_get, + .value_set_fn = manipulator_bisect_prop_translate_set, + .range_get_fn = NULL, + .user_data = NULL, + }); + + WM_manipulator_property_def_func( man->rotate_c, "offset", &(const struct wmManipulatorPropertyFnParams) { .value_get_fn = manipulator_bisect_prop_angle_get, diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 16ccf1da916..e64e9841139 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -128,6 +128,7 @@ void ED_spacetypes_init(void) /* manipulator types */ ED_manipulatortypes_dial_3d(); + ED_manipulatortypes_grab_3d(); ED_manipulatortypes_arrow_2d(); ED_manipulatortypes_arrow_3d(); ED_manipulatortypes_primitive_3d(); |