diff options
19 files changed, 797 insertions, 1474 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index cf94fccd4e3..e921a65bfe8 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -43,6 +43,7 @@ set(INC ../editors/space_view3d ../render/extern/include ../render/intern/include + ../windowmanager ../../../intern/glew-mx ../../../intern/guardedalloc diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index eba72fac958..a0f0fb1a9ee 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -41,6 +41,9 @@ #include "UI_resources.h" +#include "WM_api.h" +#include "WM_types.h" + #include "BKE_global.h" #include "BKE_object.h" #include "BKE_paint.h" @@ -699,5 +702,13 @@ void DRW_draw_manipulator(void) const bContext *C = DRW_get_context(); View3D *v3d = CTX_wm_view3d(C); v3d->zbuf = false; - BIF_draw_manipulator(C); + ARegion *ar = CTX_wm_region(C); + + + /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */ + + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D); } diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 898eecd3e42..376ae8ca567 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -112,6 +112,8 @@ struct TransInfo; struct BaseLegacy; struct Scene; struct Object; +struct wmManipulatorGroup; +struct wmManipulatorGroupType; struct wmOperator; /* UNUSED */ @@ -152,10 +154,17 @@ int BIF_countTransformOrientation(const struct bContext *C); void Transform_Properties(struct wmOperatorType *ot, int flags); -/* view3d manipulators */ +/* transform manipulators */ + +void TRANSFORM_WGT_manipulator(struct wmManipulatorGroupType *wgt); + +void TRANSFORM_WGT_object(struct wmManipulatorGroupType *wgt); + +bool WIDGETGROUP_manipulator2d_poll(const struct bContext *C, struct wmManipulatorGroupType *wgrouptype); +void WIDGETGROUP_manipulator2d_init(const struct bContext *C, struct wmManipulatorGroup *wgroup); +void WIDGETGROUP_manipulator2d_refresh(const struct bContext *C, struct wmManipulatorGroup *wgroup); +void WIDGETGROUP_manipulator2d_draw_prepare(const struct bContext *C, struct wmManipulatorGroup *wgroup); -int BIF_do_manipulator(struct bContext *C, const struct wmEvent *event, struct wmOperator *op); -void BIF_draw_manipulator(const struct bContext *C); /* Snapping */ diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index b1d708ebc07..758ef43590e 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -137,23 +137,6 @@ static void keymap_particle(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "PARTICLE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "unselected", true); - /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", true); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", true); - - /* Using KM_ANY here to allow holding modifiers before starting to transform. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PARTICLE_OT_brush_edit", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 62bcb771226..af25c9de781 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -54,6 +54,7 @@ #include "ED_space_api.h" #include "ED_screen.h" +#include "ED_transform.h" #include "GPU_compositing.h" #include "GPU_framebuffer.h" @@ -341,7 +342,7 @@ static SpaceLink *view3d_new(const bContext *C) v3d->near = 0.01f; v3d->far = 1000.0f; - v3d->twflag |= U.tw_flag & V3D_USE_MANIPULATOR; + v3d->twflag |= U.manipulator_flag & V3D_USE_MANIPULATOR; v3d->twtype = V3D_MANIP_TRANSLATE; v3d->around = V3D_AROUND_CENTER_MEAN; @@ -488,6 +489,13 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *ar) ListBase *lb; wmKeyMap *keymap; + if (!ar->manipulator_map) { + ar->manipulator_map = WM_manipulatormap_new_from_type(&(const struct wmManipulatorMapType_Params) { + "View3D", SPACE_VIEW3D, RGN_TYPE_WINDOW}); + } + + WM_manipulatormap_add_handlers(ar, ar->manipulator_map); + /* object ops. */ /* important to be before Pose keymap since they can both be enabled at once */ @@ -719,6 +727,16 @@ static void view3d_dropboxes(void) WM_dropbox_add(lb, "OBJECT_OT_group_instance_add", view3d_group_drop_poll, view3d_group_drop_copy); } +static void view3d_widgets(void) +{ + const struct wmManipulatorMapType_Params wmap_params = { + .idname = "View3D", + .spaceid = SPACE_VIEW3D, .regionid = RGN_TYPE_WINDOW, + }; + wmManipulatorMapType *wmaptype = WM_manipulatormaptype_ensure(&wmap_params); + + WM_manipulatorgrouptype_append(wmaptype, TRANSFORM_WGT_manipulator); +} /* type callback, not region itself */ @@ -815,7 +833,9 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w { Scene *scene = sc->scene; View3D *v3d = sa->spacedata.first; - + RegionView3D *rv3d = ar->regiondata; + wmManipulatorMap *mmap = ar->manipulator_map; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -841,6 +861,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w if (wmn->reference) view3d_recalc_used_layers(ar, wmn, wmn->reference); ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; case ND_FRAME: case ND_TRANSFORM: @@ -852,6 +873,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_MARKERS: case ND_MODE: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; case ND_WORLD: /* handled by space_view3d_listener() for v3d access */ @@ -859,7 +881,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (scene == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -884,6 +905,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_POINTCACHE: case ND_LOD: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } switch (wmn->action) { @@ -896,6 +918,8 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w switch (wmn->data) { case ND_SELECT: { + WM_manipulatormap_tag_refresh(mmap); + if (scene->obedit) { Object *ob = scene->obedit; if (ob->type == OB_MESH) { @@ -920,7 +944,6 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case ND_DRAW_RENDER_VIEWPORT: { if (v3d->camera && (v3d->camera->data == wmn->reference)) { - RegionView3D *rv3d = ar->regiondata; if (rv3d->persp == RV3D_CAMOB) { ED_region_tag_redraw(ar); } @@ -979,6 +1002,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w break; case ND_LIGHTING_DRAW: ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); break; } break; @@ -998,10 +1022,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w case NC_SPACE: if (wmn->data == ND_SPACE_VIEW3D) { if (wmn->subtype == NS_VIEW3D_GPU) { - RegionView3D *rv3d = ar->regiondata; rv3d->rflag |= RV3D_GPULIGHT_UPDATE; } ED_region_tag_redraw(ar); + WM_manipulatormap_tag_refresh(mmap); } break; case NC_ID: @@ -1023,6 +1047,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w bScreen *sc_ref = wmn->reference; view3d_recalc_used_layers(ar, wmn, sc_ref->scene); } + WM_manipulatormap_tag_refresh(mmap); ED_region_tag_redraw(ar); break; } @@ -1393,6 +1418,7 @@ void ED_spacetype_view3d(void) st->operatortypes = view3d_operatortypes; st->keymap = view3d_keymap; st->dropboxes = view3d_dropboxes; + st->manipulators = view3d_widgets; st->context = view3d_context; st->id_remap = view3d_id_remap; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e98cff85d0d..a3bdc09143f 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -84,6 +84,7 @@ #include "RE_engine.h" #include "WM_api.h" +#include "WM_types.h" #include "view3d_intern.h" /* own include */ @@ -2211,12 +2212,18 @@ static void view3d_draw_reference_images(const bContext *UNUSED(C)) /** * 3D manipulators -*/ -static void view3d_draw_manipulator(const bContext *C) + */ +static void view3d_draw_manipulators(const bContext *C, const ARegion *ar) { View3D *v3d = CTX_wm_view3d(C); v3d->zbuf = false; - BIF_draw_manipulator(C); + + /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */ + + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D); } /** @@ -2309,7 +2316,7 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data view3d_draw_other_elements(C, ar); view3d_draw_tool_ui(C); view3d_draw_reference_images(C); - view3d_draw_manipulator(C); + view3d_draw_manipulators(C, ar); gpuMatrixEnd(); diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c index 7070cadb414..14b8f78e4c7 100644 --- a/source/blender/editors/space_view3d/view3d_draw_legacy.c +++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c @@ -79,6 +79,7 @@ #include "BIF_glutil.h" #include "WM_api.h" +#include "WM_types.h" #include "BLF_api.h" #include "BLT_translation.h" @@ -1709,10 +1710,6 @@ static void view3d_draw_objects( view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame); } - if (!draw_offscreen) { - BIF_draw_manipulator(C); - } - /* cleanup */ if (v3d->zbuf) { v3d->zbuf = false; @@ -2429,6 +2426,11 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Sce /* main drawing call */ view3d_draw_objects(C, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL); + /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */ + /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should + * later become _IN_SCENE (and draw _3D separate) */ + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D); + /* post process */ if (do_compositing) { GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL); @@ -2553,6 +2555,13 @@ void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar) if (v3d->drawtype == OB_RENDER) view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect); + VP_legacy_view3d_main_region_setup_view(scene, v3d, ar, NULL, NULL); + glClear(GL_DEPTH_BUFFER_BIT); + + WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D); + + ED_region_pixelspace(ar); + view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border); glMatrixMode(GL_PROJECTION); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 46592194035..804336b2976 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4746,45 +4746,6 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* ***************** manipulator op ******************* */ - -static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - View3D *v3d = CTX_wm_view3d(C); - - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH; - - /* note; otherwise opengl won't work */ - view3d_operator_needs_opengl(C); - - if (BIF_do_manipulator(C, event, op) == 0) - return OPERATOR_PASS_THROUGH; - - return OPERATOR_FINISHED; -} - -void VIEW3D_OT_manipulator(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "3D Manipulator"; - ot->description = "Manipulate selected item by axis"; - ot->idname = "VIEW3D_OT_manipulator"; - - /* api callbacks */ - ot->invoke = manipulator_invoke; - - ot->poll = ED_operator_view3d_active; - - /* properties to pass to transform */ - Transform_Properties(ot, P_CONSTRAINT); - - prop = RNA_def_boolean(ot->srna, "use_planar_constraint", false, "Planar Constraint", "Limit the transformation to the " - "two axes that have not been clicked (translate/scale only)"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); -} - static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index db16f95d69b..721215a1281 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -51,6 +51,7 @@ struct SceneLayer; struct wmOperatorType; struct wmWindowManager; struct wmKeyConfig; +struct wmManipulatorGroupType; /* drawing flags: */ enum { @@ -101,7 +102,6 @@ void VIEW3D_OT_view_orbit(struct wmOperatorType *ot); void VIEW3D_OT_view_roll(struct wmOperatorType *ot); void VIEW3D_OT_clip_border(struct wmOperatorType *ot); void VIEW3D_OT_cursor3d(struct wmOperatorType *ot); -void VIEW3D_OT_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_enable_manipulator(struct wmOperatorType *ot); void VIEW3D_OT_render_border(struct wmOperatorType *ot); void VIEW3D_OT_clear_render_border(struct wmOperatorType *ot); @@ -313,6 +313,12 @@ ARegion *view3d_has_tools_region(ScrArea *sa); extern const char *view3d_context_dir[]; /* doc access */ +/* view3d_widgets.c */ +void VIEW3D_WGT_lamp (struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_camera (struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_force_field (struct wmManipulatorGroupType *wgt); +void VIEW3D_WGT_armature_facemaps(struct wmManipulatorGroupType *wgt); + /* draw_volume.c */ void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob, const float min[3], const float max[3], diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index d71639c35d2..e14a0c63ee4 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -193,7 +193,6 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_render_border); WM_operatortype_append(VIEW3D_OT_clear_render_border); WM_operatortype_append(VIEW3D_OT_zoom_border); - WM_operatortype_append(VIEW3D_OT_manipulator); WM_operatortype_append(VIEW3D_OT_enable_manipulator); WM_operatortype_append(VIEW3D_OT_cursor3d); WM_operatortype_append(VIEW3D_OT_select_lasso); @@ -240,23 +239,6 @@ void view3d_keymap(wmKeyConfig *keyconf) /* only for region 3D window */ keymap = WM_keymap_find(keyconf, "3D View", SPACE_VIEW3D, 0); - /* Shift+LMB behavior first, so it has priority over KM_ANY item below. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", true); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", true); - - /* Using KM_ANY here to allow holding modifiers before starting to transform. */ - kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_manipulator", LEFTMOUSE, KM_PRESS, KM_ANY, 0); - RNA_boolean_set(kmi->ptr, "release_confirm", true); - RNA_boolean_set(kmi->ptr, "use_planar_constraint", false); - RNA_boolean_set(kmi->ptr, "use_accurate", false); - WM_keymap_verify_item(keymap, "VIEW3D_OT_cursor3d", ACTIONMOUSE, KM_PRESS, 0, 0); WM_keymap_verify_item(keymap, "VIEW3D_OT_rotate", MIDDLEMOUSE, KM_PRESS, 0, 0); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index ead3817bae4..1be4d0c3172 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1702,7 +1702,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) { TransInfo *t = (TransInfo *)customdata; - if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) { + if (t->helpline != HLP_NONE) { float vecrot[3], cent[2]; float mval[3] = { x, y, 0.0f }; @@ -3423,7 +3423,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) constraintTransLim(t, td); } -static void applyResize(TransInfo *t, const int mval[2]) +static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { TransData *td; float mat[3][3]; @@ -3434,15 +3434,7 @@ static void applyResize(TransInfo *t, const int mval[2]) copy_v3_v3(t->values, t->auto_values); } else { - float ratio; - - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } + float ratio = t->values[0]; copy_v3_fl(t->values, ratio); @@ -5266,23 +5258,14 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) td->loc[1] = oldy; } -static void applyBoneSize(TransInfo *t, const int mval[2]) +static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; float size[3], mat[3][3]; - float ratio; + float ratio = t->values[0]; int i; char str[UI_MAX_DRAW_STR]; - - // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } - + copy_v3_fl(size, ratio); snapGridIncrement(t, size); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 774f5ad6790..8765169fcb2 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -498,8 +498,7 @@ typedef struct TransInfo { #define T_CAMERA (1 << 4) // trans on points, having no rotation/scale #define T_POINTS (1 << 6) - // for manipulator exceptions, like scaling using center point, drawing help lines -#define T_USES_MANIPULATOR (1 << 7) +/* empty slot - (1 << 7) */ /* restrictions flags */ #define T_ALL_RESTRICTIONS ((1 << 8)|(1 << 9)|(1 << 10)) @@ -636,7 +635,10 @@ void flushTransMasking(TransInfo *t); void flushTransPaintCurve(TransInfo *t); void restoreBones(TransInfo *t); -/*********************** exported from transform_manipulator.c ********** */ +/*********************** transform_manipulator.c ********** */ + +#define MANIPULATOR_AXIS_LINE_WIDTH 2.0 + bool gimbal_axis(struct Object *ob, float gmat[3][3]); /* return 0 when no gimbal for selection */ /*********************** TransData Creation and General Handling *********** */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index d9c0942dece..cd724370e17 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -706,8 +706,6 @@ void drawConstraint(TransInfo *t) return; if (!(tc->mode & CON_APPLY)) return; - if (t->flag & T_USES_MANIPULATOR) - return; if (t->flag & T_NO_CONSTRAINT) return; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 1cf53f95ef1..3e427d2973b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1228,7 +1228,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->animtimer = (animscreen) ? animscreen->animtimer : NULL; /* turn manipulator off during transform */ - // FIXME: but don't do this when USING the manipulator... if (t->flag & T_MODAL) { t->twtype = v3d->twtype; v3d->twtype = 0; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 624cd7db679..91aaa5da0e9 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -39,6 +39,7 @@ #include "DNA_curve_types.h" #include "DNA_gpencil_types.h" #include "DNA_lattice_types.h" +#include "DNA_manipulator_types.h" #include "DNA_meta_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" @@ -67,15 +68,19 @@ #include "ED_armature.h" #include "ED_curve.h" +#include "ED_object.h" #include "ED_particle.h" #include "ED_view3d.h" #include "ED_gpencil.h" +#include "ED_screen.h" #include "UI_resources.h" /* local module include */ #include "transform.h" +#include "MEM_guardedalloc.h" + #include "GPU_select.h" #include "GPU_immediate.h" #include "GPU_matrix.h" @@ -90,25 +95,350 @@ #define MAN_ROT_X (1 << 3) #define MAN_ROT_Y (1 << 4) #define MAN_ROT_Z (1 << 5) -#define MAN_ROT_V (1 << 6) -#define MAN_ROT_T (1 << 7) -#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z | MAN_ROT_V | MAN_ROT_T) +#define MAN_ROT_C (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z) #define MAN_SCALE_X (1 << 8) #define MAN_SCALE_Y (1 << 9) #define MAN_SCALE_Z (1 << 10) #define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z) -/* color codes */ - -#define MAN_RGB 0 -#define MAN_GHOST 1 -#define MAN_MOVECOL 2 - /* threshold for testing view aligned manipulator axis */ #define TW_AXIS_DOT_MIN 0.02f #define TW_AXIS_DOT_MAX 0.1f +/* axes as index */ +enum { + MAN_AXIS_TRANS_X = 0, + MAN_AXIS_TRANS_Y, + MAN_AXIS_TRANS_Z, + MAN_AXIS_TRANS_C, + + MAN_AXIS_ROT_X, + MAN_AXIS_ROT_Y, + MAN_AXIS_ROT_Z, + MAN_AXIS_ROT_C, + MAN_AXIS_ROT_T, /* trackball rotation */ + + MAN_AXIS_SCALE_X, + MAN_AXIS_SCALE_Y, + MAN_AXIS_SCALE_Z, + MAN_AXIS_SCALE_C, + + /* special */ + MAN_AXIS_TRANS_XY, + MAN_AXIS_TRANS_YZ, + MAN_AXIS_TRANS_ZX, + + MAN_AXIS_SCALE_XY, + MAN_AXIS_SCALE_YZ, + MAN_AXIS_SCALE_ZX, + + MAN_AXIS_LAST, +}; + +/* axis types */ +enum { + MAN_AXES_ALL = 0, + MAN_AXES_TRANSLATE, + MAN_AXES_ROTATE, + MAN_AXES_SCALE, +}; + +typedef struct ManipulatorGroup { + bool all_hidden; + + struct wmManipulator *translate_x, + *translate_y, + *translate_z, + *translate_xy, + *translate_yz, + *translate_zx, + *translate_c, + + *rotate_x, + *rotate_y, + *rotate_z, + *rotate_c, + *rotate_t, /* trackball rotation */ + + *scale_x, + *scale_y, + *scale_z, + *scale_xy, + *scale_yz, + *scale_zx, + *scale_c; +} ManipulatorGroup; + + +/* **************** Utilities **************** */ + +/* loop over axes */ +#define MAN_ITER_AXES_BEGIN(axis, axis_idx) \ + { \ + wmManipulator *axis; \ + int axis_idx; \ + for (axis_idx = 0; axis_idx < MAN_AXIS_LAST; axis_idx++) { \ + axis = manipulator_get_axis_from_index(man, axis_idx); + +#define MAN_ITER_AXES_END \ + } \ + } ((void)0) + +static wmManipulator *manipulator_get_axis_from_index(const ManipulatorGroup *man, const short axis_idx) +{ + BLI_assert(IN_RANGE_INCL(axis_idx, (float)MAN_AXIS_TRANS_X, (float)MAN_AXIS_LAST)); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + return man->translate_x; + case MAN_AXIS_TRANS_Y: + return man->translate_y; + case MAN_AXIS_TRANS_Z: + return man->translate_z; + case MAN_AXIS_TRANS_XY: + return man->translate_xy; + case MAN_AXIS_TRANS_YZ: + return man->translate_yz; + case MAN_AXIS_TRANS_ZX: + return man->translate_zx; + case MAN_AXIS_TRANS_C: + return man->translate_c; + case MAN_AXIS_ROT_X: + return man->rotate_x; + case MAN_AXIS_ROT_Y: + return man->rotate_y; + case MAN_AXIS_ROT_Z: + return man->rotate_z; + case MAN_AXIS_ROT_C: + return man->rotate_c; + case MAN_AXIS_ROT_T: + return man->rotate_t; + case MAN_AXIS_SCALE_X: + return man->scale_x; + case MAN_AXIS_SCALE_Y: + return man->scale_y; + case MAN_AXIS_SCALE_Z: + return man->scale_z; + case MAN_AXIS_SCALE_XY: + return man->scale_xy; + case MAN_AXIS_SCALE_YZ: + return man->scale_yz; + case MAN_AXIS_SCALE_ZX: + return man->scale_zx; + case MAN_AXIS_SCALE_C: + return man->scale_c; + } + + return NULL; +} + +static short manipulator_get_axis_type(const ManipulatorGroup *man, const wmManipulator *axis) +{ + if (ELEM(axis, man->translate_x, man->translate_y, man->translate_z, man->translate_c, + man->translate_xy, man->translate_yz, man->translate_zx)) + { + return MAN_AXES_TRANSLATE; + } + else if (ELEM(axis, man->rotate_x, man->rotate_y, man->rotate_z, man->rotate_c, man->rotate_t)) { + return MAN_AXES_ROTATE; + } + else { + return MAN_AXES_SCALE; + } +} + +/* get index within axis type, so that x == 0, y == 1 and z == 2, no matter which axis type */ +static unsigned int manipulator_index_normalize(const int axis_idx) +{ + if (axis_idx > MAN_AXIS_TRANS_ZX) { + return axis_idx - 16; + } + else if (axis_idx > MAN_AXIS_SCALE_C) { + return axis_idx - 13; + } + else if (axis_idx > MAN_AXIS_ROT_T) { + return axis_idx - 9; + } + else if (axis_idx > MAN_AXIS_TRANS_C) { + return axis_idx - 4; + } + + return axis_idx; +} + +static bool manipulator_is_axis_visible( + const View3D *v3d, const RegionView3D *rv3d, + const float idot[3], const int axis_type, const int axis_idx) +{ + const unsigned int aidx_norm = manipulator_index_normalize(axis_idx); + /* don't draw axis perpendicular to the view */ + if (aidx_norm < 3 && idot[aidx_norm] < TW_AXIS_DOT_MIN) { + return false; + } + + if ((axis_type == MAN_AXES_TRANSLATE && !(v3d->twtype & V3D_MANIP_TRANSLATE)) || + (axis_type == MAN_AXES_ROTATE && !(v3d->twtype & V3D_MANIP_ROTATE)) || + (axis_type == MAN_AXES_SCALE && !(v3d->twtype & V3D_MANIP_SCALE))) + { + return false; + } + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + return (rv3d->twdrawflag & MAN_TRANS_X); + case MAN_AXIS_TRANS_Y: + return (rv3d->twdrawflag & MAN_TRANS_Y); + case MAN_AXIS_TRANS_Z: + return (rv3d->twdrawflag & MAN_TRANS_Z); + case MAN_AXIS_TRANS_C: + return (rv3d->twdrawflag & MAN_TRANS_C); + case MAN_AXIS_ROT_X: + return (rv3d->twdrawflag & MAN_ROT_X); + case MAN_AXIS_ROT_Y: + return (rv3d->twdrawflag & MAN_ROT_Y); + case MAN_AXIS_ROT_Z: + return (rv3d->twdrawflag & MAN_ROT_Z); + case MAN_AXIS_ROT_C: + case MAN_AXIS_ROT_T: + return (rv3d->twdrawflag & MAN_ROT_C); + case MAN_AXIS_SCALE_X: + return (rv3d->twdrawflag & MAN_SCALE_X); + case MAN_AXIS_SCALE_Y: + return (rv3d->twdrawflag & MAN_SCALE_Y); + case MAN_AXIS_SCALE_Z: + return (rv3d->twdrawflag & MAN_SCALE_Z); + case MAN_AXIS_SCALE_C: + return (rv3d->twdrawflag & MAN_SCALE_C && (v3d->twtype & V3D_MANIP_TRANSLATE) == 0); + case MAN_AXIS_TRANS_XY: + return (rv3d->twdrawflag & MAN_TRANS_X && + rv3d->twdrawflag & MAN_TRANS_Y && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_TRANS_YZ: + return (rv3d->twdrawflag & MAN_TRANS_Y && + rv3d->twdrawflag & MAN_TRANS_Z && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_TRANS_ZX: + return (rv3d->twdrawflag & MAN_TRANS_Z && + rv3d->twdrawflag & MAN_TRANS_X && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_XY: + return (rv3d->twdrawflag & MAN_SCALE_X && + rv3d->twdrawflag & MAN_SCALE_Y && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_YZ: + return (rv3d->twdrawflag & MAN_SCALE_Y && + rv3d->twdrawflag & MAN_SCALE_Z && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + case MAN_AXIS_SCALE_ZX: + return (rv3d->twdrawflag & MAN_SCALE_Z && + rv3d->twdrawflag & MAN_SCALE_X && + (v3d->twtype & V3D_MANIP_TRANSLATE) == 0 && + (v3d->twtype & V3D_MANIP_ROTATE) == 0); + } + return false; +} + +static void manipulator_get_axis_color( + const int axis_idx, const float idot[3], + float r_col[4], float r_col_hi[4]) +{ + /* alpha values for normal/highlighted states */ + const float alpha = 0.6f; + const float alpha_hi = 1.0f; + float alpha_fac; + + const int axis_idx_norm = manipulator_index_normalize(axis_idx); + /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */ + if (axis_idx_norm < 3) { + const float idot_axis = idot[axis_idx_norm]; + alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ? + 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ? + 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); + } + else { + /* trackball rotation axis is a special case, we only draw a slight overlay */ + alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f; + } + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_ROT_X: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_SCALE_XY: + UI_GetThemeColor4fv(TH_AXIS_X, r_col); + break; + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_SCALE_YZ: + UI_GetThemeColor4fv(TH_AXIS_Y, r_col); + break; + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_ROT_Z: + case MAN_AXIS_SCALE_Z: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_ZX: + UI_GetThemeColor4fv(TH_AXIS_Z, r_col); + break; + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + copy_v4_fl(r_col, 1.0f); + break; + } + + copy_v4_v4(r_col_hi, r_col); + + r_col[3] = alpha * alpha_fac; + r_col_hi[3] = alpha_hi * alpha_fac; +} + +static void manipulator_get_axis_constraint(const int axis_idx, int r_axis[3]) +{ + zero_v3_int(r_axis); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_ROT_X: + case MAN_AXIS_SCALE_X: + r_axis[0] = 1; + break; + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_SCALE_Y: + r_axis[1] = 1; + break; + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_ROT_Z: + case MAN_AXIS_SCALE_Z: + r_axis[2] = 1; + break; + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_SCALE_XY: + r_axis[0] = r_axis[1] = 1; + break; + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_SCALE_YZ: + r_axis[1] = r_axis[2] = 1; + break; + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_ZX: + r_axis[2] = r_axis[0] = 1; + break; + default: + break; + } +} + + +/* **************** Preparation Stuff **************** */ + /* transform widget center calc helper for below */ static void calc_tw_center(Scene *scene, const float co[3]) { @@ -591,7 +921,6 @@ static int calc_manipulator_stats(const bContext *C) if (ob == NULL) ob = base->object; calc_tw_center(scene, base->object->obmat[3]); - protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag); totsel++; } } @@ -671,1387 +1000,389 @@ static int calc_manipulator_stats(const bContext *C) return totsel; } -/* don't draw axis perpendicular to the view */ -static void test_manipulator_axis(const bContext *C) +static void manipulator_get_idot(RegionView3D *rv3d, float r_idot[3]) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); float view_vec[3], axis_vec[3]; - float idot; - int i; - - const int twdrawflag_axis[3] = { - (MAN_TRANS_X | MAN_SCALE_X), - (MAN_TRANS_Y | MAN_SCALE_Y), - (MAN_TRANS_Z | MAN_SCALE_Z)}; - ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], view_vec); - - for (i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) { normalize_v3_v3(axis_vec, rv3d->twmat[i]); - rv3d->tw_idot[i] = idot = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec)); - if (idot < TW_AXIS_DOT_MIN) { - rv3d->twdrawflag &= ~twdrawflag_axis[i]; - } - } -} - - -/* ******************** DRAWING STUFFIES *********** */ - -static float screen_aligned(RegionView3D *rv3d, float mat[4][4]) -{ - gpuTranslate3fv(mat[3]); - - /* sets view screen aligned */ - gpuRotate3f(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]); - - return len_v3(mat[0]); /* draw scale */ -} - - -/* radring = radius of doughnut rings - * radhole = radius hole - * start = starting segment (based on nrings) - * end = end segment - * nsides = amount of points in ring - * nrigns = amount of rings - */ -static void partial_doughnut(unsigned int pos, float radring, float radhole, int start, int end, int nsides, int nrings) -{ - float theta, phi, theta1; - float cos_theta, sin_theta; - float cos_theta1, sin_theta1; - float ring_delta, side_delta; - int i, j, do_caps = true; - - if (start == 0 && end == nrings) do_caps = false; - - ring_delta = 2.0f * (float)M_PI / (float)nrings; - side_delta = 2.0f * (float)M_PI / (float)nsides; - - theta = (float)M_PI + 0.5f * ring_delta; - cos_theta = cosf(theta); - sin_theta = sinf(theta); - - for (i = nrings - 1; i >= 0; i--) { - theta1 = theta + ring_delta; - cos_theta1 = cosf(theta1); - sin_theta1 = sinf(theta1); - - if (do_caps && i == start) { // cap - immBegin(GL_TRIANGLE_FAN, nsides+1); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi += side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - immVertex3f(pos, cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); - } - immEnd(); - } - if (i >= start && i <= end) { - immBegin(GL_TRIANGLE_STRIP, (nsides+1) * 2); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi += side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - immVertex3f(pos, cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); - immVertex3f(pos, cos_theta * dist, -sin_theta * dist, radring * sin_phi); - } - immEnd(); - } - - if (do_caps && i == end) { // cap - immBegin(GL_TRIANGLE_FAN, nsides+1); - phi = 0.0; - for (j = nsides; j >= 0; j--) { - float cos_phi, sin_phi, dist; - - phi -= side_delta; - cos_phi = cosf(phi); - sin_phi = sinf(phi); - dist = radhole + radring * cos_phi; - - immVertex3f(pos, cos_theta * dist, -sin_theta * dist, radring * sin_phi); - } - immEnd(); - } - - - theta = theta1; - cos_theta = cos_theta1; - sin_theta = sin_theta1; + r_idot[i] = 1.0f - fabsf(dot_v3v3(view_vec, axis_vec)); } } -static char axisBlendAngle(float idot) +static void manipulator_prepare_mat(const bContext *C, View3D *v3d, RegionView3D *rv3d) { - if (idot > TW_AXIS_DOT_MAX) { - return 255; - } - else if (idot < TW_AXIS_DOT_MIN) { - return 0; - } - else { - return (char)(255.0f * (idot - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN)); - } -} + Scene *scene = CTX_data_scene(C); + SceneLayer *sl = CTX_data_scene_layer(C); -/* three colors can be set: - * gray for ghosting - * moving: in transform theme color - * else the red/green/blue - */ -static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned char alpha) -{ - unsigned char col[4] = {0}; - col[3] = alpha; + switch (v3d->around) { + case V3D_AROUND_CENTER_BOUNDS: + case V3D_AROUND_ACTIVE: + { + bGPdata *gpd = CTX_data_gpencil_data(C); + Object *ob = OBACT_NEW; - if (colcode == MAN_GHOST) { - col[3] = 70; - } - else if (colcode == MAN_MOVECOL) { - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - } - else { - switch (axis) { - case 'C': - UI_GetThemeColor3ubv(TH_TRANSFORM, col); - if (v3d->twmode == V3D_MANIP_LOCAL) { - col[0] = col[0] > 200 ? 255 : col[0] + 55; - col[1] = col[1] > 200 ? 255 : col[1] + 55; - col[2] = col[2] > 200 ? 255 : col[2] + 55; + if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) && + ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) && + (!(ob->mode & OB_MODE_POSE))) + { + copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); } - else if (v3d->twmode == V3D_MANIP_NORMAL) { - col[0] = col[0] < 55 ? 0 : col[0] - 55; - col[1] = col[1] < 55 ? 0 : col[1] - 55; - col[2] = col[2] < 55 ? 0 : col[2] - 55; + else { + mid_v3_v3v3(rv3d->twmat[3], scene->twmin, scene->twmax); } break; - case 'X': - UI_GetThemeColor3ubv(TH_AXIS_X, col); - break; - case 'Y': - UI_GetThemeColor3ubv(TH_AXIS_Y, col); - break; - case 'Z': - UI_GetThemeColor3ubv(TH_AXIS_Z, col); - break; - default: - BLI_assert(0); - break; } + case V3D_AROUND_LOCAL_ORIGINS: + case V3D_AROUND_CENTER_MEAN: + copy_v3_v3(rv3d->twmat[3], scene->twcent); + break; + case V3D_AROUND_CURSOR: + copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d)); + break; } - - immUniformColor4ubv(col); } -static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3]) +/** + * Sets up \a r_start and \a r_len to define arrow line range. + * Needed to adjust line drawing for combined manipulator axis types. + */ +static void manipulator_line_range(const View3D *v3d, const short axis_type, float *r_start, float *r_len) { - float axis_values[3]; - float vec[3]; + const float ofs = 0.2f; - ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec); + *r_start = 0.2f; + *r_len = 1.0f; - axis_values[0] = -dot_v3v3(rv3d->twmat[0], vec); - axis_values[1] = -dot_v3v3(rv3d->twmat[1], vec); - axis_values[2] = -dot_v3v3(rv3d->twmat[2], vec); - - axis_sort_v3(axis_values, r_axis_order); -} - -/* viewmatrix should have been set OK, also no shademode! */ -static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int colcode, - int flagx, int flagy, int flagz, int axis, - const bool is_picksel, unsigned int pos) -{ - switch (axis) { - case 0: - /* axes */ - if (flagx) { - if (is_picksel) { - if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X); - else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X); - } - else { - manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - } - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.2f, 0.0f, 0.0f); - immVertex3f(pos, 1.0f, 0.0f, 0.0f); - immEnd(); + switch (axis_type) { + case MAN_AXES_TRANSLATE: + if (v3d->twtype & V3D_MANIP_SCALE) { + *r_start = *r_len - ofs + 0.075f; } - break; - case 1: - if (flagy) { - if (is_picksel) { - if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y); - else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y); - } - else { - manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - } - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0f, 0.2f, 0.0f); - immVertex3f(pos, 0.0f, 1.0f, 0.0f); - immEnd(); + if (v3d->twtype & V3D_MANIP_ROTATE) { + *r_len += ofs; } break; - case 2: - if (flagz) { - if (is_picksel) { - if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z); - else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z); - } - else { - manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - } - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0f, 0.0f, 0.2f); - immVertex3f(pos, 0.0f, 0.0f, 1.0f); - immEnd(); + case MAN_AXES_SCALE: + if (v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) { + *r_len -= ofs + 0.025f; } break; } -} -static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, - int flagx, int flagy, int flagz, - const int axis_order[3], const bool is_picksel, unsigned int pos) -{ - int i; - for (i = 0; i < 3; i++) { - draw_manipulator_axes_single(v3d, rv3d, colcode, flagx, flagy, flagz, axis_order[i], is_picksel, pos); - } -} - -static void preOrthoFront(const bool ortho, float twmat[4][4], int axis) -{ - if (ortho == false) { - float omat[4][4]; - copy_m4_m4(omat, twmat); - orthogonalize_m4(omat, axis); - gpuPushMatrix(); - gpuMultMatrix3D(omat); - glFrontFace(is_negative_m4(omat) ? GL_CW : GL_CCW); - } -} -static void postOrtho(const bool ortho) -{ - if (ortho == false) { - gpuPopMatrix(); - } + *r_len -= *r_start; } -static void twmat_to_rotation_axis_mat( - const float twmat[4][4], const int axis, const bool ortho, - float r_axis_mat[4][4]) -{ - copy_m4_m4(r_axis_mat, twmat); - if (!ortho) { - orthogonalize_m4(r_axis_mat, axis); /* for gimbal */ - } - - if (ELEM(axis, 0, 1)) { - const char rot_axis = (axis == 0) ? 'Y' : 'X'; - const float angle = (axis == 0) ? M_PI_2 : -M_PI_2; - rotate_m4(r_axis_mat, rot_axis, angle); - } -} +/* **************** Actual Widget Stuff **************** */ -BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags) +static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *wgroup) { - return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)); + ManipulatorGroup *man; + + man = MEM_callocN(sizeof(ManipulatorGroup), "manipulator_data"); + + /* add/init widgets - order matters! */ + man->rotate_t = MANIPULATOR_dial_new(wgroup, "rotate_t", MANIPULATOR_DIAL_STYLE_RING_FILLED); + + man->scale_c = MANIPULATOR_dial_new(wgroup, "scale_c", MANIPULATOR_DIAL_STYLE_RING); + man->scale_x = MANIPULATOR_arrow_new(wgroup, "scale_x", MANIPULATOR_ARROW_STYLE_BOX); + man->scale_y = MANIPULATOR_arrow_new(wgroup, "scale_y", MANIPULATOR_ARROW_STYLE_BOX); + man->scale_z = MANIPULATOR_arrow_new(wgroup, "scale_z", MANIPULATOR_ARROW_STYLE_BOX); + man->scale_xy = MANIPULATOR_primitive_new(wgroup, "scale_xy", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + man->scale_yz = MANIPULATOR_primitive_new(wgroup, "scale_yz", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + man->scale_zx = MANIPULATOR_primitive_new(wgroup, "scale_zx", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + + man->rotate_x = MANIPULATOR_dial_new(wgroup, "rotate_x", MANIPULATOR_DIAL_STYLE_RING_CLIPPED); + man->rotate_y = MANIPULATOR_dial_new(wgroup, "rotate_y", MANIPULATOR_DIAL_STYLE_RING_CLIPPED); + man->rotate_z = MANIPULATOR_dial_new(wgroup, "rotate_z", MANIPULATOR_DIAL_STYLE_RING_CLIPPED); + /* init screen aligned widget last here, looks better, behaves better */ + man->rotate_c = MANIPULATOR_dial_new(wgroup, "rotate_c", MANIPULATOR_DIAL_STYLE_RING); + + man->translate_c = MANIPULATOR_dial_new(wgroup, "translate_c", MANIPULATOR_DIAL_STYLE_RING); + man->translate_x = MANIPULATOR_arrow_new(wgroup, "translate_x", MANIPULATOR_ARROW_STYLE_NORMAL); + man->translate_y = MANIPULATOR_arrow_new(wgroup, "translate_y", MANIPULATOR_ARROW_STYLE_NORMAL); + man->translate_z = MANIPULATOR_arrow_new(wgroup, "translate_z", MANIPULATOR_ARROW_STYLE_NORMAL); + man->translate_xy = MANIPULATOR_primitive_new(wgroup, "translate_xy", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + man->translate_yz = MANIPULATOR_primitive_new(wgroup, "translate_yz", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + man->translate_zx = MANIPULATOR_primitive_new(wgroup, "translate_zx", MANIPULATOR_PRIMITIVE_STYLE_PLANE); + + return man; } -static void draw_manipulator_rotate( - View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, - const bool is_moving, const bool is_picksel) +/** + * Custom handler for manipulator widgets + */ +static int manipulator_handler(bContext *C, const wmEvent *UNUSED(event), wmManipulator *widget, const int UNUSED(flag)) { - float matt[4][4]; - float size, unitmat[4][4]; - float cywid = 0.33f * 0.01f * (float)U.tw_handlesize; - float cusize = cywid * 0.65f; - bool arcs = (G.debug_value != 2); - const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB; - bool ortho; - - /* skip drawing if all axes are locked */ - if (manipulator_rotate_is_visible(drawflags) == false) return; - - /* Init stuff */ - glDisable(GL_DEPTH_TEST); - unit_m4(unitmat); - - - /* prepare for screen aligned draw */ - size = len_v3(rv3d->twmat[0]); - gpuPushMatrix(); - gpuTranslate3fv(rv3d->twmat[3]); - - - const unsigned pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); - - /* sets view screen aligned */ - gpuRotate3f(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - /* Screen aligned help circle */ - if (arcs) { - if (is_picksel == false) { - immUniformThemeColorShade(TH_BACK, -30); - imm_drawcircball(unitmat[3], size, unitmat, pos); - } - } - - /* Screen aligned trackball rot circle */ - if (drawflags & MAN_ROT_T) { - if (is_picksel) GPU_select_load_id(MAN_ROT_T); - else immUniformThemeColor(TH_TRANSFORM); - - imm_drawcircball(unitmat[3], 0.2f * size, unitmat, pos); - } - - /* Screen aligned view rot circle */ - if (drawflags & MAN_ROT_V) { - if (is_picksel) GPU_select_load_id(MAN_ROT_V); - else immUniformThemeColor(TH_TRANSFORM); - imm_drawcircball(unitmat[3], 1.2f * size, unitmat, pos); - - if (is_moving) { - float vec[3]; - vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]); - vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]); - vec[2] = 0.0f; - normalize_v3_length(vec, 1.2f * size); - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0f, 0.0f, 0.0f); - immVertex3fv(pos,vec); - immEnd(); - } - } - gpuPopMatrix(); - - gpuPushMatrix(); - - ortho = is_orthogonal_m4(rv3d->twmat); - - /* apply the transform delta */ - if (is_moving) { - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - if (ortho) { - gpuMultMatrix3D(matt); - glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW); - } - } - else { - if (ortho) { - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - gpuMultMatrix3D(rv3d->twmat); - } - } - - /* axes */ - if (arcs == false) { - if (!is_picksel) { - if ((combo & V3D_MANIP_SCALE) == 0) { - /* axis */ - if ((drawflags & MAN_ROT_X) || (is_moving && (drawflags & MAN_ROT_Z))) { - preOrthoFront(ortho, rv3d->twmat, 2); - manipulator_setcolor(v3d, 'X', colcode, 255); - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.2f, 0.0f, 0.0f); - immVertex3f(pos, 1.0f, 0.0f, 0.0f); - immEnd(); - postOrtho(ortho); - } - if ((drawflags & MAN_ROT_Y) || (is_moving && (drawflags & MAN_ROT_X))) { - preOrthoFront(ortho, rv3d->twmat, 0); - manipulator_setcolor(v3d, 'Y', colcode, 255); - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0f, 0.2f, 0.0f); - immVertex3f(pos, 0.0f, 1.0f, 0.0f); - immEnd(); - postOrtho(ortho); - } - if ((drawflags & MAN_ROT_Z) || (is_moving && (drawflags & MAN_ROT_Y))) { - preOrthoFront(ortho, rv3d->twmat, 1); - manipulator_setcolor(v3d, 'Z', colcode, 255); - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0f, 0.0f, 0.2f); - immVertex3f(pos, 0.0f, 0.0f, 1.0f); - immEnd(); - postOrtho(ortho); - } - } - } - } - - if (arcs == false && is_moving) { - - /* Z circle */ - if (drawflags & MAN_ROT_Z) { - preOrthoFront(ortho, matt, 2); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); - imm_drawcircball(unitmat[3], 1.0, unitmat, pos); - postOrtho(ortho); - } - /* X circle */ - if (drawflags & MAN_ROT_X) { - preOrthoFront(ortho, matt, 0); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); - gpuPushMatrix(); - gpuRotateAxis(90.0, 'Y'); - imm_drawcircball(unitmat[3], 1.0, unitmat, pos); - gpuPopMatrix(); - postOrtho(ortho); - } - /* Y circle */ - if (drawflags & MAN_ROT_Y) { - preOrthoFront(ortho, matt, 1); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); - gpuPushMatrix(); - gpuRotateAxis(-90.0, 'X'); - imm_drawcircball(unitmat[3], 1.0, unitmat, pos); - gpuPopMatrix(); - postOrtho(ortho); - } - } - // donut arcs - if (arcs) { - float axis_model_mat[4][4]; - -#if !APPLE_LEGACY - float clip_plane[4]; - - copy_v3_v3(clip_plane, rv3d->viewinv[2]); - clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], rv3d->twmat[3]); - clip_plane[3] -= 0.02f * size; /* clip just a bit more so view aligned arcs are not visible */ -#endif - - gpuPopMatrix(); /* we setup our own matrix, pop previously set twmat */ - -#if !APPLE_LEGACY - immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR); - immUniform4fv("ClipPlane", clip_plane); - - glEnable(GL_CLIP_DISTANCE0); -#endif - - /* Z circle */ - if (drawflags & MAN_ROT_Z) { - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); - - twmat_to_rotation_axis_mat(rv3d->twmat, 2, ortho, axis_model_mat); -#if !APPLE_LEGACY - immUniformMatrix4fv("ModelMatrix", axis_model_mat); -#endif - gpuPushMatrix(); - gpuMultMatrix3D(axis_model_mat); - - partial_doughnut(pos, cusize / 4.0f, 1.0f, 0, 48, 8, 48); - gpuPopMatrix(); - } - /* X circle */ - if (drawflags & MAN_ROT_X) { - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); - - twmat_to_rotation_axis_mat(rv3d->twmat, 0, ortho, axis_model_mat); -#if !APPLE_LEGACY - immUniformMatrix4fv("ModelMatrix", axis_model_mat); -#endif - gpuPushMatrix(); - gpuMultMatrix3D(axis_model_mat); - - partial_doughnut(pos, cusize / 4.0f, 1.0f, 0, 48, 8, 48); - gpuPopMatrix(); - } - /* Y circle */ - if (drawflags & MAN_ROT_Y) { - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); - - twmat_to_rotation_axis_mat(rv3d->twmat, 1, ortho, axis_model_mat); -#if !APPLE_LEGACY - immUniformMatrix4fv("ModelMatrix", axis_model_mat); -#endif - gpuPushMatrix(); - gpuMultMatrix3D(axis_model_mat); - - partial_doughnut(pos, cusize / 4.0f, 1.0f, 0, 48, 8, 48); - gpuPopMatrix(); - } - -#if !APPLE_LEGACY - glDisable(GL_CLIP_DISTANCE0); -#endif - - gpuPushMatrix(); /* to balance final pop at end of function */ - } - else { - - /* Z handle on X axis */ - if (drawflags & MAN_ROT_Z) { - preOrthoFront(ortho, rv3d->twmat, 2); - gpuPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - else manipulator_setcolor(v3d, 'Z', colcode, 255); - - partial_doughnut(pos, 0.7f * cusize, 1.0f, 31, 33, 8, 64); - - gpuPopMatrix(); - postOrtho(ortho); - } - - /* Y handle on X axis */ - if (drawflags & MAN_ROT_Y) { - preOrthoFront(ortho, rv3d->twmat, 1); - gpuPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - else manipulator_setcolor(v3d, 'Y', colcode, 255); - - gpuRotateAxis(90.0, 'X'); - gpuRotateAxis(90.0, 'Z'); - partial_doughnut(pos, 0.7f * cusize, 1.0f, 31, 33, 8, 64); - - gpuPopMatrix(); - postOrtho(ortho); - } - - /* X handle on Z axis */ - if (drawflags & MAN_ROT_X) { - preOrthoFront(ortho, rv3d->twmat, 0); - gpuPushMatrix(); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - else manipulator_setcolor(v3d, 'X', colcode, 255); - - gpuRotateAxis(-90.0, 'Y'); - gpuRotateAxis(90.0, 'Z'); - partial_doughnut(pos, 0.7f * cusize, 1.0f, 31, 33, 8, 64); + const ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + View3D *v3d = sa->spacedata.first; + RegionView3D *rv3d = ar->regiondata; - gpuPopMatrix(); - postOrtho(ortho); - } + if (calc_manipulator_stats(C)) { + manipulator_prepare_mat(C, v3d, rv3d); + WM_manipulator_set_origin(widget, rv3d->twmat[3]); } - /* Note: Shader is not ensured to be GPU_SHADER_3D_UNIFORM_COLOR from here on, twmat might have been popped too! */ - - /* restore */ - gpuPopMatrix(); - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - immUnbindProgram(); -} + ED_region_tag_redraw(ar); -static void drawsolidcube(unsigned int pos, float size) -{ - const float cube[8][3] = { - {-1.0, -1.0, -1.0}, - {-1.0, -1.0, 1.0}, - {-1.0, 1.0, 1.0}, - {-1.0, 1.0, -1.0}, - { 1.0, -1.0, -1.0}, - { 1.0, -1.0, 1.0}, - { 1.0, 1.0, 1.0}, - { 1.0, 1.0, -1.0}, - }; - - gpuPushMatrix(); - gpuScaleUniform(size); - - immBegin(GL_TRIANGLES, 12 * 3); - immVertex3fv(pos, cube[0]); immVertex3fv(pos, cube[1]); immVertex3fv(pos, cube[2]); - immVertex3fv(pos, cube[0]); immVertex3fv(pos, cube[2]); immVertex3fv(pos, cube[3]); - immVertex3fv(pos, cube[0]); immVertex3fv(pos, cube[4]); immVertex3fv(pos, cube[5]); - immVertex3fv(pos, cube[0]); immVertex3fv(pos, cube[5]); immVertex3fv(pos, cube[1]); - immVertex3fv(pos, cube[4]); immVertex3fv(pos, cube[7]); immVertex3fv(pos, cube[6]); - immVertex3fv(pos, cube[4]); immVertex3fv(pos, cube[6]); immVertex3fv(pos, cube[5]); - immVertex3fv(pos, cube[7]); immVertex3fv(pos, cube[3]); immVertex3fv(pos, cube[2]); - immVertex3fv(pos, cube[7]); immVertex3fv(pos, cube[2]); immVertex3fv(pos, cube[6]); - immVertex3fv(pos, cube[1]); immVertex3fv(pos, cube[5]); immVertex3fv(pos, cube[6]); - immVertex3fv(pos, cube[1]); immVertex3fv(pos, cube[6]); immVertex3fv(pos, cube[2]); - immVertex3fv(pos, cube[7]); immVertex3fv(pos, cube[4]); immVertex3fv(pos, cube[0]); - immVertex3fv(pos, cube[7]); immVertex3fv(pos, cube[0]); immVertex3fv(pos, cube[3]); - immEnd(); - - gpuPopMatrix(); + return OPERATOR_PASS_THROUGH; } - -static void draw_manipulator_scale( - View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, const int colcode, - const bool is_moving, const bool is_picksel) +static void WIDGETGROUP_manipulator_init(const bContext *UNUSED(C), wmManipulatorGroup *wgroup) { - float cywid = 0.25f * 0.01f * (float)U.tw_handlesize; - float cusize = cywid * 0.75f, dz; - int axis_order[3] = {2, 0, 1}; - int i; - - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_SCALE_C) == 0) return; - - manipulator_axis_order(rv3d, axis_order); - - glDisable(GL_DEPTH_TEST); - - const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - gpuPushMatrix(); - - /* not in combo mode */ - if ((combo & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE)) == 0) { - float size, unitmat[4][4]; - int shift = 0; // XXX - - /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C); - else manipulator_setcolor(v3d, 'C', colcode, 255); - - gpuPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - unit_m4(unitmat); - imm_drawcircball(unitmat[3], 0.2f * size, unitmat, pos); - gpuPopMatrix(); - - dz = 1.0; - } - else { - dz = 1.0f - 4.0f * cusize; - } - - if (is_moving) { - float matt[4][4]; - - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - gpuMultMatrix3D(matt); - glFrontFace(is_negative_m4(matt) ? GL_CW : GL_CCW); - } - else { - gpuMultMatrix3D(rv3d->twmat); - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - } - - /* axis */ + ManipulatorGroup *man = manipulatorgroup_init(wgroup); + wgroup->customdata = man; - /* in combo mode, this is always drawn as first type */ - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z, - axis_order, is_picksel, pos); + /* *** set properties for axes *** */ - - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* X cube */ - if (drawflags & MAN_SCALE_X) { - gpuTranslate3f(dz, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_SCALE_X); - else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - drawsolidcube(pos, cusize); - gpuTranslate3f(-dz, 0.0, 0.0); - } + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + const short axis_type = manipulator_get_axis_type(man, axis); + int constraint_axis[3] = {1, 0, 0}; + PointerRNA *ptr; + + manipulator_get_axis_constraint(axis_idx, constraint_axis); + + /* custom handler! */ + WM_manipulator_set_custom_handler(axis, manipulator_handler); + + switch(axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_SCALE_Z: + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); break; - case 1: /* Y cube */ - if (drawflags & MAN_SCALE_Y) { - gpuTranslate3f(0.0, dz, 0.0); - if (is_picksel) GPU_select_load_id(MAN_SCALE_Y); - else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - drawsolidcube(pos, cusize); - gpuTranslate3f(0.0, -dz, 0.0); - } + case MAN_AXIS_ROT_X: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_ROT_Z: + /* increased line width for better display */ + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH + 1.0f); + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); break; - case 2: /* Z cube */ - if (drawflags & MAN_SCALE_Z) { - gpuTranslate3f(0.0, 0.0, dz); - if (is_picksel) GPU_select_load_id(MAN_SCALE_Z); - else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - drawsolidcube(pos, cusize); - gpuTranslate3f(0.0, 0.0, -dz); - } + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_XY: + case MAN_AXIS_SCALE_YZ: + case MAN_AXIS_SCALE_ZX: + { + const float ofs_ax = 11.0f; + const float ofs[3] = {ofs_ax, ofs_ax, 0.0f}; + WM_manipulator_set_scale(axis, 0.07f); + WM_manipulator_set_offset(axis, ofs); break; - } - } - -#if 0 // XXX - /* if shiftkey, center point as last, for selectbuffer order */ - if (is_picksel) { - int shift = 0; // XXX - - if (shift) { - gpuTranslate3f(0.0, -dz, 0.0); - GPU_select_load_id(MAN_SCALE_C); - /* TODO: set glPointSize before drawing center point */ - immBegin(GL_POINTS, 1); - immVertex3f(0.0, 0.0, 0.0); - immEnd(); - } - } -#endif - - /* restore */ - gpuPopMatrix(); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - glFrontFace(GL_CCW); - - immUnbindProgram(); -} - -#define NSEGMENTS 8 -static void draw_cone(unsigned int pos, float len, float width) -{ - /* a ring of vertices in the XY plane */ - float p[NSEGMENTS][2]; - for (int i = 0; i < NSEGMENTS; ++i) { - float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); - p[i][0] = width * cosf(angle); - p[i][1] = width * sinf(angle); - } - - float zbase = -0.5f * len; - float ztop = 0.5f * len; - - /* cone sides */ - immBegin(GL_TRIANGLE_FAN, NSEGMENTS + 2); - immVertex3f(pos, 0, 0, ztop); - for (int i = 0; i < NSEGMENTS; ++i) - immVertex3f(pos, p[i][0], p[i][1], zbase); - immVertex3f(pos, p[0][0], p[0][1], zbase); - immEnd(); - - /* end cap */ - immBegin(GL_TRIANGLE_FAN, NSEGMENTS); - for (int i = NSEGMENTS - 1; i >= 0; --i) - immVertex3f(pos, p[i][0], p[i][1], zbase); - immEnd(); -} - -static void draw_cylinder(unsigned int pos, float len, float width) -{ - width *= 0.8f; // just for beauty - - /* a ring of vertices in the XY plane */ - float p[NSEGMENTS][2]; - for (int i = 0; i < NSEGMENTS; ++i) { - float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS); - p[i][0] = width * cosf(angle); - p[i][1] = width * sinf(angle); - } - - float zbase = -0.5f * len; - float ztop = 0.5f * len; - - /* cylinder sides */ - immBegin(GL_TRIANGLE_STRIP, (NSEGMENTS + 1) * 2); - for (int i = 0; i < NSEGMENTS; ++i) { - immVertex3f(pos, p[i][0], p[i][1], zbase); - immVertex3f(pos, p[i][0], p[i][1], ztop); - } - immVertex3f(pos, p[0][0], p[0][1], zbase); - immVertex3f(pos, p[0][0], p[0][1], ztop); - immEnd(); - - /* end caps */ - immBegin(GL_TRIANGLE_FAN, NSEGMENTS); - for (int i = NSEGMENTS - 1; i >= 0; --i) - immVertex3f(pos, p[i][0], p[i][1], zbase); - immEnd(); - immBegin(GL_TRIANGLE_FAN, NSEGMENTS); - for (int i = 0; i < NSEGMENTS; ++i) - immVertex3f(pos, p[i][0], p[i][1], ztop); - immEnd(); -} -#undef NSEGMENTS - -static void draw_manipulator_translate( - View3D *v3d, RegionView3D *rv3d, int drawflags, int combo, int colcode, - const bool UNUSED(is_moving), const bool is_picksel) -{ - float cylen = 0.01f * (float)U.tw_handlesize; - float cywid = 0.25f * cylen, dz, size; - float unitmat[4][4]; - int shift = 0; // XXX - int axis_order[3] = {0, 1, 2}; - int i; - - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_TRANS_C) == 0) return; - - manipulator_axis_order(rv3d, axis_order); - - // XXX if (moving) gpuTranslate3fv(t->vec); - glDisable(GL_DEPTH_TEST); - - const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - gpuPushMatrix(); - - /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C); - else manipulator_setcolor(v3d, 'C', colcode, 255); - - gpuPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - unit_m4(unitmat); - imm_drawcircball(unitmat[3], 0.2f * size, unitmat, pos); - gpuPopMatrix(); - - /* and now apply matrix, we move to local matrix drawing */ - gpuMultMatrix3D(rv3d->twmat); - - /* axis */ - GPU_select_load_id(-1); - - // translate drawn as last, only axis when no combo with scale, or for ghosting - if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) { - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z, - axis_order, is_picksel, pos); - } - - /* offset in combo mode, for rotate a bit more */ - if (combo & (V3D_MANIP_ROTATE)) dz = 1.0f + 2.0f * cylen; - else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen; - else dz = 1.0f; - - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* Z Cone */ - if (drawflags & MAN_TRANS_Z) { - gpuPushMatrix(); - gpuTranslate3f(0.0, 0.0, dz); - if (is_picksel) GPU_select_load_id(MAN_TRANS_Z); - else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); - draw_cone(pos, cylen, cywid); - gpuPopMatrix(); + } + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH); + if (axis_idx == MAN_AXIS_ROT_T) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_HOVER, true); } - break; - case 1: /* X Cone */ - if (drawflags & MAN_TRANS_X) { - gpuPushMatrix(); - gpuTranslate3f(dz, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_TRANS_X); - else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); - gpuRotateAxis(90.0, 'Y'); - draw_cone(pos, cylen, cywid); - gpuPopMatrix(); + else if (axis_idx == MAN_AXIS_ROT_C) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true); } - break; - case 2: /* Y Cone */ - if (drawflags & MAN_TRANS_Y) { - gpuPushMatrix(); - gpuTranslate3f(0.0, dz, 0.0); - if (is_picksel) GPU_select_load_id(MAN_TRANS_Y); - else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); - gpuRotateAxis(-90.0, 'X'); - draw_cone(pos, cylen, cywid); - gpuPopMatrix(); + else { + WM_manipulator_set_scale(axis, 0.2f); } break; } - } - - gpuPopMatrix(); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - - immUnbindProgram(); -} - -static void draw_manipulator_rotate_cyl( - View3D *v3d, RegionView3D *rv3d, int drawflags, const int combo, const int colcode, - const bool is_moving, const bool is_picksel) -{ - float size; - float cylen = 0.01f * (float)U.tw_handlesize; - float cywid = 0.25f * cylen; - int axis_order[3] = {2, 0, 1}; - int i; - - /* skip drawing if all axes are locked */ - if (manipulator_rotate_is_visible(drawflags) == false) return; - - manipulator_axis_order(rv3d, axis_order); - - const unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - gpuPushMatrix(); - - /* prepare for screen aligned draw */ - gpuPushMatrix(); - size = screen_aligned(rv3d, rv3d->twmat); - - glDisable(GL_DEPTH_TEST); - - /* Screen aligned view rot circle */ - if (drawflags & MAN_ROT_V) { - float unitmat[4][4]; - - unit_m4(unitmat); - - if (is_picksel) GPU_select_load_id(MAN_ROT_V); - immUniformThemeColor(TH_TRANSFORM); - imm_drawcircball(unitmat[3], 1.2f * size, unitmat, pos); - - if (is_moving) { - float vec[3]; - vec[0] = 0; // XXX (float)(t->mouse.imval[0] - t->center2d[0]); - vec[1] = 0; // XXX (float)(t->mouse.imval[1] - t->center2d[1]); - vec[2] = 0.0f; - normalize_v3_length(vec, 1.2f * size); - immBegin(GL_LINES, 2); - immVertex3f(pos, 0.0, 0.0, 0.0); - immVertex3fv(pos, vec); - immEnd(); - } - } - gpuPopMatrix(); - - /* apply the transform delta */ - if (is_moving) { - float matt[4][4]; - copy_m4_m4(matt, rv3d->twmat); // to copy the parts outside of [3][3] - // XXX if (t->flag & T_USES_MANIPULATOR) { - // XXX mul_m4_m3m4(matt, t->mat, rv3d->twmat); - // XXX } - gpuMultMatrix3D(matt); - } - else { - gpuMultMatrix3D(rv3d->twmat); - } - - glFrontFace(is_negative_m4(rv3d->twmat) ? GL_CW : GL_CCW); - - /* axis */ - if (is_picksel == false) { - - // only draw axis when combo didn't draw scale axes - if ((combo & V3D_MANIP_SCALE) == 0) { - draw_manipulator_axes(v3d, rv3d, colcode, - drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z, - axis_order, is_picksel, pos); - } - } - for (i = 0; i < 3; i++) { - switch (axis_order[i]) { - case 0: /* X cylinder */ - if (drawflags & MAN_ROT_X) { - gpuPushMatrix(); - gpuTranslate3f(1.0, 0.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_X); - gpuRotateAxis(90.0, 'Y'); - manipulator_setcolor(v3d, 'X', colcode, 255); - draw_cylinder(pos, cylen, cywid); - gpuPopMatrix(); - } + switch (axis_type) { + case MAN_AXES_TRANSLATE: + ptr = WM_manipulator_set_operator(axis, "TRANSFORM_OT_translate"); break; - case 1: /* Y cylinder */ - if (drawflags & MAN_ROT_Y) { - gpuPushMatrix(); - gpuTranslate3f(0.0, 1.0, 0.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_Y); - gpuRotateAxis(-90.0, 'X'); - manipulator_setcolor(v3d, 'Y', colcode, 255); - draw_cylinder(pos, cylen, cywid); - gpuPopMatrix(); - } + case MAN_AXES_ROTATE: + ptr = WM_manipulator_set_operator( + axis, (axis_idx == MAN_AXIS_ROT_T) ? + "TRANSFORM_OT_trackball" : "TRANSFORM_OT_rotate"); break; - case 2: /* Z cylinder */ - if (drawflags & MAN_ROT_Z) { - gpuPushMatrix(); - gpuTranslate3f(0.0, 0.0, 1.0); - if (is_picksel) GPU_select_load_id(MAN_ROT_Z); - manipulator_setcolor(v3d, 'Z', colcode, 255); - draw_cylinder(pos, cylen, cywid); - gpuPopMatrix(); - } + case MAN_AXES_SCALE: + ptr = WM_manipulator_set_operator(axis, "TRANSFORM_OT_resize"); break; } + if (RNA_struct_find_property(ptr, "constraint_axis")) + RNA_boolean_set_array(ptr, "constraint_axis", constraint_axis); + RNA_boolean_set(ptr, "release_confirm", 1); } - - /* restore */ - gpuPopMatrix(); - - if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - - immUnbindProgram(); + MAN_ITER_AXES_END; } - -/* ********************************************* */ - -/* main call, does calc centers & orientation too */ -static int drawflags = 0xFFFF; // only for the calls below, belongs in scene...? - -void BIF_draw_manipulator(const bContext *C) +static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGroup *wgroup) { + ManipulatorGroup *man = wgroup->customdata; ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - SceneLayer *sl = CTX_data_scene_layer(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - int totsel; - const bool is_picksel = false; + /* skip, we don't draw anything anyway */ + if ((man->all_hidden = (calc_manipulator_stats(C) == 0))) + return; - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return; + manipulator_prepare_mat(C, v3d, rv3d); - if ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) return; + /* *** set properties for axes *** */ + MAN_ITER_AXES_BEGIN(axis, axis_idx) { - v3d->twflag &= ~V3D_DRAW_MANIPULATOR; - - totsel = calc_manipulator_stats(C); - if (totsel == 0) return; - - v3d->twflag |= V3D_DRAW_MANIPULATOR; - - /* now we can define center */ - switch (v3d->around) { - case V3D_AROUND_CENTER_BOUNDS: - case V3D_AROUND_ACTIVE: + const short axis_type = manipulator_get_axis_type(man, axis); + const int aidx_norm = manipulator_index_normalize(axis_idx); + + WM_manipulator_set_origin(axis, rv3d->twmat[3]); + + switch (axis_idx) { + case MAN_AXIS_TRANS_X: + case MAN_AXIS_TRANS_Y: + case MAN_AXIS_TRANS_Z: + case MAN_AXIS_SCALE_X: + case MAN_AXIS_SCALE_Y: + case MAN_AXIS_SCALE_Z: { - bGPdata *gpd = CTX_data_gpencil_data(C); - Object *ob = OBACT_NEW; + float start_co[3] = {0.0f, 0.0f, 0.0f}; + float len; - if (((v3d->around == V3D_AROUND_ACTIVE) && (scene->obedit == NULL)) && - ((gpd == NULL) || !(gpd->flag & GP_DATA_STROKE_EDITMODE)) && - (ob && !(ob->mode & OB_MODE_POSE))) - { - copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); - } - else { - mid_v3_v3v3(rv3d->twmat[3], scene->twmin, scene->twmax); - } + manipulator_line_range(v3d, axis_type, &start_co[2], &len); + + MANIPULATOR_arrow_set_direction(axis, rv3d->twmat[aidx_norm]); + MANIPULATOR_arrow_set_line_len(axis, len); + WM_manipulator_set_offset(axis, start_co); break; } - case V3D_AROUND_LOCAL_ORIGINS: - case V3D_AROUND_CENTER_MEAN: - copy_v3_v3(rv3d->twmat[3], scene->twcent); + case MAN_AXIS_ROT_X: + case MAN_AXIS_ROT_Y: + case MAN_AXIS_ROT_Z: + MANIPULATOR_dial_set_up_vector(axis, rv3d->twmat[aidx_norm]); break; - case V3D_AROUND_CURSOR: - copy_v3_v3(rv3d->twmat[3], ED_view3d_cursor3d_get(scene, v3d)); + case MAN_AXIS_TRANS_XY: + case MAN_AXIS_TRANS_YZ: + case MAN_AXIS_TRANS_ZX: + case MAN_AXIS_SCALE_XY: + case MAN_AXIS_SCALE_YZ: + case MAN_AXIS_SCALE_ZX: + MANIPULATOR_primitive_set_direction(axis, rv3d->twmat[aidx_norm - 1 < 0 ? 2 : aidx_norm - 1]); + MANIPULATOR_primitive_set_up_vector(axis, rv3d->twmat[aidx_norm + 1 > 2 ? 0 : aidx_norm + 1]); break; } - - mul_mat3_m4_fl(rv3d->twmat, ED_view3d_pixel_size(rv3d, rv3d->twmat[3]) * U.tw_size); - } - - /* when looking through a selected camera, the manipulator can be at the - * exact same position as the view, skip so we don't break selection */ - if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) - return; - - test_manipulator_axis(C); - drawflags = rv3d->twdrawflag; /* set in calc_manipulator_stats */ - - if (v3d->twflag & V3D_DRAW_MANIPULATOR) { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glLineWidth(1.0f); - - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) { - if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) - draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_MOVECOL, true, is_picksel); - else - draw_manipulator_rotate_cyl(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); - } - else { - draw_manipulator_rotate(v3d, rv3d, drawflags, v3d->twtype, false, is_picksel); - } - } - if (v3d->twtype & V3D_MANIP_SCALE) { - draw_manipulator_scale(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); - } - if (v3d->twtype & V3D_MANIP_TRANSLATE) { - draw_manipulator_translate(v3d, rv3d, drawflags, v3d->twtype, MAN_RGB, false, is_picksel); - } - - glDisable(GL_BLEND); } + MAN_ITER_AXES_END; } -static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], float hotspot) +static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulatorGroup *wgroup) { + ManipulatorGroup *man = wgroup->customdata; + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - rcti rect; - GLuint buffer[64]; // max 4 items per select, so large enuf - short hits; - const bool is_picksel = true; - const bool do_passes = GPU_select_query_check_active(); - - /* XXX check a bit later on this... (ton) */ - extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rcti *rect); + float idot[3]; /* when looking through a selected camera, the manipulator can be at the * exact same position as the view, skip so we don't break selection */ - if (fabsf(mat4_to_scale(rv3d->twmat)) < 1e-7f) - return 0; - - rect.xmin = mval[0] - hotspot; - rect.xmax = mval[0] + hotspot; - rect.ymin = mval[1] - hotspot; - rect.ymax = mval[1] + hotspot; - - view3d_winmatrix_set(ar, v3d, &rect); - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - - if (do_passes) - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0); - else - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_ALL, 0); - - /* do the drawing */ - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel); + if (man->all_hidden || fabsf(ED_view3d_pixel_size(rv3d, rv3d->twmat[3])) < 1e-6f) { + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true); + } + MAN_ITER_AXES_END; + return; } - if (v3d->twtype & V3D_MANIP_SCALE) - draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - if (v3d->twtype & V3D_MANIP_TRANSLATE) - draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); + manipulator_get_idot(rv3d, idot); - hits = GPU_select_end(); + /* *** set properties for axes *** */ - if (do_passes) { - GPU_select_begin(buffer, 64, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits); - - /* do the drawing */ - if (v3d->twtype & V3D_MANIP_ROTATE) { - if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel); + MAN_ITER_AXES_BEGIN(axis, axis_idx) + { + const short axis_type = manipulator_get_axis_type(man, axis); + /* XXX maybe unset _HIDDEN flag on redraw? */ + if (manipulator_is_axis_visible(v3d, rv3d, idot, axis_type, axis_idx)) { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, false); + } + else { + WM_manipulator_set_flag(axis, WM_MANIPULATOR_HIDDEN, true); + continue; } - if (v3d->twtype & V3D_MANIP_SCALE) - draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - if (v3d->twtype & V3D_MANIP_TRANSLATE) - draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - GPU_select_end(); - } + float col[4], col_hi[4]; + manipulator_get_axis_color(axis_idx, idot, col, col_hi); + WM_manipulator_set_colors(axis, col, col_hi); - view3d_winmatrix_set(ar, v3d, NULL); - mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); + switch (axis_idx) { + case MAN_AXIS_TRANS_C: + case MAN_AXIS_ROT_C: + case MAN_AXIS_SCALE_C: + case MAN_AXIS_ROT_T: + MANIPULATOR_dial_set_up_vector(axis, rv3d->viewinv[2]); + break; + } + } + MAN_ITER_AXES_END; +} - if (hits == 1) return buffer[3]; - else if (hits > 1) { - GLuint val, dep, mindep = 0, mindeprot = 0, minval = 0, minvalrot = 0; - int a; +static bool WIDGETGROUP_manipulator_poll(const struct bContext *C, struct wmManipulatorGroupType *UNUSED(wgrouptype)) +{ + /* it's a given we only use this in 3D view */ + const ScrArea *sa = CTX_wm_area(C); + const View3D *v3d = sa->spacedata.first; - /* we compare the hits in buffer, but value centers highest */ - /* we also store the rotation hits separate (because of arcs) and return hits on other widgets if there are */ + return (((v3d->twflag & V3D_USE_MANIPULATOR) != 0) && + ((v3d->twtype & (V3D_MANIP_TRANSLATE | V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) != 0)); +} - for (a = 0; a < hits; a++) { - dep = buffer[4 * a + 1]; - val = buffer[4 * a + 3]; +void TRANSFORM_WGT_manipulator(wmManipulatorGroupType *wgt) +{ + wgt->name = "Transform Manipulator"; - if (val == MAN_TRANS_C) { - return MAN_TRANS_C; - } - else if (val == MAN_SCALE_C) { - return MAN_SCALE_C; - } - else { - if (val & MAN_ROT_C) { - if (minvalrot == 0 || dep < mindeprot) { - mindeprot = dep; - minvalrot = val; - } - } - else { - if (minval == 0 || dep < mindep) { - mindep = dep; - minval = val; - } - } - } - } + wgt->poll = WIDGETGROUP_manipulator_poll; + wgt->init = WIDGETGROUP_manipulator_init; + wgt->refresh = WIDGETGROUP_manipulator_refresh; + wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare; - if (minval) - return minval; - else - return minvalrot; - } - return 0; + wgt->flag |= (WM_MANIPULATORGROUPTYPE_IS_3D | WM_MANIPULATORGROUPTYPE_SCALE_3D); } -static const char *manipulator_get_operator_name(int man_val) + +/* -------------------------------------------------------------------- */ +/* Custom Object Manipulator (unfinished - unsure if this will stay) */ +#if 0 +static void WIDGETGROUP_object_manipulator_init(const bContext *C, wmManipulatorGroup *wgroup) { - if (man_val & MAN_TRANS_C) { - return "TRANSFORM_OT_translate"; - } - else if (man_val == MAN_ROT_T) { - return "TRANSFORM_OT_trackball"; - } - else if (man_val & MAN_ROT_C) { - return "TRANSFORM_OT_rotate"; - } - else if (man_val & MAN_SCALE_C) { - return "TRANSFORM_OT_resize"; + Object *ob = ED_object_active_context((bContext *)C); + + if (ob->wgroup == NULL) { + ob->wgroup = wgroup; } - return NULL; + WIDGETGROUP_manipulator_init(C, wgroup); } -/* return 0; nothing happened */ -int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) +static bool WIDGETGROUP_object_manipulator_poll(const bContext *C, wmManipulatorGroupType *wgrouptype) { - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - ARegion *ar = CTX_wm_region(C); - int constraint_axis[3] = {0, 0, 0}; - int val; - const bool use_planar = RNA_boolean_get(op->ptr, "use_planar_constraint"); - - if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return 0; - if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return 0; - - /* Force orientation */ - RNA_enum_set(op->ptr, "constraint_orientation", v3d->twmode); - - // find the hotspots first test narrow hotspot - val = manipulator_selectbuf(sa, ar, event->mval, 0.5f * (float)U.tw_hotspot); - if (val) { - wmOperatorType *ot; - PointerRNA props_ptr; - PropertyRNA *prop; - const char *opname; - - // drawflags still global, for drawing call above - drawflags = manipulator_selectbuf(sa, ar, event->mval, 0.2f * (float)U.tw_hotspot); - if (drawflags == 0) drawflags = val; - - /* Planar constraint doesn't make sense for rotation, give other keymaps a chance */ - if ((drawflags & MAN_ROT_C) && use_planar) { - return 0; - } - - opname = manipulator_get_operator_name(drawflags); - ot = WM_operatortype_find(opname, true); - WM_operator_properties_create_ptr(&props_ptr, ot); + Object *ob = ED_object_active_context((bContext *)C); - if (drawflags & MAN_TRANS_C) { - switch (drawflags) { - case MAN_TRANS_C: - break; - case MAN_TRANS_X: - if (use_planar) { - constraint_axis[1] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[0] = 1; - break; - case MAN_TRANS_Y: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[1] = 1; - break; - case MAN_TRANS_Z: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[1] = 1; - } - else - constraint_axis[2] = 1; - break; - } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); - } - else if (drawflags & MAN_SCALE_C) { - switch (drawflags) { - case MAN_SCALE_X: - if (use_planar) { - constraint_axis[1] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[0] = 1; - break; - case MAN_SCALE_Y: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[2] = 1; - } - else - constraint_axis[1] = 1; - break; - case MAN_SCALE_Z: - if (use_planar) { - constraint_axis[0] = 1; - constraint_axis[1] = 1; - } - else - constraint_axis[2] = 1; - break; - } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); - } - else if (drawflags == MAN_ROT_T) { - /* pass */ - } - else if (drawflags & MAN_ROT_C) { - switch (drawflags) { - case MAN_ROT_X: - constraint_axis[0] = 1; - break; - case MAN_ROT_Y: - constraint_axis[1] = 1; - break; - case MAN_ROT_Z: - constraint_axis[2] = 1; - break; - } - RNA_boolean_set_array(&props_ptr, "constraint_axis", constraint_axis); + if (ED_operator_object_active((bContext *)C)) { + if (STREQ(wgrouptype->idname, ob->id.name)) { + return true; } + } + return false; +} - /* pass operator properties on to transform operators */ - prop = RNA_struct_find_property(op->ptr, "use_accurate"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); - } - prop = RNA_struct_find_property(op->ptr, "release_confirm"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_set(&props_ptr, prop, RNA_property_boolean_get(op->ptr, prop)); - } - prop = RNA_struct_find_property(op->ptr, "constraint_orientation"); - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_enum_set(&props_ptr, prop, RNA_property_enum_get(op->ptr, prop)); - } +/* XXX should this really be in transform_manipulator.c? */ +void TRANSFORM_WGT_object(wmManipulatorGroupType *wgt) +{ + wgt->name = "Object Widgets"; - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); - WM_operator_properties_free(&props_ptr); - } - /* after transform, restore drawflags */ - drawflags = 0xFFFF; + wgt->poll = WIDGETGROUP_object_manipulator_poll; + wgt->init = WIDGETGROUP_object_manipulator_init; + wgt->refresh = WIDGETGROUP_manipulator_refresh; + wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare; - return val; + wgt->flag |= (WM_MANIPULATORGROUPTYPE_IS_3D | WM_MANIPULATORGROUPTYPE_SCALE_3D); } - +#endif diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c b/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c index 3fb5059cae5..8236d9950a2 100644 --- a/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c @@ -101,20 +101,19 @@ static void manipulator_arrow_get_final_pos(wmManipulator *manipulator, float r_ static void arrow_draw_geom(const ArrowManipulator *arrow, const bool select, const float color[4]) { - /* USE_IMM for other arrow types */ - glColor4fv(color); - if (arrow->style & MANIPULATOR_ARROW_STYLE_CROSS) { - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_LIGHTING); - glBegin(GL_LINES); - glVertex2f(-1.0, 0.f); - glVertex2f(1.0, 0.f); - glVertex2f(0.f, -1.0); - glVertex2f(0.f, 1.0); - glEnd(); - - glPopAttrib(); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT); + immUniformColor4fv(color); + + immBegin(GL_LINES, 4); + immVertex2f(pos, -1.0, 0.f); + immVertex2f(pos, 1.0, 0.f); + immVertex2f(pos, 0.f, -1.0); + immVertex2f(pos, 0.f, 1.0); + immEnd(); + + immUnbindProgram(); } else if (arrow->style & MANIPULATOR_ARROW_STYLE_CONE) { const float unitx = arrow->aspect[0]; @@ -126,29 +125,48 @@ static void arrow_draw_geom(const ArrowManipulator *arrow, const bool select, co {-unitx, unity, 0}, }; + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); + glLineWidth(arrow->manipulator.line_width); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vec); - glDrawArrays(GL_LINE_LOOP, 0, ARRAY_SIZE(vec)); - glDisableClientState(GL_VERTEX_ARRAY); + + const int vec_size = ARRAY_SIZE(vec); + immBegin(PRIM_LINE_STRIP, vec_size); + for (int i = 0; i < vec_size; i++) { + immVertex3fv(pos, vec[i]); + } + immEnd(); + glLineWidth(1.0); + immUnbindProgram(); + } else { #ifdef USE_MANIPULATOR_CUSTOM_ARROWS - wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_arrow, select); + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_arrow, select, color); #else + unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR); + immUniformColor4fv(color); + const float vec[2][3] = { {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, arrow->len}, }; glLineWidth(arrow->manipulator.line_width); - glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vec); - glDrawArrays(GL_LINE_STRIP, 0, ARRAY_SIZE(vec)); - glDisableClientState(GL_VERTEX_ARRAY); - glLineWidth(1.0); + const int vec_size = ARRAY_SIZE(vec); + immBegin(PRIM_LINE_STRIP, vec_size); + for (int i = 0; i < vec_size; i++) { + immVertex3fv(pos, vec[i]); + } + immEnd(); + + glLineWidth(1.0); /* *** draw arrow head *** */ @@ -163,7 +181,8 @@ static void arrow_draw_geom(const ArrowManipulator *arrow, const bool select, co gpuScale3f(size, size, size); /* draw cube */ - wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_cube, select); + immUnbindProgram(); + wm_manipulator_geometryinfo_draw(&wm_manipulator_geom_data_cube, select, color); } else { const float len = 0.25f; @@ -171,12 +190,8 @@ static void arrow_draw_geom(const ArrowManipulator *arrow, const bool select, co const bool use_lighting = select == false && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0); /* translate to line end */ - unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT); gpuTranslate3f(0.0f, 0.0f, arrow->len); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor4fv(color); - if (use_lighting) { glShadeModel(GL_SMOOTH); } @@ -184,15 +199,15 @@ static void arrow_draw_geom(const ArrowManipulator *arrow, const bool select, co imm_draw_circle_fill_3d(pos, 0.0, 0.0, width, 8); imm_draw_cylinder_fill_3d(pos, width, 0.0, len, 8, 1); - immUnbindProgram(); - if (use_lighting) { glShadeModel(GL_FLAT); } + immUnbindProgram(); } gpuPopMatrix(); + #endif /* USE_MANIPULATOR_CUSTOM_ARROWS */ } } diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c b/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c index e1f52a56e64..844de194845 100644 --- a/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c @@ -66,12 +66,6 @@ #include "manipulator_geometry.h" #include "manipulator_library_intern.h" -#define USE_IMM - -#ifndef USE_IMM -#include <GL/glu.h> -#endif - /* to use custom dials exported to geom_dial_manipulator.c */ // #define USE_MANIPULATOR_CUSTOM_DIAL diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c index b82a7469520..1917c473d94 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c @@ -39,7 +39,8 @@ #include "ED_screen.h" #include "ED_view3d.h" -#include "GL/glew.h" +#include "GPU_batch.h" +#include "GPU_glew.h" #include "MEM_guardedalloc.h" @@ -57,53 +58,58 @@ /** * Main draw call for ManipulatorGeomInfo data */ -void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const bool select) +void wm_manipulator_geometryinfo_draw(const ManipulatorGeomInfo *info, const bool select, const float color[4]) { - GLuint buf[3]; - const bool use_lighting = !select && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0); + /* TODO store the Batches inside the ManipulatorGeomInfo and updated it when geom changes + * So we don't need to re-created and discard it every time */ - if (use_lighting) - glGenBuffers(3, buf); - else - glGenBuffers(2, buf); + const bool use_lighting = true || (!select && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0)); + VertexBuffer *vbo; + ElementList *el; + Batch *batch; + ElementListBuilder elb = {0}; - glEnableClientState(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, buf[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * info->nverts, info->verts, GL_STATIC_DRAW); - glVertexPointer(3, GL_FLOAT, 0, NULL); + VertexFormat format = {0}; + unsigned int pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + unsigned int nor_id; if (use_lighting) { - glEnableClientState(GL_NORMAL_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, buf[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * info->nverts, info->normals, GL_STATIC_DRAW); - glNormalPointer(GL_FLOAT, 0, NULL); - glShadeModel(GL_SMOOTH); + nor_id = VertexFormat_add_attrib(&format, "nor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT); } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf[1]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * (3 * info->ntris), info->indices, GL_STATIC_DRAW); + /* Elements */ + ElementListBuilder_init(&elb, GL_TRIANGLES, info->ntris, info->nverts); + for (int i = 0; i < info->ntris; ++i) { + const unsigned short *idx = &info->indices[i * 3]; + add_triangle_vertices(&elb, idx[0], idx[1], idx[2]); + } + el = ElementList_build(&elb); + + vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, info->nverts); + + VertexBuffer_fill_attrib(vbo, pos_id, info->verts); + + if (use_lighting) { + /* Normals are expected to be smooth. */ + VertexBuffer_fill_attrib(vbo, nor_id, info->normals); + } + + batch = Batch_create(GL_TRIANGLES, vbo, el); + Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR); + + Batch_Uniform4fv(batch, "color", color); glEnable(GL_CULL_FACE); // glEnable(GL_DEPTH_TEST); - glDrawElements(GL_TRIANGLES, info->ntris * 3, GL_UNSIGNED_SHORT, NULL); + Batch_draw(batch); glDisable(GL_DEPTH_TEST); // glDisable(GL_CULL_FACE); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - glDisableClientState(GL_VERTEX_ARRAY); - if (use_lighting) { - glDisableClientState(GL_NORMAL_ARRAY); - glShadeModel(GL_FLAT); - glDeleteBuffers(3, buf); - } - else { - glDeleteBuffers(2, buf); - } + Batch_discard_all(batch); } /* Still unused */ diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h index a1ea4bfc8ae..2acc72afc95 100644 --- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h +++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h @@ -218,7 +218,7 @@ bool wm_manipulatormap_deselect_all(struct wmManipulatorMap *mmap, struct wmMani /* -------------------------------------------------------------------- */ /* Manipulator drawing */ -void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select); +void wm_manipulator_geometryinfo_draw(const struct ManipulatorGeomInfo *info, const bool select, const float color[4]); #endif /* __WM_MANIPULATOR_INTERN_H__ */ |