From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/editors/curve/CMakeLists.txt | 56 +- source/blender/editors/curve/curve_intern.h | 57 +- source/blender/editors/curve/curve_ops.c | 230 +- source/blender/editors/curve/editcurve.c | 12123 +++++++++++----------- source/blender/editors/curve/editcurve_add.c | 1260 +-- source/blender/editors/curve/editcurve_paint.c | 1981 ++-- source/blender/editors/curve/editcurve_select.c | 3271 +++--- source/blender/editors/curve/editcurve_undo.c | 380 +- source/blender/editors/curve/editfont.c | 3180 +++--- source/blender/editors/curve/editfont_undo.c | 394 +- 10 files changed, 11656 insertions(+), 11276 deletions(-) (limited to 'source/blender/editors/curve') diff --git a/source/blender/editors/curve/CMakeLists.txt b/source/blender/editors/curve/CMakeLists.txt index 4ccf8d59e1f..3df6f3c97d4 100644 --- a/source/blender/editors/curve/CMakeLists.txt +++ b/source/blender/editors/curve/CMakeLists.txt @@ -16,46 +16,46 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - ../include - ../../blenkernel - ../../blenlib - ../../blentranslation - ../../depsgraph - ../../gpu - ../../makesdna - ../../makesrna - ../../windowmanager - ../../../../intern/clog - ../../../../intern/guardedalloc - ../../../../intern/glew-mx - ../../../../extern/curve_fit_nd + ../include + ../../blenkernel + ../../blenlib + ../../blentranslation + ../../depsgraph + ../../gpu + ../../makesdna + ../../makesrna + ../../windowmanager + ../../../../intern/clog + ../../../../intern/guardedalloc + ../../../../intern/glew-mx + ../../../../extern/curve_fit_nd ) set(INC_SYS - ${GLEW_INCLUDE_PATH} + ${GLEW_INCLUDE_PATH} ) set(SRC - curve_ops.c - editcurve.c - editcurve_add.c - editcurve_paint.c - editcurve_select.c - editcurve_undo.c - editfont.c - editfont_undo.c - - curve_intern.h + curve_ops.c + editcurve.c + editcurve_add.c + editcurve_paint.c + editcurve_select.c + editcurve_undo.c + editfont.c + editfont_undo.c + + curve_intern.h ) set(LIB - bf_blenkernel - bf_blenlib - extern_curve_fit_nd + bf_blenkernel + bf_blenlib + extern_curve_fit_nd ) if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) endif() add_definitions(${GL_DEFINITIONS}) diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index c741b5393dc..201ba2560dc 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -21,7 +21,6 @@ * \ingroup edcurve */ - #ifndef __CURVE_INTERN_H__ #define __CURVE_INTERN_H__ @@ -34,24 +33,42 @@ struct ViewContext; struct wmOperatorType; /* editfont.c */ -enum { DEL_NEXT_CHAR, DEL_PREV_CHAR, DEL_NEXT_WORD, DEL_PREV_WORD, DEL_SELECTION, DEL_NEXT_SEL, DEL_PREV_SEL }; +enum { + DEL_NEXT_CHAR, + DEL_PREV_CHAR, + DEL_NEXT_WORD, + DEL_PREV_WORD, + DEL_SELECTION, + DEL_NEXT_SEL, + DEL_PREV_SEL +}; enum { CASE_LOWER, CASE_UPPER }; -enum { LINE_BEGIN, LINE_END, PREV_CHAR, NEXT_CHAR, PREV_WORD, NEXT_WORD, - PREV_LINE, NEXT_LINE, PREV_PAGE, NEXT_PAGE }; +enum { + LINE_BEGIN, + LINE_END, + PREV_CHAR, + NEXT_CHAR, + PREV_WORD, + NEXT_WORD, + PREV_LINE, + NEXT_LINE, + PREV_PAGE, + NEXT_PAGE +}; typedef enum eVisible_Types { - HIDDEN = true, - VISIBLE = false, + HIDDEN = true, + VISIBLE = false, } eVisible_Types; typedef enum eEndPoint_Types { - FIRST = true, - LAST = false, + FIRST = true, + LAST = false, } eEndPoint_Types; typedef enum eCurveElem_Types { - CURVE_VERTEX = 0, - CURVE_SEGMENT, + CURVE_VERTEX = 0, + CURVE_SEGMENT, } eCurveElem_Types; /* internal select utils */ @@ -86,7 +103,6 @@ void FONT_OT_unlink(struct wmOperatorType *ot); void FONT_OT_textbox_add(struct wmOperatorType *ot); void FONT_OT_textbox_remove(struct wmOperatorType *ot); - /* editcurve.c */ void CURVE_OT_hide(struct wmOperatorType *ot); void CURVE_OT_reveal(struct wmOperatorType *ot); @@ -124,17 +140,24 @@ void CURVE_OT_match_texture_space(struct wmOperatorType *ot); /* exported for editcurve_undo.c */ struct GHash *ED_curve_keyindex_hash_duplicate(struct GHash *keyindex); -void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu); +void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu); -bool ED_curve_pick_vert( - struct ViewContext *vc, short sel, - struct Nurb **r_nurb, struct BezTriple **r_bezt, struct BPoint **r_bp, short *r_handle, - struct Base **r_base); +bool ED_curve_pick_vert(struct ViewContext *vc, + short sel, + struct Nurb **r_nurb, + struct BezTriple **r_bezt, + struct BPoint **r_bp, + short *r_handle, + struct Base **r_base); /* helper functions */ void ed_editnurb_translate_flag(struct ListBase *editnurb, short flag, const float vec[3]); bool ed_editnurb_extrude_flag(struct EditNurb *editnurb, const short flag); -bool ed_editnurb_spin(float viewmat[4][4], struct View3D *v3d, struct Object *obedit, const float axis[3], const float cent[3]); +bool ed_editnurb_spin(float viewmat[4][4], + struct View3D *v3d, + struct Object *obedit, + const float axis[3], + const float cent[3]); /* editcurve_select.c */ void CURVE_OT_de_select_first(struct wmOperatorType *ot); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index de6fe686356..782b093fab4 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -21,11 +21,9 @@ * \ingroup edcurve */ - #include #include - #include "DNA_curve_types.h" #include "DNA_scene_types.h" @@ -46,125 +44,129 @@ void ED_operatortypes_curve(void) { - WM_operatortype_append(FONT_OT_text_insert); - WM_operatortype_append(FONT_OT_line_break); - - WM_operatortype_append(FONT_OT_case_toggle); - WM_operatortype_append(FONT_OT_case_set); - WM_operatortype_append(FONT_OT_style_toggle); - WM_operatortype_append(FONT_OT_style_set); - - WM_operatortype_append(FONT_OT_select_all); - - WM_operatortype_append(FONT_OT_text_copy); - WM_operatortype_append(FONT_OT_text_cut); - WM_operatortype_append(FONT_OT_text_paste); - WM_operatortype_append(FONT_OT_text_paste_from_file); - - WM_operatortype_append(FONT_OT_move); - WM_operatortype_append(FONT_OT_move_select); - WM_operatortype_append(FONT_OT_delete); - - WM_operatortype_append(FONT_OT_change_character); - WM_operatortype_append(FONT_OT_change_spacing); - - WM_operatortype_append(FONT_OT_open); - WM_operatortype_append(FONT_OT_unlink); - - WM_operatortype_append(FONT_OT_textbox_add); - WM_operatortype_append(FONT_OT_textbox_remove); - - WM_operatortype_append(CURVE_OT_hide); - WM_operatortype_append(CURVE_OT_reveal); - - WM_operatortype_append(CURVE_OT_separate); - WM_operatortype_append(CURVE_OT_split); - WM_operatortype_append(CURVE_OT_duplicate); - WM_operatortype_append(CURVE_OT_delete); - WM_operatortype_append(CURVE_OT_dissolve_verts); - - WM_operatortype_append(CURVE_OT_spline_type_set); - WM_operatortype_append(CURVE_OT_radius_set); - WM_operatortype_append(CURVE_OT_spline_weight_set); - WM_operatortype_append(CURVE_OT_handle_type_set); - WM_operatortype_append(CURVE_OT_normals_make_consistent); - WM_operatortype_append(CURVE_OT_decimate); - WM_operatortype_append(CURVE_OT_shade_smooth); - WM_operatortype_append(CURVE_OT_shade_flat); - WM_operatortype_append(CURVE_OT_tilt_clear); - - WM_operatortype_append(CURVE_OT_primitive_bezier_curve_add); - WM_operatortype_append(CURVE_OT_primitive_bezier_circle_add); - WM_operatortype_append(CURVE_OT_primitive_nurbs_curve_add); - WM_operatortype_append(CURVE_OT_primitive_nurbs_circle_add); - WM_operatortype_append(CURVE_OT_primitive_nurbs_path_add); - - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_curve_add); - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_circle_add); - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_surface_add); - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_cylinder_add); - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_sphere_add); - WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add); - - WM_operatortype_append(CURVE_OT_smooth); - WM_operatortype_append(CURVE_OT_smooth_weight); - WM_operatortype_append(CURVE_OT_smooth_radius); - WM_operatortype_append(CURVE_OT_smooth_tilt); - - WM_operatortype_append(CURVE_OT_de_select_first); - WM_operatortype_append(CURVE_OT_de_select_last); - WM_operatortype_append(CURVE_OT_select_all); - WM_operatortype_append(CURVE_OT_select_linked); - WM_operatortype_append(CURVE_OT_select_linked_pick); - WM_operatortype_append(CURVE_OT_select_row); - WM_operatortype_append(CURVE_OT_select_next); - WM_operatortype_append(CURVE_OT_select_previous); - WM_operatortype_append(CURVE_OT_select_more); - WM_operatortype_append(CURVE_OT_select_less); - WM_operatortype_append(CURVE_OT_select_random); - WM_operatortype_append(CURVE_OT_select_nth); - WM_operatortype_append(CURVE_OT_select_similar); - WM_operatortype_append(CURVE_OT_shortest_path_pick); - - WM_operatortype_append(CURVE_OT_switch_direction); - WM_operatortype_append(CURVE_OT_subdivide); - WM_operatortype_append(CURVE_OT_make_segment); - WM_operatortype_append(CURVE_OT_spin); - WM_operatortype_append(CURVE_OT_vertex_add); - WM_operatortype_append(CURVE_OT_draw); - WM_operatortype_append(CURVE_OT_extrude); - WM_operatortype_append(CURVE_OT_cyclic_toggle); - - WM_operatortype_append(CURVE_OT_match_texture_space); + WM_operatortype_append(FONT_OT_text_insert); + WM_operatortype_append(FONT_OT_line_break); + + WM_operatortype_append(FONT_OT_case_toggle); + WM_operatortype_append(FONT_OT_case_set); + WM_operatortype_append(FONT_OT_style_toggle); + WM_operatortype_append(FONT_OT_style_set); + + WM_operatortype_append(FONT_OT_select_all); + + WM_operatortype_append(FONT_OT_text_copy); + WM_operatortype_append(FONT_OT_text_cut); + WM_operatortype_append(FONT_OT_text_paste); + WM_operatortype_append(FONT_OT_text_paste_from_file); + + WM_operatortype_append(FONT_OT_move); + WM_operatortype_append(FONT_OT_move_select); + WM_operatortype_append(FONT_OT_delete); + + WM_operatortype_append(FONT_OT_change_character); + WM_operatortype_append(FONT_OT_change_spacing); + + WM_operatortype_append(FONT_OT_open); + WM_operatortype_append(FONT_OT_unlink); + + WM_operatortype_append(FONT_OT_textbox_add); + WM_operatortype_append(FONT_OT_textbox_remove); + + WM_operatortype_append(CURVE_OT_hide); + WM_operatortype_append(CURVE_OT_reveal); + + WM_operatortype_append(CURVE_OT_separate); + WM_operatortype_append(CURVE_OT_split); + WM_operatortype_append(CURVE_OT_duplicate); + WM_operatortype_append(CURVE_OT_delete); + WM_operatortype_append(CURVE_OT_dissolve_verts); + + WM_operatortype_append(CURVE_OT_spline_type_set); + WM_operatortype_append(CURVE_OT_radius_set); + WM_operatortype_append(CURVE_OT_spline_weight_set); + WM_operatortype_append(CURVE_OT_handle_type_set); + WM_operatortype_append(CURVE_OT_normals_make_consistent); + WM_operatortype_append(CURVE_OT_decimate); + WM_operatortype_append(CURVE_OT_shade_smooth); + WM_operatortype_append(CURVE_OT_shade_flat); + WM_operatortype_append(CURVE_OT_tilt_clear); + + WM_operatortype_append(CURVE_OT_primitive_bezier_curve_add); + WM_operatortype_append(CURVE_OT_primitive_bezier_circle_add); + WM_operatortype_append(CURVE_OT_primitive_nurbs_curve_add); + WM_operatortype_append(CURVE_OT_primitive_nurbs_circle_add); + WM_operatortype_append(CURVE_OT_primitive_nurbs_path_add); + + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_curve_add); + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_circle_add); + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_surface_add); + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_cylinder_add); + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_sphere_add); + WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add); + + WM_operatortype_append(CURVE_OT_smooth); + WM_operatortype_append(CURVE_OT_smooth_weight); + WM_operatortype_append(CURVE_OT_smooth_radius); + WM_operatortype_append(CURVE_OT_smooth_tilt); + + WM_operatortype_append(CURVE_OT_de_select_first); + WM_operatortype_append(CURVE_OT_de_select_last); + WM_operatortype_append(CURVE_OT_select_all); + WM_operatortype_append(CURVE_OT_select_linked); + WM_operatortype_append(CURVE_OT_select_linked_pick); + WM_operatortype_append(CURVE_OT_select_row); + WM_operatortype_append(CURVE_OT_select_next); + WM_operatortype_append(CURVE_OT_select_previous); + WM_operatortype_append(CURVE_OT_select_more); + WM_operatortype_append(CURVE_OT_select_less); + WM_operatortype_append(CURVE_OT_select_random); + WM_operatortype_append(CURVE_OT_select_nth); + WM_operatortype_append(CURVE_OT_select_similar); + WM_operatortype_append(CURVE_OT_shortest_path_pick); + + WM_operatortype_append(CURVE_OT_switch_direction); + WM_operatortype_append(CURVE_OT_subdivide); + WM_operatortype_append(CURVE_OT_make_segment); + WM_operatortype_append(CURVE_OT_spin); + WM_operatortype_append(CURVE_OT_vertex_add); + WM_operatortype_append(CURVE_OT_draw); + WM_operatortype_append(CURVE_OT_extrude); + WM_operatortype_append(CURVE_OT_cyclic_toggle); + + WM_operatortype_append(CURVE_OT_match_texture_space); } void ED_operatormacros_curve(void) { - wmOperatorType *ot; - wmOperatorTypeMacro *otmacro; - - ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move", "Add Duplicate", "Duplicate curve and move", - OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "CURVE_OT_duplicate"); - otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - RNA_enum_set(otmacro->ptr, "proportional", 0); - RNA_boolean_set(otmacro->ptr, "mirror", false); - - ot = WM_operatortype_append_macro("CURVE_OT_extrude_move", "Extrude Curve and Move", - "Extrude curve and move result", OPTYPE_UNDO | OPTYPE_REGISTER); - WM_operatortype_macro_define(ot, "CURVE_OT_extrude"); - otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); - RNA_enum_set(otmacro->ptr, "proportional", 0); - RNA_boolean_set(otmacro->ptr, "mirror", false); + wmOperatorType *ot; + wmOperatorTypeMacro *otmacro; + + ot = WM_operatortype_append_macro("CURVE_OT_duplicate_move", + "Add Duplicate", + "Duplicate curve and move", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "CURVE_OT_duplicate"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); + + ot = WM_operatortype_append_macro("CURVE_OT_extrude_move", + "Extrude Curve and Move", + "Extrude curve and move result", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "CURVE_OT_extrude"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", false); } void ED_keymap_curve(wmKeyConfig *keyconf) { - /* only set in editmode font, by space_view3d listener */ - wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", 0, 0); - keymap->poll = ED_operator_editfont; + /* only set in editmode font, by space_view3d listener */ + wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Font", 0, 0); + keymap->poll = ED_operator_editfont; - /* only set in editmode curve, by space_view3d listener */ - keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0); - keymap->poll = ED_operator_editsurfcurve; + /* only set in editmode curve, by space_view3d listener */ + keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0); + keymap->poll = ED_operator_editsurfcurve; } diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 4aaf0dc2a2f..c37ce4cc89d 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -77,17 +77,18 @@ #include "RNA_enum_types.h" void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus); -static void adduplicateflagNurb(Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split); +static void adduplicateflagNurb( + Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split); static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split); static bool curve_delete_vertices(Object *obedit, View3D *v3d); ListBase *object_editcurve_get(Object *ob) { - if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; - return &cu->editnurb->nurbs; - } - return NULL; + if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) { + Curve *cu = ob->data; + return &cu->editnurb->nurbs; + } + return NULL; } /* ******************* PRINTS ********************* */ @@ -95,2725 +96,2741 @@ ListBase *object_editcurve_get(Object *ob) #if 0 void printknots(Object *obedit) { - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - int a, num; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(nu) && nu->type == CU_NURBS) { - if (nu->knotsu) { - num = KNOTSU(nu); - for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]); - } - if (nu->knotsv) { - num = KNOTSV(nu); - for (a = 0; a < num; a++) printf("knotv %d: %f\n", a, nu->knotsv[a]); - } - } - } + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + int a, num; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(nu) && nu->type == CU_NURBS) { + if (nu->knotsu) { + num = KNOTSU(nu); + for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]); + } + if (nu->knotsv) { + num = KNOTSV(nu); + for (a = 0; a < num; a++) printf("knotv %d: %f\n", a, nu->knotsv[a]); + } + } + } } #endif /* ********************* Shape keys *************** */ -static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index) +static CVKeyIndex *init_cvKeyIndex( + void *cv, int key_index, int nu_index, int pt_index, int vertex_index) { - CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__); + CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__); - cvIndex->orig_cv = cv; - cvIndex->key_index = key_index; - cvIndex->nu_index = nu_index; - cvIndex->pt_index = pt_index; - cvIndex->vertex_index = vertex_index; - cvIndex->switched = false; + cvIndex->orig_cv = cv; + cvIndex->key_index = key_index; + cvIndex->nu_index = nu_index; + cvIndex->pt_index = pt_index; + cvIndex->vertex_index = vertex_index; + cvIndex->switched = false; - return cvIndex; + return cvIndex; } static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase) { - Nurb *nu = editnurb->nurbs.first; - Nurb *orignu = origBase->first; - GHash *gh; - BezTriple *bezt, *origbezt; - BPoint *bp, *origbp; - CVKeyIndex *keyIndex; - int a, key_index = 0, nu_index = 0, pt_index = 0, vertex_index = 0; - - if (editnurb->keyindex) { - return; - } - - gh = BLI_ghash_ptr_new("editNurb keyIndex"); - - while (orignu) { - if (orignu->bezt) { - a = orignu->pntsu; - bezt = nu->bezt; - origbezt = orignu->bezt; - pt_index = 0; - while (a--) { - /* We cannot keep *any* reference to curve obdata, - * it might be replaced and freed while editcurve remain in use - * (in viewport render case e.g.). Note that we could use a pool to avoid - * lots of malloc's here, but... not really a problem for now. */ - BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__); - *origbezt_cpy = *origbezt; - keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index); - BLI_ghash_insert(gh, bezt, keyIndex); - key_index += KEYELEM_FLOAT_LEN_BEZTRIPLE; - vertex_index += 3; - bezt++; - origbezt++; - pt_index++; - } - } - else { - a = orignu->pntsu * orignu->pntsv; - bp = nu->bp; - origbp = orignu->bp; - pt_index = 0; - while (a--) { - /* We cannot keep *any* reference to curve obdata, - * it might be replaced and freed while editcurve remain in use - * (in viewport render case e.g.). Note that we could use a pool to avoid - * lots of malloc's here, but... not really a problem for now. */ - BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__); - *origbp_cpy = *origbp; - keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index); - BLI_ghash_insert(gh, bp, keyIndex); - key_index += KEYELEM_FLOAT_LEN_BPOINT; - bp++; - origbp++; - pt_index++; - vertex_index++; - } - } - - nu = nu->next; - orignu = orignu->next; - nu_index++; - } - - editnurb->keyindex = gh; + Nurb *nu = editnurb->nurbs.first; + Nurb *orignu = origBase->first; + GHash *gh; + BezTriple *bezt, *origbezt; + BPoint *bp, *origbp; + CVKeyIndex *keyIndex; + int a, key_index = 0, nu_index = 0, pt_index = 0, vertex_index = 0; + + if (editnurb->keyindex) { + return; + } + + gh = BLI_ghash_ptr_new("editNurb keyIndex"); + + while (orignu) { + if (orignu->bezt) { + a = orignu->pntsu; + bezt = nu->bezt; + origbezt = orignu->bezt; + pt_index = 0; + while (a--) { + /* We cannot keep *any* reference to curve obdata, + * it might be replaced and freed while editcurve remain in use + * (in viewport render case e.g.). Note that we could use a pool to avoid + * lots of malloc's here, but... not really a problem for now. */ + BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__); + *origbezt_cpy = *origbezt; + keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index); + BLI_ghash_insert(gh, bezt, keyIndex); + key_index += KEYELEM_FLOAT_LEN_BEZTRIPLE; + vertex_index += 3; + bezt++; + origbezt++; + pt_index++; + } + } + else { + a = orignu->pntsu * orignu->pntsv; + bp = nu->bp; + origbp = orignu->bp; + pt_index = 0; + while (a--) { + /* We cannot keep *any* reference to curve obdata, + * it might be replaced and freed while editcurve remain in use + * (in viewport render case e.g.). Note that we could use a pool to avoid + * lots of malloc's here, but... not really a problem for now. */ + BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__); + *origbp_cpy = *origbp; + keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index); + BLI_ghash_insert(gh, bp, keyIndex); + key_index += KEYELEM_FLOAT_LEN_BPOINT; + bp++; + origbp++; + pt_index++; + vertex_index++; + } + } + + nu = nu->next; + orignu = orignu->next; + nu_index++; + } + + editnurb->keyindex = gh; } static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, const void *cv) { - return BLI_ghash_lookup(editnurb->keyindex, cv); + return BLI_ghash_lookup(editnurb->keyindex, cv); } static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, const void *cv) { - return BLI_ghash_popkey(editnurb->keyindex, cv, NULL); + return BLI_ghash_popkey(editnurb->keyindex, cv, NULL); } static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, const BezTriple *bezt) { - CVKeyIndex *index = getCVKeyIndex(editnurb, bezt); + CVKeyIndex *index = getCVKeyIndex(editnurb, bezt); - if (!index) { - return NULL; - } + if (!index) { + return NULL; + } - return (BezTriple *)index->orig_cv; + return (BezTriple *)index->orig_cv; } static BPoint *getKeyIndexOrig_bp(EditNurb *editnurb, BPoint *bp) { - CVKeyIndex *index = getCVKeyIndex(editnurb, bp); + CVKeyIndex *index = getCVKeyIndex(editnurb, bp); - if (!index) { - return NULL; - } + if (!index) { + return NULL; + } - return (BPoint *)index->orig_cv; + return (BPoint *)index->orig_cv; } static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv) { - CVKeyIndex *index = getCVKeyIndex(editnurb, cv); + CVKeyIndex *index = getCVKeyIndex(editnurb, cv); - if (!index) { - return -1; - } + if (!index) { + return -1; + } - return index->key_index; + return index->key_index; } static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt) { - if (!editnurb->keyindex) { - return; - } + if (!editnurb->keyindex) { + return; + } - BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt); + BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt); } static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp) { - if (!editnurb->keyindex) { - return; - } + if (!editnurb->keyindex) { + return; + } - BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp); + BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp); } static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu) { - int a; + int a; - if (!editnurb->keyindex) { - return; - } + if (!editnurb->keyindex) { + return; + } - if (nu->bezt) { - const BezTriple *bezt = nu->bezt; - a = nu->pntsu; + if (nu->bezt) { + const BezTriple *bezt = nu->bezt; + a = nu->pntsu; - while (a--) { - BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt); - bezt++; - } - } - else { - const BPoint *bp = nu->bp; - a = nu->pntsu * nu->pntsv; + while (a--) { + BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt); + bezt++; + } + } + else { + const BPoint *bp = nu->bp; + a = nu->pntsu * nu->pntsv; - while (a--) { - BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp); - bp++; - } - } + while (a--) { + BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp); + bp++; + } + } } static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase) { - Nurb *nu = nubase->first; + Nurb *nu = nubase->first; - while (nu) { - keyIndex_delNurb(editnurb, nu); + while (nu) { + keyIndex_delNurb(editnurb, nu); - nu = nu->next; - } + nu = nu->next; + } } -static void keyIndex_updateCV(EditNurb *editnurb, char *cv, - char *newcv, int count, int size) +static void keyIndex_updateCV(EditNurb *editnurb, char *cv, char *newcv, int count, int size) { - int i; - CVKeyIndex *index; + int i; + CVKeyIndex *index; - if (editnurb->keyindex == NULL) { - /* No shape keys - updating not needed */ - return; - } + if (editnurb->keyindex == NULL) { + /* No shape keys - updating not needed */ + return; + } - for (i = 0; i < count; i++) { - index = popCVKeyIndex(editnurb, cv); + for (i = 0; i < count; i++) { + index = popCVKeyIndex(editnurb, cv); - if (index) { - BLI_ghash_insert(editnurb->keyindex, newcv, index); - } + if (index) { + BLI_ghash_insert(editnurb->keyindex, newcv, index); + } - newcv += size; - cv += size; - } + newcv += size; + cv += size; + } } -static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt, - BezTriple *newbezt, int count) +static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt, BezTriple *newbezt, int count) { - keyIndex_updateCV(editnurb, (char *)bezt, (char *)newbezt, count, sizeof(BezTriple)); + keyIndex_updateCV(editnurb, (char *)bezt, (char *)newbezt, count, sizeof(BezTriple)); } -static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp, - BPoint *newbp, int count) +static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp, BPoint *newbp, int count) { - keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint)); + keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint)); } void ED_curve_keyindex_update_nurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu) { - if (nu->bezt) { - keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu); - } - else { - keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv); - } + if (nu->bezt) { + keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu); + } + else { + keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv); + } } static void keyIndex_swap(EditNurb *editnurb, void *a, void *b) { - CVKeyIndex *index1 = popCVKeyIndex(editnurb, a); - CVKeyIndex *index2 = popCVKeyIndex(editnurb, b); + CVKeyIndex *index1 = popCVKeyIndex(editnurb, a); + CVKeyIndex *index2 = popCVKeyIndex(editnurb, b); - if (index2) { - BLI_ghash_insert(editnurb->keyindex, a, index2); - } - if (index1) { - BLI_ghash_insert(editnurb->keyindex, b, index1); - } + if (index2) { + BLI_ghash_insert(editnurb->keyindex, a, index2); + } + if (index1) { + BLI_ghash_insert(editnurb->keyindex, b, index1); + } } static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu) { - int a; - CVKeyIndex *index1, *index2; + int a; + CVKeyIndex *index1, *index2; - if (nu->bezt) { - BezTriple *bezt1, *bezt2; + if (nu->bezt) { + BezTriple *bezt1, *bezt2; - a = nu->pntsu; + a = nu->pntsu; - bezt1 = nu->bezt; - bezt2 = bezt1 + (a - 1); + bezt1 = nu->bezt; + bezt2 = bezt1 + (a - 1); - if (a & 1) { - a++; - } + if (a & 1) { + a++; + } - a /= 2; + a /= 2; - while (a--) { - index1 = getCVKeyIndex(editnurb, bezt1); - index2 = getCVKeyIndex(editnurb, bezt2); + while (a--) { + index1 = getCVKeyIndex(editnurb, bezt1); + index2 = getCVKeyIndex(editnurb, bezt2); - if (index1) { - index1->switched = !index1->switched; - } + if (index1) { + index1->switched = !index1->switched; + } - if (bezt1 != bezt2) { - keyIndex_swap(editnurb, bezt1, bezt2); + if (bezt1 != bezt2) { + keyIndex_swap(editnurb, bezt1, bezt2); - if (index2) { - index2->switched = !index2->switched; - } - } + if (index2) { + index2->switched = !index2->switched; + } + } - bezt1++; - bezt2--; - } - } - else { - BPoint *bp1, *bp2; + bezt1++; + bezt2--; + } + } + else { + BPoint *bp1, *bp2; - if (nu->pntsv == 1) { - a = nu->pntsu; - bp1 = nu->bp; - bp2 = bp1 + (a - 1); - a /= 2; - while (bp1 != bp2 && a > 0) { - index1 = getCVKeyIndex(editnurb, bp1); - index2 = getCVKeyIndex(editnurb, bp2); + if (nu->pntsv == 1) { + a = nu->pntsu; + bp1 = nu->bp; + bp2 = bp1 + (a - 1); + a /= 2; + while (bp1 != bp2 && a > 0) { + index1 = getCVKeyIndex(editnurb, bp1); + index2 = getCVKeyIndex(editnurb, bp2); - if (index1) { - index1->switched = !index1->switched; - } + if (index1) { + index1->switched = !index1->switched; + } - if (bp1 != bp2) { - if (index2) { - index2->switched = !index2->switched; - } + if (bp1 != bp2) { + if (index2) { + index2->switched = !index2->switched; + } - keyIndex_swap(editnurb, bp1, bp2); - } + keyIndex_swap(editnurb, bp1, bp2); + } - a--; - bp1++; - bp2--; - } - } - else { - int b; + a--; + bp1++; + bp2--; + } + } + else { + int b; - for (b = 0; b < nu->pntsv; b++) { + for (b = 0; b < nu->pntsv; b++) { - bp1 = &nu->bp[b * nu->pntsu]; - a = nu->pntsu; - bp2 = bp1 + (a - 1); - a /= 2; + bp1 = &nu->bp[b * nu->pntsu]; + a = nu->pntsu; + bp2 = bp1 + (a - 1); + a /= 2; - while (bp1 != bp2 && a > 0) { - index1 = getCVKeyIndex(editnurb, bp1); - index2 = getCVKeyIndex(editnurb, bp2); + while (bp1 != bp2 && a > 0) { + index1 = getCVKeyIndex(editnurb, bp1); + index2 = getCVKeyIndex(editnurb, bp2); - if (index1) { - index1->switched = !index1->switched; - } + if (index1) { + index1->switched = !index1->switched; + } - if (bp1 != bp2) { - if (index2) { - index2->switched = !index2->switched; - } + if (bp1 != bp2) { + if (index2) { + index2->switched = !index2->switched; + } - keyIndex_swap(editnurb, bp1, bp2); - } + keyIndex_swap(editnurb, bp1, bp2); + } - a--; - bp1++; - bp2--; - } - } - - } - } + a--; + bp1++; + bp2--; + } + } + } + } } static void switch_keys_direction(Curve *cu, Nurb *actnu) { - KeyBlock *currkey; - EditNurb *editnurb = cu->editnurb; - ListBase *nubase = &editnurb->nurbs; - Nurb *nu; - float *fp; - int a; - - currkey = cu->key->block.first; - while (currkey) { - fp = currkey->data; - - nu = nubase->first; - while (nu) { - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - a = nu->pntsu; - if (nu == actnu) { - while (a--) { - if (getKeyIndexOrig_bezt(editnurb, bezt)) { - swap_v3_v3(fp, fp + 6); - *(fp + 9) = -*(fp + 9); - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - bezt++; - } - } - else { - fp += a * KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - } - else { - BPoint *bp = nu->bp; - a = nu->pntsu * nu->pntsv; - if (nu == actnu) { - while (a--) { - if (getKeyIndexOrig_bp(editnurb, bp)) { - *(fp + 3) = -*(fp + 3); - fp += KEYELEM_FLOAT_LEN_BPOINT; - } - bp++; - } - } - else { - fp += a * KEYELEM_FLOAT_LEN_BPOINT; - } - } - - nu = nu->next; - } - - currkey = currkey->next; - } + KeyBlock *currkey; + EditNurb *editnurb = cu->editnurb; + ListBase *nubase = &editnurb->nurbs; + Nurb *nu; + float *fp; + int a; + + currkey = cu->key->block.first; + while (currkey) { + fp = currkey->data; + + nu = nubase->first; + while (nu) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + a = nu->pntsu; + if (nu == actnu) { + while (a--) { + if (getKeyIndexOrig_bezt(editnurb, bezt)) { + swap_v3_v3(fp, fp + 6); + *(fp + 9) = -*(fp + 9); + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + bezt++; + } + } + else { + fp += a * KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + } + else { + BPoint *bp = nu->bp; + a = nu->pntsu * nu->pntsv; + if (nu == actnu) { + while (a--) { + if (getKeyIndexOrig_bp(editnurb, bp)) { + *(fp + 3) = -*(fp + 3); + fp += KEYELEM_FLOAT_LEN_BPOINT; + } + bp++; + } + } + else { + fp += a * KEYELEM_FLOAT_LEN_BPOINT; + } + } + + nu = nu->next; + } + + currkey = currkey->next; + } } static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu) { - EditNurb *editnurb = cu->editnurb; + EditNurb *editnurb = cu->editnurb; - if (!editnurb->keyindex) { - /* no shape keys - nothing to do */ - return; - } + if (!editnurb->keyindex) { + /* no shape keys - nothing to do */ + return; + } - keyIndex_switchDirection(editnurb, nu); - if (cu->key) { - switch_keys_direction(cu, nu); - } + keyIndex_switchDirection(editnurb, nu); + if (cu->key) { + switch_keys_direction(cu, nu); + } } GHash *ED_curve_keyindex_hash_duplicate(GHash *keyindex) { - GHash *gh; - GHashIterator gh_iter; + GHash *gh; + GHashIterator gh_iter; - gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_len(keyindex)); + gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_len(keyindex)); - GHASH_ITER (gh_iter, keyindex) { - void *cv = BLI_ghashIterator_getKey(&gh_iter); - CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter); - CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index"); + GHASH_ITER (gh_iter, keyindex) { + void *cv = BLI_ghashIterator_getKey(&gh_iter); + CVKeyIndex *index = BLI_ghashIterator_getValue(&gh_iter); + CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index"); - memcpy(newIndex, index, sizeof(CVKeyIndex)); - newIndex->orig_cv = MEM_dupallocN(index->orig_cv); + memcpy(newIndex, index, sizeof(CVKeyIndex)); + newIndex->orig_cv = MEM_dupallocN(index->orig_cv); - BLI_ghash_insert(gh, cv, newIndex); - } + BLI_ghash_insert(gh, cv, newIndex); + } - return gh; + return gh; } static void key_to_bezt(float *key, BezTriple *basebezt, BezTriple *bezt) { - memcpy(bezt, basebezt, sizeof(BezTriple)); - memcpy(bezt->vec, key, sizeof(float) * 9); - bezt->tilt = key[9]; - bezt->radius = key[10]; + memcpy(bezt, basebezt, sizeof(BezTriple)); + memcpy(bezt->vec, key, sizeof(float) * 9); + bezt->tilt = key[9]; + bezt->radius = key[10]; } static void bezt_to_key(BezTriple *bezt, float *key) { - memcpy(key, bezt->vec, sizeof(float) * 9); - key[9] = bezt->tilt; - key[10] = bezt->radius; + memcpy(key, bezt->vec, sizeof(float) * 9); + key[9] = bezt->tilt; + key[10] = bezt->radius; } static void calc_keyHandles(ListBase *nurb, float *key) { - Nurb *nu; - int a; - float *fp = key; - BezTriple *bezt; - - nu = nurb->first; - while (nu) { - if (nu->bezt) { - BezTriple *prevp, *nextp; - BezTriple cur, prev, next; - float *startfp, *prevfp, *nextfp; - - bezt = nu->bezt; - a = nu->pntsu; - startfp = fp; - - if (nu->flagu & CU_NURB_CYCLIC) { - prevp = bezt + (a - 1); - prevfp = fp + (KEYELEM_FLOAT_LEN_BEZTRIPLE * (a - 1)); - } - else { - prevp = NULL; - prevfp = NULL; - } - - nextp = bezt + 1; - nextfp = fp + KEYELEM_FLOAT_LEN_BEZTRIPLE; - - while (a--) { - key_to_bezt(fp, bezt, &cur); - - if (nextp) { - key_to_bezt(nextfp, nextp, &next); - } - if (prevp) { - key_to_bezt(prevfp, prevp, &prev); - } - - BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0, 0); - bezt_to_key(&cur, fp); - - prevp = bezt; - prevfp = fp; - if (a == 1) { - if (nu->flagu & CU_NURB_CYCLIC) { - nextp = nu->bezt; - nextfp = startfp; - } - else { - nextp = NULL; - nextfp = NULL; - } - } - else { - nextp++; - nextfp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - - bezt++; - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - } - else { - a = nu->pntsu * nu->pntsv; - fp += a * KEYELEM_FLOAT_LEN_BPOINT; - } - - nu = nu->next; - } + Nurb *nu; + int a; + float *fp = key; + BezTriple *bezt; + + nu = nurb->first; + while (nu) { + if (nu->bezt) { + BezTriple *prevp, *nextp; + BezTriple cur, prev, next; + float *startfp, *prevfp, *nextfp; + + bezt = nu->bezt; + a = nu->pntsu; + startfp = fp; + + if (nu->flagu & CU_NURB_CYCLIC) { + prevp = bezt + (a - 1); + prevfp = fp + (KEYELEM_FLOAT_LEN_BEZTRIPLE * (a - 1)); + } + else { + prevp = NULL; + prevfp = NULL; + } + + nextp = bezt + 1; + nextfp = fp + KEYELEM_FLOAT_LEN_BEZTRIPLE; + + while (a--) { + key_to_bezt(fp, bezt, &cur); + + if (nextp) { + key_to_bezt(nextfp, nextp, &next); + } + if (prevp) { + key_to_bezt(prevfp, prevp, &prev); + } + + BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0, 0); + bezt_to_key(&cur, fp); + + prevp = bezt; + prevfp = fp; + if (a == 1) { + if (nu->flagu & CU_NURB_CYCLIC) { + nextp = nu->bezt; + nextfp = startfp; + } + else { + nextp = NULL; + nextfp = NULL; + } + } + else { + nextp++; + nextfp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + + bezt++; + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + } + else { + a = nu->pntsu * nu->pntsv; + fp += a * KEYELEM_FLOAT_LEN_BPOINT; + } + + nu = nu->next; + } } static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) { - Curve *cu = (Curve *)obedit->data; - - /* are there keys? */ - if (cu->key) { - int a, i; - EditNurb *editnurb = cu->editnurb; - KeyBlock *currkey; - KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1); - BezTriple *bezt, *oldbezt; - BPoint *bp, *oldbp; - Nurb *nu, *newnu; - int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs); - - float (*ofs)[3] = NULL; - float *oldkey, *newkey, *ofp; - - /* editing the base key should update others */ - if (cu->key->type == KEY_RELATIVE) { - if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */ - int totvec = 0; - - /* Calculate needed memory to store offset */ - nu = editnurb->nurbs.first; - while (nu) { - if (nu->bezt) { - /* Three vects to store handles and one for tilt. */ - totvec += nu->pntsu * 4; - } - else { - totvec += 2 * nu->pntsu * nu->pntsv; - } - - nu = nu->next; - } - - ofs = MEM_callocN(sizeof(float) * 3 * totvec, "currkey->data"); - nu = editnurb->nurbs.first; - i = 0; - while (nu) { - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); - - if (oldbezt) { - int j; - for (j = 0; j < 3; ++j) { - sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]); - i++; - } - ofs[i][0] = bezt->tilt - oldbezt->tilt; - ofs[i][1] = bezt->radius - oldbezt->radius; - i++; - } - else { - i += 4; - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - oldbp = getKeyIndexOrig_bp(editnurb, bp); - if (oldbp) { - sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec); - ofs[i + 1][0] = bp->tilt - oldbp->tilt; - ofs[i + 1][1] = bp->radius - oldbp->radius; - } - i += 2; - bp++; - } - } - - nu = nu->next; - } - } - } - - currkey = cu->key->block.first; - while (currkey) { - const bool apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative)); - - float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); - ofp = oldkey = currkey->data; - - nu = editnurb->nurbs.first; - /* We need to restore to original curve into newnurb, *not* editcurve's nurbs. - * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would - * invalidate editcurve. */ - newnu = newnurbs->first; - i = 0; - while (nu) { - if (currkey == actkey) { - const bool restore = actkey != cu->key->refkey; - - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - BezTriple *newbezt = newnu->bezt; - while (a--) { - int j; - oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); - - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], bezt->vec[j]); - - if (restore && oldbezt) { - copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]); - } - } - fp[9] = bezt->tilt; - fp[10] = bezt->radius; - - if (restore && oldbezt) { - newbezt->tilt = oldbezt->tilt; - newbezt->radius = oldbezt->radius; - } - - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - i++; - bezt++; - newbezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - BPoint *newbp = newnu->bp; - while (a--) { - oldbp = getKeyIndexOrig_bp(editnurb, bp); - - copy_v3_v3(fp, bp->vec); - - fp[3] = bp->tilt; - fp[4] = bp->radius; - - if (restore && oldbp) { - copy_v3_v3(newbp->vec, oldbp->vec); - newbp->tilt = oldbp->tilt; - newbp->radius = oldbp->radius; - } - - fp += KEYELEM_FLOAT_LEN_BPOINT; - bp++; - newbp++; - i += 2; - } - } - } - else { - int index; - const float *curofp; - - if (oldkey) { - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - - while (a--) { - index = getKeyIndexOrig_keyIndex(editnurb, bezt); - if (index >= 0) { - int j; - curofp = ofp + index; - - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], &curofp[j * 3]); - - if (apply_offset) { - add_v3_v3(&fp[j * 3], ofs[i]); - } - } - fp[9] = curofp[9]; - fp[10] = curofp[10]; - - if (apply_offset) { - /* Apply tilt offsets. */ - add_v3_v3(fp + 9, ofs[i]); - i++; - } - - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - else { - int j; - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], bezt->vec[j]); - } - fp[9] = bezt->tilt; - fp[10] = bezt->radius; - - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - index = getKeyIndexOrig_keyIndex(editnurb, bp); - - if (index >= 0) { - curofp = ofp + index; - copy_v3_v3(fp, curofp); - fp[3] = curofp[3]; - fp[4] = curofp[4]; - - if (apply_offset) { - add_v3_v3(fp, ofs[i]); - add_v3_v3(&fp[3], ofs[i + 1]); - } - } - else { - copy_v3_v3(fp, bp->vec); - fp[3] = bp->tilt; - fp[4] = bp->radius; - } - - fp += KEYELEM_FLOAT_LEN_BPOINT; - bp++; - i += 2; - } - } - } - } - - nu = nu->next; - newnu = newnu->next; - } - - if (apply_offset) { - /* handles could become malicious after offsets applying */ - calc_keyHandles(&editnurb->nurbs, newkey); - } - - currkey->totelem = totvert; - if (currkey->data) { - MEM_freeN(currkey->data); - } - currkey->data = newkey; - - currkey = currkey->next; - } - - if (ofs) { - MEM_freeN(ofs); - } - } + Curve *cu = (Curve *)obedit->data; + + /* are there keys? */ + if (cu->key) { + int a, i; + EditNurb *editnurb = cu->editnurb; + KeyBlock *currkey; + KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1); + BezTriple *bezt, *oldbezt; + BPoint *bp, *oldbp; + Nurb *nu, *newnu; + int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs); + + float(*ofs)[3] = NULL; + float *oldkey, *newkey, *ofp; + + /* editing the base key should update others */ + if (cu->key->type == KEY_RELATIVE) { + if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */ + int totvec = 0; + + /* Calculate needed memory to store offset */ + nu = editnurb->nurbs.first; + while (nu) { + if (nu->bezt) { + /* Three vects to store handles and one for tilt. */ + totvec += nu->pntsu * 4; + } + else { + totvec += 2 * nu->pntsu * nu->pntsv; + } + + nu = nu->next; + } + + ofs = MEM_callocN(sizeof(float) * 3 * totvec, "currkey->data"); + nu = editnurb->nurbs.first; + i = 0; + while (nu) { + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); + + if (oldbezt) { + int j; + for (j = 0; j < 3; ++j) { + sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]); + i++; + } + ofs[i][0] = bezt->tilt - oldbezt->tilt; + ofs[i][1] = bezt->radius - oldbezt->radius; + i++; + } + else { + i += 4; + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + oldbp = getKeyIndexOrig_bp(editnurb, bp); + if (oldbp) { + sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec); + ofs[i + 1][0] = bp->tilt - oldbp->tilt; + ofs[i + 1][1] = bp->radius - oldbp->radius; + } + i += 2; + bp++; + } + } + + nu = nu->next; + } + } + } + + currkey = cu->key->block.first; + while (currkey) { + const bool apply_offset = (ofs && (currkey != actkey) && + (editnurb->shapenr - 1 == currkey->relative)); + + float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); + ofp = oldkey = currkey->data; + + nu = editnurb->nurbs.first; + /* We need to restore to original curve into newnurb, *not* editcurve's nurbs. + * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would + * invalidate editcurve. */ + newnu = newnurbs->first; + i = 0; + while (nu) { + if (currkey == actkey) { + const bool restore = actkey != cu->key->refkey; + + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + BezTriple *newbezt = newnu->bezt; + while (a--) { + int j; + oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); + + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], bezt->vec[j]); + + if (restore && oldbezt) { + copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]); + } + } + fp[9] = bezt->tilt; + fp[10] = bezt->radius; + + if (restore && oldbezt) { + newbezt->tilt = oldbezt->tilt; + newbezt->radius = oldbezt->radius; + } + + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + i++; + bezt++; + newbezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + BPoint *newbp = newnu->bp; + while (a--) { + oldbp = getKeyIndexOrig_bp(editnurb, bp); + + copy_v3_v3(fp, bp->vec); + + fp[3] = bp->tilt; + fp[4] = bp->radius; + + if (restore && oldbp) { + copy_v3_v3(newbp->vec, oldbp->vec); + newbp->tilt = oldbp->tilt; + newbp->radius = oldbp->radius; + } + + fp += KEYELEM_FLOAT_LEN_BPOINT; + bp++; + newbp++; + i += 2; + } + } + } + else { + int index; + const float *curofp; + + if (oldkey) { + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + + while (a--) { + index = getKeyIndexOrig_keyIndex(editnurb, bezt); + if (index >= 0) { + int j; + curofp = ofp + index; + + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], &curofp[j * 3]); + + if (apply_offset) { + add_v3_v3(&fp[j * 3], ofs[i]); + } + } + fp[9] = curofp[9]; + fp[10] = curofp[10]; + + if (apply_offset) { + /* Apply tilt offsets. */ + add_v3_v3(fp + 9, ofs[i]); + i++; + } + + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + else { + int j; + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], bezt->vec[j]); + } + fp[9] = bezt->tilt; + fp[10] = bezt->radius; + + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + index = getKeyIndexOrig_keyIndex(editnurb, bp); + + if (index >= 0) { + curofp = ofp + index; + copy_v3_v3(fp, curofp); + fp[3] = curofp[3]; + fp[4] = curofp[4]; + + if (apply_offset) { + add_v3_v3(fp, ofs[i]); + add_v3_v3(&fp[3], ofs[i + 1]); + } + } + else { + copy_v3_v3(fp, bp->vec); + fp[3] = bp->tilt; + fp[4] = bp->radius; + } + + fp += KEYELEM_FLOAT_LEN_BPOINT; + bp++; + i += 2; + } + } + } + } + + nu = nu->next; + newnu = newnu->next; + } + + if (apply_offset) { + /* handles could become malicious after offsets applying */ + calc_keyHandles(&editnurb->nurbs, newkey); + } + + currkey->totelem = totvert; + if (currkey->data) { + MEM_freeN(currkey->data); + } + currkey->data = newkey; + + currkey = currkey->next; + } + + if (ofs) { + MEM_freeN(ofs); + } + } } /* ********************* Amimation data *************** */ static bool curve_is_animated(Curve *cu) { - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *ad = BKE_animdata_from_id(&cu->id); - return ad && (ad->action || ad->drivers.first); + return ad && (ad->action || ad->drivers.first); } -static void fcurve_path_rename(AnimData *adt, const char *orig_rna_path, char *rna_path, - ListBase *orig_curves, ListBase *curves) +static void fcurve_path_rename(AnimData *adt, + const char *orig_rna_path, + char *rna_path, + ListBase *orig_curves, + ListBase *curves) { - FCurve *fcu, *nfcu, *nextfcu; - int len = strlen(orig_rna_path); + FCurve *fcu, *nfcu, *nextfcu; + int len = strlen(orig_rna_path); - for (fcu = orig_curves->first; fcu; fcu = nextfcu) { - nextfcu = fcu->next; - if (STREQLEN(fcu->rna_path, orig_rna_path, len)) { - char *spath, *suffix = fcu->rna_path + len; - nfcu = copy_fcurve(fcu); - spath = nfcu->rna_path; - nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix); - BLI_addtail(curves, nfcu); + for (fcu = orig_curves->first; fcu; fcu = nextfcu) { + nextfcu = fcu->next; + if (STREQLEN(fcu->rna_path, orig_rna_path, len)) { + char *spath, *suffix = fcu->rna_path + len; + nfcu = copy_fcurve(fcu); + spath = nfcu->rna_path; + nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix); + BLI_addtail(curves, nfcu); - if (fcu->grp) { - action_groups_remove_channel(adt->action, fcu); - action_groups_add_channel(adt->action, fcu->grp, nfcu); - } - else if ((adt->action) && (&adt->action->curves == orig_curves)) { - BLI_remlink(&adt->action->curves, fcu); - } - else { - BLI_remlink(&adt->drivers, fcu); - } + if (fcu->grp) { + action_groups_remove_channel(adt->action, fcu); + action_groups_add_channel(adt->action, fcu->grp, nfcu); + } + else if ((adt->action) && (&adt->action->curves == orig_curves)) { + BLI_remlink(&adt->action->curves, fcu); + } + else { + BLI_remlink(&adt->drivers, fcu); + } - free_fcurve(fcu); + free_fcurve(fcu); - MEM_freeN(spath); - } - } + MEM_freeN(spath); + } + } } static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu) { - if (orig_curves == &adt->drivers) { - BLI_remlink(&adt->drivers, fcu); - } - else { - action_groups_remove_channel(adt->action, fcu); - } + if (orig_curves == &adt->drivers) { + BLI_remlink(&adt->drivers, fcu); + } + else { + action_groups_remove_channel(adt->action, fcu); + } - free_fcurve(fcu); + free_fcurve(fcu); } static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) { - int nu_index = 0, a, pt_index; - EditNurb *editnurb = cu->editnurb; - Nurb *nu; - CVKeyIndex *keyIndex; - char rna_path[64], orig_rna_path[64]; - AnimData *adt = BKE_animdata_from_id(&cu->id); - ListBase curves = {NULL, NULL}; - FCurve *fcu, *next; - - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - a = nu->pntsu; - pt_index = 0; - - while (a--) { - keyIndex = getCVKeyIndex(editnurb, bezt); - if (keyIndex) { - BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index); - BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].bezier_points[%d]", keyIndex->nu_index, keyIndex->pt_index); - - if (keyIndex->switched) { - char handle_path[64], orig_handle_path[64]; - BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); - BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); - fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); - - BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); - BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); - fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); - } - - fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); - - keyIndex->nu_index = nu_index; - keyIndex->pt_index = pt_index; - } - - bezt++; - pt_index++; - } - } - else { - BPoint *bp = nu->bp; - a = nu->pntsu * nu->pntsv; - pt_index = 0; - - while (a--) { - keyIndex = getCVKeyIndex(editnurb, bp); - if (keyIndex) { - BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); - BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index); - fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); - - keyIndex->nu_index = nu_index; - keyIndex->pt_index = pt_index; - } - - bp++; - pt_index++; - } - } - } - - /* remove paths for removed control points - * need this to make further step with copying non-cv related curves copying - * not touching cv's f-curves */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - - if (STREQLEN(fcu->rna_path, "splines", 7)) { - const char *ch = strchr(fcu->rna_path, '.'); - - if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7))) { - fcurve_remove(adt, orig_curves, fcu); - } - } - } - - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { - keyIndex = NULL; - if (nu->pntsu) { - if (nu->bezt) { - keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]); - } - else { - keyIndex = getCVKeyIndex(editnurb, &nu->bp[0]); - } - } - - if (keyIndex) { - BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); - BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); - fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); - } - } - - /* the remainders in orig_curves can be copied back (like follow path) */ - /* (if it's not path to spline) */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - - if (STREQLEN(fcu->rna_path, "splines", 7)) { - fcurve_remove(adt, orig_curves, fcu); - } - else { - BLI_addtail(&curves, fcu); - } - } - - *orig_curves = curves; + int nu_index = 0, a, pt_index; + EditNurb *editnurb = cu->editnurb; + Nurb *nu; + CVKeyIndex *keyIndex; + char rna_path[64], orig_rna_path[64]; + AnimData *adt = BKE_animdata_from_id(&cu->id); + ListBase curves = {NULL, NULL}; + FCurve *fcu, *next; + + for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + a = nu->pntsu; + pt_index = 0; + + while (a--) { + keyIndex = getCVKeyIndex(editnurb, bezt); + if (keyIndex) { + BLI_snprintf( + rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index); + BLI_snprintf(orig_rna_path, + sizeof(orig_rna_path), + "splines[%d].bezier_points[%d]", + keyIndex->nu_index, + keyIndex->pt_index); + + if (keyIndex->switched) { + char handle_path[64], orig_handle_path[64]; + BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); + BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); + + BLI_snprintf( + orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); + BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); + } + + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); + + keyIndex->nu_index = nu_index; + keyIndex->pt_index = pt_index; + } + + bezt++; + pt_index++; + } + } + else { + BPoint *bp = nu->bp; + a = nu->pntsu * nu->pntsv; + pt_index = 0; + + while (a--) { + keyIndex = getCVKeyIndex(editnurb, bp); + if (keyIndex) { + BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); + BLI_snprintf(orig_rna_path, + sizeof(orig_rna_path), + "splines[%d].points[%d]", + keyIndex->nu_index, + keyIndex->pt_index); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); + + keyIndex->nu_index = nu_index; + keyIndex->pt_index = pt_index; + } + + bp++; + pt_index++; + } + } + } + + /* remove paths for removed control points + * need this to make further step with copying non-cv related curves copying + * not touching cv's f-curves */ + for (fcu = orig_curves->first; fcu; fcu = next) { + next = fcu->next; + + if (STREQLEN(fcu->rna_path, "splines", 7)) { + const char *ch = strchr(fcu->rna_path, '.'); + + if (ch && (STREQLEN(ch, ".bezier_points", 14) || STREQLEN(ch, ".points", 7))) { + fcurve_remove(adt, orig_curves, fcu); + } + } + } + + for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + keyIndex = NULL; + if (nu->pntsu) { + if (nu->bezt) { + keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]); + } + else { + keyIndex = getCVKeyIndex(editnurb, &nu->bp[0]); + } + } + + if (keyIndex) { + BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); + BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); + } + } + + /* the remainders in orig_curves can be copied back (like follow path) */ + /* (if it's not path to spline) */ + for (fcu = orig_curves->first; fcu; fcu = next) { + next = fcu->next; + + if (STREQLEN(fcu->rna_path, "splines", 7)) { + fcurve_remove(adt, orig_curves, fcu); + } + else { + BLI_addtail(&curves, fcu); + } + } + + *orig_curves = curves; } /* return 0 if animation data wasn't changed, 1 otherwise */ int ED_curve_updateAnimPaths(Main *bmain, Curve *cu) { - AnimData *adt = BKE_animdata_from_id(&cu->id); - EditNurb *editnurb = cu->editnurb; + AnimData *adt = BKE_animdata_from_id(&cu->id); + EditNurb *editnurb = cu->editnurb; - if (!editnurb->keyindex) { - return 0; - } + if (!editnurb->keyindex) { + return 0; + } - if (!curve_is_animated(cu)) { - return 0; - } + if (!curve_is_animated(cu)) { + return 0; + } - if (adt->action != NULL) { - curve_rename_fcurves(cu, &adt->action->curves); - DEG_id_tag_update(&adt->action->id, ID_RECALC_COPY_ON_WRITE); - } + if (adt->action != NULL) { + curve_rename_fcurves(cu, &adt->action->curves); + DEG_id_tag_update(&adt->action->id, ID_RECALC_COPY_ON_WRITE); + } - curve_rename_fcurves(cu, &adt->drivers); - DEG_id_tag_update(&cu->id, ID_RECALC_COPY_ON_WRITE); + curve_rename_fcurves(cu, &adt->drivers); + DEG_id_tag_update(&cu->id, ID_RECALC_COPY_ON_WRITE); - /* TODO(sergey): Only update if something actually changed. */ - DEG_relations_tag_update(bmain); + /* TODO(sergey): Only update if something actually changed. */ + DEG_relations_tag_update(bmain); - return 1; + return 1; } /* ********************* LOAD and MAKE *************** */ static int *initialize_index_map(Object *obedit, int *r_old_totvert) { - Curve *curve = (Curve *) obedit->data; - EditNurb *editnurb = curve->editnurb; - Nurb *nu; - CVKeyIndex *keyIndex; - int *old_to_new_map; - int old_totvert, i; - int vertex_index; - - for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) { - if (nu->bezt) { - old_totvert += nu->pntsu * 3; - } - else { - old_totvert += nu->pntsu * nu->pntsv; - } - } - - old_to_new_map = MEM_mallocN(old_totvert * sizeof(int), "curve old to new index map"); - for (i = 0; i < old_totvert; i++) { - old_to_new_map[i] = -1; - } - - for (nu = editnurb->nurbs.first, vertex_index = 0; - nu != NULL; - nu = nu->next) - { - if (nu->bezt) { - BezTriple *bezt = nu->bezt; - int a = nu->pntsu; - - while (a--) { - keyIndex = getCVKeyIndex(editnurb, bezt); - if (keyIndex && keyIndex->vertex_index + 2 < old_totvert) { - if (keyIndex->switched) { - old_to_new_map[keyIndex->vertex_index] = vertex_index + 2; - old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1; - old_to_new_map[keyIndex->vertex_index + 2] = vertex_index; - } - else { - old_to_new_map[keyIndex->vertex_index] = vertex_index; - old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1; - old_to_new_map[keyIndex->vertex_index + 2] = vertex_index + 2; - } - } - vertex_index += 3; - bezt++; - } - } - else { - BPoint *bp = nu->bp; - int a = nu->pntsu * nu->pntsv; - - while (a--) { - keyIndex = getCVKeyIndex(editnurb, bp); - if (keyIndex) { - old_to_new_map[keyIndex->vertex_index] = vertex_index; - } - vertex_index++; - bp++; - } - } - } - - *r_old_totvert = old_totvert; - return old_to_new_map; + Curve *curve = (Curve *)obedit->data; + EditNurb *editnurb = curve->editnurb; + Nurb *nu; + CVKeyIndex *keyIndex; + int *old_to_new_map; + int old_totvert, i; + int vertex_index; + + for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) { + if (nu->bezt) { + old_totvert += nu->pntsu * 3; + } + else { + old_totvert += nu->pntsu * nu->pntsv; + } + } + + old_to_new_map = MEM_mallocN(old_totvert * sizeof(int), "curve old to new index map"); + for (i = 0; i < old_totvert; i++) { + old_to_new_map[i] = -1; + } + + for (nu = editnurb->nurbs.first, vertex_index = 0; nu != NULL; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + int a = nu->pntsu; + + while (a--) { + keyIndex = getCVKeyIndex(editnurb, bezt); + if (keyIndex && keyIndex->vertex_index + 2 < old_totvert) { + if (keyIndex->switched) { + old_to_new_map[keyIndex->vertex_index] = vertex_index + 2; + old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1; + old_to_new_map[keyIndex->vertex_index + 2] = vertex_index; + } + else { + old_to_new_map[keyIndex->vertex_index] = vertex_index; + old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1; + old_to_new_map[keyIndex->vertex_index + 2] = vertex_index + 2; + } + } + vertex_index += 3; + bezt++; + } + } + else { + BPoint *bp = nu->bp; + int a = nu->pntsu * nu->pntsv; + + while (a--) { + keyIndex = getCVKeyIndex(editnurb, bp); + if (keyIndex) { + old_to_new_map[keyIndex->vertex_index] = vertex_index; + } + vertex_index++; + bp++; + } + } + } + + *r_old_totvert = old_totvert; + return old_to_new_map; } static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) { - Object *object; - Curve *curve = (Curve *) obedit->data; - EditNurb *editnurb = curve->editnurb; - int *old_to_new_map = NULL; - int old_totvert; - - if (editnurb->keyindex == NULL) { - /* TODO(sergey): Happens when separating curves, this would lead to - * the wrong indices in the hook modifier, address this together with - * other indices issues. - */ - return; - } - - for (object = bmain->objects.first; object; object = object->id.next) { - ModifierData *md; - int index; - if ((object->parent) && - (object->parent->data == curve) && - ELEM(object->partype, PARVERT1, PARVERT3)) - { - if (old_to_new_map == NULL) { - old_to_new_map = initialize_index_map(obedit, &old_totvert); - } - - if (object->par1 < old_totvert) { - index = old_to_new_map[object->par1]; - if (index != -1) { - object->par1 = index; - } - } - if (object->par2 < old_totvert) { - index = old_to_new_map[object->par2]; - if (index != -1) { - object->par2 = index; - } - } - if (object->par3 < old_totvert) { - index = old_to_new_map[object->par3]; - if (index != -1) { - object->par3 = index; - } - } - } - if (object->data == curve) { - for (md = object->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Hook) { - HookModifierData *hmd = (HookModifierData *) md; - int i, j; - - if (old_to_new_map == NULL) { - old_to_new_map = initialize_index_map(obedit, &old_totvert); - } - - for (i = j = 0; i < hmd->totindex; i++) { - if (hmd->indexar[i] < old_totvert) { - index = old_to_new_map[hmd->indexar[i]]; - if (index != -1) { - hmd->indexar[j++] = index; - } - } - else { - j++; - } - } - - hmd->totindex = j; - } - } - } - } - if (old_to_new_map != NULL) { - MEM_freeN(old_to_new_map); - } + Object *object; + Curve *curve = (Curve *)obedit->data; + EditNurb *editnurb = curve->editnurb; + int *old_to_new_map = NULL; + int old_totvert; + + if (editnurb->keyindex == NULL) { + /* TODO(sergey): Happens when separating curves, this would lead to + * the wrong indices in the hook modifier, address this together with + * other indices issues. + */ + return; + } + + for (object = bmain->objects.first; object; object = object->id.next) { + ModifierData *md; + int index; + if ((object->parent) && (object->parent->data == curve) && + ELEM(object->partype, PARVERT1, PARVERT3)) { + if (old_to_new_map == NULL) { + old_to_new_map = initialize_index_map(obedit, &old_totvert); + } + + if (object->par1 < old_totvert) { + index = old_to_new_map[object->par1]; + if (index != -1) { + object->par1 = index; + } + } + if (object->par2 < old_totvert) { + index = old_to_new_map[object->par2]; + if (index != -1) { + object->par2 = index; + } + } + if (object->par3 < old_totvert) { + index = old_to_new_map[object->par3]; + if (index != -1) { + object->par3 = index; + } + } + } + if (object->data == curve) { + for (md = object->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + int i, j; + + if (old_to_new_map == NULL) { + old_to_new_map = initialize_index_map(obedit, &old_totvert); + } + + for (i = j = 0; i < hmd->totindex; i++) { + if (hmd->indexar[i] < old_totvert) { + index = old_to_new_map[hmd->indexar[i]]; + if (index != -1) { + hmd->indexar[j++] = index; + } + } + else { + j++; + } + } + + hmd->totindex = j; + } + } + } + } + if (old_to_new_map != NULL) { + MEM_freeN(old_to_new_map); + } } /* load editNurb in object */ void ED_curve_editnurb_load(Main *bmain, Object *obedit) { - ListBase *editnurb = object_editcurve_get(obedit); + ListBase *editnurb = object_editcurve_get(obedit); - if (obedit == NULL) { - return; - } + if (obedit == NULL) { + return; + } - if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { - Curve *cu = obedit->data; - Nurb *nu, *newnu; - ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb; + if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + Curve *cu = obedit->data; + Nurb *nu, *newnu; + ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb; - remap_hooks_and_vertex_parents(bmain, obedit); + remap_hooks_and_vertex_parents(bmain, obedit); - for (nu = editnurb->first; nu; nu = nu->next) { - newnu = BKE_nurb_duplicate(nu); - BLI_addtail(&newnurb, newnu); + for (nu = editnurb->first; nu; nu = nu->next) { + newnu = BKE_nurb_duplicate(nu); + BLI_addtail(&newnurb, newnu); - if (nu->type == CU_NURBS) { - BKE_nurb_order_clamp_u(nu); - } - } + if (nu->type == CU_NURBS) { + BKE_nurb_order_clamp_u(nu); + } + } - /* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey) - * on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing - * of editcurve, e.g. when called to generate render data...). */ - calc_shapeKeys(obedit, &newnurb); + /* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey) + * on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing + * of editcurve, e.g. when called to generate render data...). */ + calc_shapeKeys(obedit, &newnurb); - cu->nurb = newnurb; + cu->nurb = newnurb; - ED_curve_updateAnimPaths(bmain, obedit->data); + ED_curve_updateAnimPaths(bmain, obedit->data); - BKE_nurbList_free(&oldnurb); - } + BKE_nurbList_free(&oldnurb); + } } /* make copy in cu->editnurb */ void ED_curve_editnurb_make(Object *obedit) { - Curve *cu = (Curve *)obedit->data; - EditNurb *editnurb = cu->editnurb; - Nurb *nu, *newnu; - KeyBlock *actkey; + Curve *cu = (Curve *)obedit->data; + EditNurb *editnurb = cu->editnurb; + Nurb *nu, *newnu; + KeyBlock *actkey; - if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { - actkey = BKE_keyblock_from_object(obedit); + if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { + actkey = BKE_keyblock_from_object(obedit); - if (actkey) { - // XXX strcpy(G.editModeTitleExtra, "(Key) "); - /* TODO(campbell): undo_system: investigate why this was needed. */ + if (actkey) { + // XXX strcpy(G.editModeTitleExtra, "(Key) "); + /* TODO(campbell): undo_system: investigate why this was needed. */ #if 0 - undo_editmode_clear(); + undo_editmode_clear(); #endif - } - - if (editnurb) { - BKE_nurbList_free(&editnurb->nurbs); - BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex); - } - else { - editnurb = MEM_callocN(sizeof(EditNurb), "editnurb"); - cu->editnurb = editnurb; - } - - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); - BKE_nurb_test_2d(newnu); // after join, or any other creation of curve - BLI_addtail(&editnurb->nurbs, newnu); - nu = nu->next; - } - - /* animation could be added in editmode even if there was no animdata in - * object mode hence we always need CVs index be created */ - init_editNurb_keyIndex(editnurb, &cu->nurb); - - if (actkey) { - editnurb->shapenr = obedit->shapenr; - /* Apply shapekey to new nurbs of editnurb, not those of original curve - * (and *after* we generated keyIndex), else we do not have valid 'original' data - * to properly restore curve when leaving editmode. */ - BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs); - } - } + } + + if (editnurb) { + BKE_nurbList_free(&editnurb->nurbs); + BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex); + } + else { + editnurb = MEM_callocN(sizeof(EditNurb), "editnurb"); + cu->editnurb = editnurb; + } + + nu = cu->nurb.first; + while (nu) { + newnu = BKE_nurb_duplicate(nu); + BKE_nurb_test_2d(newnu); // after join, or any other creation of curve + BLI_addtail(&editnurb->nurbs, newnu); + nu = nu->next; + } + + /* animation could be added in editmode even if there was no animdata in + * object mode hence we always need CVs index be created */ + init_editNurb_keyIndex(editnurb, &cu->nurb); + + if (actkey) { + editnurb->shapenr = obedit->shapenr; + /* Apply shapekey to new nurbs of editnurb, not those of original curve + * (and *after* we generated keyIndex), else we do not have valid 'original' data + * to properly restore curve when leaving editmode. */ + BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs); + } + } } void ED_curve_editnurb_free(Object *obedit) { - Curve *cu = obedit->data; + Curve *cu = obedit->data; - BKE_curve_editNurb_free(cu); + BKE_curve_editNurb_free(cu); } /******************** separate operator ***********************/ static int separate_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - struct { - int changed; - int unselected; - int error_vertex_keys; - int error_generic; - } status = {0}; - - WM_cursor_wait(1); - - uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &bases_len); - for (uint b_index = 0; b_index < bases_len; b_index++) { - Base *oldbase = bases[b_index]; - Base *newbase; - Object *oldob, *newob; - Curve *oldcu, *newcu; - EditNurb *newedit; - ListBase newnurb = {NULL, NULL}; - - oldob = oldbase->object; - oldcu = oldob->data; - - if (oldcu->key) { - status.error_vertex_keys++; - continue; - } - - if (!ED_curve_select_check(v3d, oldcu->editnurb)) { - status.unselected++; - continue; - } - - /* 1. Duplicate geometry and check for valid selection for separate. */ - adduplicateflagNurb(oldob, v3d, &newnurb, SELECT, true); - - if (BLI_listbase_is_empty(&newnurb)) { - status.error_generic++; - continue; - } - - /* 2. Duplicate the object and data. */ - newbase = ED_object_add_duplicate( - bmain, scene, view_layer, oldbase, 0); /* 0 = fully linked. */ - DEG_relations_tag_update(bmain); - - newob = newbase->object; - newcu = newob->data = BKE_curve_copy(bmain, oldcu); - newcu->editnurb = NULL; - id_us_min(&oldcu->id); /* Because new curve is a copy: reduce user count. */ - - /* 3. Put new object in editmode, clear it and set separated nurbs. */ - ED_curve_editnurb_make(newob); - newedit = newcu->editnurb; - BKE_nurbList_free(&newedit->nurbs); - BKE_curve_editNurb_keyIndex_free(&newedit->keyindex); - BLI_movelisttolist(&newedit->nurbs, &newnurb); - - /* 4. Put old object out of editmode and delete separated geometry. */ - ED_curve_editnurb_load(bmain, newob); - ED_curve_editnurb_free(newob); - curve_delete_segments(oldob, v3d, true); - - DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* This is the original one. */ - DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* This is the separated one. */ - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob); - status.changed++; - } - MEM_freeN(bases); - WM_cursor_wait(0); - - if (status.unselected == bases_len) { - BKE_report(op->reports, RPT_ERROR, "No point was selected"); - return OPERATOR_CANCELLED; - } - - const int tot_errors = status.error_vertex_keys + status.error_generic; - if (tot_errors > 0) { - - /* Some curves changed, but some curves failed: don't explain why it failed. */ - if (status.changed) { - BKE_reportf(op->reports, - RPT_INFO, - tot_errors == 1 ? "%d curve could not be separated" : - "%d curves could not be separated", - tot_errors); - return OPERATOR_FINISHED; - } - - /* All curves failed: If there is more than one error give a generic error report. */ - if (((status.error_vertex_keys ? 1 : 0) + (status.error_generic ? 1 : 0)) > 1) { - BKE_report(op->reports, - RPT_ERROR, - tot_errors == 1 ? "Could not separate selected curves" : - "Could not separate selected curve"); - } - - /* All curves failed due to the same error. */ - if (status.error_vertex_keys) { - BKE_report(op->reports, RPT_ERROR, "Cannot separate curves with vertex keys"); - } - else { - BLI_assert(status.error_generic); - BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection"); - } - return OPERATOR_CANCELLED; - } - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + struct { + int changed; + int unselected; + int error_vertex_keys; + int error_generic; + } status = {0}; + + WM_cursor_wait(1); + + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &bases_len); + for (uint b_index = 0; b_index < bases_len; b_index++) { + Base *oldbase = bases[b_index]; + Base *newbase; + Object *oldob, *newob; + Curve *oldcu, *newcu; + EditNurb *newedit; + ListBase newnurb = {NULL, NULL}; + + oldob = oldbase->object; + oldcu = oldob->data; + + if (oldcu->key) { + status.error_vertex_keys++; + continue; + } + + if (!ED_curve_select_check(v3d, oldcu->editnurb)) { + status.unselected++; + continue; + } + + /* 1. Duplicate geometry and check for valid selection for separate. */ + adduplicateflagNurb(oldob, v3d, &newnurb, SELECT, true); + + if (BLI_listbase_is_empty(&newnurb)) { + status.error_generic++; + continue; + } + + /* 2. Duplicate the object and data. */ + newbase = ED_object_add_duplicate( + bmain, scene, view_layer, oldbase, 0); /* 0 = fully linked. */ + DEG_relations_tag_update(bmain); + + newob = newbase->object; + newcu = newob->data = BKE_curve_copy(bmain, oldcu); + newcu->editnurb = NULL; + id_us_min(&oldcu->id); /* Because new curve is a copy: reduce user count. */ + + /* 3. Put new object in editmode, clear it and set separated nurbs. */ + ED_curve_editnurb_make(newob); + newedit = newcu->editnurb; + BKE_nurbList_free(&newedit->nurbs); + BKE_curve_editNurb_keyIndex_free(&newedit->keyindex); + BLI_movelisttolist(&newedit->nurbs, &newnurb); + + /* 4. Put old object out of editmode and delete separated geometry. */ + ED_curve_editnurb_load(bmain, newob); + ED_curve_editnurb_free(newob); + curve_delete_segments(oldob, v3d, true); + + DEG_id_tag_update(&oldob->id, ID_RECALC_GEOMETRY); /* This is the original one. */ + DEG_id_tag_update(&newob->id, ID_RECALC_GEOMETRY); /* This is the separated one. */ + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob); + status.changed++; + } + MEM_freeN(bases); + WM_cursor_wait(0); + + if (status.unselected == bases_len) { + BKE_report(op->reports, RPT_ERROR, "No point was selected"); + return OPERATOR_CANCELLED; + } + + const int tot_errors = status.error_vertex_keys + status.error_generic; + if (tot_errors > 0) { + + /* Some curves changed, but some curves failed: don't explain why it failed. */ + if (status.changed) { + BKE_reportf(op->reports, + RPT_INFO, + tot_errors == 1 ? "%d curve could not be separated" : + "%d curves could not be separated", + tot_errors); + return OPERATOR_FINISHED; + } + + /* All curves failed: If there is more than one error give a generic error report. */ + if (((status.error_vertex_keys ? 1 : 0) + (status.error_generic ? 1 : 0)) > 1) { + BKE_report(op->reports, + RPT_ERROR, + tot_errors == 1 ? "Could not separate selected curves" : + "Could not separate selected curve"); + } + + /* All curves failed due to the same error. */ + if (status.error_vertex_keys) { + BKE_report(op->reports, RPT_ERROR, "Cannot separate curves with vertex keys"); + } + else { + BLI_assert(status.error_generic); + BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection"); + } + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; } void CURVE_OT_separate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Separate"; - ot->idname = "CURVE_OT_separate"; - ot->description = "Separate selected points from connected unselected points into a new object"; + /* identifiers */ + ot->name = "Separate"; + ot->idname = "CURVE_OT_separate"; + ot->description = "Separate selected points from connected unselected points into a new object"; - /* api callbacks */ - ot->invoke = WM_operator_confirm; - ot->exec = separate_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->invoke = WM_operator_confirm; + ot->exec = separate_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************** split operator ***********************/ static int curve_split_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - int ok = -1; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + int ok = -1; - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - ListBase newnurb = {NULL, NULL}; + ListBase newnurb = {NULL, NULL}; - adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, true); + adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, true); - if (BLI_listbase_is_empty(&newnurb)) { - ok = MAX2(ok, 0); - continue; - } + if (BLI_listbase_is_empty(&newnurb)) { + ok = MAX2(ok, 0); + continue; + } - ListBase *editnurb = object_editcurve_get(obedit); - const int len_orig = BLI_listbase_count(editnurb); + ListBase *editnurb = object_editcurve_get(obedit); + const int len_orig = BLI_listbase_count(editnurb); - curve_delete_segments(obedit, v3d, true); - cu->actnu -= len_orig - BLI_listbase_count(editnurb); - BLI_movelisttolist(editnurb, &newnurb); + curve_delete_segments(obedit, v3d, true); + cu->actnu -= len_orig - BLI_listbase_count(editnurb); + BLI_movelisttolist(editnurb, &newnurb); - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } - ok = 1; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); + ok = 1; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); - if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot split current selection"); - return OPERATOR_CANCELLED; - } - return OPERATOR_FINISHED; + if (ok == 0) { + BKE_report(op->reports, RPT_ERROR, "Cannot split current selection"); + return OPERATOR_CANCELLED; + } + return OPERATOR_FINISHED; } void CURVE_OT_split(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Split"; - ot->idname = "CURVE_OT_split"; - ot->description = "Split off selected points from connected unselected points"; + /* identifiers */ + ot->name = "Split"; + ot->idname = "CURVE_OT_split"; + ot->description = "Split off selected points from connected unselected points"; - /* api callbacks */ - ot->exec = curve_split_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_split_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* ******************* FLAGS ********************* */ -static bool isNurbselUV( - const Nurb *nu, int flag, - int *r_u, int *r_v) -{ - /* return (u != -1): 1 row in u-direction selected. U has value between 0-pntsv - * return (v != -1): 1 column in v-direction selected. V has value between 0-pntsu - */ - BPoint *bp; - int a, b, sel; - - *r_u = *r_v = -1; - - bp = nu->bp; - for (b = 0; b < nu->pntsv; b++) { - sel = 0; - for (a = 0; a < nu->pntsu; a++, bp++) { - if (bp->f1 & flag) { - sel++; - } - } - if (sel == nu->pntsu) { - if (*r_u == -1) { - *r_u = b; - } - else { - return 0; - } - } - else if (sel > 1) { - return 0; /* because sel == 1 is still ok */ - } - } - - for (a = 0; a < nu->pntsu; a++) { - sel = 0; - bp = &nu->bp[a]; - for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) { - if (bp->f1 & flag) { - sel++; - } - } - if (sel == nu->pntsv) { - if (*r_v == -1) { - *r_v = a; - } - else { - return 0; - } - } - else if (sel > 1) { - return 0; - } - } - - if (*r_u == -1 && *r_v > -1) { - return 1; - } - if (*r_v == -1 && *r_u > -1) { - return 1; - } - return 0; +static bool isNurbselUV(const Nurb *nu, int flag, int *r_u, int *r_v) +{ + /* return (u != -1): 1 row in u-direction selected. U has value between 0-pntsv + * return (v != -1): 1 column in v-direction selected. V has value between 0-pntsu + */ + BPoint *bp; + int a, b, sel; + + *r_u = *r_v = -1; + + bp = nu->bp; + for (b = 0; b < nu->pntsv; b++) { + sel = 0; + for (a = 0; a < nu->pntsu; a++, bp++) { + if (bp->f1 & flag) { + sel++; + } + } + if (sel == nu->pntsu) { + if (*r_u == -1) { + *r_u = b; + } + else { + return 0; + } + } + else if (sel > 1) { + return 0; /* because sel == 1 is still ok */ + } + } + + for (a = 0; a < nu->pntsu; a++) { + sel = 0; + bp = &nu->bp[a]; + for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) { + if (bp->f1 & flag) { + sel++; + } + } + if (sel == nu->pntsv) { + if (*r_v == -1) { + *r_v = a; + } + else { + return 0; + } + } + else if (sel > 1) { + return 0; + } + } + + if (*r_u == -1 && *r_v > -1) { + return 1; + } + if (*r_v == -1 && *r_u > -1) { + return 1; + } + return 0; } /* return true if U direction is selected and number of selected columns v */ static bool isNurbselU(Nurb *nu, int *v, int flag) { - BPoint *bp; - int a, b, sel; + BPoint *bp; + int a, b, sel; - *v = 0; + *v = 0; - for (b = 0, bp = nu->bp; b < nu->pntsv; b++) { - sel = 0; - for (a = 0; a < nu->pntsu; a++, bp++) { - if (bp->f1 & flag) { - sel++; - } - } - if (sel == nu->pntsu) { - (*v)++; - } - else if (sel >= 1) { - *v = 0; - return 0; - } - } + for (b = 0, bp = nu->bp; b < nu->pntsv; b++) { + sel = 0; + for (a = 0; a < nu->pntsu; a++, bp++) { + if (bp->f1 & flag) { + sel++; + } + } + if (sel == nu->pntsu) { + (*v)++; + } + else if (sel >= 1) { + *v = 0; + return 0; + } + } - return 1; + return 1; } /* return true if V direction is selected and number of selected rows u */ static bool isNurbselV(Nurb *nu, int *u, int flag) { - BPoint *bp; - int a, b, sel; + BPoint *bp; + int a, b, sel; - *u = 0; + *u = 0; - for (a = 0; a < nu->pntsu; a++) { - bp = &nu->bp[a]; - sel = 0; - for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) { - if (bp->f1 & flag) { - sel++; - } - } - if (sel == nu->pntsv) { - (*u)++; - } - else if (sel >= 1) { - *u = 0; - return 0; - } - } + for (a = 0; a < nu->pntsu; a++) { + bp = &nu->bp[a]; + sel = 0; + for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) { + if (bp->f1 & flag) { + sel++; + } + } + if (sel == nu->pntsv) { + (*u)++; + } + else if (sel >= 1) { + *u = 0; + return 0; + } + } - return 1; + return 1; } static void rotateflagNurb(ListBase *editnurb, short flag, const float cent[3], float rotmat[3][3]) { - /* all verts with (flag & 'flag') rotate */ - Nurb *nu; - BPoint *bp; - int a; + /* all verts with (flag & 'flag') rotate */ + Nurb *nu; + BPoint *bp; + int a; - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_NURBS) { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_NURBS) { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->f1 & flag) { - sub_v3_v3(bp->vec, cent); - mul_m3_v3(rotmat, bp->vec); - add_v3_v3(bp->vec, cent); - } - bp++; - } - } - } + while (a--) { + if (bp->f1 & flag) { + sub_v3_v3(bp->vec, cent); + mul_m3_v3(rotmat, bp->vec); + add_v3_v3(bp->vec, cent); + } + bp++; + } + } + } } void ed_editnurb_translate_flag(ListBase *editnurb, short flag, const float vec[3]) { - /* all verts with ('flag' & flag) translate */ - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - if (bezt->f1 & flag) { add_v3_v3(bezt->vec[0], vec); } - if (bezt->f2 & flag) { add_v3_v3(bezt->vec[1], vec); } - if (bezt->f3 & flag) { add_v3_v3(bezt->vec[2], vec); } - bezt++; - } - } - else { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - if (bp->f1 & flag) { - add_v3_v3(bp->vec, vec); - } - bp++; - } - } - - BKE_nurb_test_2d(nu); - } + /* all verts with ('flag' & flag) translate */ + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + if (bezt->f1 & flag) { + add_v3_v3(bezt->vec[0], vec); + } + if (bezt->f2 & flag) { + add_v3_v3(bezt->vec[1], vec); + } + if (bezt->f3 & flag) { + add_v3_v3(bezt->vec[2], vec); + } + bezt++; + } + } + else { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + if (bp->f1 & flag) { + add_v3_v3(bp->vec, vec); + } + bp++; + } + } + + BKE_nurb_test_2d(nu); + } } static void weightflagNurb(ListBase *editnurb, short flag, float w) { - Nurb *nu; - BPoint *bp; - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_NURBS) { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - if (bp->f1 & flag) { - /* a mode used to exist for replace/multiple but is was unused */ - bp->vec[3] *= w; - } - bp++; - } - } - } + Nurb *nu; + BPoint *bp; + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_NURBS) { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + if (bp->f1 & flag) { + /* a mode used to exist for replace/multiple but is was unused */ + bp->vec[3] *= w; + } + bp++; + } + } + } } static void ed_surf_delete_selected(Object *obedit) { - Curve *cu = obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *next; - BPoint *bp, *bpn, *newbp; - int a, b, newu, newv; - - BLI_assert(obedit->type == OB_SURF); - - nu = editnurb->first; - while (nu) { - next = nu->next; - - /* is entire nurb selected */ - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a) { - a--; - if (bp->f1 & SELECT) { - /* pass */ - } - else { - break; - } - bp++; - } - if (a == 0) { - BLI_remlink(editnurb, nu); - keyIndex_delNurb(cu->editnurb, nu); - BKE_nurb_free(nu); nu = NULL; - } - else { - if (isNurbselU(nu, &newv, SELECT)) { - /* U direction selected */ - newv = nu->pntsv - newv; - if (newv != nu->pntsv) { - /* delete */ - bp = nu->bp; - bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb"); - for (b = 0; b < nu->pntsv; b++) { - if ((bp->f1 & SELECT) == 0) { - memcpy(bpn, bp, nu->pntsu * sizeof(BPoint)); - keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu); - bpn += nu->pntsu; - } - else { - keyIndex_delBP(cu->editnurb, bp); - } - bp += nu->pntsu; - } - nu->pntsv = newv; - MEM_freeN(nu->bp); - nu->bp = newbp; - BKE_nurb_order_clamp_v(nu); - - BKE_nurb_knot_calc_v(nu); - } - } - else if (isNurbselV(nu, &newu, SELECT)) { - /* V direction selected */ - newu = nu->pntsu - newu; - if (newu != nu->pntsu) { - /* delete */ - bp = nu->bp; - bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb"); - for (b = 0; b < nu->pntsv; b++) { - for (a = 0; a < nu->pntsu; a++, bp++) { - if ((bp->f1 & SELECT) == 0) { - *bpn = *bp; - keyIndex_updateBP(cu->editnurb, bp, bpn, 1); - bpn++; - } - else { - keyIndex_delBP(cu->editnurb, bp); - } - } - } - MEM_freeN(nu->bp); - nu->bp = newbp; - if (newu == 1 && nu->pntsv > 1) { /* make a U spline */ - nu->pntsu = nu->pntsv; - nu->pntsv = 1; - SWAP(short, nu->orderu, nu->orderv); - BKE_nurb_order_clamp_u(nu); - if (nu->knotsv) { - MEM_freeN(nu->knotsv); - } - nu->knotsv = NULL; - } - else { - nu->pntsu = newu; - BKE_nurb_order_clamp_u(nu); - } - BKE_nurb_knot_calc_u(nu); - } - } - } - nu = next; - } + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu, *next; + BPoint *bp, *bpn, *newbp; + int a, b, newu, newv; + + BLI_assert(obedit->type == OB_SURF); + + nu = editnurb->first; + while (nu) { + next = nu->next; + + /* is entire nurb selected */ + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a) { + a--; + if (bp->f1 & SELECT) { + /* pass */ + } + else { + break; + } + bp++; + } + if (a == 0) { + BLI_remlink(editnurb, nu); + keyIndex_delNurb(cu->editnurb, nu); + BKE_nurb_free(nu); + nu = NULL; + } + else { + if (isNurbselU(nu, &newv, SELECT)) { + /* U direction selected */ + newv = nu->pntsv - newv; + if (newv != nu->pntsv) { + /* delete */ + bp = nu->bp; + bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb"); + for (b = 0; b < nu->pntsv; b++) { + if ((bp->f1 & SELECT) == 0) { + memcpy(bpn, bp, nu->pntsu * sizeof(BPoint)); + keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu); + bpn += nu->pntsu; + } + else { + keyIndex_delBP(cu->editnurb, bp); + } + bp += nu->pntsu; + } + nu->pntsv = newv; + MEM_freeN(nu->bp); + nu->bp = newbp; + BKE_nurb_order_clamp_v(nu); + + BKE_nurb_knot_calc_v(nu); + } + } + else if (isNurbselV(nu, &newu, SELECT)) { + /* V direction selected */ + newu = nu->pntsu - newu; + if (newu != nu->pntsu) { + /* delete */ + bp = nu->bp; + bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb"); + for (b = 0; b < nu->pntsv; b++) { + for (a = 0; a < nu->pntsu; a++, bp++) { + if ((bp->f1 & SELECT) == 0) { + *bpn = *bp; + keyIndex_updateBP(cu->editnurb, bp, bpn, 1); + bpn++; + } + else { + keyIndex_delBP(cu->editnurb, bp); + } + } + } + MEM_freeN(nu->bp); + nu->bp = newbp; + if (newu == 1 && nu->pntsv > 1) { /* make a U spline */ + nu->pntsu = nu->pntsv; + nu->pntsv = 1; + SWAP(short, nu->orderu, nu->orderv); + BKE_nurb_order_clamp_u(nu); + if (nu->knotsv) { + MEM_freeN(nu->knotsv); + } + nu->knotsv = NULL; + } + else { + nu->pntsu = newu; + BKE_nurb_order_clamp_u(nu); + } + BKE_nurb_knot_calc_u(nu); + } + } + } + nu = next; + } } static void ed_curve_delete_selected(Object *obedit, View3D *v3d) { - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - ListBase *nubase = &editnurb->nurbs; - Nurb *nu, *next; - BezTriple *bezt, *bezt1; - BPoint *bp, *bp1; - int a, type, nuindex = 0; - - /* first loop, can we remove entire pieces? */ - nu = nubase->first; - while (nu) { - next = nu->next; - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - if (a) { - while (a) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - /* pass */ - } - else { - break; - } - a--; - bezt++; - } - if (a == 0) { - if (cu->actnu == nuindex) { - cu->actnu = CU_ACT_NONE; - } - - BLI_remlink(nubase, nu); - keyIndex_delNurb(editnurb, nu); - BKE_nurb_free(nu); nu = NULL; - } - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - if (a) { - while (a) { - if (bp->f1 & SELECT) { - /* pass */ - } - else { - break; - } - a--; - bp++; - } - if (a == 0) { - if (cu->actnu == nuindex) { - cu->actnu = CU_ACT_NONE; - } - - BLI_remlink(nubase, nu); - keyIndex_delNurb(editnurb, nu); - BKE_nurb_free(nu); nu = NULL; - } - } - } - - /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + ListBase *nubase = &editnurb->nurbs; + Nurb *nu, *next; + BezTriple *bezt, *bezt1; + BPoint *bp, *bp1; + int a, type, nuindex = 0; + + /* first loop, can we remove entire pieces? */ + nu = nubase->first; + while (nu) { + next = nu->next; + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + if (a) { + while (a) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + /* pass */ + } + else { + break; + } + a--; + bezt++; + } + if (a == 0) { + if (cu->actnu == nuindex) { + cu->actnu = CU_ACT_NONE; + } + + BLI_remlink(nubase, nu); + keyIndex_delNurb(editnurb, nu); + BKE_nurb_free(nu); + nu = NULL; + } + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + if (a) { + while (a) { + if (bp->f1 & SELECT) { + /* pass */ + } + else { + break; + } + a--; + bp++; + } + if (a == 0) { + if (cu->actnu == nuindex) { + cu->actnu = CU_ACT_NONE; + } + + BLI_remlink(nubase, nu); + keyIndex_delNurb(editnurb, nu); + BKE_nurb_free(nu); + nu = NULL; + } + } + } + + /* Never allow the order to exceed the number of points + * - note, this is ok but changes unselected nurbs, disable for now */ #if 0 - if ((nu != NULL) && (nu->type == CU_NURBS)) { - clamp_nurb_order_u(nu); - } + if ((nu != NULL) && (nu->type == CU_NURBS)) { + clamp_nurb_order_u(nu); + } #endif - nu = next; - nuindex++; - } - /* 2nd loop, delete small pieces: just for curves */ - nu = nubase->first; - while (nu) { - next = nu->next; - type = 0; - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - for (a = 0; a < nu->pntsu; a++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple)); - keyIndex_delBezt(editnurb, bezt); - keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1); - nu->pntsu--; - a--; - type = 1; - } - else { - bezt++; - } - } - if (type) { - bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb"); - memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple)); - keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu); - MEM_freeN(nu->bezt); - nu->bezt = bezt1; - BKE_nurb_handles_calc(nu); - } - } - else if (nu->pntsv == 1) { - bp = nu->bp; - - for (a = 0; a < nu->pntsu; a++) { - if (bp->f1 & SELECT) { - memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint)); - keyIndex_delBP(editnurb, bp); - keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1); - nu->pntsu--; - a--; - type = 1; - } - else { - bp++; - } - } - if (type) { - bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2"); - memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint)); - keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu); - MEM_freeN(nu->bp); - nu->bp = bp1; - - /* Never allow the order to exceed the number of points - * - note, this is ok but changes unselected nurbs, disable for now */ + nu = next; + nuindex++; + } + /* 2nd loop, delete small pieces: just for curves */ + nu = nubase->first; + while (nu) { + next = nu->next; + type = 0; + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + for (a = 0; a < nu->pntsu; a++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple)); + keyIndex_delBezt(editnurb, bezt); + keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1); + nu->pntsu--; + a--; + type = 1; + } + else { + bezt++; + } + } + if (type) { + bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb"); + memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple)); + keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu); + MEM_freeN(nu->bezt); + nu->bezt = bezt1; + BKE_nurb_handles_calc(nu); + } + } + else if (nu->pntsv == 1) { + bp = nu->bp; + + for (a = 0; a < nu->pntsu; a++) { + if (bp->f1 & SELECT) { + memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint)); + keyIndex_delBP(editnurb, bp); + keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1); + nu->pntsu--; + a--; + type = 1; + } + else { + bp++; + } + } + if (type) { + bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2"); + memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint)); + keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu); + MEM_freeN(nu->bp); + nu->bp = bp1; + + /* Never allow the order to exceed the number of points + * - note, this is ok but changes unselected nurbs, disable for now */ #if 0 - if (nu->type == CU_NURBS) { - clamp_nurb_order_u(nu); - } + if (nu->type == CU_NURBS) { + clamp_nurb_order_u(nu); + } #endif - } - BKE_nurb_order_clamp_u(nu); - BKE_nurb_knot_calc_u(nu); - } - nu = next; - } + } + BKE_nurb_order_clamp_u(nu); + BKE_nurb_knot_calc_u(nu); + } + nu = next; + } } /* only for OB_SURF */ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const short flag) { - Nurb *nu; - BPoint *bp, *bpn, *newbp; - int a, u, v, len; - bool ok = false; - - nu = editnurb->nurbs.first; - while (nu) { - - if (nu->pntsv == 1) { - bp = nu->bp; - a = nu->pntsu; - while (a) { - if (bp->f1 & flag) { - /* pass */ - } - else { - break; - } - bp++; - a--; - } - if (a == 0) { - ok = true; - newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1"); - ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); - bp = newbp + nu->pntsu; - ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu); - MEM_freeN(nu->bp); - nu->bp = newbp; - a = nu->pntsu; - while (a--) { - select_bpoint(bp, SELECT, flag, HIDDEN); - select_bpoint(newbp, DESELECT, flag, HIDDEN); - bp++; - newbp++; - } - - nu->pntsv = 2; - nu->orderv = 2; - BKE_nurb_knot_calc_v(nu); - } - } - else { - /* which row or column is selected */ - - if (isNurbselUV(nu, flag, &u, &v)) { - - /* deselect all */ - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - select_bpoint(bp, DESELECT, flag, HIDDEN); - bp++; - } - - if (u == 0 || u == nu->pntsv - 1) { /* row in u-direction selected */ - ok = true; - newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) * - sizeof(BPoint), "extrudeNurb1"); - if (u == 0) { - len = nu->pntsv * nu->pntsu; - ED_curve_bpcpy(editnurb, newbp + nu->pntsu, nu->bp, len); - ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); - bp = newbp; - } - else { - len = nu->pntsv * nu->pntsu; - ED_curve_bpcpy(editnurb, newbp, nu->bp, len); - ED_curve_bpcpy(editnurb, newbp + len, &nu->bp[len - nu->pntsu], nu->pntsu); - bp = newbp + len; - } - - a = nu->pntsu; - while (a--) { - select_bpoint(bp, SELECT, flag, HIDDEN); - bp++; - } - - MEM_freeN(nu->bp); - nu->bp = newbp; - nu->pntsv++; - BKE_nurb_knot_calc_v(nu); - } - else if (v == 0 || v == nu->pntsu - 1) { /* column in v-direction selected */ - ok = true; - bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1"); - bp = nu->bp; - - for (a = 0; a < nu->pntsv; a++) { - if (v == 0) { - *bpn = *bp; - bpn->f1 |= flag; - bpn++; - } - ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu); - bp += nu->pntsu; - bpn += nu->pntsu; - if (v == nu->pntsu - 1) { - *bpn = *(bp - 1); - bpn->f1 |= flag; - bpn++; - } - } - - MEM_freeN(nu->bp); - nu->bp = newbp; - nu->pntsu++; - BKE_nurb_knot_calc_u(nu); - } - } - } - nu = nu->next; - } - - return ok; + Nurb *nu; + BPoint *bp, *bpn, *newbp; + int a, u, v, len; + bool ok = false; + + nu = editnurb->nurbs.first; + while (nu) { + + if (nu->pntsv == 1) { + bp = nu->bp; + a = nu->pntsu; + while (a) { + if (bp->f1 & flag) { + /* pass */ + } + else { + break; + } + bp++; + a--; + } + if (a == 0) { + ok = true; + newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1"); + ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); + bp = newbp + nu->pntsu; + ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu); + MEM_freeN(nu->bp); + nu->bp = newbp; + a = nu->pntsu; + while (a--) { + select_bpoint(bp, SELECT, flag, HIDDEN); + select_bpoint(newbp, DESELECT, flag, HIDDEN); + bp++; + newbp++; + } + + nu->pntsv = 2; + nu->orderv = 2; + BKE_nurb_knot_calc_v(nu); + } + } + else { + /* which row or column is selected */ + + if (isNurbselUV(nu, flag, &u, &v)) { + + /* deselect all */ + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + select_bpoint(bp, DESELECT, flag, HIDDEN); + bp++; + } + + if (u == 0 || u == nu->pntsv - 1) { /* row in u-direction selected */ + ok = true; + newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) * sizeof(BPoint), + "extrudeNurb1"); + if (u == 0) { + len = nu->pntsv * nu->pntsu; + ED_curve_bpcpy(editnurb, newbp + nu->pntsu, nu->bp, len); + ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu); + bp = newbp; + } + else { + len = nu->pntsv * nu->pntsu; + ED_curve_bpcpy(editnurb, newbp, nu->bp, len); + ED_curve_bpcpy(editnurb, newbp + len, &nu->bp[len - nu->pntsu], nu->pntsu); + bp = newbp + len; + } + + a = nu->pntsu; + while (a--) { + select_bpoint(bp, SELECT, flag, HIDDEN); + bp++; + } + + MEM_freeN(nu->bp); + nu->bp = newbp; + nu->pntsv++; + BKE_nurb_knot_calc_v(nu); + } + else if (v == 0 || v == nu->pntsu - 1) { /* column in v-direction selected */ + ok = true; + bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), + "extrudeNurb1"); + bp = nu->bp; + + for (a = 0; a < nu->pntsv; a++) { + if (v == 0) { + *bpn = *bp; + bpn->f1 |= flag; + bpn++; + } + ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu); + bp += nu->pntsu; + bpn += nu->pntsu; + if (v == nu->pntsu - 1) { + *bpn = *(bp - 1); + bpn->f1 |= flag; + bpn++; + } + } + + MEM_freeN(nu->bp); + nu->bp = newbp; + nu->pntsu++; + BKE_nurb_knot_calc_u(nu); + } + } + } + nu = nu->next; + } + + return ok; } static bool calc_duplicate_actvert( - const ListBase *editnurb, const ListBase *newnurb, Curve *cu, - int start, int end, int vert) -{ - if ((start <= cu->actvert) && (end > cu->actvert)) { - cu->actvert = vert; - cu->actnu = BLI_listbase_count(editnurb) + BLI_listbase_count(newnurb); - return true; - } - return false; -} - -static void adduplicateflagNurb(Object *obedit, View3D *v3d, ListBase *newnurb, - const short flag, const bool split) -{ - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *newnu; - BezTriple *bezt, *bezt1; - BPoint *bp, *bp1, *bp2, *bp3; - Curve *cu = (Curve *)obedit->data; - int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i; - char *usel; - - for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) { - cyclicu = cyclicv = 0; - if (nu->type == CU_BEZIER) { - for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { - enda = -1; - starta = a; - while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { - if (!split) { - select_beztriple(bezt, DESELECT, flag, HIDDEN); - } - enda = a; - if (a >= nu->pntsu - 1) { - break; - } - a++; - bezt++; - } - if (enda >= starta) { - newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */ - - if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) { - cyclicu = newu; - } - else { - if (enda == nu->pntsu - 1) { - newu += cyclicu; - } - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - starta, starta + diffa, cu->actvert - starta); - } - - newnu = BKE_nurb_copy(nu, newu, 1); - memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple)); - if (newu != diffa) { - memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple)); - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - 0, cyclicu, newu - cyclicu + cu->actvert); - } - cyclicu = 0; - } - - if (newu != nu->pntsu) { - newnu->flagu &= ~CU_NURB_CYCLIC; - } - - for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, SELECT, flag, HIDDEN); - } - - BLI_addtail(newnurb, newnu); - } - } - } - - if (cyclicu != 0) { - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - 0, cyclicu, cu->actvert); - } - - newnu = BKE_nurb_copy(nu, cyclicu, 1); - memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple)); - newnu->flagu &= ~CU_NURB_CYCLIC; - - for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, SELECT, flag, HIDDEN); - } - - BLI_addtail(newnurb, newnu); - } - } - else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */ - for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) { - enda = -1; - starta = a; - while (bp->f1 & flag) { - if (!split) { - select_bpoint(bp, DESELECT, flag, HIDDEN); - } - enda = a; - if (a >= nu->pntsu - 1) { - break; - } - a++; - bp++; - } - if (enda >= starta) { - newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */ - - if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) { - cyclicu = newu; - } - else { - if (enda == nu->pntsu - 1) { - newu += cyclicu; - } - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - starta, starta + diffa, cu->actvert - starta); - } - - newnu = BKE_nurb_copy(nu, newu, 1); - memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint)); - if (newu != diffa) { - memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint)); - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - 0, cyclicu, newu - cyclicu + cu->actvert); - } - cyclicu = 0; - } - - if (newu != nu->pntsu) { - newnu->flagu &= ~CU_NURB_CYCLIC; - } - - for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { - select_bpoint(bp1, SELECT, flag, HIDDEN); - } - - BLI_addtail(newnurb, newnu); - } - } - } - - if (cyclicu != 0) { - if (i == cu->actnu) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - 0, cyclicu, cu->actvert); - } - - newnu = BKE_nurb_copy(nu, cyclicu, 1); - memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint)); - newnu->flagu &= ~CU_NURB_CYCLIC; - - for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { - select_bpoint(bp1, SELECT, flag, HIDDEN); - } - - BLI_addtail(newnurb, newnu); - } - } - else { - if (ED_curve_nurb_select_check(v3d, nu)) { - /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */ - usel = MEM_callocN(nu->pntsu, "adduplicateN3"); - bp = nu->bp; - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++, bp++) { - if (bp->f1 & flag) { - usel[b]++; - } - } - } - newu = 0; - newv = 0; - for (a = 0; a < nu->pntsu; a++) { - if (usel[a]) { - if (newv == 0 || usel[a] == newv) { - newv = usel[a]; - newu++; - } - else { - newv = 0; - break; - } - } - } - MEM_freeN(usel); - - if ((newu == 0 || newv == 0) || - (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT))) - { - if (G.debug & G_DEBUG) { - printf("Can't duplicate Nurb\n"); - } - } - else { - for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) { - newv = newu = 0; - - if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) { - /* point selected, now loop over points in U and V directions */ - for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) { - if (bp2->f1 & flag) { - newu++; - for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) { - if (bp3->f1 & flag) { - /* flag as seen so skipped on future iterations */ - bp3->f1 |= SURF_SEEN; - if (newu == 1) { - newv++; - } - } - else { - break; - } - } - } - else { - break; - } - } - } - - if ((newu + newv) > 2) { - /* ignore single points */ - if (a == 0) { - /* check if need to save cyclic selection and continue if so */ - if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) { - cyclicv = newv; - } - if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) { - cyclicu = newu; - } - if (cyclicu != 0 || cyclicv != 0) { - continue; - } - } - - if (a + newu == nu->pntsu && cyclicu != 0) { - /* cyclic in U direction */ - newnu = BKE_nurb_copy(nu, newu + cyclicu, newv); - for (b = 0; b < newv; b++) { - memcpy(&newnu->bp[b * newnu->pntsu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint)); - memcpy(&newnu->bp[b * newnu->pntsu + newu], &nu->bp[b * nu->pntsu], cyclicu * sizeof(BPoint)); - } - - if (cu->actnu == i) { - for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { - starta = b * nu->pntsu + a; - if (calc_duplicate_actvert( - editnurb, newnurb, cu, - cu->actvert, starta, - cu->actvert % nu->pntsu + newu + b * newnu->pntsu)) - { - /* actvert in cyclicu selection */ - break; - } - else if (calc_duplicate_actvert( - editnurb, newnurb, cu, - starta, starta + newu, - cu->actvert - starta + b * newnu->pntsu)) - { - /* actvert in 'current' iteration selection */ - break; - } - } - } - cyclicu = cyclicv = 0; - } - else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) { - /* cyclic in V direction */ - newnu = BKE_nurb_copy(nu, newu, newv + cyclicv); - memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint)); - memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint)); - - /* check for actvert in cylicv selection */ - if (cu->actnu == i) { - calc_duplicate_actvert( - editnurb, newnurb, cu, - cu->actvert, a, - (newu * newv) + cu->actvert); - } - cyclicu = cyclicv = 0; - } - else { - newnu = BKE_nurb_copy(nu, newu, newv); - for (b = 0; b < newv; b++) { - memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint)); - } - } - - /* general case if not handled by cyclicu or cyclicv */ - if (cu->actnu == i) { - for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { - starta = b * nu->pntsu + a; - if (calc_duplicate_actvert( - editnurb, newnurb, cu, - starta, starta + newu, - cu->actvert - (a / nu->pntsu * nu->pntsu + diffa + (starta % nu->pntsu)))) - { - break; - } - } - } - BLI_addtail(newnurb, newnu); - - if (newu != nu->pntsu) { - newnu->flagu &= ~CU_NURB_CYCLIC; - } - if (newv != nu->pntsv) { - newnu->flagv &= ~CU_NURB_CYCLIC; - } - } - } - - if (cyclicu != 0 || cyclicv != 0) { - /* copy start of a cyclic surface, or copying all selected points */ - newu = cyclicu == 0 ? nu->pntsu : cyclicu; - newv = cyclicv == 0 ? nu->pntsv : cyclicv; - - newnu = BKE_nurb_copy(nu, newu, newv); - for (b = 0; b < newv; b++) { - memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint)); - } - - /* check for actvert in the unused cyclicuv selection */ - if (cu->actnu == i) { - for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { - starta = b * nu->pntsu; - if (calc_duplicate_actvert( - editnurb, newnurb, cu, - starta, starta + newu, - cu->actvert - (diffa + (starta % nu->pntsu)))) - { - break; - } - } - } - BLI_addtail(newnurb, newnu); - - if (newu != nu->pntsu) { - newnu->flagu &= ~CU_NURB_CYCLIC; - } - if (newv != nu->pntsv) { - newnu->flagv &= ~CU_NURB_CYCLIC; - } - } - - for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { - bp1->f1 &= ~SURF_SEEN; - if (!split) { - select_bpoint(bp1, DESELECT, flag, HIDDEN); - } - } - } - } - } - } - - if (BLI_listbase_is_empty(newnurb) == false) { - for (nu = newnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - if (split) { - /* recalc first and last */ - BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]); - BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]); - } - } - else { - /* knots done after duplicate as pntsu may change */ - BKE_nurb_order_clamp_u(nu); - BKE_nurb_knot_calc_u(nu); - - if (obedit->type == OB_SURF) { - for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) { - bp->f1 &= ~SURF_SEEN; - } - - BKE_nurb_order_clamp_v(nu); - BKE_nurb_knot_calc_v(nu); - } - } - } - } + const ListBase *editnurb, const ListBase *newnurb, Curve *cu, int start, int end, int vert) +{ + if ((start <= cu->actvert) && (end > cu->actvert)) { + cu->actvert = vert; + cu->actnu = BLI_listbase_count(editnurb) + BLI_listbase_count(newnurb); + return true; + } + return false; +} + +static void adduplicateflagNurb( + Object *obedit, View3D *v3d, ListBase *newnurb, const short flag, const bool split) +{ + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu, *newnu; + BezTriple *bezt, *bezt1; + BPoint *bp, *bp1, *bp2, *bp3; + Curve *cu = (Curve *)obedit->data; + int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i; + char *usel; + + for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) { + cyclicu = cyclicv = 0; + if (nu->type == CU_BEZIER) { + for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { + enda = -1; + starta = a; + while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { + if (!split) { + select_beztriple(bezt, DESELECT, flag, HIDDEN); + } + enda = a; + if (a >= nu->pntsu - 1) { + break; + } + a++; + bezt++; + } + if (enda >= starta) { + newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */ + + if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) { + cyclicu = newu; + } + else { + if (enda == nu->pntsu - 1) { + newu += cyclicu; + } + if (i == cu->actnu) { + calc_duplicate_actvert( + editnurb, newnurb, cu, starta, starta + diffa, cu->actvert - starta); + } + + newnu = BKE_nurb_copy(nu, newu, 1); + memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple)); + if (newu != diffa) { + memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple)); + if (i == cu->actnu) { + calc_duplicate_actvert( + editnurb, newnurb, cu, 0, cyclicu, newu - cyclicu + cu->actvert); + } + cyclicu = 0; + } + + if (newu != nu->pntsu) { + newnu->flagu &= ~CU_NURB_CYCLIC; + } + + for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { + select_beztriple(bezt1, SELECT, flag, HIDDEN); + } + + BLI_addtail(newnurb, newnu); + } + } + } + + if (cyclicu != 0) { + if (i == cu->actnu) { + calc_duplicate_actvert(editnurb, newnurb, cu, 0, cyclicu, cu->actvert); + } + + newnu = BKE_nurb_copy(nu, cyclicu, 1); + memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple)); + newnu->flagu &= ~CU_NURB_CYCLIC; + + for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) { + select_beztriple(bezt1, SELECT, flag, HIDDEN); + } + + BLI_addtail(newnurb, newnu); + } + } + else if (nu->pntsv == 1) { /* because UV Nurb has a different method for dupli */ + for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) { + enda = -1; + starta = a; + while (bp->f1 & flag) { + if (!split) { + select_bpoint(bp, DESELECT, flag, HIDDEN); + } + enda = a; + if (a >= nu->pntsu - 1) { + break; + } + a++; + bp++; + } + if (enda >= starta) { + newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */ + + if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) { + cyclicu = newu; + } + else { + if (enda == nu->pntsu - 1) { + newu += cyclicu; + } + if (i == cu->actnu) { + calc_duplicate_actvert( + editnurb, newnurb, cu, starta, starta + diffa, cu->actvert - starta); + } + + newnu = BKE_nurb_copy(nu, newu, 1); + memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint)); + if (newu != diffa) { + memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint)); + if (i == cu->actnu) { + calc_duplicate_actvert( + editnurb, newnurb, cu, 0, cyclicu, newu - cyclicu + cu->actvert); + } + cyclicu = 0; + } + + if (newu != nu->pntsu) { + newnu->flagu &= ~CU_NURB_CYCLIC; + } + + for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { + select_bpoint(bp1, SELECT, flag, HIDDEN); + } + + BLI_addtail(newnurb, newnu); + } + } + } + + if (cyclicu != 0) { + if (i == cu->actnu) { + calc_duplicate_actvert(editnurb, newnurb, cu, 0, cyclicu, cu->actvert); + } + + newnu = BKE_nurb_copy(nu, cyclicu, 1); + memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint)); + newnu->flagu &= ~CU_NURB_CYCLIC; + + for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) { + select_bpoint(bp1, SELECT, flag, HIDDEN); + } + + BLI_addtail(newnurb, newnu); + } + } + else { + if (ED_curve_nurb_select_check(v3d, nu)) { + /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */ + usel = MEM_callocN(nu->pntsu, "adduplicateN3"); + bp = nu->bp; + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++, bp++) { + if (bp->f1 & flag) { + usel[b]++; + } + } + } + newu = 0; + newv = 0; + for (a = 0; a < nu->pntsu; a++) { + if (usel[a]) { + if (newv == 0 || usel[a] == newv) { + newv = usel[a]; + newu++; + } + else { + newv = 0; + break; + } + } + } + MEM_freeN(usel); + + if ((newu == 0 || newv == 0) || + (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT))) { + if (G.debug & G_DEBUG) { + printf("Can't duplicate Nurb\n"); + } + } + else { + for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) { + newv = newu = 0; + + if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) { + /* point selected, now loop over points in U and V directions */ + for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) { + if (bp2->f1 & flag) { + newu++; + for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) { + if (bp3->f1 & flag) { + /* flag as seen so skipped on future iterations */ + bp3->f1 |= SURF_SEEN; + if (newu == 1) { + newv++; + } + } + else { + break; + } + } + } + else { + break; + } + } + } + + if ((newu + newv) > 2) { + /* ignore single points */ + if (a == 0) { + /* check if need to save cyclic selection and continue if so */ + if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) { + cyclicv = newv; + } + if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) { + cyclicu = newu; + } + if (cyclicu != 0 || cyclicv != 0) { + continue; + } + } + + if (a + newu == nu->pntsu && cyclicu != 0) { + /* cyclic in U direction */ + newnu = BKE_nurb_copy(nu, newu + cyclicu, newv); + for (b = 0; b < newv; b++) { + memcpy(&newnu->bp[b * newnu->pntsu], + &nu->bp[b * nu->pntsu + a], + newu * sizeof(BPoint)); + memcpy(&newnu->bp[b * newnu->pntsu + newu], + &nu->bp[b * nu->pntsu], + cyclicu * sizeof(BPoint)); + } + + if (cu->actnu == i) { + for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { + starta = b * nu->pntsu + a; + if (calc_duplicate_actvert(editnurb, + newnurb, + cu, + cu->actvert, + starta, + cu->actvert % nu->pntsu + newu + + b * newnu->pntsu)) { + /* actvert in cyclicu selection */ + break; + } + else if (calc_duplicate_actvert(editnurb, + newnurb, + cu, + starta, + starta + newu, + cu->actvert - starta + b * newnu->pntsu)) { + /* actvert in 'current' iteration selection */ + break; + } + } + } + cyclicu = cyclicv = 0; + } + else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) { + /* cyclic in V direction */ + newnu = BKE_nurb_copy(nu, newu, newv + cyclicv); + memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint)); + memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint)); + + /* check for actvert in cylicv selection */ + if (cu->actnu == i) { + calc_duplicate_actvert( + editnurb, newnurb, cu, cu->actvert, a, (newu * newv) + cu->actvert); + } + cyclicu = cyclicv = 0; + } + else { + newnu = BKE_nurb_copy(nu, newu, newv); + for (b = 0; b < newv; b++) { + memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint)); + } + } + + /* general case if not handled by cyclicu or cyclicv */ + if (cu->actnu == i) { + for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { + starta = b * nu->pntsu + a; + if (calc_duplicate_actvert(editnurb, + newnurb, + cu, + starta, + starta + newu, + cu->actvert - (a / nu->pntsu * nu->pntsu + diffa + + (starta % nu->pntsu)))) { + break; + } + } + } + BLI_addtail(newnurb, newnu); + + if (newu != nu->pntsu) { + newnu->flagu &= ~CU_NURB_CYCLIC; + } + if (newv != nu->pntsv) { + newnu->flagv &= ~CU_NURB_CYCLIC; + } + } + } + + if (cyclicu != 0 || cyclicv != 0) { + /* copy start of a cyclic surface, or copying all selected points */ + newu = cyclicu == 0 ? nu->pntsu : cyclicu; + newv = cyclicv == 0 ? nu->pntsv : cyclicv; + + newnu = BKE_nurb_copy(nu, newu, newv); + for (b = 0; b < newv; b++) { + memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint)); + } + + /* check for actvert in the unused cyclicuv selection */ + if (cu->actnu == i) { + for (b = 0, diffa = 0; b < newv; b++, diffa += nu->pntsu - newu) { + starta = b * nu->pntsu; + if (calc_duplicate_actvert(editnurb, + newnurb, + cu, + starta, + starta + newu, + cu->actvert - (diffa + (starta % nu->pntsu)))) { + break; + } + } + } + BLI_addtail(newnurb, newnu); + + if (newu != nu->pntsu) { + newnu->flagu &= ~CU_NURB_CYCLIC; + } + if (newv != nu->pntsv) { + newnu->flagv &= ~CU_NURB_CYCLIC; + } + } + + for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { + bp1->f1 &= ~SURF_SEEN; + if (!split) { + select_bpoint(bp1, DESELECT, flag, HIDDEN); + } + } + } + } + } + } + + if (BLI_listbase_is_empty(newnurb) == false) { + for (nu = newnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + if (split) { + /* recalc first and last */ + BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]); + BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]); + } + } + else { + /* knots done after duplicate as pntsu may change */ + BKE_nurb_order_clamp_u(nu); + BKE_nurb_knot_calc_u(nu); + + if (obedit->type == OB_SURF) { + for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) { + bp->f1 &= ~SURF_SEEN; + } + + BKE_nurb_order_clamp_v(nu); + BKE_nurb_knot_calc_v(nu); + } + } + } + } } /**************** switch direction operator ***************/ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - EditNurb *editnurb = cu->editnurb; - Nurb *nu; - int i; - - for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) { - if (ED_curve_nurb_select_check(v3d, nu)) { - BKE_nurb_direction_switch(nu); - keyData_switchDirectionNurb(cu, nu); - if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) { - cu->actvert = (nu->pntsu - 1) - cu->actvert; - } - } - } - - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + EditNurb *editnurb = cu->editnurb; + Nurb *nu; + int i; + + for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) { + if (ED_curve_nurb_select_check(v3d, nu)) { + BKE_nurb_direction_switch(nu); + keyData_switchDirectionNurb(cu, nu); + if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) { + cu->actvert = (nu->pntsu - 1) - cu->actvert; + } + } + } + + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_switch_direction(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Switch Direction"; - ot->description = "Switch direction of selected splines"; - ot->idname = "CURVE_OT_switch_direction"; + /* identifiers */ + ot->name = "Switch Direction"; + ot->description = "Switch direction of selected splines"; + ot->idname = "CURVE_OT_switch_direction"; - /* api callbacks */ - ot->exec = switch_direction_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = switch_direction_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /****************** set weight operator *******************/ static int set_goal_weight_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float weight = RNA_float_get(op->ptr, "weight"); - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->weight = weight; - } - } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->weight = weight; - } - } - } - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float weight = RNA_float_get(op->ptr, "weight"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->weight = weight; + } + } + } + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->weight = weight; + } + } + } + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; } void CURVE_OT_spline_weight_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Goal Weight"; - ot->description = "Set softbody goal weight for selected points"; - ot->idname = "CURVE_OT_spline_weight_set"; + /* identifiers */ + ot->name = "Set Goal Weight"; + ot->description = "Set softbody goal weight for selected points"; + ot->idname = "CURVE_OT_spline_weight_set"; - /* api callbacks */ - ot->exec = set_goal_weight_exec; - ot->invoke = WM_operator_props_popup; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = set_goal_weight_exec; + ot->invoke = WM_operator_props_popup; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); + /* properties */ + RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f); } /******************* set radius operator ******************/ static int set_radius_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - float radius = RNA_float_get(op->ptr, "radius"); - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - bezt->radius = radius; - } - } - } - else if (nu->bp) { - for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { - if (bp->f1 & SELECT) { - bp->radius = radius; - } - } - } - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + float radius = RNA_float_get(op->ptr, "radius"); + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + bezt->radius = radius; + } + } + } + else if (nu->bp) { + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->f1 & SELECT) { + bp->radius = radius; + } + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + + return OPERATOR_FINISHED; } void CURVE_OT_radius_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Curve Radius"; - ot->description = "Set per-point radius which is used for bevel tapering"; - ot->idname = "CURVE_OT_radius_set"; + /* identifiers */ + ot->name = "Set Curve Radius"; + ot->description = "Set per-point radius which is used for bevel tapering"; + ot->idname = "CURVE_OT_radius_set"; - /* api callbacks */ - ot->exec = set_radius_exec; - ot->invoke = WM_operator_props_popup; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = set_radius_exec; + ot->invoke = WM_operator_props_popup; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f); + /* properties */ + RNA_def_float( + ot->srna, "radius", 1.0f, 0.0f, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.0001f, 10.0f); } /********************* smooth operator ********************/ -static void smooth_single_bezt( - BezTriple *bezt, - const BezTriple *bezt_orig_prev, const BezTriple *bezt_orig_next, - float factor) +static void smooth_single_bezt(BezTriple *bezt, + const BezTriple *bezt_orig_prev, + const BezTriple *bezt_orig_next, + float factor) { - int i; + int i; - BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f)); + BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f)); - for (i = 0; i < 3; i++) { - float val_old, val_new, offset; + for (i = 0; i < 3; i++) { + float val_old, val_new, offset; - /* get single dimension pos of the mid handle */ - val_old = bezt->vec[1][i]; + /* get single dimension pos of the mid handle */ + val_old = bezt->vec[1][i]; - /* get the weights of the previous/next mid handles and calc offset */ - val_new = (bezt_orig_prev->vec[1][i] * 0.5f) + (bezt_orig_next->vec[1][i] * 0.5f); - offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old; + /* get the weights of the previous/next mid handles and calc offset */ + val_new = (bezt_orig_prev->vec[1][i] * 0.5f) + (bezt_orig_next->vec[1][i] * 0.5f); + offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old; - /* offset midpoint and 2 handles */ - bezt->vec[1][i] += offset; - bezt->vec[0][i] += offset; - bezt->vec[2][i] += offset; - } + /* offset midpoint and 2 handles */ + bezt->vec[1][i] += offset; + bezt->vec[0][i] += offset; + bezt->vec[2][i] += offset; + } } /** * Same as #smooth_single_bezt(), keep in sync. */ -static void smooth_single_bp( - BPoint *bp, - const BPoint *bp_orig_prev, const BPoint *bp_orig_next, - float factor) +static void smooth_single_bp(BPoint *bp, + const BPoint *bp_orig_prev, + const BPoint *bp_orig_next, + float factor) { - int i; + int i; - BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f)); + BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f)); - for (i = 0; i < 3; i++) { - float val_old, val_new, offset; + for (i = 0; i < 3; i++) { + float val_old, val_new, offset; - val_old = bp->vec[i]; - val_new = (bp_orig_prev->vec[i] * 0.5f) + (bp_orig_next->vec[i] * 0.5f); - offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old; + val_old = bp->vec[i]; + val_new = (bp_orig_prev->vec[i] * 0.5f) + (bp_orig_next->vec[i] * 0.5f); + offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old; - bp->vec[i] += offset; - } + bp->vec[i] += offset; + } } static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) { - const float factor = 1.0f / 6.0f; - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - - int a, a_end; - bool changed = false; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - /* duplicate the curve to use in weight calculation */ - const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); - BezTriple *bezt; - changed = false; - - /* check whether its cyclic or not, and set initial & final conditions */ - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } - - /* for all the curve points */ - for (; a < a_end; a++) { - /* respect selection */ - bezt = &nu->bezt[a]; - if (bezt->f2 & SELECT) { - const BezTriple *bezt_orig_prev, *bezt_orig_next; - - bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; - bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; - - smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); - - changed = true; - } - } - MEM_freeN((void *)bezt_orig); - if (changed) { - BKE_nurb_handles_calc(nu); - } - } - else if (nu->bp) { - /* Same as above, keep these the same! */ - const BPoint *bp_orig = MEM_dupallocN(nu->bp); - BPoint *bp; - - if (nu->flagu & CU_NURB_CYCLIC) { - a = 0; - a_end = nu->pntsu; - } - else { - a = 1; - a_end = nu->pntsu - 1; - } - - for (; a < a_end; a++) { - bp = &nu->bp[a]; - if (bp->f1 & SELECT) { - const BPoint *bp_orig_prev, *bp_orig_next; - - bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; - bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; - - smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); - } - } - MEM_freeN((void *)bp_orig); - } - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - - return OPERATOR_FINISHED; + const float factor = 1.0f / 6.0f; + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + + int a, a_end; + bool changed = false; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + /* duplicate the curve to use in weight calculation */ + const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); + BezTriple *bezt; + changed = false; + + /* check whether its cyclic or not, and set initial & final conditions */ + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } + + /* for all the curve points */ + for (; a < a_end; a++) { + /* respect selection */ + bezt = &nu->bezt[a]; + if (bezt->f2 & SELECT) { + const BezTriple *bezt_orig_prev, *bezt_orig_next; + + bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)]; + bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)]; + + smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor); + + changed = true; + } + } + MEM_freeN((void *)bezt_orig); + if (changed) { + BKE_nurb_handles_calc(nu); + } + } + else if (nu->bp) { + /* Same as above, keep these the same! */ + const BPoint *bp_orig = MEM_dupallocN(nu->bp); + BPoint *bp; + + if (nu->flagu & CU_NURB_CYCLIC) { + a = 0; + a_end = nu->pntsu; + } + else { + a = 1; + a_end = nu->pntsu - 1; + } + + for (; a < a_end; a++) { + bp = &nu->bp[a]; + if (bp->f1 & SELECT) { + const BPoint *bp_orig_prev, *bp_orig_next; + + bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)]; + bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)]; + + smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor); + } + } + MEM_freeN((void *)bp_orig); + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + + return OPERATOR_FINISHED; } void CURVE_OT_smooth(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth"; - ot->description = "Flatten angles of selected points"; - ot->idname = "CURVE_OT_smooth"; + /* identifiers */ + ot->name = "Smooth"; + ot->description = "Flatten angles of selected points"; + ot->idname = "CURVE_OT_smooth"; - /* api callbacks */ - ot->exec = smooth_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = smooth_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* -------------------------------------------------------------------- */ @@ -2823,418 +2840,439 @@ void CURVE_OT_smooth(wmOperatorType *ot) * TODO: support cyclic curves */ -static void curve_smooth_value(ListBase *editnurb, - const int bezt_offsetof, const int bp_offset) +static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset) { - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; - /* use for smoothing */ - int last_sel; - int start_sel, end_sel; /* selection indices, inclusive */ - float start_rad, end_rad, fac, range; + /* use for smoothing */ + int last_sel; + int start_sel, end_sel; /* selection indices, inclusive */ + float start_rad, end_rad, fac, range; - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { #define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof))) - for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { - /* loop over selection segments of a curve, smooth each */ - - /* Start BezTriple code, - * this is duplicated below for points, make sure these functions stay in sync */ - start_sel = -1; - for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) { - if (bezt->f2 & SELECT) { - start_sel = a; - break; - } - } - /* in case there are no other selected verts */ - end_sel = start_sel; - for (bezt = &nu->bezt[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bezt++) { - if ((bezt->f2 & SELECT) == 0) { - break; - } - end_sel = a; - } - - if (start_sel == -1) { - last_sel = nu->pntsu; /* next... */ - } - else { - last_sel = end_sel; /* before we modify it */ - - /* now blend between start and end sel */ - start_rad = end_rad = FLT_MAX; - - if (start_sel == end_sel) { - /* simple, only 1 point selected */ - if (start_sel > 0) { start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); } - if (end_sel != -1 && end_sel < nu->pntsu) { end_rad = BEZT_VALUE(&nu->bezt[start_sel + 1]); } - - if (start_rad != FLT_MAX && end_rad >= FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f; } - else if (start_rad != FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = start_rad; } - else if (end_rad != FLT_MAX) { BEZT_VALUE(&nu->bezt[start_sel]) = end_rad; } - } - else { - /* if endpoints selected, then use them */ - if (start_sel == 0) { - start_rad = BEZT_VALUE(&nu->bezt[start_sel]); - start_sel++; /* we don't want to edit the selected endpoint */ - } - else { - start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); - } - if (end_sel == nu->pntsu - 1) { - end_rad = BEZT_VALUE(&nu->bezt[end_sel]); - end_sel--; /* we don't want to edit the selected endpoint */ - } - else { - end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]); - } - - /* Now Blend between the points */ - range = (float)(end_sel - start_sel) + 2.0f; - for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) { - fac = (float)(1 + a - start_sel) / range; - BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac; - } - } - } - } + for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { + /* loop over selection segments of a curve, smooth each */ + + /* Start BezTriple code, + * this is duplicated below for points, make sure these functions stay in sync */ + start_sel = -1; + for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) { + if (bezt->f2 & SELECT) { + start_sel = a; + break; + } + } + /* in case there are no other selected verts */ + end_sel = start_sel; + for (bezt = &nu->bezt[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bezt++) { + if ((bezt->f2 & SELECT) == 0) { + break; + } + end_sel = a; + } + + if (start_sel == -1) { + last_sel = nu->pntsu; /* next... */ + } + else { + last_sel = end_sel; /* before we modify it */ + + /* now blend between start and end sel */ + start_rad = end_rad = FLT_MAX; + + if (start_sel == end_sel) { + /* simple, only 1 point selected */ + if (start_sel > 0) { + start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); + } + if (end_sel != -1 && end_sel < nu->pntsu) { + end_rad = BEZT_VALUE(&nu->bezt[start_sel + 1]); + } + + if (start_rad != FLT_MAX && end_rad >= FLT_MAX) { + BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f; + } + else if (start_rad != FLT_MAX) { + BEZT_VALUE(&nu->bezt[start_sel]) = start_rad; + } + else if (end_rad != FLT_MAX) { + BEZT_VALUE(&nu->bezt[start_sel]) = end_rad; + } + } + else { + /* if endpoints selected, then use them */ + if (start_sel == 0) { + start_rad = BEZT_VALUE(&nu->bezt[start_sel]); + start_sel++; /* we don't want to edit the selected endpoint */ + } + else { + start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); + } + if (end_sel == nu->pntsu - 1) { + end_rad = BEZT_VALUE(&nu->bezt[end_sel]); + end_sel--; /* we don't want to edit the selected endpoint */ + } + else { + end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]); + } + + /* Now Blend between the points */ + range = (float)(end_sel - start_sel) + 2.0f; + for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) { + fac = (float)(1 + a - start_sel) / range; + BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac; + } + } + } + } #undef BEZT_VALUE - } - else if (nu->bp) { + } + else if (nu->bp) { #define BP_VALUE(bp) (*((float *)((char *)(bp) + bp_offset))) - /* Same as above, keep these the same! */ - for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { - /* loop over selection segments of a curve, smooth each */ - - /* Start BezTriple code, - * this is duplicated below for points, make sure these functions stay in sync */ - start_sel = -1; - for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) { - if (bp->f1 & SELECT) { - start_sel = a; - break; - } - } - /* in case there are no other selected verts */ - end_sel = start_sel; - for (bp = &nu->bp[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bp++) { - if ((bp->f1 & SELECT) == 0) { - break; - } - end_sel = a; - } - - if (start_sel == -1) { - last_sel = nu->pntsu; /* next... */ - } - else { - last_sel = end_sel; /* before we modify it */ - - /* now blend between start and end sel */ - start_rad = end_rad = FLT_MAX; - - if (start_sel == end_sel) { - /* simple, only 1 point selected */ - if (start_sel > 0) { start_rad = BP_VALUE(&nu->bp[start_sel - 1]); } - if (end_sel != -1 && end_sel < nu->pntsu) { end_rad = BP_VALUE(&nu->bp[start_sel + 1]); } - - if (start_rad != FLT_MAX && end_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = (start_rad + end_rad) / 2; } - else if (start_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = start_rad; } - else if (end_rad != FLT_MAX) { BP_VALUE(&nu->bp[start_sel]) = end_rad; } - } - else { - /* if endpoints selected, then use them */ - if (start_sel == 0) { - start_rad = BP_VALUE(&nu->bp[start_sel]); - start_sel++; /* we don't want to edit the selected endpoint */ - } - else { - start_rad = BP_VALUE(&nu->bp[start_sel - 1]); - } - if (end_sel == nu->pntsu - 1) { - end_rad = BP_VALUE(&nu->bp[end_sel]); - end_sel--; /* we don't want to edit the selected endpoint */ - } - else { - end_rad = BP_VALUE(&nu->bp[end_sel + 1]); - } - - /* Now Blend between the points */ - range = (float)(end_sel - start_sel) + 2.0f; - for (bp = &nu->bp[start_sel], a = start_sel; a <= end_sel; a++, bp++) { - fac = (float)(1 + a - start_sel) / range; - BP_VALUE(bp) = start_rad * (1.0f - fac) + end_rad * fac; - } - } - } - } + /* Same as above, keep these the same! */ + for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { + /* loop over selection segments of a curve, smooth each */ + + /* Start BezTriple code, + * this is duplicated below for points, make sure these functions stay in sync */ + start_sel = -1; + for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) { + if (bp->f1 & SELECT) { + start_sel = a; + break; + } + } + /* in case there are no other selected verts */ + end_sel = start_sel; + for (bp = &nu->bp[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bp++) { + if ((bp->f1 & SELECT) == 0) { + break; + } + end_sel = a; + } + + if (start_sel == -1) { + last_sel = nu->pntsu; /* next... */ + } + else { + last_sel = end_sel; /* before we modify it */ + + /* now blend between start and end sel */ + start_rad = end_rad = FLT_MAX; + + if (start_sel == end_sel) { + /* simple, only 1 point selected */ + if (start_sel > 0) { + start_rad = BP_VALUE(&nu->bp[start_sel - 1]); + } + if (end_sel != -1 && end_sel < nu->pntsu) { + end_rad = BP_VALUE(&nu->bp[start_sel + 1]); + } + + if (start_rad != FLT_MAX && end_rad != FLT_MAX) { + BP_VALUE(&nu->bp[start_sel]) = (start_rad + end_rad) / 2; + } + else if (start_rad != FLT_MAX) { + BP_VALUE(&nu->bp[start_sel]) = start_rad; + } + else if (end_rad != FLT_MAX) { + BP_VALUE(&nu->bp[start_sel]) = end_rad; + } + } + else { + /* if endpoints selected, then use them */ + if (start_sel == 0) { + start_rad = BP_VALUE(&nu->bp[start_sel]); + start_sel++; /* we don't want to edit the selected endpoint */ + } + else { + start_rad = BP_VALUE(&nu->bp[start_sel - 1]); + } + if (end_sel == nu->pntsu - 1) { + end_rad = BP_VALUE(&nu->bp[end_sel]); + end_sel--; /* we don't want to edit the selected endpoint */ + } + else { + end_rad = BP_VALUE(&nu->bp[end_sel + 1]); + } + + /* Now Blend between the points */ + range = (float)(end_sel - start_sel) + 2.0f; + for (bp = &nu->bp[start_sel], a = start_sel; a <= end_sel; a++, bp++) { + fac = (float)(1 + a - start_sel) / range; + BP_VALUE(bp) = start_rad * (1.0f - fac) + end_rad * fac; + } + } + } + } #undef BP_VALUE - } - } + } + } } static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); - curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); + curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_smooth_weight(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth Curve Weight"; - ot->description = "Interpolate weight of selected points"; - ot->idname = "CURVE_OT_smooth_weight"; + /* identifiers */ + ot->name = "Smooth Curve Weight"; + ot->description = "Interpolate weight of selected points"; + ot->idname = "CURVE_OT_smooth_weight"; - /* api clastbacks */ - ot->exec = curve_smooth_weight_exec; - ot->poll = ED_operator_editsurfcurve; + /* api clastbacks */ + ot->exec = curve_smooth_weight_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); - curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); + curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_smooth_radius(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth Curve Radius"; - ot->description = "Interpolate radii of selected points"; - ot->idname = "CURVE_OT_smooth_radius"; + /* identifiers */ + ot->name = "Smooth Curve Radius"; + ot->description = "Interpolate radii of selected points"; + ot->idname = "CURVE_OT_smooth_radius"; - /* api clastbacks */ - ot->exec = curve_smooth_radius_exec; - ot->poll = ED_operator_editsurfcurve; + /* api clastbacks */ + ot->exec = curve_smooth_radius_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); - curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); + curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt)); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_smooth_tilt(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Smooth Curve Tilt"; - ot->description = "Interpolate tilt of selected points"; - ot->idname = "CURVE_OT_smooth_tilt"; + /* identifiers */ + ot->name = "Smooth Curve Tilt"; + ot->description = "Interpolate tilt of selected points"; + ot->idname = "CURVE_OT_smooth_tilt"; - /* api clastbacks */ - ot->exec = curve_smooth_tilt_exec; - ot->poll = ED_operator_editsurfcurve; + /* api clastbacks */ + ot->exec = curve_smooth_tilt_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** hide operator *********************/ static int hide_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - const bool invert = RNA_boolean_get(op->ptr, "unselected"); - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (!(invert || ED_curve_select_check(v3d, cu->editnurb))) { - continue; - } - - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a, sel; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - sel = 0; - while (a--) { - if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - bezt->hide = 1; - } - else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - bezt->hide = 1; - } - if (bezt->hide) { - sel++; - } - bezt++; - } - if (sel == nu->pntsu) { - nu->hide = 1; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - sel = 0; - while (a--) { - if (invert == 0 && (bp->f1 & SELECT)) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); - bp->hide = 1; - } - else if (invert && (bp->f1 & SELECT) == 0) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); - bp->hide = 1; - } - if (bp->hide) { - sel++; - } - bp++; - } - if (sel == nu->pntsu * nu->pntsv) { - nu->hide = 1; - } - } - } - - DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + const bool invert = RNA_boolean_get(op->ptr, "unselected"); + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (!(invert || ED_curve_select_check(v3d, cu->editnurb))) { + continue; + } + + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a, sel; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + sel = 0; + while (a--) { + if (invert == 0 && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + bezt->hide = 1; + } + else if (invert && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + bezt->hide = 1; + } + if (bezt->hide) { + sel++; + } + bezt++; + } + if (sel == nu->pntsu) { + nu->hide = 1; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + sel = 0; + while (a--) { + if (invert == 0 && (bp->f1 & SELECT)) { + select_bpoint(bp, DESELECT, SELECT, HIDDEN); + bp->hide = 1; + } + else if (invert && (bp->f1 & SELECT) == 0) { + select_bpoint(bp, DESELECT, SELECT, HIDDEN); + bp->hide = 1; + } + if (bp->hide) { + sel++; + } + bp++; + } + if (sel == nu->pntsu * nu->pntsv) { + nu->hide = 1; + } + } + } + + DEG_id_tag_update(obedit->data, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + BKE_curve_nurb_vert_active_validate(obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_hide(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Hide Selected"; - ot->idname = "CURVE_OT_hide"; - ot->description = "Hide (un)selected control points"; + /* identifiers */ + ot->name = "Hide Selected"; + ot->idname = "CURVE_OT_hide"; + ot->description = "Hide (un)selected control points"; - /* api callbacks */ - ot->exec = hide_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = hide_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); + /* props */ + RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); } /********************** reveal operator *********************/ static int reveal_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - const bool select = RNA_boolean_get(op->ptr, "select"); - bool changed_multi = false; - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - bool changed = false; - - for (nu = editnurb->first; nu; nu = nu->next) { - nu->hide = 0; - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (bezt->hide) { - select_beztriple(bezt, select, SELECT, HIDDEN); - bezt->hide = 0; - changed = true; - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->hide) { - select_bpoint(bp, select, SELECT, HIDDEN); - bp->hide = 0; - changed = true; - } - bp++; - } - } - } - - if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - changed_multi = true; - } - } - MEM_freeN(objects); - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool select = RNA_boolean_get(op->ptr, "select"); + bool changed_multi = false; + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + bool changed = false; + + for (nu = editnurb->first; nu; nu = nu->next) { + nu->hide = 0; + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + if (bezt->hide) { + select_beztriple(bezt, select, SELECT, HIDDEN); + bezt->hide = 0; + changed = true; + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->hide) { + select_bpoint(bp, select, SELECT, HIDDEN); + bp->hide = 0; + changed = true; + } + bp++; + } + } + } + + if (changed) { + DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + changed_multi = true; + } + } + MEM_freeN(objects); + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } void CURVE_OT_reveal(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Reveal Hidden"; - ot->idname = "CURVE_OT_reveal"; - ot->description = "Reveal hidden control points"; + /* identifiers */ + ot->name = "Reveal Hidden"; + ot->idname = "CURVE_OT_reveal"; + ot->description = "Reveal hidden control points"; - /* api callbacks */ - ot->exec = reveal_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = reveal_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "select", true, "Select", ""); + RNA_def_boolean(ot->srna, "select", true, "Select", ""); } /********************** subdivide operator *********************/ @@ -3245,779 +3283,814 @@ void CURVE_OT_reveal(wmOperatorType *ot) */ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) { - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - Nurb *nu; - BezTriple *bezt, *beztnew, *beztn; - BPoint *bp, *prevbp, *bpnew, *bpn; - float vec[15]; - int a, b, sel, amount, *usel, *vsel, i; - float factor; - - // printf("*** subdivideNurb: entering subdivide\n"); - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - amount = 0; - if (nu->type == CU_BEZIER) { - BezTriple *nextbezt; - - /* - * Insert a point into a 2D Bezier curve. - * Endpoints are preserved. Otherwise, all selected and inserted points are - * newly created. Old points are discarded. - */ - /* count */ - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - nextbezt = BKE_nurb_bezt_get_next(nu, bezt); - if (nextbezt == NULL) { - break; - } - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) { - amount += number_cuts; - } - bezt++; - } - - if (amount) { - /* insert */ - beztnew = (BezTriple *)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb"); - beztn = beztnew; - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - memcpy(beztn, bezt, sizeof(BezTriple)); - keyIndex_updateBezt(editnurb, bezt, beztn, 1); - beztn++; - - nextbezt = BKE_nurb_bezt_get_next(nu, bezt); - if (nextbezt == NULL) { - break; - } - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) { - float prevvec[3][3]; - - memcpy(prevvec, bezt->vec, sizeof(float) * 9); - - for (i = 0; i < number_cuts; i++) { - factor = 1.0f / (number_cuts + 1 - i); - - memcpy(beztn, nextbezt, sizeof(BezTriple)); - - /* midpoint subdividing */ - interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor); - interp_v3_v3v3(vec + 3, prevvec[2], nextbezt->vec[0], factor); - interp_v3_v3v3(vec + 6, nextbezt->vec[0], nextbezt->vec[1], factor); - - interp_v3_v3v3(vec + 9, vec, vec + 3, factor); - interp_v3_v3v3(vec + 12, vec + 3, vec + 6, factor); - - /* change handle of prev beztn */ - copy_v3_v3((beztn - 1)->vec[2], vec); - /* new point */ - copy_v3_v3(beztn->vec[0], vec + 9); - interp_v3_v3v3(beztn->vec[1], vec + 9, vec + 12, factor); - copy_v3_v3(beztn->vec[2], vec + 12); - /* handle of next bezt */ - if (a == 0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) { copy_v3_v3(beztnew->vec[0], vec + 6); } - else { copy_v3_v3(nextbezt->vec[0], vec + 6); } - - beztn->radius = (bezt->radius + nextbezt->radius) / 2; - beztn->weight = (bezt->weight + nextbezt->weight) / 2; - - memcpy(prevvec, beztn->vec, sizeof(float) * 9); - beztn++; - } - } - - bezt++; - } - - MEM_freeN(nu->bezt); - nu->bezt = beztnew; - nu->pntsu += amount; - - BKE_nurb_handles_calc(nu); - } - } /* End of 'if (nu->type == CU_BEZIER)' */ - else if (nu->pntsv == 1) { - BPoint *nextbp; - - /* - * All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves - * are handled together with the regular NURB plane division, as it - * should be. I split it off just now, let's see if it is - * stable... nzc 30-5-'00 - */ - /* count */ - a = nu->pntsu; - bp = nu->bp; - while (a--) { - nextbp = BKE_nurb_bpoint_get_next(nu, bp); - if (nextbp == NULL) { - break; - } - - if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) { - amount += number_cuts; - } - bp++; - } - - if (amount) { - /* insert */ - bpnew = (BPoint *)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2"); - bpn = bpnew; - - a = nu->pntsu; - bp = nu->bp; - - while (a--) { - /* Copy "old" point. */ - memcpy(bpn, bp, sizeof(BPoint)); - keyIndex_updateBP(editnurb, bp, bpn, 1); - bpn++; - - nextbp = BKE_nurb_bpoint_get_next(nu, bp); - if (nextbp == NULL) { - break; - } - - if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) { - // printf("*** subdivideNurb: insert 'linear' point\n"); - for (i = 0; i < number_cuts; i++) { - factor = (float)(i + 1) / (number_cuts + 1); - - memcpy(bpn, nextbp, sizeof(BPoint)); - interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor); - bpn++; - } - - } - bp++; - } - - MEM_freeN(nu->bp); - nu->bp = bpnew; - nu->pntsu += amount; - - if (nu->type & CU_NURBS) { - BKE_nurb_knot_calc_u(nu); - } - } - } /* End of 'else if (nu->pntsv == 1)' */ - else if (nu->type == CU_NURBS) { - /* This is a very strange test ... */ - /** - * Subdivide NURB surfaces - nzc 30-5-'00 - - * - * Subdivision of a NURB curve can be effected by adding a - * control point (insertion of a knot), or by raising the - * degree of the functions used to build the NURB. The - * expression - * - * degree = #knots - #controlpoints + 1 (J Walter piece) - * degree = #knots - #controlpoints (Blender - * implementation) - * ( this is confusing.... what is true? Another concern - * is that the JW piece allows the curve to become - * explicitly 1st order derivative discontinuous, while - * this is not what we want here... ) - * - * is an invariant for a single NURB curve. Raising the degree - * of the NURB is done elsewhere; the degree is assumed - * constant during this operation. Degree is a property shared - * by all controlpoints in a curve (even though it is stored - * per control point - this can be misleading). - * Adding a knot is done by searching for the place in the - * knot vector where a certain knot value must be inserted, or - * by picking an appropriate knot value between two existing - * ones. The number of controlpoints that is influenced by the - * insertion depends on the order of the curve. A certain - * minimum number of knots is needed to form high-order - * curves, as can be seen from the equation above. In Blender, - * currently NURBs may be up to 6th order, so we modify at - * most 6 points. One point is added. For an n-degree curve, - * n points are discarded, and n+1 points inserted - * (so effectively, n points are modified). (that holds for - * the JW piece, but it seems not for our NURBs) - * In practice, the knot spacing is copied, but the tail - * (the points following the insertion point) need to be - * offset to keep the knot series ascending. The knot series - * is always a series of monotonically ascending integers in - * Blender. When not enough control points are available to - * fit the order, duplicates of the endpoints are added as - * needed. - */ - /* selection-arrays */ - usel = MEM_callocN(sizeof(int) * nu->pntsu, "subivideNurb3"); - vsel = MEM_callocN(sizeof(int) * nu->pntsv, "subivideNurb3"); - sel = 0; - - /* Count the number of selected points. */ - bp = nu->bp; - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++) { - if (bp->f1 & SELECT) { - usel[b]++; - vsel[a]++; - sel++; - } - bp++; - } - } - if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */ - /* Global subdivision is a special case of partial - * subdivision. Strange it is considered separately... */ - - /* count of nodes (after subdivision) along U axis */ - int countu = nu->pntsu + (nu->pntsu - 1) * number_cuts; - - /* total count of nodes after subdivision */ - int tot = ((number_cuts + 1) * nu->pntsu - number_cuts) * ((number_cuts + 1) * nu->pntsv - number_cuts); - - bpn = bpnew = MEM_mallocN(tot * sizeof(BPoint), "subdivideNurb4"); - bp = nu->bp; - /* first subdivide rows */ - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++) { - *bpn = *bp; - keyIndex_updateBP(editnurb, bp, bpn, 1); - bpn++; - bp++; - if (b < nu->pntsu - 1) { - prevbp = bp - 1; - for (i = 0; i < number_cuts; i++) { - factor = (float)(i + 1) / (number_cuts + 1); - *bpn = *bp; - interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); - bpn++; - } - } - } - bpn += number_cuts * countu; - } - /* now insert new */ - bpn = bpnew + ((number_cuts + 1) * nu->pntsu - number_cuts); - bp = bpnew + (number_cuts + 1) * ((number_cuts + 1) * nu->pntsu - number_cuts); - prevbp = bpnew; - for (a = 1; a < nu->pntsv; a++) { - - for (b = 0; b < (number_cuts + 1) * nu->pntsu - number_cuts; b++) { - BPoint *tmp = bpn; - for (i = 0; i < number_cuts; i++) { - factor = (float)(i + 1) / (number_cuts + 1); - *tmp = *bp; - interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor); - tmp += countu; - } - bp++; - prevbp++; - bpn++; - } - bp += number_cuts * countu; - bpn += number_cuts * countu; - prevbp += number_cuts * countu; - } - MEM_freeN(nu->bp); - nu->bp = bpnew; - nu->pntsu = (number_cuts + 1) * nu->pntsu - number_cuts; - nu->pntsv = (number_cuts + 1) * nu->pntsv - number_cuts; - BKE_nurb_knot_calc_u(nu); - BKE_nurb_knot_calc_v(nu); - } /* End of 'if (sel == nu->pntsu * nu->pntsv)' (subdivide entire NURB) */ - else { - /* subdivide in v direction? */ - sel = 0; - for (a = 0; a < nu->pntsv - 1; a++) { - if (vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) { - sel += number_cuts; - } - } - - if (sel) { /* V ! */ - bpn = bpnew = MEM_mallocN((sel + nu->pntsv) * nu->pntsu * sizeof(BPoint), "subdivideNurb4"); - bp = nu->bp; - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++) { - *bpn = *bp; - keyIndex_updateBP(editnurb, bp, bpn, 1); - bpn++; - bp++; - } - if ( (a < nu->pntsv - 1) && vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) { - for (i = 0; i < number_cuts; i++) { - factor = (float)(i + 1) / (number_cuts + 1); - prevbp = bp - nu->pntsu; - for (b = 0; b < nu->pntsu; b++) { - /* - * This simple bisection must be replaces by a - * subtle resampling of a number of points. Our - * task is made slightly easier because each - * point in our curve is a separate data - * node. (is it?) - */ - *bpn = *prevbp; - interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); - bpn++; - - prevbp++; - bp++; - } - bp -= nu->pntsu; - } - } - } - MEM_freeN(nu->bp); - nu->bp = bpnew; - nu->pntsv += sel; - BKE_nurb_knot_calc_v(nu); - } - else { - /* or in u direction? */ - sel = 0; - for (a = 0; a < nu->pntsu - 1; a++) { - if (usel[a] == nu->pntsv && usel[a + 1] == nu->pntsv) { - sel += number_cuts; - } - } - - if (sel) { /* U ! */ - /* Inserting U points is sort of 'default' Flat curves only get */ - /* U points inserted in them. */ - bpn = bpnew = MEM_mallocN((sel + nu->pntsu) * nu->pntsv * sizeof(BPoint), "subdivideNurb4"); - bp = nu->bp; - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++) { - *bpn = *bp; - keyIndex_updateBP(editnurb, bp, bpn, 1); - bpn++; - bp++; - if ( (b < nu->pntsu - 1) && usel[b] == nu->pntsv && usel[b + 1] == nu->pntsv) { - /* - * One thing that bugs me here is that the - * orders of things are not the same as in - * the JW piece. Also, this implies that we - * handle at most 3rd order curves? I miss - * some symmetry here... - */ - for (i = 0; i < number_cuts; i++) { - factor = (float)(i + 1) / (number_cuts + 1); - prevbp = bp - 1; - *bpn = *prevbp; - interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); - bpn++; - } - } - } - } - MEM_freeN(nu->bp); - nu->bp = bpnew; - nu->pntsu += sel; - BKE_nurb_knot_calc_u(nu); /* shift knots forward */ - } - } - } - MEM_freeN(usel); - MEM_freeN(vsel); - - } /* End of 'if (nu->type == CU_NURBS)' */ - } + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + Nurb *nu; + BezTriple *bezt, *beztnew, *beztn; + BPoint *bp, *prevbp, *bpnew, *bpn; + float vec[15]; + int a, b, sel, amount, *usel, *vsel, i; + float factor; + + // printf("*** subdivideNurb: entering subdivide\n"); + + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + amount = 0; + if (nu->type == CU_BEZIER) { + BezTriple *nextbezt; + + /* + * Insert a point into a 2D Bezier curve. + * Endpoints are preserved. Otherwise, all selected and inserted points are + * newly created. Old points are discarded. + */ + /* count */ + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + nextbezt = BKE_nurb_bezt_get_next(nu, bezt); + if (nextbezt == NULL) { + break; + } + + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) { + amount += number_cuts; + } + bezt++; + } + + if (amount) { + /* insert */ + beztnew = (BezTriple *)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb"); + beztn = beztnew; + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + memcpy(beztn, bezt, sizeof(BezTriple)); + keyIndex_updateBezt(editnurb, bezt, beztn, 1); + beztn++; + + nextbezt = BKE_nurb_bezt_get_next(nu, bezt); + if (nextbezt == NULL) { + break; + } + + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nextbezt)) { + float prevvec[3][3]; + + memcpy(prevvec, bezt->vec, sizeof(float) * 9); + + for (i = 0; i < number_cuts; i++) { + factor = 1.0f / (number_cuts + 1 - i); + + memcpy(beztn, nextbezt, sizeof(BezTriple)); + + /* midpoint subdividing */ + interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor); + interp_v3_v3v3(vec + 3, prevvec[2], nextbezt->vec[0], factor); + interp_v3_v3v3(vec + 6, nextbezt->vec[0], nextbezt->vec[1], factor); + + interp_v3_v3v3(vec + 9, vec, vec + 3, factor); + interp_v3_v3v3(vec + 12, vec + 3, vec + 6, factor); + + /* change handle of prev beztn */ + copy_v3_v3((beztn - 1)->vec[2], vec); + /* new point */ + copy_v3_v3(beztn->vec[0], vec + 9); + interp_v3_v3v3(beztn->vec[1], vec + 9, vec + 12, factor); + copy_v3_v3(beztn->vec[2], vec + 12); + /* handle of next bezt */ + if (a == 0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) { + copy_v3_v3(beztnew->vec[0], vec + 6); + } + else { + copy_v3_v3(nextbezt->vec[0], vec + 6); + } + + beztn->radius = (bezt->radius + nextbezt->radius) / 2; + beztn->weight = (bezt->weight + nextbezt->weight) / 2; + + memcpy(prevvec, beztn->vec, sizeof(float) * 9); + beztn++; + } + } + + bezt++; + } + + MEM_freeN(nu->bezt); + nu->bezt = beztnew; + nu->pntsu += amount; + + BKE_nurb_handles_calc(nu); + } + } /* End of 'if (nu->type == CU_BEZIER)' */ + else if (nu->pntsv == 1) { + BPoint *nextbp; + + /* + * All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves + * are handled together with the regular NURB plane division, as it + * should be. I split it off just now, let's see if it is + * stable... nzc 30-5-'00 + */ + /* count */ + a = nu->pntsu; + bp = nu->bp; + while (a--) { + nextbp = BKE_nurb_bpoint_get_next(nu, bp); + if (nextbp == NULL) { + break; + } + + if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) { + amount += number_cuts; + } + bp++; + } + + if (amount) { + /* insert */ + bpnew = (BPoint *)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2"); + bpn = bpnew; + + a = nu->pntsu; + bp = nu->bp; + + while (a--) { + /* Copy "old" point. */ + memcpy(bpn, bp, sizeof(BPoint)); + keyIndex_updateBP(editnurb, bp, bpn, 1); + bpn++; + + nextbp = BKE_nurb_bpoint_get_next(nu, bp); + if (nextbp == NULL) { + break; + } + + if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) { + // printf("*** subdivideNurb: insert 'linear' point\n"); + for (i = 0; i < number_cuts; i++) { + factor = (float)(i + 1) / (number_cuts + 1); + + memcpy(bpn, nextbp, sizeof(BPoint)); + interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor); + bpn++; + } + } + bp++; + } + + MEM_freeN(nu->bp); + nu->bp = bpnew; + nu->pntsu += amount; + + if (nu->type & CU_NURBS) { + BKE_nurb_knot_calc_u(nu); + } + } + } /* End of 'else if (nu->pntsv == 1)' */ + else if (nu->type == CU_NURBS) { + /* This is a very strange test ... */ + /** + * Subdivide NURB surfaces - nzc 30-5-'00 - + * + * Subdivision of a NURB curve can be effected by adding a + * control point (insertion of a knot), or by raising the + * degree of the functions used to build the NURB. The + * expression + * + * degree = #knots - #controlpoints + 1 (J Walter piece) + * degree = #knots - #controlpoints (Blender + * implementation) + * ( this is confusing.... what is true? Another concern + * is that the JW piece allows the curve to become + * explicitly 1st order derivative discontinuous, while + * this is not what we want here... ) + * + * is an invariant for a single NURB curve. Raising the degree + * of the NURB is done elsewhere; the degree is assumed + * constant during this operation. Degree is a property shared + * by all controlpoints in a curve (even though it is stored + * per control point - this can be misleading). + * Adding a knot is done by searching for the place in the + * knot vector where a certain knot value must be inserted, or + * by picking an appropriate knot value between two existing + * ones. The number of controlpoints that is influenced by the + * insertion depends on the order of the curve. A certain + * minimum number of knots is needed to form high-order + * curves, as can be seen from the equation above. In Blender, + * currently NURBs may be up to 6th order, so we modify at + * most 6 points. One point is added. For an n-degree curve, + * n points are discarded, and n+1 points inserted + * (so effectively, n points are modified). (that holds for + * the JW piece, but it seems not for our NURBs) + * In practice, the knot spacing is copied, but the tail + * (the points following the insertion point) need to be + * offset to keep the knot series ascending. The knot series + * is always a series of monotonically ascending integers in + * Blender. When not enough control points are available to + * fit the order, duplicates of the endpoints are added as + * needed. + */ + /* selection-arrays */ + usel = MEM_callocN(sizeof(int) * nu->pntsu, "subivideNurb3"); + vsel = MEM_callocN(sizeof(int) * nu->pntsv, "subivideNurb3"); + sel = 0; + + /* Count the number of selected points. */ + bp = nu->bp; + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++) { + if (bp->f1 & SELECT) { + usel[b]++; + vsel[a]++; + sel++; + } + bp++; + } + } + if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */ + /* Global subdivision is a special case of partial + * subdivision. Strange it is considered separately... */ + + /* count of nodes (after subdivision) along U axis */ + int countu = nu->pntsu + (nu->pntsu - 1) * number_cuts; + + /* total count of nodes after subdivision */ + int tot = ((number_cuts + 1) * nu->pntsu - number_cuts) * + ((number_cuts + 1) * nu->pntsv - number_cuts); + + bpn = bpnew = MEM_mallocN(tot * sizeof(BPoint), "subdivideNurb4"); + bp = nu->bp; + /* first subdivide rows */ + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++) { + *bpn = *bp; + keyIndex_updateBP(editnurb, bp, bpn, 1); + bpn++; + bp++; + if (b < nu->pntsu - 1) { + prevbp = bp - 1; + for (i = 0; i < number_cuts; i++) { + factor = (float)(i + 1) / (number_cuts + 1); + *bpn = *bp; + interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); + bpn++; + } + } + } + bpn += number_cuts * countu; + } + /* now insert new */ + bpn = bpnew + ((number_cuts + 1) * nu->pntsu - number_cuts); + bp = bpnew + (number_cuts + 1) * ((number_cuts + 1) * nu->pntsu - number_cuts); + prevbp = bpnew; + for (a = 1; a < nu->pntsv; a++) { + + for (b = 0; b < (number_cuts + 1) * nu->pntsu - number_cuts; b++) { + BPoint *tmp = bpn; + for (i = 0; i < number_cuts; i++) { + factor = (float)(i + 1) / (number_cuts + 1); + *tmp = *bp; + interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor); + tmp += countu; + } + bp++; + prevbp++; + bpn++; + } + bp += number_cuts * countu; + bpn += number_cuts * countu; + prevbp += number_cuts * countu; + } + MEM_freeN(nu->bp); + nu->bp = bpnew; + nu->pntsu = (number_cuts + 1) * nu->pntsu - number_cuts; + nu->pntsv = (number_cuts + 1) * nu->pntsv - number_cuts; + BKE_nurb_knot_calc_u(nu); + BKE_nurb_knot_calc_v(nu); + } /* End of 'if (sel == nu->pntsu * nu->pntsv)' (subdivide entire NURB) */ + else { + /* subdivide in v direction? */ + sel = 0; + for (a = 0; a < nu->pntsv - 1; a++) { + if (vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) { + sel += number_cuts; + } + } + + if (sel) { /* V ! */ + bpn = bpnew = MEM_mallocN((sel + nu->pntsv) * nu->pntsu * sizeof(BPoint), + "subdivideNurb4"); + bp = nu->bp; + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++) { + *bpn = *bp; + keyIndex_updateBP(editnurb, bp, bpn, 1); + bpn++; + bp++; + } + if ((a < nu->pntsv - 1) && vsel[a] == nu->pntsu && vsel[a + 1] == nu->pntsu) { + for (i = 0; i < number_cuts; i++) { + factor = (float)(i + 1) / (number_cuts + 1); + prevbp = bp - nu->pntsu; + for (b = 0; b < nu->pntsu; b++) { + /* + * This simple bisection must be replaces by a + * subtle resampling of a number of points. Our + * task is made slightly easier because each + * point in our curve is a separate data + * node. (is it?) + */ + *bpn = *prevbp; + interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); + bpn++; + + prevbp++; + bp++; + } + bp -= nu->pntsu; + } + } + } + MEM_freeN(nu->bp); + nu->bp = bpnew; + nu->pntsv += sel; + BKE_nurb_knot_calc_v(nu); + } + else { + /* or in u direction? */ + sel = 0; + for (a = 0; a < nu->pntsu - 1; a++) { + if (usel[a] == nu->pntsv && usel[a + 1] == nu->pntsv) { + sel += number_cuts; + } + } + + if (sel) { /* U ! */ + /* Inserting U points is sort of 'default' Flat curves only get */ + /* U points inserted in them. */ + bpn = bpnew = MEM_mallocN((sel + nu->pntsu) * nu->pntsv * sizeof(BPoint), + "subdivideNurb4"); + bp = nu->bp; + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++) { + *bpn = *bp; + keyIndex_updateBP(editnurb, bp, bpn, 1); + bpn++; + bp++; + if ((b < nu->pntsu - 1) && usel[b] == nu->pntsv && usel[b + 1] == nu->pntsv) { + /* + * One thing that bugs me here is that the + * orders of things are not the same as in + * the JW piece. Also, this implies that we + * handle at most 3rd order curves? I miss + * some symmetry here... + */ + for (i = 0; i < number_cuts; i++) { + factor = (float)(i + 1) / (number_cuts + 1); + prevbp = bp - 1; + *bpn = *prevbp; + interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor); + bpn++; + } + } + } + } + MEM_freeN(nu->bp); + nu->bp = bpnew; + nu->pntsu += sel; + BKE_nurb_knot_calc_u(nu); /* shift knots forward */ + } + } + } + MEM_freeN(usel); + MEM_freeN(vsel); + + } /* End of 'if (nu->type == CU_NURBS)' */ + } } static int subdivide_exec(bContext *C, wmOperator *op) { - const int number_cuts = RNA_int_get(op->ptr, "number_cuts"); + const int number_cuts = RNA_int_get(op->ptr, "number_cuts"); - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - subdividenurb(obedit, v3d, number_cuts); + subdividenurb(obedit, v3d, number_cuts); - if (ED_curve_updateAnimPaths(bmain, cu)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } + if (ED_curve_updateAnimPaths(bmain, cu)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, cu); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, cu); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_subdivide(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Subdivide"; - ot->description = "Subdivide selected segments"; - ot->idname = "CURVE_OT_subdivide"; + /* identifiers */ + ot->name = "Subdivide"; + ot->description = "Subdivide selected segments"; + ot->idname = "CURVE_OT_subdivide"; - /* api callbacks */ - ot->exec = subdivide_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = subdivide_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10); - /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */ - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of cuts", "", 1, 10); + /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */ + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /******************** find nearest ************************/ -static void ED_curve_pick_vert__doClosest(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) -{ - struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; bool is_changed; } *data = userData; - - short flag; - float dist_test; - - if (bp) { - flag = bp->f1; - } - else { - if (beztindex == 0) { - flag = bezt->f1; - } - else if (beztindex == 1) { - flag = bezt->f2; - } - else { - flag = bezt->f3; - } - } - - dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if ((flag & SELECT) == data->select) { - dist_test += 5.0f; - } - if (bezt && beztindex == 1) { - dist_test += 3.0f; /* middle points get a small disadvantage */ - } - - if (dist_test < data->dist) { - data->dist = dist_test; - - data->bp = bp; - data->bezt = bezt; - data->nurb = nu; - data->hpoint = bezt ? beztindex : 0; - data->is_changed = true; - } -} - -bool ED_curve_pick_vert( - ViewContext *vc, short sel, - Nurb **r_nurb, BezTriple **r_bezt, BPoint **r_bp, short *r_handle, - Base **r_base) -{ - /* (sel == 1): selected gets a disadvantage */ - /* in nurb and bezt or bp the nearest is written */ - /* return 0 1 2: handlepunt */ - struct { BPoint *bp; BezTriple *bezt; Nurb *nurb; float dist; int hpoint, select; float mval_fl[2]; bool is_changed; } data = {NULL}; - - data.dist = ED_view3d_select_dist_px(); - data.hpoint = 0; - data.select = sel; - data.mval_fl[0] = vc->mval[0]; - data.mval_fl[1] = vc->mval[1]; - - uint bases_len; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &bases_len); - for (uint base_index = 0; base_index < bases_len; base_index++) { - Base *base = bases[base_index]; - data.is_changed = false; - - ED_view3d_viewcontext_init_object(vc, base->object); - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - - if (r_base && data.is_changed) { - *r_base = base; - } - } - MEM_freeN(bases); - - *r_nurb = data.nurb; - *r_bezt = data.bezt; - *r_bp = data.bp; - - if (r_handle) { - *r_handle = data.hpoint; - } - - return (data.bezt || data.bp); +static void ED_curve_pick_vert__doClosest( + void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2]) +{ + struct { + BPoint *bp; + BezTriple *bezt; + Nurb *nurb; + float dist; + int hpoint, select; + float mval_fl[2]; + bool is_changed; + } *data = userData; + + short flag; + float dist_test; + + if (bp) { + flag = bp->f1; + } + else { + if (beztindex == 0) { + flag = bezt->f1; + } + else if (beztindex == 1) { + flag = bezt->f2; + } + else { + flag = bezt->f3; + } + } + + dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + if ((flag & SELECT) == data->select) { + dist_test += 5.0f; + } + if (bezt && beztindex == 1) { + dist_test += 3.0f; /* middle points get a small disadvantage */ + } + + if (dist_test < data->dist) { + data->dist = dist_test; + + data->bp = bp; + data->bezt = bezt; + data->nurb = nu; + data->hpoint = bezt ? beztindex : 0; + data->is_changed = true; + } +} + +bool ED_curve_pick_vert(ViewContext *vc, + short sel, + Nurb **r_nurb, + BezTriple **r_bezt, + BPoint **r_bp, + short *r_handle, + Base **r_base) +{ + /* (sel == 1): selected gets a disadvantage */ + /* in nurb and bezt or bp the nearest is written */ + /* return 0 1 2: handlepunt */ + struct { + BPoint *bp; + BezTriple *bezt; + Nurb *nurb; + float dist; + int hpoint, select; + float mval_fl[2]; + bool is_changed; + } data = {NULL}; + + data.dist = ED_view3d_select_dist_px(); + data.hpoint = 0; + data.select = sel; + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; + + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc->view_layer, vc->v3d, &bases_len); + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base = bases[base_index]; + data.is_changed = false; + + ED_view3d_viewcontext_init_object(vc, base->object); + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + nurbs_foreachScreenVert(vc, ED_curve_pick_vert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + if (r_base && data.is_changed) { + *r_base = base; + } + } + MEM_freeN(bases); + + *r_nurb = data.nurb; + *r_bezt = data.bezt; + *r_bp = data.bp; + + if (r_handle) { + *r_handle = data.hpoint; + } + + return (data.bezt || data.bp); } static void findselectedNurbvert( - Curve *cu, View3D *v3d, - Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp) -{ - /* in nu and (bezt or bp) selected are written if there's 1 sel. */ - /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ - ListBase *editnurb = &cu->editnurb->nurbs; - Nurb *nu1; - BezTriple *bezt1; - BPoint *bp1; - int a; - - *r_nu = NULL; - *r_bezt = NULL; - *r_bp = NULL; - - for (nu1 = editnurb->first; nu1; nu1 = nu1->next) { - if (nu1->type == CU_BEZIER) { - bezt1 = nu1->bezt; - a = nu1->pntsu; - while (a--) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) { - if (*r_nu != NULL && *r_nu != nu1) { - *r_nu = NULL; - *r_bp = NULL; - *r_bezt = NULL; - return; - } - else if (*r_bezt || *r_bp) { - *r_bp = NULL; - *r_bezt = NULL; - } - else { - *r_bezt = bezt1; - *r_nu = nu1; - } - } - bezt1++; - } - } - else { - bp1 = nu1->bp; - a = nu1->pntsu * nu1->pntsv; - while (a--) { - if (bp1->f1 & SELECT) { - if (*r_nu != NULL && *r_nu != nu1) { - *r_bp = NULL; - *r_bezt = NULL; - *r_nu = NULL; - return; - } - else if (*r_bezt || *r_bp) { - *r_bp = NULL; - *r_bezt = NULL; - } - else { - *r_bp = bp1; - *r_nu = nu1; - } - } - bp1++; - } - } - } + Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp) +{ + /* in nu and (bezt or bp) selected are written if there's 1 sel. */ + /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ + ListBase *editnurb = &cu->editnurb->nurbs; + Nurb *nu1; + BezTriple *bezt1; + BPoint *bp1; + int a; + + *r_nu = NULL; + *r_bezt = NULL; + *r_bp = NULL; + + for (nu1 = editnurb->first; nu1; nu1 = nu1->next) { + if (nu1->type == CU_BEZIER) { + bezt1 = nu1->bezt; + a = nu1->pntsu; + while (a--) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) { + if (*r_nu != NULL && *r_nu != nu1) { + *r_nu = NULL; + *r_bp = NULL; + *r_bezt = NULL; + return; + } + else if (*r_bezt || *r_bp) { + *r_bp = NULL; + *r_bezt = NULL; + } + else { + *r_bezt = bezt1; + *r_nu = nu1; + } + } + bezt1++; + } + } + else { + bp1 = nu1->bp; + a = nu1->pntsu * nu1->pntsv; + while (a--) { + if (bp1->f1 & SELECT) { + if (*r_nu != NULL && *r_nu != nu1) { + *r_bp = NULL; + *r_bezt = NULL; + *r_nu = NULL; + return; + } + else if (*r_bezt || *r_bp) { + *r_bp = NULL; + *r_bezt = NULL; + } + else { + *r_bp = bp1; + *r_nu = nu1; + } + } + bp1++; + } + } + } } /***************** set spline type operator *******************/ static int set_spline_type_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Object *obedit = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - bool changed = false; - bool changed_size = false; - const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); - const int type = RNA_enum_get(op->ptr, "type"); - - if (type == CU_CARDINAL || type == CU_BSPLINE) { - BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); - return OPERATOR_CANCELLED; - } - - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - const int pntsu_prev = nu->pntsu; - if (BKE_nurb_type_convert(nu, type, use_handles)) { - changed = true; - if (pntsu_prev != nu->pntsu) { - changed_size = true; - } - } - else { - BKE_report(op->reports, RPT_ERROR, "No conversion possible"); - } - } - } - - if (changed) { - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - - if (changed_size) { - Curve *cu = obedit->data; - cu->actvert = CU_ACT_NONE; - } - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + Main *bmain = CTX_data_main(C); + Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + bool changed = false; + bool changed_size = false; + const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); + const int type = RNA_enum_get(op->ptr, "type"); + + if (type == CU_CARDINAL || type == CU_BSPLINE) { + BKE_report(op->reports, RPT_ERROR, "Not yet implemented"); + return OPERATOR_CANCELLED; + } + + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + const int pntsu_prev = nu->pntsu; + if (BKE_nurb_type_convert(nu, type, use_handles)) { + changed = true; + if (pntsu_prev != nu->pntsu) { + changed_size = true; + } + } + else { + BKE_report(op->reports, RPT_ERROR, "No conversion possible"); + } + } + } + + if (changed) { + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + if (changed_size) { + Curve *cu = obedit->data; + cu->actvert = CU_ACT_NONE; + } + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void CURVE_OT_spline_type_set(wmOperatorType *ot) { - static const EnumPropertyItem type_items[] = { - {CU_POLY, "POLY", 0, "Poly", ""}, - {CU_BEZIER, "BEZIER", 0, "Bezier", ""}, -// {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""}, -// {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""}, - {CU_NURBS, "NURBS", 0, "NURBS", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - /* identifiers */ - ot->name = "Set Spline Type"; - ot->description = "Set type of active spline"; - ot->idname = "CURVE_OT_spline_type_set"; - - /* api callbacks */ - ot->exec = set_spline_type_exec; - ot->invoke = WM_menu_invoke; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type"); - RNA_def_boolean(ot->srna, "use_handles", 0, "Handles", "Use handles when converting bezier curves into polygons"); + static const EnumPropertyItem type_items[] = { + {CU_POLY, "POLY", 0, "Poly", ""}, + {CU_BEZIER, "BEZIER", 0, "Bezier", ""}, + // {CU_CARDINAL, "CARDINAL", 0, "Cardinal", ""}, + // {CU_BSPLINE, "B_SPLINE", 0, "B-Spline", ""}, + {CU_NURBS, "NURBS", 0, "NURBS", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + /* identifiers */ + ot->name = "Set Spline Type"; + ot->description = "Set type of active spline"; + ot->idname = "CURVE_OT_spline_type_set"; + + /* api callbacks */ + ot->exec = set_spline_type_exec; + ot->invoke = WM_menu_invoke; + ot->poll = ED_operator_editcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", type_items, CU_POLY, "Type", "Spline type"); + RNA_def_boolean(ot->srna, + "use_handles", + 0, + "Handles", + "Use handles when converting bezier curves into polygons"); } /***************** set handle type operator *******************/ static int set_handle_type_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - const int handle_type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + const int handle_type = RNA_enum_get(op->ptr, "type"); - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - ListBase *editnurb = object_editcurve_get(obedit); - BKE_nurbList_handles_set(editnurb, handle_type); + ListBase *editnurb = object_editcurve_get(obedit); + BKE_nurbList_handles_set(editnurb, handle_type); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_handle_type_set(wmOperatorType *ot) { - /* keep in sync with graphkeys_handle_type_items */ - static const EnumPropertyItem editcurve_handle_type_items[] = { - {HD_AUTO, "AUTOMATIC", 0, "Automatic", ""}, - {HD_VECT, "VECTOR", 0, "Vector", ""}, - {5, "ALIGNED", 0, "Aligned", ""}, - {6, "FREE_ALIGN", 0, "Free", ""}, - {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""}, - {0, NULL, 0, NULL, NULL}, - }; + /* keep in sync with graphkeys_handle_type_items */ + static const EnumPropertyItem editcurve_handle_type_items[] = { + {HD_AUTO, "AUTOMATIC", 0, "Automatic", ""}, + {HD_VECT, "VECTOR", 0, "Vector", ""}, + {5, "ALIGNED", 0, "Aligned", ""}, + {6, "FREE_ALIGN", 0, "Free", ""}, + {3, "TOGGLE_FREE_ALIGN", 0, "Toggle Free/Align", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Set Handle Type"; - ot->description = "Set type of handles for selected control points"; - ot->idname = "CURVE_OT_handle_type_set"; + /* identifiers */ + ot->name = "Set Handle Type"; + ot->description = "Set type of handles for selected control points"; + ot->idname = "CURVE_OT_handle_type_set"; - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = set_handle_type_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = set_handle_type_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type"); } /***************** recalculate handles operator **********************/ static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); - const bool calc_length = RNA_boolean_get(op->ptr, "calc_length"); + const bool calc_length = RNA_boolean_get(op->ptr, "calc_length"); - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - ListBase *editnurb = object_editcurve_get(obedit); - BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT); + ListBase *editnurb = object_editcurve_get(obedit); + BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_normals_make_consistent(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Recalc Normals"; - ot->description = "Recalculate the direction of selected handles"; - ot->idname = "CURVE_OT_normals_make_consistent"; + /* identifiers */ + ot->name = "Recalc Normals"; + ot->description = "Recalculate the direction of selected handles"; + ot->idname = "CURVE_OT_normals_make_consistent"; - /* api callbacks */ - ot->exec = curve_normals_make_consistent_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = curve_normals_make_consistent_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* props */ - RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length"); + /* props */ + RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length"); } /***************** make segment operator **********************/ @@ -4026,94 +4099,94 @@ void CURVE_OT_normals_make_consistent(wmOperatorType *ot) static void switchdirection_knots(float *base, int tot) { - float *fp1, *fp2, *tempf; - int a; - - if (base == NULL || tot == 0) { - return; - } - - /* reverse knots */ - a = tot; - fp1 = base; - fp2 = fp1 + (a - 1); - a /= 2; - while (fp1 != fp2 && a > 0) { - SWAP(float, *fp1, *fp2); - a--; - fp1++; - fp2--; - } - - /* and make in increasing order again */ - a = tot - 1; - fp1 = base; - fp2 = tempf = MEM_mallocN(sizeof(float) * tot, "switchdirect"); - while (a--) { - fp2[0] = fabsf(fp1[1] - fp1[0]); - fp1++; - fp2++; - } - fp2[0] = 0.0f; - - a = tot - 1; - fp1 = base; - fp2 = tempf; - fp1[0] = 0.0; - fp1++; - while (a--) { - fp1[0] = fp1[-1] + fp2[0]; - fp1++; - fp2++; - } - MEM_freeN(tempf); + float *fp1, *fp2, *tempf; + int a; + + if (base == NULL || tot == 0) { + return; + } + + /* reverse knots */ + a = tot; + fp1 = base; + fp2 = fp1 + (a - 1); + a /= 2; + while (fp1 != fp2 && a > 0) { + SWAP(float, *fp1, *fp2); + a--; + fp1++; + fp2--; + } + + /* and make in increasing order again */ + a = tot - 1; + fp1 = base; + fp2 = tempf = MEM_mallocN(sizeof(float) * tot, "switchdirect"); + while (a--) { + fp2[0] = fabsf(fp1[1] - fp1[0]); + fp1++; + fp2++; + } + fp2[0] = 0.0f; + + a = tot - 1; + fp1 = base; + fp2 = tempf; + fp1[0] = 0.0; + fp1++; + while (a--) { + fp1[0] = fp1[-1] + fp2[0]; + fp1++; + fp2++; + } + MEM_freeN(tempf); } static void rotate_direction_nurb(Nurb *nu) { - BPoint *bp1, *bp2, *temp; - int u, v; + BPoint *bp1, *bp2, *temp; + int u, v; - SWAP(int, nu->pntsu, nu->pntsv); - SWAP(short, nu->orderu, nu->orderv); - SWAP(short, nu->resolu, nu->resolv); - SWAP(short, nu->flagu, nu->flagv); + SWAP(int, nu->pntsu, nu->pntsv); + SWAP(short, nu->orderu, nu->orderv); + SWAP(short, nu->resolu, nu->resolv); + SWAP(short, nu->flagu, nu->flagv); - SWAP(float *, nu->knotsu, nu->knotsv); - switchdirection_knots(nu->knotsv, KNOTSV(nu)); + SWAP(float *, nu->knotsu, nu->knotsv); + switchdirection_knots(nu->knotsv, KNOTSV(nu)); - temp = MEM_dupallocN(nu->bp); - bp1 = nu->bp; - for (v = 0; v < nu->pntsv; v++) { - for (u = 0; u < nu->pntsu; u++, bp1++) { - bp2 = temp + (nu->pntsu - u - 1) * (nu->pntsv) + v; - *bp1 = *bp2; - } - } + temp = MEM_dupallocN(nu->bp); + bp1 = nu->bp; + for (v = 0; v < nu->pntsv; v++) { + for (u = 0; u < nu->pntsu; u++, bp1++) { + bp2 = temp + (nu->pntsu - u - 1) * (nu->pntsv) + v; + *bp1 = *bp2; + } + } - MEM_freeN(temp); + MEM_freeN(temp); } static bool is_u_selected(Nurb *nu, int u) { - BPoint *bp; - int v; + BPoint *bp; + int v; - /* what about resolu == 2? */ - bp = &nu->bp[u]; - for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) { - if ((v != 0) && (bp->f1 & SELECT)) { - return true; - } - } + /* what about resolu == 2? */ + bp = &nu->bp[u]; + for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) { + if ((v != 0) && (bp->f1 & SELECT)) { + return true; + } + } - return false; + return false; } typedef struct NurbSort { - struct NurbSort *next, *prev; - Nurb *nu; - float vec[3]; + struct NurbSort *next, *prev; + Nurb *nu; + float vec[3]; } NurbSort; static ListBase nsortbase = {NULL, NULL}; @@ -4121,2837 +4194,2877 @@ static ListBase nsortbase = {NULL, NULL}; static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb) { - ListBase nbase = {NULL, NULL}; - NurbSort *nus, *nustest, *headdo, *taildo; - Nurb *nu; - BPoint *bp; - float dist, headdist, taildist; - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - - nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort"); - BLI_addhead(&nbase, nus); - nus->nu = nu; - - bp = nu->bp; - a = nu->pntsu; - while (a--) { - add_v3_v3(nus->vec, bp->vec); - bp++; - } - mul_v3_fl(nus->vec, 1.0f / (float)nu->pntsu); - - - } - } - - /* just add the first one */ - nus = nbase.first; - BLI_remlink(&nbase, nus); - BLI_addtail(&nsortbase, nus); - - /* now add, either at head or tail, the closest one */ - while (nbase.first) { - - headdist = taildist = 1.0e30; - headdo = taildo = NULL; - - nustest = nbase.first; - while (nustest) { - dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.first)->vec); - - if (dist < headdist) { - headdist = dist; - headdo = nustest; - } - dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.last)->vec); - - if (dist < taildist) { - taildist = dist; - taildo = nustest; - } - nustest = nustest->next; - } - - if (headdist < taildist) { - BLI_remlink(&nbase, headdo); - BLI_addhead(&nsortbase, headdo); - } - else { - BLI_remlink(&nbase, taildo); - BLI_addtail(&nsortbase, taildo); - } - } + ListBase nbase = {NULL, NULL}; + NurbSort *nus, *nustest, *headdo, *taildo; + Nurb *nu; + BPoint *bp; + float dist, headdist, taildist; + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + + nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort"); + BLI_addhead(&nbase, nus); + nus->nu = nu; + + bp = nu->bp; + a = nu->pntsu; + while (a--) { + add_v3_v3(nus->vec, bp->vec); + bp++; + } + mul_v3_fl(nus->vec, 1.0f / (float)nu->pntsu); + } + } + + /* just add the first one */ + nus = nbase.first; + BLI_remlink(&nbase, nus); + BLI_addtail(&nsortbase, nus); + + /* now add, either at head or tail, the closest one */ + while (nbase.first) { + + headdist = taildist = 1.0e30; + headdo = taildo = NULL; + + nustest = nbase.first; + while (nustest) { + dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.first)->vec); + + if (dist < headdist) { + headdist = dist; + headdo = nustest; + } + dist = len_v3v3(nustest->vec, ((NurbSort *)nsortbase.last)->vec); + + if (dist < taildist) { + taildist = dist; + taildo = nustest; + } + nustest = nustest->next; + } + + if (headdist < taildist) { + BLI_remlink(&nbase, headdo); + BLI_addhead(&nsortbase, headdo); + } + else { + BLI_remlink(&nbase, taildo); + BLI_addtail(&nsortbase, taildo); + } + } } enum { - CURVE_MERGE_OK = 0, - CURVE_MERGE_ERR_FEW_SELECTION, - CURVE_MERGE_ERR_RESOLUTION_ALL, - CURVE_MERGE_ERR_RESOLUTION_SOME, + CURVE_MERGE_OK = 0, + CURVE_MERGE_ERR_FEW_SELECTION, + CURVE_MERGE_ERR_RESOLUTION_ALL, + CURVE_MERGE_ERR_RESOLUTION_SOME, }; static bool merge_2_nurb(Curve *cu, ListBase *editnurb, Nurb *nu1, Nurb *nu2) { - BPoint *bp, *bp1, *bp2, *temp; - float len1, len2; - int origu, u, v; - - /* first nurbs will be changed to make u = resolu-1 selected */ - /* 2nd nurbs will be changed to make u = 0 selected */ - - /* first nurbs: u = resolu-1 selected */ - - if (is_u_selected(nu1, nu1->pntsu - 1)) { - /* pass */ - } - else { - /* For 2D curves blender uses (orderv = 0). It doesn't make any sense mathematically. */ - /* but after rotating (orderu = 0) will be confusing. */ - if (nu1->orderv == 0) { - nu1->orderv = 1; - } - - rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) { - /* pass */ - } - else { - rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) { - /* pass */ - } - else { - rotate_direction_nurb(nu1); - if (is_u_selected(nu1, nu1->pntsu - 1)) { - /* pass */ - } - else { - /* rotate again, now its OK! */ - if (nu1->pntsv != 1) { - rotate_direction_nurb(nu1); - } - return true; - } - } - } - } - - /* 2nd nurbs: u = 0 selected */ - if (is_u_selected(nu2, 0)) { - /* pass */ - } - else { - if (nu2->orderv == 0) { - nu2->orderv = 1; - } - rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) { - /* pass */ - } - else { - rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) { - /* pass */ - } - else { - rotate_direction_nurb(nu2); - if (is_u_selected(nu2, 0)) { - /* pass */ - } - else { - /* rotate again, now its OK! */ - if (nu1->pntsu == 1) { - rotate_direction_nurb(nu1); - } - if (nu2->pntsv != 1) { - rotate_direction_nurb(nu2); - } - return true; - } - } - } - } - - if (nu1->pntsv != nu2->pntsv) { - return false; - } - - /* ok, now nu1 has the rightmost column and nu2 the leftmost column selected */ - /* maybe we need a 'v' flip of nu2? */ - - bp1 = &nu1->bp[nu1->pntsu - 1]; - bp2 = nu2->bp; - len1 = 0.0; - - for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 += nu2->pntsu) { - len1 += len_v3v3(bp1->vec, bp2->vec); - } - - bp1 = &nu1->bp[nu1->pntsu - 1]; - bp2 = &nu2->bp[nu2->pntsu * (nu2->pntsv - 1)]; - len2 = 0.0; - - for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 -= nu2->pntsu) { - len2 += len_v3v3(bp1->vec, bp2->vec); - } - - /* merge */ - origu = nu1->pntsu; - nu1->pntsu += nu2->pntsu; - if (nu1->orderu < 3 && nu1->orderu < nu1->pntsu) { - nu1->orderu++; - } - if (nu1->orderv < 3 && nu1->orderv < nu1->pntsv) { - nu1->orderv++; - } - temp = nu1->bp; - nu1->bp = MEM_mallocN(nu1->pntsu * nu1->pntsv * sizeof(BPoint), "mergeBP"); - - bp = nu1->bp; - bp1 = temp; - - for (v = 0; v < nu1->pntsv; v++) { - - /* switch direction? */ - if (len1 < len2) { - bp2 = &nu2->bp[v * nu2->pntsu]; - } - else { - bp2 = &nu2->bp[(nu1->pntsv - v - 1) * nu2->pntsu]; - } - - for (u = 0; u < nu1->pntsu; u++, bp++) { - if (u < origu) { - keyIndex_updateBP(cu->editnurb, bp1, bp, 1); - *bp = *bp1; bp1++; - select_bpoint(bp, SELECT, SELECT, HIDDEN); - } - else { - keyIndex_updateBP(cu->editnurb, bp2, bp, 1); - *bp = *bp2; bp2++; - } - } - } - - if (nu1->type == CU_NURBS) { - /* merge knots */ - BKE_nurb_knot_calc_u(nu1); - - /* make knots, for merged curved for example */ - BKE_nurb_knot_calc_v(nu1); - } - - MEM_freeN(temp); - BLI_remlink(editnurb, nu2); - BKE_nurb_free(nu2); - return true; + BPoint *bp, *bp1, *bp2, *temp; + float len1, len2; + int origu, u, v; + + /* first nurbs will be changed to make u = resolu-1 selected */ + /* 2nd nurbs will be changed to make u = 0 selected */ + + /* first nurbs: u = resolu-1 selected */ + + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } + else { + /* For 2D curves blender uses (orderv = 0). It doesn't make any sense mathematically. */ + /* but after rotating (orderu = 0) will be confusing. */ + if (nu1->orderv == 0) { + nu1->orderv = 1; + } + + rotate_direction_nurb(nu1); + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } + else { + rotate_direction_nurb(nu1); + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } + else { + rotate_direction_nurb(nu1); + if (is_u_selected(nu1, nu1->pntsu - 1)) { + /* pass */ + } + else { + /* rotate again, now its OK! */ + if (nu1->pntsv != 1) { + rotate_direction_nurb(nu1); + } + return true; + } + } + } + } + + /* 2nd nurbs: u = 0 selected */ + if (is_u_selected(nu2, 0)) { + /* pass */ + } + else { + if (nu2->orderv == 0) { + nu2->orderv = 1; + } + rotate_direction_nurb(nu2); + if (is_u_selected(nu2, 0)) { + /* pass */ + } + else { + rotate_direction_nurb(nu2); + if (is_u_selected(nu2, 0)) { + /* pass */ + } + else { + rotate_direction_nurb(nu2); + if (is_u_selected(nu2, 0)) { + /* pass */ + } + else { + /* rotate again, now its OK! */ + if (nu1->pntsu == 1) { + rotate_direction_nurb(nu1); + } + if (nu2->pntsv != 1) { + rotate_direction_nurb(nu2); + } + return true; + } + } + } + } + + if (nu1->pntsv != nu2->pntsv) { + return false; + } + + /* ok, now nu1 has the rightmost column and nu2 the leftmost column selected */ + /* maybe we need a 'v' flip of nu2? */ + + bp1 = &nu1->bp[nu1->pntsu - 1]; + bp2 = nu2->bp; + len1 = 0.0; + + for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 += nu2->pntsu) { + len1 += len_v3v3(bp1->vec, bp2->vec); + } + + bp1 = &nu1->bp[nu1->pntsu - 1]; + bp2 = &nu2->bp[nu2->pntsu * (nu2->pntsv - 1)]; + len2 = 0.0; + + for (v = 0; v < nu1->pntsv; v++, bp1 += nu1->pntsu, bp2 -= nu2->pntsu) { + len2 += len_v3v3(bp1->vec, bp2->vec); + } + + /* merge */ + origu = nu1->pntsu; + nu1->pntsu += nu2->pntsu; + if (nu1->orderu < 3 && nu1->orderu < nu1->pntsu) { + nu1->orderu++; + } + if (nu1->orderv < 3 && nu1->orderv < nu1->pntsv) { + nu1->orderv++; + } + temp = nu1->bp; + nu1->bp = MEM_mallocN(nu1->pntsu * nu1->pntsv * sizeof(BPoint), "mergeBP"); + + bp = nu1->bp; + bp1 = temp; + + for (v = 0; v < nu1->pntsv; v++) { + + /* switch direction? */ + if (len1 < len2) { + bp2 = &nu2->bp[v * nu2->pntsu]; + } + else { + bp2 = &nu2->bp[(nu1->pntsv - v - 1) * nu2->pntsu]; + } + + for (u = 0; u < nu1->pntsu; u++, bp++) { + if (u < origu) { + keyIndex_updateBP(cu->editnurb, bp1, bp, 1); + *bp = *bp1; + bp1++; + select_bpoint(bp, SELECT, SELECT, HIDDEN); + } + else { + keyIndex_updateBP(cu->editnurb, bp2, bp, 1); + *bp = *bp2; + bp2++; + } + } + } + + if (nu1->type == CU_NURBS) { + /* merge knots */ + BKE_nurb_knot_calc_u(nu1); + + /* make knots, for merged curved for example */ + BKE_nurb_knot_calc_v(nu1); + } + + MEM_freeN(temp); + BLI_remlink(editnurb, nu2); + BKE_nurb_free(nu2); + return true; } static int merge_nurb(View3D *v3d, Object *obedit) { - Curve *cu = obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - NurbSort *nus1, *nus2; - bool ok = true; - - make_selection_list_nurb(v3d, editnurb); - - if (nsortbase.first == nsortbase.last) { - BLI_freelistN(&nsortbase); - return CURVE_MERGE_ERR_FEW_SELECTION; - } - - nus1 = nsortbase.first; - nus2 = nus1->next; - - /* resolution match, to avoid uv rotations */ - if (nus1->nu->pntsv == 1) { - if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) { - /* pass */ - } - else { - ok = false; - } - } - else if (nus2->nu->pntsv == 1) { - if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) { - /* pass */ - } - else { - ok = false; - } - } - else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) { - /* pass */ - } - else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) { - /* pass */ - } - else { - ok = false; - } - - if (ok == false) { - BLI_freelistN(&nsortbase); - return CURVE_MERGE_ERR_RESOLUTION_ALL; - } - - while (nus2) { - /* There is a change a few curves merged properly, but not all. - * In this case we still update the curve, yet report the error. */ - ok &= merge_2_nurb(cu, editnurb, nus1->nu, nus2->nu); - nus2 = nus2->next; - } - - BLI_freelistN(&nsortbase); - BKE_curve_nurb_active_set(obedit->data, NULL); - - return ok ? CURVE_MERGE_OK : CURVE_MERGE_ERR_RESOLUTION_SOME; + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); + NurbSort *nus1, *nus2; + bool ok = true; + + make_selection_list_nurb(v3d, editnurb); + + if (nsortbase.first == nsortbase.last) { + BLI_freelistN(&nsortbase); + return CURVE_MERGE_ERR_FEW_SELECTION; + } + + nus1 = nsortbase.first; + nus2 = nus1->next; + + /* resolution match, to avoid uv rotations */ + if (nus1->nu->pntsv == 1) { + if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsu == nus2->nu->pntsv) { + /* pass */ + } + else { + ok = false; + } + } + else if (nus2->nu->pntsv == 1) { + if (nus2->nu->pntsu == nus1->nu->pntsu || nus2->nu->pntsu == nus1->nu->pntsv) { + /* pass */ + } + else { + ok = false; + } + } + else if (nus1->nu->pntsu == nus2->nu->pntsu || nus1->nu->pntsv == nus2->nu->pntsv) { + /* pass */ + } + else if (nus1->nu->pntsu == nus2->nu->pntsv || nus1->nu->pntsv == nus2->nu->pntsu) { + /* pass */ + } + else { + ok = false; + } + + if (ok == false) { + BLI_freelistN(&nsortbase); + return CURVE_MERGE_ERR_RESOLUTION_ALL; + } + + while (nus2) { + /* There is a change a few curves merged properly, but not all. + * In this case we still update the curve, yet report the error. */ + ok &= merge_2_nurb(cu, editnurb, nus1->nu, nus2->nu); + nus2 = nus2->next; + } + + BLI_freelistN(&nsortbase); + BKE_curve_nurb_active_set(obedit->data, NULL); + + return ok ? CURVE_MERGE_OK : CURVE_MERGE_ERR_RESOLUTION_SOME; } static int make_segment_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - struct { - int changed; - int unselected; - int error_selected_few; - int error_resolution; - int error_generic; - } status = {0}; - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - status.unselected++; - continue; - } - - ListBase *nubase = object_editcurve_get(obedit); - Nurb *nu, *nu1 = NULL, *nu2 = NULL; - BPoint *bp; - bool ok = false; - - /* first decide if this is a surface merge! */ - if (obedit->type == OB_SURF) { - nu = nubase->first; - } - else { - nu = NULL; - } - - while (nu) { - const int nu_select_num = ED_curve_nurb_select_count(v3d, nu); - if (nu_select_num) { - - if (nu->pntsu > 1 && nu->pntsv > 1) { - break; - } - - if (nu_select_num > 1) { - break; - } - else { - /* only 1 selected, not first or last, a little complex, but intuitive */ - if (nu->pntsv == 1) { - if ((nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) { - /* pass */ - } - else { - break; - } - } - } - } - nu = nu->next; - } - - if (nu) { - int merge_result = merge_nurb(v3d, obedit); - switch (merge_result) { - case CURVE_MERGE_OK: - status.changed++; - goto curve_merge_tag_object; - case CURVE_MERGE_ERR_RESOLUTION_SOME: - status.error_resolution++; - goto curve_merge_tag_object; - case CURVE_MERGE_ERR_FEW_SELECTION: - status.error_selected_few++; - break; - case CURVE_MERGE_ERR_RESOLUTION_ALL: - status.error_resolution++; - break; - } - continue; - } - - /* find both nurbs and points, nu1 will be put behind nu2 */ - for (nu = nubase->first; nu; nu = nu->next) { - if (nu->pntsu == 1) { - nu->flagu &= ~CU_NURB_CYCLIC; - } - - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */ - if (nu->type == CU_BEZIER) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu->pntsu - 1]))) { - /* Last point is selected, preferred for nu2 */ - if (nu2 == NULL) { - nu2 = nu; - } - else if (nu1 == NULL) { - nu1 = nu; - - /* Just in case both of first/last CV are selected check - * whether we really need to switch the direction. - */ - if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt)) { - BKE_nurb_direction_switch(nu1); - keyData_switchDirectionNurb(cu, nu1); - } - } - } - else if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu->bezt)) { - /* First point is selected, preferred for nu1 */ - if (nu1 == NULL) { - nu1 = nu; - } - else if (nu2 == NULL) { - nu2 = nu; - - /* Just in case both of first/last CV are selected check - * whether we really need to switch the direction. - */ - if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu2->pntsu - 1]))) { - BKE_nurb_direction_switch(nu2); - keyData_switchDirectionNurb(cu, nu2); - } - } - } - } - else if (nu->pntsv == 1) { - /* Same logic as above: if first point is selected spline is - * preferred for nu1, if last point is selected spline is - * preferred for u2u. - */ - - bp = nu->bp; - if (bp[nu->pntsu - 1].f1 & SELECT) { - if (nu2 == NULL) { - nu2 = nu; - } - else if (nu1 == NULL) { - nu1 = nu; - - if ((bp->f1 & SELECT) == 0) { - BKE_nurb_direction_switch(nu); - keyData_switchDirectionNurb(cu, nu); - } - } - } - else if (bp->f1 & SELECT) { - if (nu1 == NULL) { - nu1 = nu; - } - else if (nu2 == NULL) { - nu2 = nu; - - if ((bp[nu->pntsu - 1].f1 & SELECT) == 0) { - BKE_nurb_direction_switch(nu); - keyData_switchDirectionNurb(cu, nu); - } - } - } - } - } - - if (nu1 && nu2) { - /* Got second spline, no need to loop over rest of the splines. */ - break; - } - } - - if ((nu1 && nu2) && (nu1 != nu2)) { - if (nu1->type == nu2->type) { - if (nu1->type == CU_BEZIER) { - BezTriple *bezt = (BezTriple *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BezTriple), "addsegmentN"); - ED_curve_beztcpy(cu->editnurb, bezt, nu2->bezt, nu2->pntsu); - ED_curve_beztcpy(cu->editnurb, bezt + nu2->pntsu, nu1->bezt, nu1->pntsu); - - MEM_freeN(nu1->bezt); - nu1->bezt = bezt; - nu1->pntsu += nu2->pntsu; - BLI_remlink(nubase, nu2); - keyIndex_delNurb(cu->editnurb, nu2); - BKE_nurb_free(nu2); nu2 = NULL; - BKE_nurb_handles_calc(nu1); - } - else { - bp = (BPoint *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BPoint), "addsegmentN2"); - ED_curve_bpcpy(cu->editnurb, bp, nu2->bp, nu2->pntsu); - ED_curve_bpcpy(cu->editnurb, bp + nu2->pntsu, nu1->bp, nu1->pntsu); - MEM_freeN(nu1->bp); - nu1->bp = bp; - - /* a = nu1->pntsu + nu1->orderu; */ /* UNUSED */ - - nu1->pntsu += nu2->pntsu; - BLI_remlink(nubase, nu2); - - /* now join the knots */ - if (nu1->type == CU_NURBS) { - if (nu1->knotsu != NULL) { - MEM_freeN(nu1->knotsu); - nu1->knotsu = NULL; - } - - BKE_nurb_knot_calc_u(nu1); - } - keyIndex_delNurb(cu->editnurb, nu2); - BKE_nurb_free(nu2); nu2 = NULL; - } - - BKE_curve_nurb_active_set(cu, nu1); /* for selected */ - ok = true; - } - } - else if ((nu1 && !nu2) || (!nu1 && nu2)) { - if (nu2) { - SWAP(Nurb *, nu1, nu2); - } - - if (!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu > 1) { - if (nu1->type == CU_BEZIER && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu1->bezt[nu1->pntsu - 1])) - { - nu1->flagu |= CU_NURB_CYCLIC; - BKE_nurb_handles_calc(nu1); - ok = true; - } - else if (nu1->type == CU_NURBS && nu1->bp->f1 & SELECT && (nu1->bp[nu1->pntsu - 1].f1 & SELECT)) { - nu1->flagu |= CU_NURB_CYCLIC; - BKE_nurb_knot_calc_u(nu1); - ok = true; - } - } - } - - if (!ok) { - status.error_generic++; - continue; - } - - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - status.changed++; - -curve_merge_tag_object: - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - - if (status.unselected == objects_len) { - BKE_report(op->reports, RPT_ERROR, "No points were selected"); - return OPERATOR_CANCELLED; - } - - const int tot_errors = status.error_selected_few + status.error_resolution + status.error_generic; - if (tot_errors > 0) { - /* Some curves changed, but some curves failed: don't explain why it failed. */ - if (status.changed) { - BKE_reportf(op->reports, - RPT_INFO, - tot_errors == 1 ? "%d curve could not make segments" : - "%d curves could not make segments", - tot_errors); - return OPERATOR_FINISHED; - } - - /* All curves failed: If there is more than one error give a generic error report. */ - if (((status.error_selected_few ? 1 : 0) + - (status.error_resolution ? 1 : 0) + - (status.error_generic ? 1 : 0)) > 1) - { - BKE_report(op->reports, RPT_ERROR, "Could not make new segments"); - } - - /* All curves failed due to the same error. */ - if (status.error_selected_few) { - BKE_report(op->reports, RPT_ERROR, "Too few selections to merge"); - } - else if (status.error_resolution) { - BKE_report(op->reports, RPT_ERROR, "Resolution does not match"); - } - else { - BLI_assert(status.error_generic); - BKE_report(op->reports, RPT_ERROR, "Cannot make segment"); - } - return OPERATOR_CANCELLED; - } - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + struct { + int changed; + int unselected; + int error_selected_few; + int error_resolution; + int error_generic; + } status = {0}; + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + status.unselected++; + continue; + } + + ListBase *nubase = object_editcurve_get(obedit); + Nurb *nu, *nu1 = NULL, *nu2 = NULL; + BPoint *bp; + bool ok = false; + + /* first decide if this is a surface merge! */ + if (obedit->type == OB_SURF) { + nu = nubase->first; + } + else { + nu = NULL; + } + + while (nu) { + const int nu_select_num = ED_curve_nurb_select_count(v3d, nu); + if (nu_select_num) { + + if (nu->pntsu > 1 && nu->pntsv > 1) { + break; + } + + if (nu_select_num > 1) { + break; + } + else { + /* only 1 selected, not first or last, a little complex, but intuitive */ + if (nu->pntsv == 1) { + if ((nu->bp->f1 & SELECT) || (nu->bp[nu->pntsu - 1].f1 & SELECT)) { + /* pass */ + } + else { + break; + } + } + } + } + nu = nu->next; + } + + if (nu) { + int merge_result = merge_nurb(v3d, obedit); + switch (merge_result) { + case CURVE_MERGE_OK: + status.changed++; + goto curve_merge_tag_object; + case CURVE_MERGE_ERR_RESOLUTION_SOME: + status.error_resolution++; + goto curve_merge_tag_object; + case CURVE_MERGE_ERR_FEW_SELECTION: + status.error_selected_few++; + break; + case CURVE_MERGE_ERR_RESOLUTION_ALL: + status.error_resolution++; + break; + } + continue; + } + + /* find both nurbs and points, nu1 will be put behind nu2 */ + for (nu = nubase->first; nu; nu = nu->next) { + if (nu->pntsu == 1) { + nu->flagu &= ~CU_NURB_CYCLIC; + } + + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */ + if (nu->type == CU_BEZIER) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu->pntsu - 1]))) { + /* Last point is selected, preferred for nu2 */ + if (nu2 == NULL) { + nu2 = nu; + } + else if (nu1 == NULL) { + nu1 = nu; + + /* Just in case both of first/last CV are selected check + * whether we really need to switch the direction. + */ + if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt)) { + BKE_nurb_direction_switch(nu1); + keyData_switchDirectionNurb(cu, nu1); + } + } + } + else if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu->bezt)) { + /* First point is selected, preferred for nu1 */ + if (nu1 == NULL) { + nu1 = nu; + } + else if (nu2 == NULL) { + nu2 = nu; + + /* Just in case both of first/last CV are selected check + * whether we really need to switch the direction. + */ + if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &(nu->bezt[nu2->pntsu - 1]))) { + BKE_nurb_direction_switch(nu2); + keyData_switchDirectionNurb(cu, nu2); + } + } + } + } + else if (nu->pntsv == 1) { + /* Same logic as above: if first point is selected spline is + * preferred for nu1, if last point is selected spline is + * preferred for u2u. + */ + + bp = nu->bp; + if (bp[nu->pntsu - 1].f1 & SELECT) { + if (nu2 == NULL) { + nu2 = nu; + } + else if (nu1 == NULL) { + nu1 = nu; + + if ((bp->f1 & SELECT) == 0) { + BKE_nurb_direction_switch(nu); + keyData_switchDirectionNurb(cu, nu); + } + } + } + else if (bp->f1 & SELECT) { + if (nu1 == NULL) { + nu1 = nu; + } + else if (nu2 == NULL) { + nu2 = nu; + + if ((bp[nu->pntsu - 1].f1 & SELECT) == 0) { + BKE_nurb_direction_switch(nu); + keyData_switchDirectionNurb(cu, nu); + } + } + } + } + } + + if (nu1 && nu2) { + /* Got second spline, no need to loop over rest of the splines. */ + break; + } + } + + if ((nu1 && nu2) && (nu1 != nu2)) { + if (nu1->type == nu2->type) { + if (nu1->type == CU_BEZIER) { + BezTriple *bezt = (BezTriple *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BezTriple), + "addsegmentN"); + ED_curve_beztcpy(cu->editnurb, bezt, nu2->bezt, nu2->pntsu); + ED_curve_beztcpy(cu->editnurb, bezt + nu2->pntsu, nu1->bezt, nu1->pntsu); + + MEM_freeN(nu1->bezt); + nu1->bezt = bezt; + nu1->pntsu += nu2->pntsu; + BLI_remlink(nubase, nu2); + keyIndex_delNurb(cu->editnurb, nu2); + BKE_nurb_free(nu2); + nu2 = NULL; + BKE_nurb_handles_calc(nu1); + } + else { + bp = (BPoint *)MEM_mallocN((nu1->pntsu + nu2->pntsu) * sizeof(BPoint), "addsegmentN2"); + ED_curve_bpcpy(cu->editnurb, bp, nu2->bp, nu2->pntsu); + ED_curve_bpcpy(cu->editnurb, bp + nu2->pntsu, nu1->bp, nu1->pntsu); + MEM_freeN(nu1->bp); + nu1->bp = bp; + + /* a = nu1->pntsu + nu1->orderu; */ /* UNUSED */ + + nu1->pntsu += nu2->pntsu; + BLI_remlink(nubase, nu2); + + /* now join the knots */ + if (nu1->type == CU_NURBS) { + if (nu1->knotsu != NULL) { + MEM_freeN(nu1->knotsu); + nu1->knotsu = NULL; + } + + BKE_nurb_knot_calc_u(nu1); + } + keyIndex_delNurb(cu->editnurb, nu2); + BKE_nurb_free(nu2); + nu2 = NULL; + } + + BKE_curve_nurb_active_set(cu, nu1); /* for selected */ + ok = true; + } + } + else if ((nu1 && !nu2) || (!nu1 && nu2)) { + if (nu2) { + SWAP(Nurb *, nu1, nu2); + } + + if (!(nu1->flagu & CU_NURB_CYCLIC) && nu1->pntsu > 1) { + if (nu1->type == CU_BEZIER && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, nu1->bezt) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, &nu1->bezt[nu1->pntsu - 1])) { + nu1->flagu |= CU_NURB_CYCLIC; + BKE_nurb_handles_calc(nu1); + ok = true; + } + else if (nu1->type == CU_NURBS && nu1->bp->f1 & SELECT && + (nu1->bp[nu1->pntsu - 1].f1 & SELECT)) { + nu1->flagu |= CU_NURB_CYCLIC; + BKE_nurb_knot_calc_u(nu1); + ok = true; + } + } + } + + if (!ok) { + status.error_generic++; + continue; + } + + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + status.changed++; + + curve_merge_tag_object: + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + + if (status.unselected == objects_len) { + BKE_report(op->reports, RPT_ERROR, "No points were selected"); + return OPERATOR_CANCELLED; + } + + const int tot_errors = status.error_selected_few + status.error_resolution + + status.error_generic; + if (tot_errors > 0) { + /* Some curves changed, but some curves failed: don't explain why it failed. */ + if (status.changed) { + BKE_reportf(op->reports, + RPT_INFO, + tot_errors == 1 ? "%d curve could not make segments" : + "%d curves could not make segments", + tot_errors); + return OPERATOR_FINISHED; + } + + /* All curves failed: If there is more than one error give a generic error report. */ + if (((status.error_selected_few ? 1 : 0) + (status.error_resolution ? 1 : 0) + + (status.error_generic ? 1 : 0)) > 1) { + BKE_report(op->reports, RPT_ERROR, "Could not make new segments"); + } + + /* All curves failed due to the same error. */ + if (status.error_selected_few) { + BKE_report(op->reports, RPT_ERROR, "Too few selections to merge"); + } + else if (status.error_resolution) { + BKE_report(op->reports, RPT_ERROR, "Resolution does not match"); + } + else { + BLI_assert(status.error_generic); + BKE_report(op->reports, RPT_ERROR, "Cannot make segment"); + } + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; } void CURVE_OT_make_segment(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Make Segment"; - ot->idname = "CURVE_OT_make_segment"; - ot->description = "Join two curves by their selected ends"; + /* identifiers */ + ot->name = "Make Segment"; + ot->idname = "CURVE_OT_make_segment"; + ot->description = "Join two curves by their selected ends"; - /* api callbacks */ - ot->exec = make_segment_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = make_segment_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /***************** pick select from 3d view **********************/ -bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) -{ - ViewContext vc; - Nurb *nu; - BezTriple *bezt = NULL; - BPoint *bp = NULL; - Base *basact = NULL; - short hand; - - view3d_operator_needs_opengl(C); - ED_view3d_viewcontext_init(C, &vc); - copy_v2_v2_int(vc.mval, mval); - - if (ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact)) { - Object *obedit = basact->object; - Curve *cu = obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - const void *vert = BKE_curve_vert_active_get(cu); - - if (!extend && !deselect && !toggle) { - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *ob_iter = objects[ob_index]; - - ED_curve_deselect_all(((Curve *)ob_iter->data)->editnurb); - - DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); - } - MEM_freeN(objects); - } - - if (extend) { - if (bezt) { - if (hand == 1) { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); - } - else { - if (hand == 0) { - bezt->f1 |= SELECT; - } - else { - bezt->f3 |= SELECT; - } - } - BKE_curve_nurb_vert_active_set(cu, nu, bezt); - } - else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); - BKE_curve_nurb_vert_active_set(cu, nu, bp); - } - } - else if (deselect) { - if (bezt) { - if (hand == 1) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - if (bezt == vert) { - cu->actvert = CU_ACT_NONE; - } - } - else if (hand == 0) { - bezt->f1 &= ~SELECT; - } - else { - bezt->f3 &= ~SELECT; - } - } - else { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); - if (bp == vert) { - cu->actvert = CU_ACT_NONE; - } - } - } - else if (toggle) { - if (bezt) { - if (hand == 1) { - if (bezt->f2 & SELECT) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - if (bezt == vert) { - cu->actvert = CU_ACT_NONE; - } - } - else { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); - BKE_curve_nurb_vert_active_set(cu, nu, bezt); - } - } - else if (hand == 0) { - bezt->f1 ^= SELECT; - } - else { - bezt->f3 ^= SELECT; - } - } - else { - if (bp->f1 & SELECT) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); - if (bp == vert) { - cu->actvert = CU_ACT_NONE; - } - } - else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); - BKE_curve_nurb_vert_active_set(cu, nu, bp); - } - } - } - else { - BKE_nurbList_flag_set(editnurb, 0); - - if (bezt) { - - if (hand == 1) { - select_beztriple(bezt, SELECT, SELECT, HIDDEN); - } - else { - if (hand == 0) { - bezt->f1 |= SELECT; - } - else { - bezt->f3 |= SELECT; - } - } - BKE_curve_nurb_vert_active_set(cu, nu, bezt); - } - else { - select_bpoint(bp, SELECT, SELECT, HIDDEN); - BKE_curve_nurb_vert_active_set(cu, nu, bp); - } - } - - if (nu != BKE_curve_nurb_active_get(cu)) { - cu->actvert = CU_ACT_NONE; - BKE_curve_nurb_active_set(cu, nu); - } - - if (vc.view_layer->basact != basact) { - ED_object_base_activate(C, basact); - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return true; - } - - return false; +bool ED_curve_editnurb_select_pick( + bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +{ + ViewContext vc; + Nurb *nu; + BezTriple *bezt = NULL; + BPoint *bp = NULL; + Base *basact = NULL; + short hand; + + view3d_operator_needs_opengl(C); + ED_view3d_viewcontext_init(C, &vc); + copy_v2_v2_int(vc.mval, mval); + + if (ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact)) { + Object *obedit = basact->object; + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); + const void *vert = BKE_curve_vert_active_get(cu); + + if (!extend && !deselect && !toggle) { + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + vc.view_layer, vc.v3d, &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob_iter = objects[ob_index]; + + ED_curve_deselect_all(((Curve *)ob_iter->data)->editnurb); + + DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data); + } + MEM_freeN(objects); + } + + if (extend) { + if (bezt) { + if (hand == 1) { + select_beztriple(bezt, SELECT, SELECT, HIDDEN); + } + else { + if (hand == 0) { + bezt->f1 |= SELECT; + } + else { + bezt->f3 |= SELECT; + } + } + BKE_curve_nurb_vert_active_set(cu, nu, bezt); + } + else { + select_bpoint(bp, SELECT, SELECT, HIDDEN); + BKE_curve_nurb_vert_active_set(cu, nu, bp); + } + } + else if (deselect) { + if (bezt) { + if (hand == 1) { + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + if (bezt == vert) { + cu->actvert = CU_ACT_NONE; + } + } + else if (hand == 0) { + bezt->f1 &= ~SELECT; + } + else { + bezt->f3 &= ~SELECT; + } + } + else { + select_bpoint(bp, DESELECT, SELECT, HIDDEN); + if (bp == vert) { + cu->actvert = CU_ACT_NONE; + } + } + } + else if (toggle) { + if (bezt) { + if (hand == 1) { + if (bezt->f2 & SELECT) { + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + if (bezt == vert) { + cu->actvert = CU_ACT_NONE; + } + } + else { + select_beztriple(bezt, SELECT, SELECT, HIDDEN); + BKE_curve_nurb_vert_active_set(cu, nu, bezt); + } + } + else if (hand == 0) { + bezt->f1 ^= SELECT; + } + else { + bezt->f3 ^= SELECT; + } + } + else { + if (bp->f1 & SELECT) { + select_bpoint(bp, DESELECT, SELECT, HIDDEN); + if (bp == vert) { + cu->actvert = CU_ACT_NONE; + } + } + else { + select_bpoint(bp, SELECT, SELECT, HIDDEN); + BKE_curve_nurb_vert_active_set(cu, nu, bp); + } + } + } + else { + BKE_nurbList_flag_set(editnurb, 0); + + if (bezt) { + + if (hand == 1) { + select_beztriple(bezt, SELECT, SELECT, HIDDEN); + } + else { + if (hand == 0) { + bezt->f1 |= SELECT; + } + else { + bezt->f3 |= SELECT; + } + } + BKE_curve_nurb_vert_active_set(cu, nu, bezt); + } + else { + select_bpoint(bp, SELECT, SELECT, HIDDEN); + BKE_curve_nurb_vert_active_set(cu, nu, bp); + } + } + + if (nu != BKE_curve_nurb_active_get(cu)) { + cu->actvert = CU_ACT_NONE; + BKE_curve_nurb_active_set(cu, nu); + } + + if (vc.view_layer->basact != basact) { + ED_object_base_activate(C, basact); + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return true; + } + + return false; } /******************** spin operator ***********************/ /* 'cent' is in object space and 'dvec' in worldspace. */ -bool ed_editnurb_spin(float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3]) -{ - Curve *cu = (Curve *)obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - float cmat[3][3], tmat[3][3], imat[3][3]; - float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3]; - float persmat[3][3], persinv[3][3]; - bool ok, changed = false; - int a; - - copy_m3_m4(persmat, viewmat); - invert_m3_m3(persinv, persmat); - - /* imat and center and size */ - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(imat, bmat); - - axis_angle_to_mat3(cmat, axis, M_PI / 4.0); - mul_m3_m3m3(tmat, cmat, bmat); - mul_m3_m3m3(rotmat, imat, tmat); - - unit_m3(scalemat1); - scalemat1[0][0] = M_SQRT2; - scalemat1[1][1] = M_SQRT2; - - mul_m3_m3m3(tmat, persmat, bmat); - mul_m3_m3m3(cmat, scalemat1, tmat); - mul_m3_m3m3(tmat, persinv, cmat); - mul_m3_m3m3(scalemat1, imat, tmat); - - unit_m3(scalemat2); - scalemat2[0][0] /= (float)M_SQRT2; - scalemat2[1][1] /= (float)M_SQRT2; - - mul_m3_m3m3(tmat, persmat, bmat); - mul_m3_m3m3(cmat, scalemat2, tmat); - mul_m3_m3m3(tmat, persinv, cmat); - mul_m3_m3m3(scalemat2, imat, tmat); - - ok = true; - - for (a = 0; a < 7; a++) { - ok = ed_editnurb_extrude_flag(cu->editnurb, SELECT); - - if (ok == false) { - return changed; - } - - changed = true; - - rotateflagNurb(editnurb, SELECT, cent, rotmat); - - if ((a & 1) == 0) { - rotateflagNurb(editnurb, SELECT, cent, scalemat1); - weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2); - } - else { - rotateflagNurb(editnurb, SELECT, cent, scalemat2); - weightflagNurb(editnurb, SELECT, 4.0 / M_SQRT2); - } - } - - if (ok) { - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - nu->orderv = 4; - nu->flagv |= CU_NURB_CYCLIC; - BKE_nurb_knot_calc_v(nu); - } - } - } - - return changed; +bool ed_editnurb_spin( + float viewmat[4][4], View3D *v3d, Object *obedit, const float axis[3], const float cent[3]) +{ + Curve *cu = (Curve *)obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + float cmat[3][3], tmat[3][3], imat[3][3]; + float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3]; + float persmat[3][3], persinv[3][3]; + bool ok, changed = false; + int a; + + copy_m3_m4(persmat, viewmat); + invert_m3_m3(persinv, persmat); + + /* imat and center and size */ + copy_m3_m4(bmat, obedit->obmat); + invert_m3_m3(imat, bmat); + + axis_angle_to_mat3(cmat, axis, M_PI / 4.0); + mul_m3_m3m3(tmat, cmat, bmat); + mul_m3_m3m3(rotmat, imat, tmat); + + unit_m3(scalemat1); + scalemat1[0][0] = M_SQRT2; + scalemat1[1][1] = M_SQRT2; + + mul_m3_m3m3(tmat, persmat, bmat); + mul_m3_m3m3(cmat, scalemat1, tmat); + mul_m3_m3m3(tmat, persinv, cmat); + mul_m3_m3m3(scalemat1, imat, tmat); + + unit_m3(scalemat2); + scalemat2[0][0] /= (float)M_SQRT2; + scalemat2[1][1] /= (float)M_SQRT2; + + mul_m3_m3m3(tmat, persmat, bmat); + mul_m3_m3m3(cmat, scalemat2, tmat); + mul_m3_m3m3(tmat, persinv, cmat); + mul_m3_m3m3(scalemat2, imat, tmat); + + ok = true; + + for (a = 0; a < 7; a++) { + ok = ed_editnurb_extrude_flag(cu->editnurb, SELECT); + + if (ok == false) { + return changed; + } + + changed = true; + + rotateflagNurb(editnurb, SELECT, cent, rotmat); + + if ((a & 1) == 0) { + rotateflagNurb(editnurb, SELECT, cent, scalemat1); + weightflagNurb(editnurb, SELECT, 0.25 * M_SQRT2); + } + else { + rotateflagNurb(editnurb, SELECT, cent, scalemat2); + weightflagNurb(editnurb, SELECT, 4.0 / M_SQRT2); + } + } + + if (ok) { + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + nu->orderv = 4; + nu->flagv |= CU_NURB_CYCLIC; + BKE_nurb_knot_calc_v(nu); + } + } + } + + return changed; } static int spin_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - float cent[3], axis[3], viewmat[4][4]; - int ok = -1; - - RNA_float_get_array(op->ptr, "center", cent); - RNA_float_get_array(op->ptr, "axis", axis); - - if (rv3d) { - copy_m4_m4(viewmat, rv3d->viewmat); - } - else { - unit_m4(viewmat); - } - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = (Curve *)obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - invert_m4_m4(obedit->imat, obedit->obmat); - mul_m4_v3(obedit->imat, cent); - - if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) { - ok = MAX2(ok, 0); - continue; - } - - ok = 1; - if (ED_curve_updateAnimPaths(bmain, cu)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - - if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot spin"); - } - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + float cent[3], axis[3], viewmat[4][4]; + int ok = -1; + + RNA_float_get_array(op->ptr, "center", cent); + RNA_float_get_array(op->ptr, "axis", axis); + + if (rv3d) { + copy_m4_m4(viewmat, rv3d->viewmat); + } + else { + unit_m4(viewmat); + } + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = (Curve *)obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + invert_m4_m4(obedit->imat, obedit->obmat); + mul_m4_v3(obedit->imat, cent); + + if (!ed_editnurb_spin(viewmat, v3d, obedit, axis, cent)) { + ok = MAX2(ok, 0); + continue; + } + + ok = 1; + if (ED_curve_updateAnimPaths(bmain, cu)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + + if (ok == 0) { + BKE_report(op->reports, RPT_ERROR, "Cannot spin"); + } + return OPERATOR_FINISHED; } static int spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Scene *scene = CTX_data_scene(C); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - float axis[3] = {0.0f, 0.0f, 1.0f}; + Scene *scene = CTX_data_scene(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + float axis[3] = {0.0f, 0.0f, 1.0f}; - if (rv3d) { - copy_v3_v3(axis, rv3d->viewinv[2]); - } + if (rv3d) { + copy_v3_v3(axis, rv3d->viewinv[2]); + } - RNA_float_set_array(op->ptr, "center", scene->cursor.location); - RNA_float_set_array(op->ptr, "axis", axis); + RNA_float_set_array(op->ptr, "center", scene->cursor.location); + RNA_float_set_array(op->ptr, "axis", axis); - return spin_exec(C, op); + return spin_exec(C, op); } void CURVE_OT_spin(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Spin"; - ot->idname = "CURVE_OT_spin"; - ot->description = "Extrude selected boundary row around pivot point and current view axis"; - - /* api callbacks */ - ot->exec = spin_exec; - ot->invoke = spin_invoke; - ot->poll = ED_operator_editsurf; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - RNA_def_float_vector_xyz(ot->srna, "center", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF, - "Center", "Center in global view space", -1000.0f, 1000.0f); - RNA_def_float_vector(ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); + /* identifiers */ + ot->name = "Spin"; + ot->idname = "CURVE_OT_spin"; + ot->description = "Extrude selected boundary row around pivot point and current view axis"; + + /* api callbacks */ + ot->exec = spin_exec; + ot->invoke = spin_invoke; + ot->poll = ED_operator_editsurf; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_float_vector_xyz(ot->srna, + "center", + 3, + NULL, + -OBJECT_ADD_SIZE_MAXF, + OBJECT_ADD_SIZE_MAXF, + "Center", + "Center in global view space", + -1000.0f, + 1000.0f); + RNA_def_float_vector( + ot->srna, "axis", 3, NULL, -1.0f, 1.0f, "Axis", "Axis in global view space", -1.0f, 1.0f); } /***************** extrude vertex operator **********************/ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d) { - Nurb *nu = NULL; - Nurb *nu_last = NULL; - - bool changed = false; - - Nurb *cu_actnu; - union { - BezTriple *bezt; - BPoint *bp; - void *p; - } cu_actvert; + Nurb *nu = NULL; + Nurb *nu_last = NULL; - if (BLI_listbase_is_empty(&editnurb->nurbs)) { - return changed; - } + bool changed = false; - BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p); - BKE_curve_nurb_vert_active_set(cu, NULL, NULL); + Nurb *cu_actnu; + union { + BezTriple *bezt; + BPoint *bp; + void *p; + } cu_actvert; - /* first pass (endpoints) */ - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if (BLI_listbase_is_empty(&editnurb->nurbs)) { + return changed; + } - if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { - continue; - } + BKE_curve_nurb_vert_active_get(cu, &cu_actnu, &cu_actvert.p); + BKE_curve_nurb_vert_active_set(cu, NULL, NULL); + + /* first pass (endpoints) */ + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { + if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { + continue; + } - /* Check to see if the first bezier point is selected */ - if (nu->pntsu > 0 && nu->bezt != NULL) { - BezTriple *nu_bezt_old = nu->bezt; - BezTriple *bezt = nu->bezt; + if (nu->type == CU_BEZIER) { + + /* Check to see if the first bezier point is selected */ + if (nu->pntsu > 0 && nu->bezt != NULL) { + BezTriple *nu_bezt_old = nu->bezt; + BezTriple *bezt = nu->bezt; - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - BezTriple *bezt_new; - BEZT_DESEL_ALL(bezt); + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + BezTriple *bezt_new; + BEZT_DESEL_ALL(bezt); - bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); - ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu); - *bezt_new = *bezt; + bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); + ED_curve_beztcpy(editnurb, bezt_new + 1, bezt, nu->pntsu); + *bezt_new = *bezt; + MEM_freeN(nu->bezt); + nu->bezt = bezt_new; - MEM_freeN(nu->bezt); - nu->bezt = bezt_new; + nu->pntsu += 1; - nu->pntsu += 1; + if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { + cu_actvert.bezt = (cu_actvert.bezt == bezt) ? + bezt_new : + &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1]; + BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); + } - if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { - cu_actvert.bezt = (cu_actvert.bezt == bezt) ? - bezt_new : &nu->bezt[(cu_actvert.bezt - nu_bezt_old) + 1]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); - } + BEZT_SEL_ALL(bezt_new); + changed = true; + } + } - BEZT_SEL_ALL(bezt_new); - changed = true; - } - } - - /* Check to see if the last bezier point is selected */ - if (nu->pntsu > 1) { - BezTriple *nu_bezt_old = nu->bezt; - BezTriple *bezt = &nu->bezt[nu->pntsu - 1]; - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - BezTriple *bezt_new; - BEZT_DESEL_ALL(bezt); - - bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); - ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu); - bezt_new[nu->pntsu] = *bezt; - - MEM_freeN(nu->bezt); - nu->bezt = bezt_new; - - bezt_new += nu->pntsu; - nu->pntsu += 1; - - if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { - cu_actvert.bezt = (cu_actvert.bezt == bezt) ? - bezt_new : &nu->bezt[cu_actvert.bezt - nu_bezt_old]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); - } - - BEZT_SEL_ALL(bezt_new); - changed = true; - } - } - } - else { - - /* Check to see if the first bpoint is selected */ - if (nu->pntsu > 0 && nu->bp != NULL) { - BPoint *nu_bp_old = nu->bp; - BPoint *bp = nu->bp; - - if (bp->f1 & SELECT) { - BPoint *bp_new; - bp->f1 &= ~SELECT; - - bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); - ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu); - *bp_new = *bp; - - MEM_freeN(nu->bp); - nu->bp = bp_new; - - nu->pntsu += 1; - BKE_nurb_knot_calc_u(nu); - - if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { - cu_actvert.bp = (cu_actvert.bp == bp) ? - bp_new : &nu->bp[(cu_actvert.bp - nu_bp_old) + 1]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); - } - - bp_new->f1 |= SELECT; - changed = true; - } - } - - /* Check to see if the last bpoint is selected */ - if (nu->pntsu > 1) { - BPoint *nu_bp_old = nu->bp; - BPoint *bp = &nu->bp[nu->pntsu - 1]; - - if (bp->f1 & SELECT) { - BPoint *bp_new; - bp->f1 &= ~SELECT; - - bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); - ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu); - bp_new[nu->pntsu] = *bp; - - MEM_freeN(nu->bp); - nu->bp = bp_new; - - bp_new += nu->pntsu; - nu->pntsu += 1; - - if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { - cu_actvert.bp = (cu_actvert.bp == bp) ? - bp_new : &nu->bp[cu_actvert.bp - nu_bp_old]; - BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); - } - - BKE_nurb_knot_calc_u(nu); - - bp_new->f1 |= SELECT; - changed = true; - } - } - } - } - - /* second pass (interior points) */ - nu_last = editnurb->nurbs.last; - for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) { - int i, i_end; - - if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { - /* all points are interior */ - i = 0; - i_end = nu->pntsu; - } - else { - /* skip endpoints */ - i = 1; - i_end = nu->pntsu - 1; - } - - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - - for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - Nurb *nurb_new; - BezTriple *bezt_new; - - BEZT_DESEL_ALL(bezt); - nurb_new = BKE_nurb_copy(nu, 1, 1); - nurb_new->flagu &= ~CU_NURB_CYCLIC; - BLI_addtail(&editnurb->nurbs, nurb_new); - bezt_new = nurb_new->bezt; - ED_curve_beztcpy(editnurb, bezt_new, bezt, 1); - BEZT_SEL_ALL(bezt_new); - - if (cu_actvert.bezt == bezt || cu_actnu == NULL) { - BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new); - } - - changed = true; - } - } - } - else { - BPoint *bp; - - for (bp = &nu->bp[i]; i < i_end; i++, bp++) { - if (bp->f1 & SELECT) { - Nurb *nurb_new; - BPoint *bp_new; - - bp->f1 &= ~SELECT; - nurb_new = BKE_nurb_copy(nu, 1, 1); - nurb_new->flagu &= ~CU_NURB_CYCLIC; - BLI_addtail(&editnurb->nurbs, nurb_new); - bp_new = nurb_new->bp; - ED_curve_bpcpy(editnurb, bp_new, bp, 1); - bp_new->f1 |= SELECT; - - if (cu_actvert.bp == bp || cu_actnu == NULL) { - BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new); - } - - changed = true; - } - } - } - } - - if (changed == false) { - BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p); - } - - return changed; + /* Check to see if the last bezier point is selected */ + if (nu->pntsu > 1) { + BezTriple *nu_bezt_old = nu->bezt; + BezTriple *bezt = &nu->bezt[nu->pntsu - 1]; + + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + BezTriple *bezt_new; + BEZT_DESEL_ALL(bezt); + + bezt_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BezTriple), __func__); + ED_curve_beztcpy(editnurb, bezt_new, nu->bezt, nu->pntsu); + bezt_new[nu->pntsu] = *bezt; + + MEM_freeN(nu->bezt); + nu->bezt = bezt_new; + + bezt_new += nu->pntsu; + nu->pntsu += 1; + + if (ARRAY_HAS_ITEM(cu_actvert.bezt, nu_bezt_old, nu->pntsu - 1)) { + cu_actvert.bezt = (cu_actvert.bezt == bezt) ? bezt_new : + &nu->bezt[cu_actvert.bezt - nu_bezt_old]; + BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bezt); + } + + BEZT_SEL_ALL(bezt_new); + changed = true; + } + } + } + else { + + /* Check to see if the first bpoint is selected */ + if (nu->pntsu > 0 && nu->bp != NULL) { + BPoint *nu_bp_old = nu->bp; + BPoint *bp = nu->bp; + + if (bp->f1 & SELECT) { + BPoint *bp_new; + bp->f1 &= ~SELECT; + + bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); + ED_curve_bpcpy(editnurb, bp_new + 1, bp, nu->pntsu); + *bp_new = *bp; + + MEM_freeN(nu->bp); + nu->bp = bp_new; + + nu->pntsu += 1; + BKE_nurb_knot_calc_u(nu); + + if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { + cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : + &nu->bp[(cu_actvert.bp - nu_bp_old) + 1]; + BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); + } + + bp_new->f1 |= SELECT; + changed = true; + } + } + + /* Check to see if the last bpoint is selected */ + if (nu->pntsu > 1) { + BPoint *nu_bp_old = nu->bp; + BPoint *bp = &nu->bp[nu->pntsu - 1]; + + if (bp->f1 & SELECT) { + BPoint *bp_new; + bp->f1 &= ~SELECT; + + bp_new = MEM_mallocN((nu->pntsu + 1) * sizeof(BPoint), __func__); + ED_curve_bpcpy(editnurb, bp_new, nu->bp, nu->pntsu); + bp_new[nu->pntsu] = *bp; + + MEM_freeN(nu->bp); + nu->bp = bp_new; + + bp_new += nu->pntsu; + nu->pntsu += 1; + + if (ARRAY_HAS_ITEM(cu_actvert.bp, nu_bp_old, nu->pntsu - 1)) { + cu_actvert.bp = (cu_actvert.bp == bp) ? bp_new : &nu->bp[cu_actvert.bp - nu_bp_old]; + BKE_curve_nurb_vert_active_set(cu, nu, cu_actvert.bp); + } + + BKE_nurb_knot_calc_u(nu); + + bp_new->f1 |= SELECT; + changed = true; + } + } + } + } + + /* second pass (interior points) */ + nu_last = editnurb->nurbs.last; + for (nu = editnurb->nurbs.first; (nu != nu_last->next); nu = nu->next) { + int i, i_end; + + if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu > 1)) { + /* all points are interior */ + i = 0; + i_end = nu->pntsu; + } + else { + /* skip endpoints */ + i = 1; + i_end = nu->pntsu - 1; + } + + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + + for (bezt = &nu->bezt[i]; i < i_end; i++, bezt++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + Nurb *nurb_new; + BezTriple *bezt_new; + + BEZT_DESEL_ALL(bezt); + nurb_new = BKE_nurb_copy(nu, 1, 1); + nurb_new->flagu &= ~CU_NURB_CYCLIC; + BLI_addtail(&editnurb->nurbs, nurb_new); + bezt_new = nurb_new->bezt; + ED_curve_beztcpy(editnurb, bezt_new, bezt, 1); + BEZT_SEL_ALL(bezt_new); + + if (cu_actvert.bezt == bezt || cu_actnu == NULL) { + BKE_curve_nurb_vert_active_set(cu, nurb_new, bezt_new); + } + + changed = true; + } + } + } + else { + BPoint *bp; + + for (bp = &nu->bp[i]; i < i_end; i++, bp++) { + if (bp->f1 & SELECT) { + Nurb *nurb_new; + BPoint *bp_new; + + bp->f1 &= ~SELECT; + nurb_new = BKE_nurb_copy(nu, 1, 1); + nurb_new->flagu &= ~CU_NURB_CYCLIC; + BLI_addtail(&editnurb->nurbs, nurb_new); + bp_new = nurb_new->bp; + ED_curve_bpcpy(editnurb, bp_new, bp, 1); + bp_new->f1 |= SELECT; + + if (cu_actvert.bp == bp || cu_actnu == NULL) { + BKE_curve_nurb_vert_active_set(cu, nurb_new, bp_new); + } + + changed = true; + } + } + } + } + + if (changed == false) { + BKE_curve_nurb_vert_active_set(cu, cu_actnu, cu_actvert.p); + } + + return changed; } /***************** add vertex operator **********************/ -static int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3]) -{ - Nurb *nu; - - float center[3]; - float temp[3]; - uint verts_len; - bool changed = false; - - zero_v3(center); - verts_len = 0; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - int i; - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - - for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - add_v3_v3(center, bezt->vec[1]); - verts_len += 1; - } - } - } - else { - BPoint *bp; - - for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) { - if (bp->f1 & SELECT) { - add_v3_v3(center, bp->vec); - verts_len += 1; - } - } - } - } - - if (verts_len && ed_editcurve_extrude(cu, editnurb, v3d)) { - float ofs[3]; - int i; - - mul_v3_fl(center, 1.0f / (float)verts_len); - sub_v3_v3v3(ofs, location_init, center); - - if ((cu->flag & CU_3D) == 0) { - ofs[2] = 0.0f; - } - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - add_v3_v3(bezt->vec[0], ofs); - add_v3_v3(bezt->vec[1], ofs); - add_v3_v3(bezt->vec[2], ofs); - - if (((nu->flagu & CU_NURB_CYCLIC) == 0) && - (i == 0 || i == nu->pntsu - 1)) - { - BKE_nurb_handle_calc_simple_auto(nu, bezt); - } - } - } - - BKE_nurb_handles_calc(nu); - } - else { - BPoint *bp; - - for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) { - if (bp->f1 & SELECT) { - add_v3_v3(bp->vec, ofs); - } - } - } - } - changed = true; - } - else { - float location[3]; - - copy_v3_v3(location, location_init); - - if ((cu->flag & CU_3D) == 0) { - location[2] = 0.0f; - } - - /* nothing selected: create a new curve */ - nu = BKE_curve_nurb_active_get(cu); - - if (!nu || nu->type == CU_BEZIER) { - Nurb *nurb_new; - BezTriple *bezt_new; - - if (nu) { - nurb_new = BKE_nurb_copy(nu, 1, 1); - } - else { - nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2"); - nurb_new->type = CU_BEZIER; - nurb_new->resolu = cu->resolu; - nurb_new->orderu = 4; - nurb_new->flag |= CU_SMOOTH; - BKE_nurb_bezierPoints_add(nurb_new, 1); - - if ((cu->flag & CU_3D) == 0) { - nurb_new->flag |= CU_2D; - } - } - BLI_addtail(&editnurb->nurbs, nurb_new); - - bezt_new = nurb_new->bezt; - - BEZT_SEL_ALL(bezt_new); - - bezt_new->h1 = HD_AUTO; - bezt_new->h2 = HD_AUTO; - - temp[0] = 1.0f; - temp[1] = 0.0f; - temp[2] = 0.0f; - - copy_v3_v3(bezt_new->vec[1], location); - sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp); - add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp); - - changed = true; - } - else { - Nurb *nurb_new; - BPoint *bp_new; - - { - nurb_new = MEM_callocN(sizeof(Nurb), __func__); - nurb_new->type = CU_POLY; - nurb_new->resolu = cu->resolu; - nurb_new->flag |= CU_SMOOTH; - nurb_new->orderu = 4; - BKE_nurb_points_add(nurb_new, 1); - - if ((cu->flag & CU_3D) == 0) { - nurb_new->flag |= CU_2D; - } - } - BLI_addtail(&editnurb->nurbs, nurb_new); - - bp_new = nurb_new->bp; - - bp_new->f1 |= SELECT; - - copy_v3_v3(bp_new->vec, location); - bp_new->vec[3] = 1.0f; - - BKE_nurb_knot_calc_u(nurb_new); - - changed = true; - } - } - - return changed; +static int ed_editcurve_addvert(Curve *cu, + EditNurb *editnurb, + View3D *v3d, + const float location_init[3]) +{ + Nurb *nu; + + float center[3]; + float temp[3]; + uint verts_len; + bool changed = false; + + zero_v3(center); + verts_len = 0; + + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + int i; + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + + for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + add_v3_v3(center, bezt->vec[1]); + verts_len += 1; + } + } + } + else { + BPoint *bp; + + for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) { + if (bp->f1 & SELECT) { + add_v3_v3(center, bp->vec); + verts_len += 1; + } + } + } + } + + if (verts_len && ed_editcurve_extrude(cu, editnurb, v3d)) { + float ofs[3]; + int i; + + mul_v3_fl(center, 1.0f / (float)verts_len); + sub_v3_v3v3(ofs, location_init, center); + + if ((cu->flag & CU_3D) == 0) { + ofs[2] = 0.0f; + } + + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + add_v3_v3(bezt->vec[0], ofs); + add_v3_v3(bezt->vec[1], ofs); + add_v3_v3(bezt->vec[2], ofs); + + if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (i == 0 || i == nu->pntsu - 1)) { + BKE_nurb_handle_calc_simple_auto(nu, bezt); + } + } + } + + BKE_nurb_handles_calc(nu); + } + else { + BPoint *bp; + + for (i = 0, bp = nu->bp; i < nu->pntsu; i++, bp++) { + if (bp->f1 & SELECT) { + add_v3_v3(bp->vec, ofs); + } + } + } + } + changed = true; + } + else { + float location[3]; + + copy_v3_v3(location, location_init); + + if ((cu->flag & CU_3D) == 0) { + location[2] = 0.0f; + } + + /* nothing selected: create a new curve */ + nu = BKE_curve_nurb_active_get(cu); + + if (!nu || nu->type == CU_BEZIER) { + Nurb *nurb_new; + BezTriple *bezt_new; + + if (nu) { + nurb_new = BKE_nurb_copy(nu, 1, 1); + } + else { + nurb_new = MEM_callocN(sizeof(Nurb), "BLI_editcurve_addvert new_bezt_nurb 2"); + nurb_new->type = CU_BEZIER; + nurb_new->resolu = cu->resolu; + nurb_new->orderu = 4; + nurb_new->flag |= CU_SMOOTH; + BKE_nurb_bezierPoints_add(nurb_new, 1); + + if ((cu->flag & CU_3D) == 0) { + nurb_new->flag |= CU_2D; + } + } + BLI_addtail(&editnurb->nurbs, nurb_new); + + bezt_new = nurb_new->bezt; + + BEZT_SEL_ALL(bezt_new); + + bezt_new->h1 = HD_AUTO; + bezt_new->h2 = HD_AUTO; + + temp[0] = 1.0f; + temp[1] = 0.0f; + temp[2] = 0.0f; + + copy_v3_v3(bezt_new->vec[1], location); + sub_v3_v3v3(bezt_new->vec[0], bezt_new->vec[1], temp); + add_v3_v3v3(bezt_new->vec[2], bezt_new->vec[1], temp); + + changed = true; + } + else { + Nurb *nurb_new; + BPoint *bp_new; + + { + nurb_new = MEM_callocN(sizeof(Nurb), __func__); + nurb_new->type = CU_POLY; + nurb_new->resolu = cu->resolu; + nurb_new->flag |= CU_SMOOTH; + nurb_new->orderu = 4; + BKE_nurb_points_add(nurb_new, 1); + + if ((cu->flag & CU_3D) == 0) { + nurb_new->flag |= CU_2D; + } + } + BLI_addtail(&editnurb->nurbs, nurb_new); + + bp_new = nurb_new->bp; + + bp_new->f1 |= SELECT; + + copy_v3_v3(bp_new->vec, location); + bp_new->vec[3] = 1.0f; + + BKE_nurb_knot_calc_u(nurb_new); + + changed = true; + } + } + + return changed; } static int add_vertex_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Object *obedit = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - float location[3]; - float imat[4][4]; + Main *bmain = CTX_data_main(C); + Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + float location[3]; + float imat[4][4]; - RNA_float_get_array(op->ptr, "location", location); + RNA_float_get_array(op->ptr, "location", location); - invert_m4_m4(imat, obedit->obmat); - mul_m4_v3(imat, location); + invert_m4_m4(imat, obedit->obmat); + mul_m4_v3(imat, location); - if (ed_editcurve_addvert(cu, editnurb, v3d, location)) { - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } + if (ed_editcurve_addvert(cu, editnurb, v3d, location)) { + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewContext vc; - - ED_view3d_viewcontext_init(C, &vc); - - if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) { - Curve *cu; - float location[3]; - const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) && - (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE)); - - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - - cu = vc.obedit->data; - - findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp); - - if (bezt) { - mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]); - } - else if (bp) { - mul_v3_m4v3(location, vc.obedit->obmat, bp->vec); - } - else { - copy_v3_v3(location, vc.scene->cursor.location); - } - - ED_view3d_win_to_3d_int(vc.v3d, vc.ar, location, event->mval, location); - - if (use_proj) { - const float mval[2] = {UNPACK2(event->mval)}; - - struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - vc.bmain, vc.scene, vc.depsgraph, 0, vc.ar, vc.v3d); - - ED_transform_snap_object_project_view3d( - snap_context, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL, - .use_object_edit_cage = false, - }, - mval, NULL, - location, NULL); - - - ED_transform_snap_object_context_destroy(snap_context); - } - - if ((cu->flag & CU_3D) == 0) { - const float eps = 1e-6f; - - /* get the view vector to 'location' */ - float view_dir[3]; - ED_view3d_global_to_vector(vc.rv3d, location, view_dir); - - /* get the plane */ - float plane[4]; - /* only normalize to avoid precision errors */ - normalize_v3_v3(plane, vc.obedit->obmat[2]); - plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]); - - if (fabsf(dot_v3v3(view_dir, plane)) < eps) { - /* can't project on an aligned plane. */ - } - else { - float lambda; - if (isect_ray_plane_v3(location, view_dir, plane, &lambda, false)) { - /* check if we're behind the viewport */ - float location_test[3]; - madd_v3_v3v3fl(location_test, location, view_dir, lambda); - if ((vc.rv3d->is_persp == false) || - (mul_project_m4_v3_zfac(vc.rv3d->persmat, location_test) > 0.0f)) - { - copy_v3_v3(location, location_test); - } - } - } - } - - RNA_float_set_array(op->ptr, "location", location); - } - - return add_vertex_exec(C, op); + ViewContext vc; + + ED_view3d_viewcontext_init(C, &vc); + + if (vc.rv3d && !RNA_struct_property_is_set(op->ptr, "location")) { + Curve *cu; + float location[3]; + const bool use_proj = ((vc.scene->toolsettings->snap_flag & SCE_SNAP) && + (vc.scene->toolsettings->snap_mode == SCE_SNAP_MODE_FACE)); + + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + + cu = vc.obedit->data; + + findselectedNurbvert(cu, vc.v3d, &nu, &bezt, &bp); + + if (bezt) { + mul_v3_m4v3(location, vc.obedit->obmat, bezt->vec[1]); + } + else if (bp) { + mul_v3_m4v3(location, vc.obedit->obmat, bp->vec); + } + else { + copy_v3_v3(location, vc.scene->cursor.location); + } + + ED_view3d_win_to_3d_int(vc.v3d, vc.ar, location, event->mval, location); + + if (use_proj) { + const float mval[2] = {UNPACK2(event->mval)}; + + struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( + vc.bmain, vc.scene, vc.depsgraph, 0, vc.ar, vc.v3d); + + ED_transform_snap_object_project_view3d( + snap_context, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = (vc.obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL, + .use_object_edit_cage = false, + }, + mval, + NULL, + location, + NULL); + + ED_transform_snap_object_context_destroy(snap_context); + } + + if ((cu->flag & CU_3D) == 0) { + const float eps = 1e-6f; + + /* get the view vector to 'location' */ + float view_dir[3]; + ED_view3d_global_to_vector(vc.rv3d, location, view_dir); + + /* get the plane */ + float plane[4]; + /* only normalize to avoid precision errors */ + normalize_v3_v3(plane, vc.obedit->obmat[2]); + plane[3] = -dot_v3v3(plane, vc.obedit->obmat[3]); + + if (fabsf(dot_v3v3(view_dir, plane)) < eps) { + /* can't project on an aligned plane. */ + } + else { + float lambda; + if (isect_ray_plane_v3(location, view_dir, plane, &lambda, false)) { + /* check if we're behind the viewport */ + float location_test[3]; + madd_v3_v3v3fl(location_test, location, view_dir, lambda); + if ((vc.rv3d->is_persp == false) || + (mul_project_m4_v3_zfac(vc.rv3d->persmat, location_test) > 0.0f)) { + copy_v3_v3(location, location_test); + } + } + } + } + + RNA_float_set_array(op->ptr, "location", location); + } + + return add_vertex_exec(C, op); } void CURVE_OT_vertex_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Vertex"; - ot->idname = "CURVE_OT_vertex_add"; - ot->description = "Add a new control point (linked to only selected end-curve one, if any)"; + /* identifiers */ + ot->name = "Add Vertex"; + ot->idname = "CURVE_OT_vertex_add"; + ot->description = "Add a new control point (linked to only selected end-curve one, if any)"; - /* api callbacks */ - ot->exec = add_vertex_exec; - ot->invoke = add_vertex_invoke; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = add_vertex_exec; + ot->invoke = add_vertex_invoke; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -OBJECT_ADD_SIZE_MAXF, OBJECT_ADD_SIZE_MAXF, - "Location", "Location to add new vertex at", -1.0e4f, 1.0e4f); + /* properties */ + RNA_def_float_vector_xyz(ot->srna, + "location", + 3, + NULL, + -OBJECT_ADD_SIZE_MAXF, + OBJECT_ADD_SIZE_MAXF, + "Location", + "Location to add new vertex at", + -1.0e4f, + 1.0e4f); } /***************** extrude operator **********************/ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - bool changed = false; - bool as_curve = false; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - /* First test: curve? */ - if (obedit->type != OB_CURVE) { - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if ((nu->pntsv == 1) && - (ED_curve_nurb_select_count(v3d, nu) == 1)) - { - as_curve = true; - break; - } - } - } - - if (obedit->type == OB_CURVE || as_curve) { - changed = ed_editcurve_extrude(cu, editnurb, v3d); - } - else { - changed = ed_editnurb_extrude_flag(editnurb, SELECT); - } - - if (changed) { - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + bool changed = false; + bool as_curve = false; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + /* First test: curve? */ + if (obedit->type != OB_CURVE) { + Nurb *nu; + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) == 1)) { + as_curve = true; + break; + } + } + } + + if (obedit->type == OB_CURVE || as_curve) { + changed = ed_editcurve_extrude(cu, editnurb, v3d); + } + else { + changed = ed_editnurb_extrude_flag(editnurb, SELECT); + } + + if (changed) { + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_extrude(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Extrude"; - ot->description = "Extrude selected control point(s)"; - ot->idname = "CURVE_OT_extrude"; + /* identifiers */ + ot->name = "Extrude"; + ot->description = "Extrude selected control point(s)"; + ot->idname = "CURVE_OT_extrude"; - /* api callbacks */ - ot->exec = curve_extrude_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_extrude_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* to give to transform */ - RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); + /* to give to transform */ + RNA_def_enum(ot->srna, "mode", rna_enum_transform_mode_types, TFM_TRANSLATION, "Mode", ""); } /***************** make cyclic operator **********************/ static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction) { - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - bool changed = false; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->pntsu > 1 || nu->pntsv > 1) { - if (nu->type == CU_POLY) { - a = nu->pntsu; - bp = nu->bp; - while (a--) { - if (bp->f1 & SELECT) { - nu->flagu ^= CU_NURB_CYCLIC; - changed = true; - break; - } - bp++; - } - } - else if (nu->type == CU_BEZIER) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - nu->flagu ^= CU_NURB_CYCLIC; - changed = true; - break; - } - bezt++; - } - BKE_nurb_handles_calc(nu); - } - else if (nu->pntsv == 1 && nu->type == CU_NURBS) { - if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */ - a = nu->pntsu; - bp = nu->bp; - while (a--) { - if (bp->f1 & SELECT) { - nu->flagu ^= CU_NURB_CYCLIC; - /* 1==u type is ignored for cyclic curves */ - BKE_nurb_knot_calc_u(nu); - changed = true; - break; - } - bp++; - } - } - } - else if (nu->type == CU_NURBS) { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - - if (bp->f1 & SELECT) { - if (direction == 0 && nu->pntsu > 1) { - nu->flagu ^= CU_NURB_CYCLIC; - /* 1==u type is ignored for cyclic curves */ - BKE_nurb_knot_calc_u(nu); - changed = true; - } - if (direction == 1 && nu->pntsv > 1) { - nu->flagv ^= CU_NURB_CYCLIC; - /* 2==v type is ignored for cyclic curves */ - BKE_nurb_knot_calc_v(nu); - changed = true; - } - break; - } - bp++; - } - } - } - } - return changed; + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + bool changed = false; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->pntsu > 1 || nu->pntsv > 1) { + if (nu->type == CU_POLY) { + a = nu->pntsu; + bp = nu->bp; + while (a--) { + if (bp->f1 & SELECT) { + nu->flagu ^= CU_NURB_CYCLIC; + changed = true; + break; + } + bp++; + } + } + else if (nu->type == CU_BEZIER) { + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + nu->flagu ^= CU_NURB_CYCLIC; + changed = true; + break; + } + bezt++; + } + BKE_nurb_handles_calc(nu); + } + else if (nu->pntsv == 1 && nu->type == CU_NURBS) { + if (nu->knotsu) { /* if check_valid_nurb_u fails the knotsu can be NULL */ + a = nu->pntsu; + bp = nu->bp; + while (a--) { + if (bp->f1 & SELECT) { + nu->flagu ^= CU_NURB_CYCLIC; + /* 1==u type is ignored for cyclic curves */ + BKE_nurb_knot_calc_u(nu); + changed = true; + break; + } + bp++; + } + } + } + else if (nu->type == CU_NURBS) { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + + if (bp->f1 & SELECT) { + if (direction == 0 && nu->pntsu > 1) { + nu->flagu ^= CU_NURB_CYCLIC; + /* 1==u type is ignored for cyclic curves */ + BKE_nurb_knot_calc_u(nu); + changed = true; + } + if (direction == 1 && nu->pntsv > 1) { + nu->flagv ^= CU_NURB_CYCLIC; + /* 2==v type is ignored for cyclic curves */ + BKE_nurb_knot_calc_v(nu); + changed = true; + } + break; + } + bp++; + } + } + } + } + return changed; } static int toggle_cyclic_exec(bContext *C, wmOperator *op) { - const int direction = RNA_enum_get(op->ptr, "direction"); - View3D *v3d = CTX_wm_view3d(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - bool changed_multi = false; + const int direction = RNA_enum_get(op->ptr, "direction"); + View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + bool changed_multi = false; - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - ListBase *editnurb = object_editcurve_get(obedit); - if (curve_toggle_cyclic(v3d, editnurb, direction)) { - changed_multi = true; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - } - MEM_freeN(objects); + ListBase *editnurb = object_editcurve_get(obedit); + if (curve_toggle_cyclic(v3d, editnurb, direction)) { + changed_multi = true; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + } + MEM_freeN(objects); - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); - uiPopupMenu *pup; - uiLayout *layout; - Nurb *nu; - - if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->pntsu > 1 || nu->pntsv > 1) { - if (nu->type == CU_NURBS) { - pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - uiItemsEnumO(layout, op->type->idname, "direction"); - UI_popup_menu_end(C, pup); - return OPERATOR_INTERFACE; - } - } - } - } - - return toggle_cyclic_exec(C, op); + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + uiPopupMenu *pup; + uiLayout *layout; + Nurb *nu; + + if (obedit->type == OB_SURF) { + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->pntsu > 1 || nu->pntsv > 1) { + if (nu->type == CU_NURBS) { + pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + uiItemsEnumO(layout, op->type->idname, "direction"); + UI_popup_menu_end(C, pup); + return OPERATOR_INTERFACE; + } + } + } + } + + return toggle_cyclic_exec(C, op); } void CURVE_OT_cyclic_toggle(wmOperatorType *ot) { - static const EnumPropertyItem direction_items[] = { - {0, "CYCLIC_U", 0, "Cyclic U", ""}, - {1, "CYCLIC_V", 0, "Cyclic V", ""}, - {0, NULL, 0, NULL, NULL}, - }; + static const EnumPropertyItem direction_items[] = { + {0, "CYCLIC_U", 0, "Cyclic U", ""}, + {1, "CYCLIC_V", 0, "Cyclic V", ""}, + {0, NULL, 0, NULL, NULL}, + }; - /* identifiers */ - ot->name = "Toggle Cyclic"; - ot->description = "Make active spline closed/opened loop"; - ot->idname = "CURVE_OT_cyclic_toggle"; + /* identifiers */ + ot->name = "Toggle Cyclic"; + ot->description = "Make active spline closed/opened loop"; + ot->idname = "CURVE_OT_cyclic_toggle"; - /* api callbacks */ - ot->exec = toggle_cyclic_exec; - ot->invoke = toggle_cyclic_invoke; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = toggle_cyclic_exec; + ot->invoke = toggle_cyclic_invoke; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to make surface cyclic in"); + /* properties */ + RNA_def_enum(ot->srna, + "direction", + direction_items, + 0, + "Direction", + "Direction to make surface cyclic in"); } /********************** add duplicate operator *********************/ static int duplicate_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - int ok = -1; + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + int ok = -1; - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } - ListBase newnurb = {NULL, NULL}; - adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, false); + ListBase newnurb = {NULL, NULL}; + adduplicateflagNurb(obedit, v3d, &newnurb, SELECT, false); - if (BLI_listbase_is_empty(&newnurb)) { - ok = MAX2(ok, 0); - continue; - } + if (BLI_listbase_is_empty(&newnurb)) { + ok = MAX2(ok, 0); + continue; + } - ok = 1; - BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); - DEG_id_tag_update(&cu->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, &cu->id); - } - MEM_freeN(objects); + ok = 1; + BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + DEG_id_tag_update(&cu->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, &cu->id); + } + MEM_freeN(objects); - if (ok == 0) { - BKE_report(op->reports, RPT_ERROR, "Cannot duplicate current selection"); - return OPERATOR_CANCELLED; - } - return OPERATOR_FINISHED; + if (ok == 0) { + BKE_report(op->reports, RPT_ERROR, "Cannot duplicate current selection"); + return OPERATOR_CANCELLED; + } + return OPERATOR_FINISHED; } void CURVE_OT_duplicate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Duplicate Curve"; - ot->description = "Duplicate selected control points"; - ot->idname = "CURVE_OT_duplicate"; + /* identifiers */ + ot->name = "Duplicate Curve"; + ot->description = "Duplicate selected control points"; + ot->idname = "CURVE_OT_duplicate"; - /* api callbacks */ - ot->exec = duplicate_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = duplicate_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** delete operator *********************/ static bool curve_delete_vertices(Object *obedit, View3D *v3d) { - if (obedit->type == OB_SURF) { - ed_surf_delete_selected(obedit); - } - else { - ed_curve_delete_selected(obedit, v3d); - } + if (obedit->type == OB_SURF) { + ed_surf_delete_selected(obedit); + } + else { + ed_curve_delete_selected(obedit, v3d); + } - return true; + return true; } static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) { - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL}; - Nurb *nu, *nu1; - BezTriple *bezt, *bezt1, *bezt2; - BPoint *bp, *bp1, *bp2; - int a, b, starta, enda, cut, cyclicut; - - for (nu = nubase->first; nu; nu = nu->next) { - nu1 = NULL; - starta = enda = cut = -1; - cyclicut = 0; - - if (nu->type == CU_BEZIER) { - for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { - if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - enda = a; - if (starta == -1) { - starta = a; - } - if (a < nu->pntsu - 1) { - continue; - } - } - else if (a < nu->pntsu - 1 && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt + 1)) { - /* if just single selected point then continue */ - continue; - } - - if (starta >= 0) { - /* got selected segment, now check where and copy */ - if (starta <= 1 && a == nu->pntsu - 1) { - /* copying all points in spline */ - if (starta == 1 && enda != a) { - nu->flagu &= ~CU_NURB_CYCLIC; - } - - starta = 0; - enda = a; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, cut, 1); - } - else if (starta == 0) { - /* if start of curve copy next end point */ - enda++; - cut = enda - starta + 1; - bezt1 = &nu->bezt[nu->pntsu - 1]; - bezt2 = &nu->bezt[nu->pntsu - 2]; - - if ((nu->flagu & CU_NURB_CYCLIC) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) - { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, cut + 1, 1); - ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut); - starta = nu->pntsu - 1; - cut = 1; - } - else { - if (nu->flagu & CU_NURB_CYCLIC) { - cyclicut = cut; - } - else { - nu1 = BKE_nurb_copy(nu, cut, 1); - } - } - } - else if (enda == nu->pntsu - 1) { - /* if end of curve copy previous start point */ - starta--; - cut = enda - starta + 1; - bezt1 = nu->bezt; - bezt2 = &nu->bezt[1]; - - if ((nu->flagu & CU_NURB_CYCLIC) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) - { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, cut + 1, 1); - ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1); - } - else if (cyclicut != 0) { - /* if cyclicut exists it is a cyclic spline, start and end should be connected */ - nu1 = BKE_nurb_copy(nu, cut + cyclicut, 1); - ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, cyclicut); - cyclicut = 0; - } - else { - nu1 = BKE_nurb_copy(nu, cut, 1); - } - } - else { - /* mid spline selection, copy adjacent start and end */ - starta--; - enda++; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, cut, 1); - } - - if (nu1 != NULL) { - ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut); - BLI_addtail(&newnurb, nu1); - - if (starta != 0 || enda != nu->pntsu - 1) { - nu1->flagu &= ~CU_NURB_CYCLIC; - } - nu1 = NULL; - } - starta = enda = -1; - } - } - - if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ - bezt1 = nu->bezt; - bezt2 = &nu->bezt[1]; - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) - { - nu1 = BKE_nurb_copy(nu, 1, 1); - ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); - BLI_addtail(&newnurb, nu1); - } - - bezt1 = &nu->bezt[nu->pntsu - 1]; - bezt2 = &nu->bezt[nu->pntsu - 2]; - - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && - BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) - { - nu1 = BKE_nurb_copy(nu, 1, 1); - ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); - BLI_addtail(&newnurb, nu1); - } - } - } - else if (nu->pntsv >= 1) { - int u, v; - - if (isNurbselV(nu, &u, SELECT)) { - for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) { - if (!(bp->f1 & SELECT)) { - enda = a; - if (starta == -1) { - starta = a; - } - if (a < nu->pntsu - 1) { - continue; - } - } - else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) { - /* if just single selected point then continue */ - continue; - } - - if (starta >= 0) { - /* got selected segment, now check where and copy */ - if (starta <= 1 && a == nu->pntsu - 1) { - /* copying all points in spline */ - if (starta == 1 && enda != a) { - nu->flagu &= ~CU_NURB_CYCLIC; - } - - starta = 0; - enda = a; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); - } - else if (starta == 0) { - /* if start of curve copy next end point */ - enda++; - cut = enda - starta + 1; - bp1 = &nu->bp[nu->pntsu - 1]; - bp2 = &nu->bp[nu->pntsu - 2]; - - if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv); - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + 1], &nu->bp[b * nu->pntsu], cut); - } - starta = nu->pntsu - 1; - cut = 1; - } - else { - if (nu->flagu & CU_NURB_CYCLIC) { - cyclicut = cut; - } - else { - nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); - } - } - } - else if (enda == nu->pntsu - 1) { - /* if end of curve copy previous start point */ - starta--; - cut = enda - starta + 1; - bp1 = nu->bp; - bp2 = &nu->bp[1]; - - if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv); - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], 1); - } - } - else if (cyclicut != 0) { - /* if cyclicut exists it is a cyclic spline, start and end should be connected */ - nu1 = BKE_nurb_copy(nu, cut + cyclicut, nu->pntsv); - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], cyclicut); - } - } - else { - nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); - } - } - else { - /* mid spline selection, copy adjacent start and end */ - starta--; - enda++; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); - } - - if (nu1 != NULL) { - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b * nu1->pntsu], &nu->bp[b * nu->pntsu + starta], cut); - } - BLI_addtail(&newnurb, nu1); - - if (starta != 0 || enda != nu->pntsu - 1) { - nu1->flagu &= ~CU_NURB_CYCLIC; - } - nu1 = NULL; - } - starta = enda = -1; - } - } - - if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ - bp1 = nu->bp; - bp2 = &nu->bp[1]; - - if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - nu1 = BKE_nurb_copy(nu, 1, nu->pntsv); - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu], 1); - } - BLI_addtail(&newnurb, nu1); - } - - bp1 = &nu->bp[nu->pntsu - 1]; - bp2 = &nu->bp[nu->pntsu - 2]; - - if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - nu1 = BKE_nurb_copy(nu, 1, nu->pntsv); - for (b = 0; b < nu->pntsv; b++) { - ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu + nu->pntsu - 1], 1); - } - BLI_addtail(&newnurb, nu1); - } - } - } - else if (isNurbselU(nu, &v, SELECT)) { - for (a = 0, bp = nu->bp; a < nu->pntsv; a++, bp += nu->pntsu) { - if (!(bp->f1 & SELECT)) { - enda = a; - if (starta == -1) { - starta = a; - } - if (a < nu->pntsv - 1) { - continue; - } - } - else if (a < nu->pntsv - 1 && !((bp + nu->pntsu)->f1 & SELECT)) { - /* if just single selected point then continue */ - continue; - } - - if (starta >= 0) { - /* got selected segment, now check where and copy */ - if (starta <= 1 && a == nu->pntsv - 1) { - /* copying all points in spline */ - if (starta == 1 && enda != a) { - nu->flagv &= ~CU_NURB_CYCLIC; - } - - starta = 0; - enda = a; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); - } - else if (starta == 0) { - /* if start of curve copy next end point */ - enda++; - cut = enda - starta + 1; - bp1 = &nu->bp[nu->pntsv * nu->pntsu - nu->pntsu]; - bp2 = &nu->bp[nu->pntsv * nu->pntsu - (nu->pntsu * 2)]; - - if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1); - ED_curve_bpcpy(editnurb, &nu1->bp[nu->pntsu], nu->bp, cut * nu->pntsu); - starta = nu->pntsv - 1; - cut = 1; - } - else { - if (nu->flagv & CU_NURB_CYCLIC) { - cyclicut = cut; - } - else { - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); - } - } - } - else if (enda == nu->pntsv - 1) { - /* if end of curve copy previous start point */ - starta--; - cut = enda - starta + 1; - bp1 = nu->bp; - bp2 = &nu->bp[nu->pntsu]; - - if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - /* check if need to join start of spline to end */ - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1); - ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu); - } - else if (cyclicut != 0) { - /* if cyclicut exists it is a cyclic spline, start and end should be connected */ - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + cyclicut); - ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu * cyclicut); - cyclicut = 0; - } - else { - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); - } - } - else { - /* mid spline selection, copy adjacent start and end */ - starta--; - enda++; - cut = enda - starta + 1; - nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); - } - - if (nu1 != NULL) { - ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta * nu->pntsu], cut * nu->pntsu); - BLI_addtail(&newnurb, nu1); - - if (starta != 0 || enda != nu->pntsv - 1) { - nu1->flagv &= ~CU_NURB_CYCLIC; - } - nu1 = NULL; - } - starta = enda = -1; - } - } - - if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ - bp1 = nu->bp; - bp2 = &nu->bp[nu->pntsu]; - - if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - nu1 = BKE_nurb_copy(nu, nu->pntsu, 1); - ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu); - BLI_addtail(&newnurb, nu1); - } - - bp1 = &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu]; - bp2 = &nu->bp[nu->pntsu * nu->pntsv - (nu->pntsu * 2)]; - - if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { - nu1 = BKE_nurb_copy(nu, nu->pntsu, 1); - ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu], nu->pntsu); - BLI_addtail(&newnurb, nu1); - } - } - } - else { - /* selection not valid, just copy nurb to new list */ - nu1 = BKE_nurb_copy(nu, nu->pntsu, nu->pntsv); - ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu * nu->pntsv); - BLI_addtail(&newnurb, nu1); - } - } - } - - for (nu = newnurb.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - if (split) { - /* deselect for split operator */ - for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) { - select_beztriple(bezt1, DESELECT, SELECT, true); - } - } - - BKE_nurb_handles_calc(nu); - } - else { - if (split) { - /* deselect for split operator */ - for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { - select_bpoint(bp1, DESELECT, SELECT, HIDDEN); - } - } - - BKE_nurb_order_clamp_u(nu); - BKE_nurb_knot_calc_u(nu); - - if (nu->pntsv > 1) { - BKE_nurb_order_clamp_v(nu); - BKE_nurb_knot_calc_v(nu); - } - } - } - - keyIndex_delNurbList(editnurb, nubase); - BKE_nurbList_free(nubase); - BLI_movelisttolist(nubase, &newnurb); - - return true; + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL}; + Nurb *nu, *nu1; + BezTriple *bezt, *bezt1, *bezt2; + BPoint *bp, *bp1, *bp2; + int a, b, starta, enda, cut, cyclicut; + + for (nu = nubase->first; nu; nu = nu->next) { + nu1 = NULL; + starta = enda = cut = -1; + cyclicut = 0; + + if (nu->type == CU_BEZIER) { + for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { + if (!BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + enda = a; + if (starta == -1) { + starta = a; + } + if (a < nu->pntsu - 1) { + continue; + } + } + else if (a < nu->pntsu - 1 && !BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt + 1)) { + /* if just single selected point then continue */ + continue; + } + + if (starta >= 0) { + /* got selected segment, now check where and copy */ + if (starta <= 1 && a == nu->pntsu - 1) { + /* copying all points in spline */ + if (starta == 1 && enda != a) { + nu->flagu &= ~CU_NURB_CYCLIC; + } + + starta = 0; + enda = a; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, cut, 1); + } + else if (starta == 0) { + /* if start of curve copy next end point */ + enda++; + cut = enda - starta + 1; + bezt1 = &nu->bezt[nu->pntsu - 1]; + bezt2 = &nu->bezt[nu->pntsu - 2]; + + if ((nu->flagu & CU_NURB_CYCLIC) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, cut + 1, 1); + ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut); + starta = nu->pntsu - 1; + cut = 1; + } + else { + if (nu->flagu & CU_NURB_CYCLIC) { + cyclicut = cut; + } + else { + nu1 = BKE_nurb_copy(nu, cut, 1); + } + } + } + else if (enda == nu->pntsu - 1) { + /* if end of curve copy previous start point */ + starta--; + cut = enda - starta + 1; + bezt1 = nu->bezt; + bezt2 = &nu->bezt[1]; + + if ((nu->flagu & CU_NURB_CYCLIC) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && + BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, cut + 1, 1); + ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1); + } + else if (cyclicut != 0) { + /* if cyclicut exists it is a cyclic spline, start and end should be connected */ + nu1 = BKE_nurb_copy(nu, cut + cyclicut, 1); + ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, cyclicut); + cyclicut = 0; + } + else { + nu1 = BKE_nurb_copy(nu, cut, 1); + } + } + else { + /* mid spline selection, copy adjacent start and end */ + starta--; + enda++; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, cut, 1); + } + + if (nu1 != NULL) { + ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut); + BLI_addtail(&newnurb, nu1); + + if (starta != 0 || enda != nu->pntsu - 1) { + nu1->flagu &= ~CU_NURB_CYCLIC; + } + nu1 = NULL; + } + starta = enda = -1; + } + } + + if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { + /* start and points copied if connecting segment was deleted and not cylic spline */ + bezt1 = nu->bezt; + bezt2 = &nu->bezt[1]; + + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) { + nu1 = BKE_nurb_copy(nu, 1, 1); + ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); + BLI_addtail(&newnurb, nu1); + } + + bezt1 = &nu->bezt[nu->pntsu - 1]; + bezt2 = &nu->bezt[nu->pntsu - 2]; + + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1) && BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt2)) { + nu1 = BKE_nurb_copy(nu, 1, 1); + ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); + BLI_addtail(&newnurb, nu1); + } + } + } + else if (nu->pntsv >= 1) { + int u, v; + + if (isNurbselV(nu, &u, SELECT)) { + for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) { + if (!(bp->f1 & SELECT)) { + enda = a; + if (starta == -1) { + starta = a; + } + if (a < nu->pntsu - 1) { + continue; + } + } + else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) { + /* if just single selected point then continue */ + continue; + } + + if (starta >= 0) { + /* got selected segment, now check where and copy */ + if (starta <= 1 && a == nu->pntsu - 1) { + /* copying all points in spline */ + if (starta == 1 && enda != a) { + nu->flagu &= ~CU_NURB_CYCLIC; + } + + starta = 0; + enda = a; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); + } + else if (starta == 0) { + /* if start of curve copy next end point */ + enda++; + cut = enda - starta + 1; + bp1 = &nu->bp[nu->pntsu - 1]; + bp2 = &nu->bp[nu->pntsu - 2]; + + if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv); + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy( + editnurb, &nu1->bp[b * nu1->pntsu + 1], &nu->bp[b * nu->pntsu], cut); + } + starta = nu->pntsu - 1; + cut = 1; + } + else { + if (nu->flagu & CU_NURB_CYCLIC) { + cyclicut = cut; + } + else { + nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); + } + } + } + else if (enda == nu->pntsu - 1) { + /* if end of curve copy previous start point */ + starta--; + cut = enda - starta + 1; + bp1 = nu->bp; + bp2 = &nu->bp[1]; + + if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, cut + 1, nu->pntsv); + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy( + editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], 1); + } + } + else if (cyclicut != 0) { + /* if cyclicut exists it is a cyclic spline, start and end should be connected */ + nu1 = BKE_nurb_copy(nu, cut + cyclicut, nu->pntsv); + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy( + editnurb, &nu1->bp[b * nu1->pntsu + cut], &nu->bp[b * nu->pntsu], cyclicut); + } + } + else { + nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); + } + } + else { + /* mid spline selection, copy adjacent start and end */ + starta--; + enda++; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, cut, nu->pntsv); + } + + if (nu1 != NULL) { + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy( + editnurb, &nu1->bp[b * nu1->pntsu], &nu->bp[b * nu->pntsu + starta], cut); + } + BLI_addtail(&newnurb, nu1); + + if (starta != 0 || enda != nu->pntsu - 1) { + nu1->flagu &= ~CU_NURB_CYCLIC; + } + nu1 = NULL; + } + starta = enda = -1; + } + } + + if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { + /* start and points copied if connecting segment was deleted and not cylic spline */ + bp1 = nu->bp; + bp2 = &nu->bp[1]; + + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = BKE_nurb_copy(nu, 1, nu->pntsv); + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu], 1); + } + BLI_addtail(&newnurb, nu1); + } + + bp1 = &nu->bp[nu->pntsu - 1]; + bp2 = &nu->bp[nu->pntsu - 2]; + + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = BKE_nurb_copy(nu, 1, nu->pntsv); + for (b = 0; b < nu->pntsv; b++) { + ED_curve_bpcpy(editnurb, &nu1->bp[b], &nu->bp[b * nu->pntsu + nu->pntsu - 1], 1); + } + BLI_addtail(&newnurb, nu1); + } + } + } + else if (isNurbselU(nu, &v, SELECT)) { + for (a = 0, bp = nu->bp; a < nu->pntsv; a++, bp += nu->pntsu) { + if (!(bp->f1 & SELECT)) { + enda = a; + if (starta == -1) { + starta = a; + } + if (a < nu->pntsv - 1) { + continue; + } + } + else if (a < nu->pntsv - 1 && !((bp + nu->pntsu)->f1 & SELECT)) { + /* if just single selected point then continue */ + continue; + } + + if (starta >= 0) { + /* got selected segment, now check where and copy */ + if (starta <= 1 && a == nu->pntsv - 1) { + /* copying all points in spline */ + if (starta == 1 && enda != a) { + nu->flagv &= ~CU_NURB_CYCLIC; + } + + starta = 0; + enda = a; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); + } + else if (starta == 0) { + /* if start of curve copy next end point */ + enda++; + cut = enda - starta + 1; + bp1 = &nu->bp[nu->pntsv * nu->pntsu - nu->pntsu]; + bp2 = &nu->bp[nu->pntsv * nu->pntsu - (nu->pntsu * 2)]; + + if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1); + ED_curve_bpcpy(editnurb, &nu1->bp[nu->pntsu], nu->bp, cut * nu->pntsu); + starta = nu->pntsv - 1; + cut = 1; + } + else { + if (nu->flagv & CU_NURB_CYCLIC) { + cyclicut = cut; + } + else { + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); + } + } + } + else if (enda == nu->pntsv - 1) { + /* if end of curve copy previous start point */ + starta--; + cut = enda - starta + 1; + bp1 = nu->bp; + bp2 = &nu->bp[nu->pntsu]; + + if ((nu->flagv & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + 1); + ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu); + } + else if (cyclicut != 0) { + /* if cyclicut exists it is a cyclic spline, start and end should be connected */ + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut + cyclicut); + ED_curve_bpcpy(editnurb, &nu1->bp[cut * nu->pntsu], nu->bp, nu->pntsu * cyclicut); + cyclicut = 0; + } + else { + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); + } + } + else { + /* mid spline selection, copy adjacent start and end */ + starta--; + enda++; + cut = enda - starta + 1; + nu1 = BKE_nurb_copy(nu, nu->pntsu, cut); + } + + if (nu1 != NULL) { + ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta * nu->pntsu], cut * nu->pntsu); + BLI_addtail(&newnurb, nu1); + + if (starta != 0 || enda != nu->pntsv - 1) { + nu1->flagv &= ~CU_NURB_CYCLIC; + } + nu1 = NULL; + } + starta = enda = -1; + } + } + + if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) { + /* start and points copied if connecting segment was deleted and not cylic spline */ + bp1 = nu->bp; + bp2 = &nu->bp[nu->pntsu]; + + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = BKE_nurb_copy(nu, nu->pntsu, 1); + ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu); + BLI_addtail(&newnurb, nu1); + } + + bp1 = &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu]; + bp2 = &nu->bp[nu->pntsu * nu->pntsv - (nu->pntsu * 2)]; + + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = BKE_nurb_copy(nu, nu->pntsu, 1); + ED_curve_bpcpy( + editnurb, nu1->bp, &nu->bp[nu->pntsu * nu->pntsv - nu->pntsu], nu->pntsu); + BLI_addtail(&newnurb, nu1); + } + } + } + else { + /* selection not valid, just copy nurb to new list */ + nu1 = BKE_nurb_copy(nu, nu->pntsu, nu->pntsv); + ED_curve_bpcpy(editnurb, nu1->bp, nu->bp, nu->pntsu * nu->pntsv); + BLI_addtail(&newnurb, nu1); + } + } + } + + for (nu = newnurb.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + if (split) { + /* deselect for split operator */ + for (b = 0, bezt1 = nu->bezt; b < nu->pntsu; b++, bezt1++) { + select_beztriple(bezt1, DESELECT, SELECT, true); + } + } + + BKE_nurb_handles_calc(nu); + } + else { + if (split) { + /* deselect for split operator */ + for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) { + select_bpoint(bp1, DESELECT, SELECT, HIDDEN); + } + } + + BKE_nurb_order_clamp_u(nu); + BKE_nurb_knot_calc_u(nu); + + if (nu->pntsv > 1) { + BKE_nurb_order_clamp_v(nu); + BKE_nurb_knot_calc_v(nu); + } + } + } + + keyIndex_delNurbList(editnurb, nubase); + BKE_nurbList_free(nubase); + BLI_movelisttolist(nubase, &newnurb); + + return true; } static int curve_delete_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - View3D *v3d = CTX_wm_view3d(C); - eCurveElem_Types type = RNA_enum_get(op->ptr, "type"); - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - bool changed_multi = false; - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = (Curve *)obedit->data; - bool changed = false; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - if (type == CURVE_VERTEX) { - changed = curve_delete_vertices(obedit, v3d); - } - else if (type == CURVE_SEGMENT) { - changed = curve_delete_segments(obedit, v3d, false); - } - else { - BLI_assert(0); - } - - if (changed) { - changed_multi = true; - cu->actnu = cu->actvert = CU_ACT_NONE; - - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - } - MEM_freeN(objects); - - if (changed_multi) { - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } + Main *bmain = CTX_data_main(C); + View3D *v3d = CTX_wm_view3d(C); + eCurveElem_Types type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + bool changed_multi = false; + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = (Curve *)obedit->data; + bool changed = false; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + if (type == CURVE_VERTEX) { + changed = curve_delete_vertices(obedit, v3d); + } + else if (type == CURVE_SEGMENT) { + changed = curve_delete_segments(obedit, v3d, false); + } + else { + BLI_assert(0); + } + + if (changed) { + changed_multi = true; + cu->actnu = cu->actvert = CU_ACT_NONE; + + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + } + MEM_freeN(objects); + + if (changed_multi) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static const EnumPropertyItem curve_delete_type_items[] = { - {CURVE_VERTEX, "VERT", 0, "Vertices", ""}, - {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""}, - {0, NULL, 0, NULL, NULL}, + {CURVE_VERTEX, "VERT", 0, "Vertices", ""}, + {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""}, + {0, NULL, 0, NULL, NULL}, }; -static const EnumPropertyItem *rna_curve_delete_type_itemf( - bContext *C, PointerRNA *UNUSED(ptr), - PropertyRNA *UNUSED(prop), bool *r_free) +static const EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) { - EnumPropertyItem *item = NULL; - int totitem = 0; + EnumPropertyItem *item = NULL; + int totitem = 0; - if (!C) { /* needed for docs and i18n tools */ - return curve_delete_type_items; - } + if (!C) { /* needed for docs and i18n tools */ + return curve_delete_type_items; + } - RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX); - RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT); - RNA_enum_item_end(&item, &totitem); - *r_free = true; + RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX); + RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT); + RNA_enum_item_end(&item, &totitem); + *r_free = true; - return item; + return item; } void CURVE_OT_delete(wmOperatorType *ot) { - PropertyRNA *prop; + PropertyRNA *prop; - /* identifiers */ - ot->name = "Delete"; - ot->description = "Delete selected control points or segments"; - ot->idname = "CURVE_OT_delete"; + /* identifiers */ + ot->name = "Delete"; + ot->description = "Delete selected control points or segments"; + ot->idname = "CURVE_OT_delete"; - /* api callbacks */ - ot->exec = curve_delete_exec; - ot->invoke = WM_menu_invoke; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_delete_exec; + ot->invoke = WM_menu_invoke; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete"); - RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - ot->prop = prop; + /* properties */ + prop = RNA_def_enum( + ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete"); + RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + ot->prop = prop; } static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data) { - View3D *v3d = user_data; - const BezTriple *bezt = bezt_v; - return BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt); + View3D *v3d = user_data; + const BezTriple *bezt = bezt_v; + return BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt); } static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) { - Main *bmain = CTX_data_main(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = (Curve *)obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - - for (nu = editnurb->first; nu; nu = nu->next) { - if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { - unsigned int span_step[2] = {nu->pntsu, nu->pntsu}; - unsigned int span_len; - - while (BLI_array_iter_span( - nu->bezt, nu->pntsu, - (nu->flagu & CU_NURB_CYCLIC) != 0, false, - test_bezt_is_sel_any, v3d, - span_step, &span_len)) - { - BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)]; - BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)]; - - int i_span_edge_len = span_len + 1; - const unsigned int dims = 3; - - const unsigned int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1; - float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__); - float *points_stride = points; - const int points_stride_len = (cu->resolu - 1); - - for (int segment = 0; segment < i_span_edge_len; segment++) { - BezTriple *bezt_a = &nu->bezt[mod_i((span_step[0] + segment) - 1, nu->pntsu)]; - BezTriple *bezt_b = &nu->bezt[mod_i((span_step[0] + segment), nu->pntsu)]; - - for (int axis = 0; axis < dims; axis++) { - BKE_curve_forward_diff_bezier( - bezt_a->vec[1][axis], bezt_a->vec[2][axis], - bezt_b->vec[0][axis], bezt_b->vec[1][axis], - points_stride + axis, points_stride_len, dims * sizeof(float)); - } - - points_stride += dims * points_stride_len; - } - - BLI_assert(points_stride + dims == points + (points_len * dims)); - - float tan_l[3], tan_r[3], error_sq_dummy; - unsigned int error_index_dummy; - - sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); - normalize_v3(tan_l); - sub_v3_v3v3(tan_r, bezt_next->vec[0], bezt_next->vec[1]); - normalize_v3(tan_r); - - curve_fit_cubic_to_points_single_fl( - points, points_len, NULL, dims, FLT_EPSILON, - tan_l, tan_r, - bezt_prev->vec[2], bezt_next->vec[0], - &error_sq_dummy, &error_index_dummy); - - if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) { - bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN; - } - if (!ELEM(bezt_next->h1, HD_FREE, HD_ALIGN)) { - bezt_next->h1 = (bezt_next->h1 == HD_VECT) ? HD_FREE : HD_ALIGN; - } - - MEM_freeN(points); - } - } - } - - ed_curve_delete_selected(obedit, v3d); - - cu->actnu = cu->actvert = CU_ACT_NONE; - - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = (Curve *)obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + + for (nu = editnurb->first; nu; nu = nu->next) { + if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { + unsigned int span_step[2] = {nu->pntsu, nu->pntsu}; + unsigned int span_len; + + while (BLI_array_iter_span(nu->bezt, + nu->pntsu, + (nu->flagu & CU_NURB_CYCLIC) != 0, + false, + test_bezt_is_sel_any, + v3d, + span_step, + &span_len)) { + BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)]; + BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)]; + + int i_span_edge_len = span_len + 1; + const unsigned int dims = 3; + + const unsigned int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1; + float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__); + float *points_stride = points; + const int points_stride_len = (cu->resolu - 1); + + for (int segment = 0; segment < i_span_edge_len; segment++) { + BezTriple *bezt_a = &nu->bezt[mod_i((span_step[0] + segment) - 1, nu->pntsu)]; + BezTriple *bezt_b = &nu->bezt[mod_i((span_step[0] + segment), nu->pntsu)]; + + for (int axis = 0; axis < dims; axis++) { + BKE_curve_forward_diff_bezier(bezt_a->vec[1][axis], + bezt_a->vec[2][axis], + bezt_b->vec[0][axis], + bezt_b->vec[1][axis], + points_stride + axis, + points_stride_len, + dims * sizeof(float)); + } + + points_stride += dims * points_stride_len; + } + + BLI_assert(points_stride + dims == points + (points_len * dims)); + + float tan_l[3], tan_r[3], error_sq_dummy; + unsigned int error_index_dummy; + + sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); + normalize_v3(tan_l); + sub_v3_v3v3(tan_r, bezt_next->vec[0], bezt_next->vec[1]); + normalize_v3(tan_r); + + curve_fit_cubic_to_points_single_fl(points, + points_len, + NULL, + dims, + FLT_EPSILON, + tan_l, + tan_r, + bezt_prev->vec[2], + bezt_next->vec[0], + &error_sq_dummy, + &error_index_dummy); + + if (!ELEM(bezt_prev->h2, HD_FREE, HD_ALIGN)) { + bezt_prev->h2 = (bezt_prev->h2 == HD_VECT) ? HD_FREE : HD_ALIGN; + } + if (!ELEM(bezt_next->h1, HD_FREE, HD_ALIGN)) { + bezt_next->h1 = (bezt_next->h1 == HD_VECT) ? HD_FREE : HD_ALIGN; + } + + MEM_freeN(points); + } + } + } + + ed_curve_delete_selected(obedit, v3d); + + cu->actnu = cu->actvert = CU_ACT_NONE; + + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_dissolve_verts(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Dissolve Vertices"; - ot->description = "Delete selected control points, correcting surrounding handles"; - ot->idname = "CURVE_OT_dissolve_verts"; + /* identifiers */ + ot->name = "Dissolve Vertices"; + ot->description = "Delete selected control points, correcting surrounding handles"; + ot->idname = "CURVE_OT_dissolve_verts"; - /* api callbacks */ - ot->exec = curve_dissolve_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = curve_dissolve_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static bool nurb_bezt_flag_any(const Nurb *nu, const char flag_test) { - BezTriple *bezt = nu->bezt; - int i; + BezTriple *bezt = nu->bezt; + int i; - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (bezt->f2 & flag_test) { - return true; - } - } + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (bezt->f2 & flag_test) { + return true; + } + } - return false; + return false; } static int curve_decimate_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - const float error_sq_max = FLT_MAX; - float ratio = RNA_float_get(op->ptr, "ratio"); - bool all_supported_multi = true; - - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = (Curve *)obedit->data; - bool all_supported = true; - bool changed = false; - - { - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) { - const int error_target_len = max_ii(2, nu->pntsu * ratio); - if (error_target_len != nu->pntsu) { - BKE_curve_decimate_nurb(nu, cu->resolu, error_sq_max, error_target_len); - changed = true; - } - } - } - else { - all_supported = false; - } - } - } - - if (all_supported == false) { - all_supported_multi = false; - } - - if (changed) { - cu->actnu = cu->actvert = CU_ACT_NONE; - if (ED_curve_updateAnimPaths(bmain, obedit->data)) { - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - } - - if (all_supported_multi == false) { - BKE_report(op->reports, RPT_WARNING, "Only bezier curves are supported"); - } - - MEM_freeN(objects); - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + const float error_sq_max = FLT_MAX; + float ratio = RNA_float_get(op->ptr, "ratio"); + bool all_supported_multi = true; + + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = (Curve *)obedit->data; + bool all_supported = true; + bool changed = false; + + { + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) { + const int error_target_len = max_ii(2, nu->pntsu * ratio); + if (error_target_len != nu->pntsu) { + BKE_curve_decimate_nurb(nu, cu->resolu, error_sq_max, error_target_len); + changed = true; + } + } + } + else { + all_supported = false; + } + } + } + + if (all_supported == false) { + all_supported_multi = false; + } + + if (changed) { + cu->actnu = cu->actvert = CU_ACT_NONE; + if (ED_curve_updateAnimPaths(bmain, obedit->data)) { + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + } + + if (all_supported_multi == false) { + BKE_report(op->reports, RPT_WARNING, "Only bezier curves are supported"); + } + + MEM_freeN(objects); + + return OPERATOR_FINISHED; } void CURVE_OT_decimate(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Decimate Curve"; - ot->description = "Simplify selected curves"; - ot->idname = "CURVE_OT_decimate"; + /* identifiers */ + ot->name = "Decimate Curve"; + ot->description = "Simplify selected curves"; + ot->idname = "CURVE_OT_decimate"; - /* api callbacks */ - ot->exec = curve_decimate_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = curve_decimate_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); + /* properties */ + RNA_def_float_factor(ot->srna, "ratio", 1.0f, 0.0f, 1.0f, "Ratio", "", 0.0f, 1.0f); } - /********************** shade smooth/flat operator *********************/ static int shade_smooth_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - int clear = (STREQ(op->idname, "CURVE_OT_shade_flat")); + Object *obedit = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + int clear = (STREQ(op->idname, "CURVE_OT_shade_flat")); - if (obedit->type != OB_CURVE) { - return OPERATOR_CANCELLED; - } + if (obedit->type != OB_CURVE) { + return OPERATOR_CANCELLED; + } - for (nu = editnurb->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - if (!clear) { - nu->flag |= CU_SMOOTH; - } - else { - nu->flag &= ~CU_SMOOTH; - } - } - } + for (nu = editnurb->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + if (!clear) { + nu->flag |= CU_SMOOTH; + } + else { + nu->flag &= ~CU_SMOOTH; + } + } + } - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_shade_smooth(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Shade Smooth"; - ot->idname = "CURVE_OT_shade_smooth"; - ot->description = "Set shading to smooth"; + /* identifiers */ + ot->name = "Shade Smooth"; + ot->idname = "CURVE_OT_shade_smooth"; + ot->description = "Set shading to smooth"; - /* api callbacks */ - ot->exec = shade_smooth_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = shade_smooth_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } void CURVE_OT_shade_flat(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Shade Flat"; - ot->idname = "CURVE_OT_shade_flat"; - ot->description = "Set shading to flat"; + /* identifiers */ + ot->name = "Shade Flat"; + ot->idname = "CURVE_OT_shade_flat"; + ot->description = "Set shading to flat"; - /* api callbacks */ - ot->exec = shade_smooth_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = shade_smooth_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************** join operator, to be used externally? ****************/ /* TODO: shape keys - as with meshes */ int join_curve_exec(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - Object *ob_active = CTX_data_active_object(C); - Curve *cu; - Nurb *nu, *newnu; - BezTriple *bezt; - BPoint *bp; - ListBase tempbase; - float imat[4][4], cmat[4][4]; - int a; - bool ok = false; - - CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) - { - if (ob_iter == ob_active) { - ok = true; - break; - } - } - CTX_DATA_END; - - /* that way the active object is always selected */ - if (ok == false) { - BKE_report(op->reports, RPT_WARNING, "Active object is not a selected curve"); - return OPERATOR_CANCELLED; - } - - BLI_listbase_clear(&tempbase); - - /* trasnform all selected curves inverse in obact */ - invert_m4_m4(imat, ob_active->obmat); - - CTX_DATA_BEGIN(C, Object *, ob_iter, selected_editable_objects) - { - if (ob_iter->type == ob_active->type) { - if (ob_iter != ob_active) { - - cu = ob_iter->data; - - if (cu->nurb.first) { - /* watch it: switch order here really goes wrong */ - mul_m4_m4m4(cmat, imat, ob_iter->obmat); - - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); - if (ob_active->totcol) { /* TODO, merge material lists */ - CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); - } - else { - newnu->mat_nr = 0; - } - BLI_addtail(&tempbase, newnu); - - if ((bezt = newnu->bezt)) { - a = newnu->pntsu; - while (a--) { - mul_m4_v3(cmat, bezt->vec[0]); - mul_m4_v3(cmat, bezt->vec[1]); - mul_m4_v3(cmat, bezt->vec[2]); - bezt++; - } - BKE_nurb_handles_calc(newnu); - } - if ((bp = newnu->bp)) { - a = newnu->pntsu * nu->pntsv; - while (a--) { - mul_m4_v3(cmat, bp->vec); - bp++; - } - } - nu = nu->next; - } - } - - ED_object_base_free_and_unlink(bmain, scene, ob_iter); - } - } - } - CTX_DATA_END; - - cu = ob_active->data; - BLI_movelisttolist(&cu->nurb, &tempbase); - - if (ob_active->type == OB_CURVE) { - /* Account for mixed 2D/3D curves when joining */ - BKE_curve_curve_dimension_update(cu); - } - - DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode! - - DEG_id_tag_update(&ob_active->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - - return OPERATOR_FINISHED; + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Object *ob_active = CTX_data_active_object(C); + Curve *cu; + Nurb *nu, *newnu; + BezTriple *bezt; + BPoint *bp; + ListBase tempbase; + float imat[4][4], cmat[4][4]; + int a; + bool ok = false; + + CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) { + if (ob_iter == ob_active) { + ok = true; + break; + } + } + CTX_DATA_END; + + /* that way the active object is always selected */ + if (ok == false) { + BKE_report(op->reports, RPT_WARNING, "Active object is not a selected curve"); + return OPERATOR_CANCELLED; + } + + BLI_listbase_clear(&tempbase); + + /* trasnform all selected curves inverse in obact */ + invert_m4_m4(imat, ob_active->obmat); + + CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) { + if (ob_iter->type == ob_active->type) { + if (ob_iter != ob_active) { + + cu = ob_iter->data; + + if (cu->nurb.first) { + /* watch it: switch order here really goes wrong */ + mul_m4_m4m4(cmat, imat, ob_iter->obmat); + + nu = cu->nurb.first; + while (nu) { + newnu = BKE_nurb_duplicate(nu); + if (ob_active->totcol) { /* TODO, merge material lists */ + CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); + } + else { + newnu->mat_nr = 0; + } + BLI_addtail(&tempbase, newnu); + + if ((bezt = newnu->bezt)) { + a = newnu->pntsu; + while (a--) { + mul_m4_v3(cmat, bezt->vec[0]); + mul_m4_v3(cmat, bezt->vec[1]); + mul_m4_v3(cmat, bezt->vec[2]); + bezt++; + } + BKE_nurb_handles_calc(newnu); + } + if ((bp = newnu->bp)) { + a = newnu->pntsu * nu->pntsv; + while (a--) { + mul_m4_v3(cmat, bp->vec); + bp++; + } + } + nu = nu->next; + } + } + + ED_object_base_free_and_unlink(bmain, scene, ob_iter); + } + } + } + CTX_DATA_END; + + cu = ob_active->data; + BLI_movelisttolist(&cu->nurb, &tempbase); + + if (ob_active->type == OB_CURVE) { + /* Account for mixed 2D/3D curves when joining */ + BKE_curve_curve_dimension_update(cu); + } + + DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode! + + DEG_id_tag_update(&ob_active->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + + return OPERATOR_FINISHED; } - /***************** clear tilt operator ********************/ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - uint objects_len; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - bezt->tilt = 0.0; - } - bezt++; - } - } - else if (nu->bp) { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->f1 & SELECT) { - bp->tilt = 0.0f; - } - bp++; - } - } - } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + uint objects_len; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + bezt->tilt = 0.0; + } + bezt++; + } + } + else if (nu->bp) { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->f1 & SELECT) { + bp->tilt = 0.0f; + } + bp++; + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_tilt_clear(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Clear Tilt"; - ot->idname = "CURVE_OT_tilt_clear"; - ot->description = "Clear the tilt of selected control points"; + /* identifiers */ + ot->name = "Clear Tilt"; + ot->idname = "CURVE_OT_tilt_clear"; + ot->description = "Clear the tilt of selected control points"; - /* api callbacks */ - ot->exec = clear_tilt_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = clear_tilt_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } void ED_curve_beztcpy(EditNurb *editnurb, BezTriple *dst, BezTriple *src, int count) { - memcpy(dst, src, count * sizeof(BezTriple)); - keyIndex_updateBezt(editnurb, src, dst, count); + memcpy(dst, src, count * sizeof(BezTriple)); + keyIndex_updateBezt(editnurb, src, dst, count); } void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count) { - memcpy(dst, src, count * sizeof(BPoint)); - keyIndex_updateBP(editnurb, src, dst, count); + memcpy(dst, src, count * sizeof(BPoint)); + keyIndex_updateBP(editnurb, src, dst, count); } bool ED_curve_active_center(Curve *cu, float center[3]) { - Nurb *nu = NULL; - void *vert = NULL; + Nurb *nu = NULL; + void *vert = NULL; - if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { - return false; - } + if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { + return false; + } - if (nu->type == CU_BEZIER) { - BezTriple *bezt = (BezTriple *)vert; - copy_v3_v3(center, bezt->vec[1]); - } - else { - BPoint *bp = (BPoint *)vert; - copy_v3_v3(center, bp->vec); - } + if (nu->type == CU_BEZIER) { + BezTriple *bezt = (BezTriple *)vert; + copy_v3_v3(center, bezt->vec[1]); + } + else { + BPoint *bp = (BPoint *)vert; + copy_v3_v3(center, bp->vec); + } - return true; + return true; } /******************** Match texture space operator ***********************/ static bool match_texture_space_poll(bContext *C) { - Object *object = CTX_data_active_object(C); + Object *object = CTX_data_active_object(C); - return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT); + return object && ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT); } static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op)) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - Object *object = CTX_data_active_object(C); - Curve *curve = (Curve *) object->data; - float min[3], max[3], size[3], loc[3]; - int a; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + Object *object = CTX_data_active_object(C); + Curve *curve = (Curve *)object->data; + float min[3], max[3], size[3], loc[3]; + int a; - if (object->runtime.curve_cache == NULL) { - BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL); - } + if (object->runtime.curve_cache == NULL) { + BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL); + } - INIT_MINMAX(min, max); - BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max); + INIT_MINMAX(min, max); + BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max); - mid_v3_v3v3(loc, min, max); + mid_v3_v3v3(loc, min, max); - size[0] = (max[0] - min[0]) / 2.0f; - size[1] = (max[1] - min[1]) / 2.0f; - size[2] = (max[2] - min[2]) / 2.0f; + size[0] = (max[0] - min[0]) / 2.0f; + size[1] = (max[1] - min[1]) / 2.0f; + size[2] = (max[2] - min[2]) / 2.0f; - for (a = 0; a < 3; a++) { - if (size[a] == 0.0f) { - size[a] = 1.0f; - } - else if (size[a] > 0.0f && size[a] < 0.00001f) { - size[a] = 0.00001f; - } - else if (size[a] < 0.0f && size[a] > -0.00001f) { - size[a] = -0.00001f; - } - } + for (a = 0; a < 3; a++) { + if (size[a] == 0.0f) { + size[a] = 1.0f; + } + else if (size[a] > 0.0f && size[a] < 0.00001f) { + size[a] = 0.00001f; + } + else if (size[a] < 0.0f && size[a] > -0.00001f) { + size[a] = -0.00001f; + } + } - copy_v3_v3(curve->loc, loc); - copy_v3_v3(curve->size, size); - zero_v3(curve->rot); + copy_v3_v3(curve->loc, loc); + copy_v3_v3(curve->size, size); + zero_v3(curve->rot); - curve->texflag &= ~CU_AUTOSPACE; + curve->texflag &= ~CU_AUTOSPACE; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void CURVE_OT_match_texture_space(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Match Texture Space"; - ot->idname = "CURVE_OT_match_texture_space"; - ot->description = "Match texture space to object's bounding box"; + /* identifiers */ + ot->name = "Match Texture Space"; + ot->idname = "CURVE_OT_match_texture_space"; + ot->description = "Match texture space to object's bounding box"; - /* api callbacks */ - ot->exec = match_texture_space_exec; - ot->poll = match_texture_space_poll; + /* api callbacks */ + ot->exec = match_texture_space_exec; + ot->poll = match_texture_space_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 0b6d4f6585a..4912ae5451d 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -51,775 +51,791 @@ #include "curve_intern.h" static const float nurbcircle[8][2] = { - {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0}, - {0.0, 1.0}, { 1.0, 1.0}, { 1.0, 0.0}, { 1.0, -1.0}, + {0.0, -1.0}, + {-1.0, -1.0}, + {-1.0, 0.0}, + {-1.0, 1.0}, + {0.0, 1.0}, + {1.0, 1.0}, + {1.0, 0.0}, + {1.0, -1.0}, }; /************ add primitive, used by object/ module ****************/ static const char *get_curve_defname(int type) { - int stype = type & CU_PRIMITIVE; - - if ((type & CU_TYPE) == CU_BEZIER) { - switch (stype) { - case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve"); - case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle"); - case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath"); - default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); - } - } - else { - switch (stype) { - case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve"); - case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle"); - case CU_PRIM_PATH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath"); - default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); - } - } + int stype = type & CU_PRIMITIVE; + + if ((type & CU_TYPE) == CU_BEZIER) { + switch (stype) { + case CU_PRIM_CURVE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCurve"); + case CU_PRIM_CIRCLE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "BezierCircle"); + case CU_PRIM_PATH: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "CurvePath"); + default: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); + } + } + else { + switch (stype) { + case CU_PRIM_CURVE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCurve"); + case CU_PRIM_CIRCLE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsCircle"); + case CU_PRIM_PATH: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "NurbsPath"); + default: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Curve"); + } + } } static const char *get_surf_defname(int type) { - int stype = type & CU_PRIMITIVE; - - switch (stype) { - case CU_PRIM_CURVE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve"); - case CU_PRIM_CIRCLE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle"); - case CU_PRIM_PATCH: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch"); - case CU_PRIM_SPHERE: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere"); - case CU_PRIM_DONUT: return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus"); - default: - return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface"); - } + int stype = type & CU_PRIMITIVE; + + switch (stype) { + case CU_PRIM_CURVE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCurve"); + case CU_PRIM_CIRCLE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfCircle"); + case CU_PRIM_PATCH: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfPatch"); + case CU_PRIM_SPHERE: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfSphere"); + case CU_PRIM_DONUT: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "SurfTorus"); + default: + return CTX_DATA_(BLT_I18NCONTEXT_ID_CURVE, "Surface"); + } } - -Nurb *ED_curve_add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type, int newob) +Nurb *ED_curve_add_nurbs_primitive( + bContext *C, Object *obedit, float mat[4][4], int type, int newob) { - static int xzproj = 0; /* this function calls itself... */ - ListBase *editnurb = object_editcurve_get(obedit); - RegionView3D *rv3d = ED_view3d_context_rv3d(C); - Nurb *nu = NULL; - BezTriple *bezt; - BPoint *bp; - Curve *cu = (Curve *)obedit->data; - float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f}; - float umat[4][4], viewmat[4][4]; - float fac; - int a, b; - const float grid = 1.0f; - const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc - const int stype = (type & CU_PRIMITIVE); - - unit_m4(umat); - unit_m4(viewmat); - - if (rv3d) { - copy_m4_m4(viewmat, rv3d->viewmat); - copy_v3_v3(zvec, rv3d->viewinv[2]); - } - - BKE_nurbList_flag_set(editnurb, 0); - - /* these types call this function to return a Nurb */ - if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) { - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim"); - nu->type = cutype; - nu->resolu = cu->resolu; - nu->resolv = cu->resolv; - } - - switch (stype) { - case CU_PRIM_CURVE: /* curve */ - nu->resolu = cu->resolu; - if (cutype == CU_BEZIER) { - nu->pntsu = 2; - nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1"); - bezt = nu->bezt; - bezt->h1 = bezt->h2 = HD_ALIGN; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = 1.0; - - bezt->vec[1][0] += -grid; - bezt->vec[0][0] += -1.5f * grid; - bezt->vec[0][1] += -0.5f * grid; - bezt->vec[2][0] += -0.5f * grid; - bezt->vec[2][1] += 0.5f * grid; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - - bezt++; - bezt->h1 = bezt->h2 = HD_ALIGN; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = bezt->weight = 1.0; - - bezt->vec[0][0] = 0; - bezt->vec[0][1] = 0; - bezt->vec[1][0] = grid; - bezt->vec[1][1] = 0; - bezt->vec[2][0] = grid * 2; - bezt->vec[2][1] = 0; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - - BKE_nurb_handles_calc(nu); - } - else { - - nu->pntsu = 4; - nu->pntsv = 1; - nu->orderu = 4; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3"); - - bp = nu->bp; - for (a = 0; a < 4; a++, bp++) { - bp->vec[3] = 1.0; - bp->f1 = SELECT; - bp->radius = bp->weight = 1.0; - } - - bp = nu->bp; - bp->vec[0] += -1.5f * grid; - bp++; - bp->vec[0] += -grid; - bp->vec[1] += grid; - bp++; - bp->vec[0] += grid; - bp->vec[1] += grid; - bp++; - bp->vec[0] += 1.5f * grid; - - bp = nu->bp; - for (a = 0; a < 4; a++, bp++) { - mul_m4_v3(mat, bp->vec); - } - - if (cutype == CU_NURBS) { - nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */ - BKE_nurb_knot_calc_u(nu); - } - - } - break; - case CU_PRIM_PATH: /* 5 point path */ - nu->pntsu = 5; - nu->pntsv = 1; - nu->orderu = 5; - nu->flagu = CU_NURB_ENDPOINT; /* endpoint */ - nu->resolu = cu->resolu; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3"); - - bp = nu->bp; - for (a = 0; a < 5; a++, bp++) { - bp->vec[3] = 1.0; - bp->f1 = SELECT; - bp->radius = bp->weight = 1.0; - } - - bp = nu->bp; - bp->vec[0] += -2.0f * grid; - bp++; - bp->vec[0] += -grid; - bp++; bp++; - bp->vec[0] += grid; - bp++; - bp->vec[0] += 2.0f * grid; - - bp = nu->bp; - for (a = 0; a < 5; a++, bp++) { - mul_m4_v3(mat, bp->vec); - } - - if (cutype == CU_NURBS) { - nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */ - BKE_nurb_knot_calc_u(nu); - } - - break; - case CU_PRIM_CIRCLE: /* circle */ - nu->resolu = cu->resolu; - - if (cutype == CU_BEZIER) { - nu->pntsu = 4; - nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1"); - nu->flagu = CU_NURB_CYCLIC; - bezt = nu->bezt; - - bezt->h1 = bezt->h2 = HD_AUTO; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->vec[1][0] += -grid; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - bezt->radius = bezt->weight = 1.0; - - bezt++; - bezt->h1 = bezt->h2 = HD_AUTO; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->vec[1][1] += grid; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - bezt->radius = bezt->weight = 1.0; - - bezt++; - bezt->h1 = bezt->h2 = HD_AUTO; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->vec[1][0] += grid; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - bezt->radius = bezt->weight = 1.0; - - bezt++; - bezt->h1 = bezt->h2 = HD_AUTO; - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->vec[1][1] += -grid; - for (a = 0; a < 3; a++) { - mul_m4_v3(mat, bezt->vec[a]); - } - bezt->radius = bezt->weight = 1.0; - - BKE_nurb_handles_calc(nu); - } - else if (cutype == CU_NURBS) { /* nurb */ - nu->pntsu = 8; - nu->pntsv = 1; - nu->orderu = 4; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6"); - nu->flagu = CU_NURB_CYCLIC; - bp = nu->bp; - - for (a = 0; a < 8; a++) { - bp->f1 = SELECT; - if (xzproj == 0) { - bp->vec[0] += nurbcircle[a][0] * grid; - bp->vec[1] += nurbcircle[a][1] * grid; - } - else { - bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid; - bp->vec[2] += 0.25f * nurbcircle[a][1] * grid; - } - if (a & 1) { - bp->vec[3] = 0.25 * M_SQRT2; - } - else { - bp->vec[3] = 1.0; - } - mul_m4_v3(mat, bp->vec); - bp->radius = bp->weight = 1.0; - - bp++; - } - - BKE_nurb_knot_calc_u(nu); - } - break; - case CU_PRIM_PATCH: /* 4x4 patch */ - if (cutype == CU_NURBS) { /* nurb */ - - nu->pntsu = 4; - nu->pntsv = 4; - nu->orderu = 4; - nu->orderv = 4; - nu->flag = CU_SMOOTH; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6"); - nu->flagu = 0; - nu->flagv = 0; - bp = nu->bp; - - for (a = 0; a < 4; a++) { - for (b = 0; b < 4; b++) { - bp->f1 = SELECT; - fac = (float)a - 1.5f; - bp->vec[0] += fac * grid; - fac = (float)b - 1.5f; - bp->vec[1] += fac * grid; - if ((a == 1 || a == 2) && (b == 1 || b == 2)) { - bp->vec[2] += grid; - } - mul_m4_v3(mat, bp->vec); - bp->vec[3] = 1.0; - bp++; - } - } - - BKE_nurb_knot_calc_u(nu); - BKE_nurb_knot_calc_v(nu); - } - break; - case CU_PRIM_TUBE: /* Cylinder */ - if (cutype == CU_NURBS) { - nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); - nu->resolu = cu->resolu; - nu->flag = CU_SMOOTH; - BLI_addtail(editnurb, nu); /* temporal for extrude and translate */ - vec[0] = vec[1] = 0.0; - vec[2] = -grid; - - mul_mat3_m4_v3(mat, vec); - - ed_editnurb_translate_flag(editnurb, SELECT, vec); - ed_editnurb_extrude_flag(cu->editnurb, SELECT); - mul_v3_fl(vec, -2.0f); - ed_editnurb_translate_flag(editnurb, SELECT, vec); - - BLI_remlink(editnurb, nu); - - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a-- > 0) { - bp->f1 |= SELECT; - bp++; - } - } - break; - case CU_PRIM_SPHERE: /* sphere */ - if (cutype == CU_NURBS) { - float tmp_cent[3] = {0.f, 0.f, 0.f}; - float tmp_vec[3] = {0.f, 0.f, 1.f}; - - nu->pntsu = 5; - nu->pntsv = 1; - nu->orderu = 3; - nu->resolu = cu->resolu; - nu->resolv = cu->resolv; - nu->flag = CU_SMOOTH; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6"); - nu->flagu = 0; - bp = nu->bp; - - for (a = 0; a < 5; a++) { - bp->f1 = SELECT; - bp->vec[0] += nurbcircle[a][0] * grid; - bp->vec[2] += nurbcircle[a][1] * grid; - if (a & 1) { - bp->vec[3] = 0.5 * M_SQRT2; - } - else { - bp->vec[3] = 1.0; - } - mul_m4_v3(mat, bp->vec); - bp++; - } - nu->flagu = CU_NURB_BEZIER; - BKE_nurb_knot_calc_u(nu); - - BLI_addtail(editnurb, nu); /* temporal for spin */ - - if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { - ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); - } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { - ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); - } - else { - ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]); - } - - BKE_nurb_knot_calc_v(nu); - - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a-- > 0) { - bp->f1 |= SELECT; - bp++; - } - BLI_remlink(editnurb, nu); - } - break; - case CU_PRIM_DONUT: /* torus */ - if (cutype == CU_NURBS) { - float tmp_cent[3] = {0.f, 0.f, 0.f}; - float tmp_vec[3] = {0.f, 0.f, 1.f}; - - xzproj = 1; - nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); - xzproj = 0; - nu->resolu = cu->resolu; - nu->resolv = cu->resolv; - nu->flag = CU_SMOOTH; - BLI_addtail(editnurb, nu); /* temporal for spin */ - - /* same as above */ - if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { - ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); - } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { - ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); - } - else { - ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]); - } - - - BLI_remlink(editnurb, nu); - - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a-- > 0) { - bp->f1 |= SELECT; - bp++; - } - - } - break; - - default: /* should never happen */ - BLI_assert(!"invalid nurbs type"); - return NULL; - } - - BLI_assert(nu != NULL); - - if (nu) { /* should always be set */ - if ((obedit->type != OB_SURF) && ((cu->flag & CU_3D) == 0)) { - nu->flag |= CU_2D; - } - - nu->flag |= CU_SMOOTH; - cu->actnu = BLI_listbase_count(editnurb); - cu->actvert = CU_ACT_NONE; - - BKE_nurb_test_2d(nu); - } - - return nu; + static int xzproj = 0; /* this function calls itself... */ + ListBase *editnurb = object_editcurve_get(obedit); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + Nurb *nu = NULL; + BezTriple *bezt; + BPoint *bp; + Curve *cu = (Curve *)obedit->data; + float vec[3], zvec[3] = {0.0f, 0.0f, 1.0f}; + float umat[4][4], viewmat[4][4]; + float fac; + int a, b; + const float grid = 1.0f; + const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc + const int stype = (type & CU_PRIMITIVE); + + unit_m4(umat); + unit_m4(viewmat); + + if (rv3d) { + copy_m4_m4(viewmat, rv3d->viewmat); + copy_v3_v3(zvec, rv3d->viewinv[2]); + } + + BKE_nurbList_flag_set(editnurb, 0); + + /* these types call this function to return a Nurb */ + if (stype != CU_PRIM_TUBE && stype != CU_PRIM_DONUT) { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "addNurbprim"); + nu->type = cutype; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + } + + switch (stype) { + case CU_PRIM_CURVE: /* curve */ + nu->resolu = cu->resolu; + if (cutype == CU_BEZIER) { + nu->pntsu = 2; + nu->bezt = (BezTriple *)MEM_callocN(2 * sizeof(BezTriple), "addNurbprim1"); + bezt = nu->bezt; + bezt->h1 = bezt->h2 = HD_ALIGN; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->radius = 1.0; + + bezt->vec[1][0] += -grid; + bezt->vec[0][0] += -1.5f * grid; + bezt->vec[0][1] += -0.5f * grid; + bezt->vec[2][0] += -0.5f * grid; + bezt->vec[2][1] += 0.5f * grid; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + + bezt++; + bezt->h1 = bezt->h2 = HD_ALIGN; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->radius = bezt->weight = 1.0; + + bezt->vec[0][0] = 0; + bezt->vec[0][1] = 0; + bezt->vec[1][0] = grid; + bezt->vec[1][1] = 0; + bezt->vec[2][0] = grid * 2; + bezt->vec[2][1] = 0; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + + BKE_nurb_handles_calc(nu); + } + else { + + nu->pntsu = 4; + nu->pntsv = 1; + nu->orderu = 4; + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3"); + + bp = nu->bp; + for (a = 0; a < 4; a++, bp++) { + bp->vec[3] = 1.0; + bp->f1 = SELECT; + bp->radius = bp->weight = 1.0; + } + + bp = nu->bp; + bp->vec[0] += -1.5f * grid; + bp++; + bp->vec[0] += -grid; + bp->vec[1] += grid; + bp++; + bp->vec[0] += grid; + bp->vec[1] += grid; + bp++; + bp->vec[0] += 1.5f * grid; + + bp = nu->bp; + for (a = 0; a < 4; a++, bp++) { + mul_m4_v3(mat, bp->vec); + } + + if (cutype == CU_NURBS) { + nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */ + BKE_nurb_knot_calc_u(nu); + } + } + break; + case CU_PRIM_PATH: /* 5 point path */ + nu->pntsu = 5; + nu->pntsv = 1; + nu->orderu = 5; + nu->flagu = CU_NURB_ENDPOINT; /* endpoint */ + nu->resolu = cu->resolu; + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3"); + + bp = nu->bp; + for (a = 0; a < 5; a++, bp++) { + bp->vec[3] = 1.0; + bp->f1 = SELECT; + bp->radius = bp->weight = 1.0; + } + + bp = nu->bp; + bp->vec[0] += -2.0f * grid; + bp++; + bp->vec[0] += -grid; + bp++; + bp++; + bp->vec[0] += grid; + bp++; + bp->vec[0] += 2.0f * grid; + + bp = nu->bp; + for (a = 0; a < 5; a++, bp++) { + mul_m4_v3(mat, bp->vec); + } + + if (cutype == CU_NURBS) { + nu->knotsu = NULL; /* nurbs_knot_calc_u allocates */ + BKE_nurb_knot_calc_u(nu); + } + + break; + case CU_PRIM_CIRCLE: /* circle */ + nu->resolu = cu->resolu; + + if (cutype == CU_BEZIER) { + nu->pntsu = 4; + nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1"); + nu->flagu = CU_NURB_CYCLIC; + bezt = nu->bezt; + + bezt->h1 = bezt->h2 = HD_AUTO; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->vec[1][0] += -grid; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + bezt->radius = bezt->weight = 1.0; + + bezt++; + bezt->h1 = bezt->h2 = HD_AUTO; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->vec[1][1] += grid; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + bezt->radius = bezt->weight = 1.0; + + bezt++; + bezt->h1 = bezt->h2 = HD_AUTO; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->vec[1][0] += grid; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + bezt->radius = bezt->weight = 1.0; + + bezt++; + bezt->h1 = bezt->h2 = HD_AUTO; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + bezt->vec[1][1] += -grid; + for (a = 0; a < 3; a++) { + mul_m4_v3(mat, bezt->vec[a]); + } + bezt->radius = bezt->weight = 1.0; + + BKE_nurb_handles_calc(nu); + } + else if (cutype == CU_NURBS) { /* nurb */ + nu->pntsu = 8; + nu->pntsv = 1; + nu->orderu = 4; + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6"); + nu->flagu = CU_NURB_CYCLIC; + bp = nu->bp; + + for (a = 0; a < 8; a++) { + bp->f1 = SELECT; + if (xzproj == 0) { + bp->vec[0] += nurbcircle[a][0] * grid; + bp->vec[1] += nurbcircle[a][1] * grid; + } + else { + bp->vec[0] += 0.25f * nurbcircle[a][0] * grid - 0.75f * grid; + bp->vec[2] += 0.25f * nurbcircle[a][1] * grid; + } + if (a & 1) { + bp->vec[3] = 0.25 * M_SQRT2; + } + else { + bp->vec[3] = 1.0; + } + mul_m4_v3(mat, bp->vec); + bp->radius = bp->weight = 1.0; + + bp++; + } + + BKE_nurb_knot_calc_u(nu); + } + break; + case CU_PRIM_PATCH: /* 4x4 patch */ + if (cutype == CU_NURBS) { /* nurb */ + + nu->pntsu = 4; + nu->pntsv = 4; + nu->orderu = 4; + nu->orderv = 4; + nu->flag = CU_SMOOTH; + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6"); + nu->flagu = 0; + nu->flagv = 0; + bp = nu->bp; + + for (a = 0; a < 4; a++) { + for (b = 0; b < 4; b++) { + bp->f1 = SELECT; + fac = (float)a - 1.5f; + bp->vec[0] += fac * grid; + fac = (float)b - 1.5f; + bp->vec[1] += fac * grid; + if ((a == 1 || a == 2) && (b == 1 || b == 2)) { + bp->vec[2] += grid; + } + mul_m4_v3(mat, bp->vec); + bp->vec[3] = 1.0; + bp++; + } + } + + BKE_nurb_knot_calc_u(nu); + BKE_nurb_knot_calc_v(nu); + } + break; + case CU_PRIM_TUBE: /* Cylinder */ + if (cutype == CU_NURBS) { + nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); + nu->resolu = cu->resolu; + nu->flag = CU_SMOOTH; + BLI_addtail(editnurb, nu); /* temporal for extrude and translate */ + vec[0] = vec[1] = 0.0; + vec[2] = -grid; + + mul_mat3_m4_v3(mat, vec); + + ed_editnurb_translate_flag(editnurb, SELECT, vec); + ed_editnurb_extrude_flag(cu->editnurb, SELECT); + mul_v3_fl(vec, -2.0f); + ed_editnurb_translate_flag(editnurb, SELECT, vec); + + BLI_remlink(editnurb, nu); + + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a-- > 0) { + bp->f1 |= SELECT; + bp++; + } + } + break; + case CU_PRIM_SPHERE: /* sphere */ + if (cutype == CU_NURBS) { + float tmp_cent[3] = {0.f, 0.f, 0.f}; + float tmp_vec[3] = {0.f, 0.f, 1.f}; + + nu->pntsu = 5; + nu->pntsv = 1; + nu->orderu = 3; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->flag = CU_SMOOTH; + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6"); + nu->flagu = 0; + bp = nu->bp; + + for (a = 0; a < 5; a++) { + bp->f1 = SELECT; + bp->vec[0] += nurbcircle[a][0] * grid; + bp->vec[2] += nurbcircle[a][1] * grid; + if (a & 1) { + bp->vec[3] = 0.5 * M_SQRT2; + } + else { + bp->vec[3] = 1.0; + } + mul_m4_v3(mat, bp->vec); + bp++; + } + nu->flagu = CU_NURB_BEZIER; + BKE_nurb_knot_calc_u(nu); + + BLI_addtail(editnurb, nu); /* temporal for spin */ + + if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { + ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); + } + else if ((U.flag & USER_ADD_VIEWALIGNED)) { + ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); + } + else { + ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]); + } + + BKE_nurb_knot_calc_v(nu); + + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a-- > 0) { + bp->f1 |= SELECT; + bp++; + } + BLI_remlink(editnurb, nu); + } + break; + case CU_PRIM_DONUT: /* torus */ + if (cutype == CU_NURBS) { + float tmp_cent[3] = {0.f, 0.f, 0.f}; + float tmp_vec[3] = {0.f, 0.f, 1.f}; + + xzproj = 1; + nu = ED_curve_add_nurbs_primitive(C, obedit, mat, CU_NURBS | CU_PRIM_CIRCLE, 0); + xzproj = 0; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->flag = CU_SMOOTH; + BLI_addtail(editnurb, nu); /* temporal for spin */ + + /* same as above */ + if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { + ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); + } + else if ((U.flag & USER_ADD_VIEWALIGNED)) { + ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); + } + else { + ed_editnurb_spin(umat, NULL, obedit, tmp_vec, mat[3]); + } + + BLI_remlink(editnurb, nu); + + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a-- > 0) { + bp->f1 |= SELECT; + bp++; + } + } + break; + + default: /* should never happen */ + BLI_assert(!"invalid nurbs type"); + return NULL; + } + + BLI_assert(nu != NULL); + + if (nu) { /* should always be set */ + if ((obedit->type != OB_SURF) && ((cu->flag & CU_3D) == 0)) { + nu->flag |= CU_2D; + } + + nu->flag |= CU_SMOOTH; + cu->actnu = BLI_listbase_count(editnurb); + cu->actvert = CU_ACT_NONE; + + BKE_nurb_test_2d(nu); + } + + return nu; } static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb; - Nurb *nu; - bool newob = false; - bool enter_editmode; - ushort local_view_bits; - float dia; - float loc[3], rot[3]; - float mat[4][4]; - - WM_operator_view3d_unit_defaults(C, op); - - if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) { - return OPERATOR_CANCELLED; - } - - if (!isSurf) { /* adding curve */ - if (obedit == NULL || obedit->type != OB_CURVE) { - const char *name = get_curve_defname(type); - Curve *cu; - - obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, local_view_bits); - newob = true; - - cu = (Curve *)obedit->data; - cu->flag |= CU_DEFORM_FILL; - - if (type & CU_PRIM_PATH) { - cu->flag |= CU_PATH | CU_3D; - } - } - else { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - } - else { /* adding surface */ - if (obedit == NULL || obedit->type != OB_SURF) { - const char *name = get_surf_defname(type); - obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, local_view_bits); - newob = true; - } - else { - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - } - - ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); - dia = RNA_float_get(op->ptr, "radius"); - mul_mat3_m4_fl(mat, dia); - - nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob); - editnurb = object_editcurve_get(obedit); - BLI_addtail(editnurb, nu); - - /* userdef */ - if (newob && !enter_editmode) { - ED_object_editmode_exit(C, EM_FREEDATA); - } - - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb; + Nurb *nu; + bool newob = false; + bool enter_editmode; + ushort local_view_bits; + float dia; + float loc[3], rot[3]; + float mat[4][4]; + + WM_operator_view3d_unit_defaults(C, op); + + if (!ED_object_add_generic_get_opts( + C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) { + return OPERATOR_CANCELLED; + } + + if (!isSurf) { /* adding curve */ + if (obedit == NULL || obedit->type != OB_CURVE) { + const char *name = get_curve_defname(type); + Curve *cu; + + obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, local_view_bits); + newob = true; + + cu = (Curve *)obedit->data; + cu->flag |= CU_DEFORM_FILL; + + if (type & CU_PRIM_PATH) { + cu->flag |= CU_PATH | CU_3D; + } + } + else { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + } + } + else { /* adding surface */ + if (obedit == NULL || obedit->type != OB_SURF) { + const char *name = get_surf_defname(type); + obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, local_view_bits); + newob = true; + } + else { + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + } + } + + ED_object_new_primitive_matrix(C, obedit, loc, rot, mat); + dia = RNA_float_get(op->ptr, "radius"); + mul_mat3_m4_fl(mat, dia); + + nu = ED_curve_add_nurbs_primitive(C, obedit, mat, type, newob); + editnurb = object_editcurve_get(obedit); + BLI_addtail(editnurb, nu); + + /* userdef */ + if (newob && !enter_editmode) { + ED_object_editmode_exit(C, EM_FREEDATA); + } + + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); + + return OPERATOR_FINISHED; } static int curve_prim_add(bContext *C, wmOperator *op, int type) { - return curvesurf_prim_add(C, op, type, 0); + return curvesurf_prim_add(C, op, type, 0); } static int surf_prim_add(bContext *C, wmOperator *op, int type) { - return curvesurf_prim_add(C, op, type, 1); + return curvesurf_prim_add(C, op, type, 1); } /* ******************** Curves ******************* */ static int add_primitive_bezier_exec(bContext *C, wmOperator *op) { - return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE); + return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CURVE); } void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Bezier"; - ot->description = "Construct a Bezier Curve"; - ot->idname = "CURVE_OT_primitive_bezier_curve_add"; + /* identifiers */ + ot->name = "Add Bezier"; + ot->description = "Construct a Bezier Curve"; + ot->idname = "CURVE_OT_primitive_bezier_curve_add"; - /* api callbacks */ - ot->exec = add_primitive_bezier_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_bezier_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op) { - return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE); + return curve_prim_add(C, op, CU_BEZIER | CU_PRIM_CIRCLE); } void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Bezier Circle"; - ot->description = "Construct a Bezier Circle"; - ot->idname = "CURVE_OT_primitive_bezier_circle_add"; + /* identifiers */ + ot->name = "Add Bezier Circle"; + ot->description = "Construct a Bezier Circle"; + ot->idname = "CURVE_OT_primitive_bezier_circle_add"; - /* api callbacks */ - ot->exec = add_primitive_bezier_circle_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_bezier_circle_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op) { - return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE); + return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CURVE); } void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Nurbs Curve"; - ot->description = "Construct a Nurbs Curve"; - ot->idname = "CURVE_OT_primitive_nurbs_curve_add"; + /* identifiers */ + ot->name = "Add Nurbs Curve"; + ot->description = "Construct a Nurbs Curve"; + ot->idname = "CURVE_OT_primitive_nurbs_curve_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_curve_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_curve_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op) { - return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE); + return curve_prim_add(C, op, CU_NURBS | CU_PRIM_CIRCLE); } void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Nurbs Circle"; - ot->description = "Construct a Nurbs Circle"; - ot->idname = "CURVE_OT_primitive_nurbs_circle_add"; + /* identifiers */ + ot->name = "Add Nurbs Circle"; + ot->description = "Construct a Nurbs Circle"; + ot->idname = "CURVE_OT_primitive_nurbs_circle_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_circle_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_circle_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_curve_path_exec(bContext *C, wmOperator *op) { - return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH); + return curve_prim_add(C, op, CU_NURBS | CU_PRIM_PATH); } void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Path"; - ot->description = "Construct a Path"; - ot->idname = "CURVE_OT_primitive_nurbs_path_add"; + /* identifiers */ + ot->name = "Add Path"; + ot->description = "Construct a Path"; + ot->idname = "CURVE_OT_primitive_nurbs_path_add"; - /* api callbacks */ - ot->exec = add_primitive_curve_path_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_curve_path_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } /* **************** NURBS surfaces ********************** */ static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_CURVE | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Curve"; - ot->description = "Construct a Nurbs surface Curve"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add"; + /* identifiers */ + ot->name = "Add Surface Curve"; + ot->description = "Construct a Nurbs surface Curve"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_curve_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_curve_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_curve_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_CIRCLE | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Circle"; - ot->description = "Construct a Nurbs surface Circle"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add"; + /* identifiers */ + ot->name = "Add Surface Circle"; + ot->description = "Construct a Nurbs surface Circle"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_circle_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_circle_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_circle_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_PATCH | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Patch"; - ot->description = "Construct a Nurbs surface Patch"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add"; + /* identifiers */ + ot->name = "Add Surface Patch"; + ot->description = "Construct a Nurbs surface Patch"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_surface_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_surface_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_surface_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_surface_cylinder_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_TUBE | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_cylinder_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Cylinder"; - ot->description = "Construct a Nurbs surface Cylinder"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add"; + /* identifiers */ + ot->name = "Add Surface Cylinder"; + ot->description = "Construct a Nurbs surface Cylinder"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_cylinder_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_cylinder_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_cylinder_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_SPHERE | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Sphere"; - ot->description = "Construct a Nurbs surface Sphere"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add"; + /* identifiers */ + ot->name = "Add Surface Sphere"; + ot->description = "Construct a Nurbs surface Sphere"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_sphere_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_sphere_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_sphere_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } static int add_primitive_nurbs_surface_torus_exec(bContext *C, wmOperator *op) { - return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS); + return surf_prim_add(C, op, CU_PRIM_DONUT | CU_NURBS); } void SURFACE_OT_primitive_nurbs_surface_torus_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Surface Torus"; - ot->description = "Construct a Nurbs surface Torus"; - ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add"; + /* identifiers */ + ot->name = "Add Surface Torus"; + ot->description = "Construct a Nurbs surface Torus"; + ot->idname = "SURFACE_OT_primitive_nurbs_surface_torus_add"; - /* api callbacks */ - ot->exec = add_primitive_nurbs_surface_torus_exec; - ot->poll = ED_operator_scene_editable; + /* api callbacks */ + ot->exec = add_primitive_nurbs_surface_torus_exec; + ot->poll = ED_operator_scene_editable; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - ED_object_add_unit_props_radius(ot); - ED_object_add_generic_props(ot, true); + ED_object_add_unit_props_radius(ot); + ED_object_add_generic_props(ot, true); } diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index d930174c25b..6811e32cc2a 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -43,7 +43,6 @@ #include "ED_view3d.h" #include "ED_curve.h" - #include "GPU_batch.h" #include "GPU_batch_presets.h" #include "GPU_immediate.h" @@ -63,7 +62,7 @@ #define USE_SPLINE_FIT #ifdef USE_SPLINE_FIT -#include "curve_fit_nd.h" +# include "curve_fit_nd.h" #endif /* Distance between input samples */ @@ -71,573 +70,567 @@ #define STROKE_SAMPLE_DIST_MAX_PX 3 /* Distance between start/end points to consider cyclic */ -#define STROKE_CYCLIC_DIST_PX 8 +#define STROKE_CYCLIC_DIST_PX 8 /* -------------------------------------------------------------------- */ /** \name StrokeElem / #RNA_OperatorStrokeElement Conversion Functions * \{ */ struct StrokeElem { - float mval[2]; - float location_world[3]; - float location_local[3]; + float mval[2]; + float location_world[3]; + float location_local[3]; - /* surface normal, may be zero'd */ - float normal_world[3]; - float normal_local[3]; + /* surface normal, may be zero'd */ + float normal_world[3]; + float normal_local[3]; - float pressure; + float pressure; }; struct CurveDrawData { - Depsgraph *depsgraph; + Depsgraph *depsgraph; - short init_event_type; - short curve_type; + short init_event_type; + short curve_type; - /* projecting 2D into 3D space */ - struct { - /* use a plane or project to the surface */ - bool use_plane; - float plane[4]; + /* projecting 2D into 3D space */ + struct { + /* use a plane or project to the surface */ + bool use_plane; + float plane[4]; - /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but that's OK. */ - bool use_depth; + /* use 'rv3d->depths', note that this will become 'damaged' while drawing, but that's OK. */ + bool use_depth; - /* offset projection by this value */ - bool use_offset; - float offset[3]; /* worldspace */ - float surface_offset; - bool use_surface_offset_absolute; - } project; + /* offset projection by this value */ + bool use_offset; + float offset[3]; /* worldspace */ + float surface_offset; + bool use_surface_offset_absolute; + } project; - /* cursor sampling */ - struct { - /* use substeps, needed for nicely interpolating depth */ - bool use_substeps; - } sample; + /* cursor sampling */ + struct { + /* use substeps, needed for nicely interpolating depth */ + bool use_substeps; + } sample; - struct { - float min, max, range; - } radius; + struct { + float min, max, range; + } radius; - struct { - float mouse[2]; - /* used incase we can't calculate the depth */ - float location_world[3]; + struct { + float mouse[2]; + /* used incase we can't calculate the depth */ + float location_world[3]; - float location_world_valid[3]; + float location_world_valid[3]; - const struct StrokeElem *selem; - } prev; + const struct StrokeElem *selem; + } prev; - ViewContext vc; - enum { - CURVE_DRAW_IDLE = 0, - CURVE_DRAW_PAINTING = 1, - } state; + ViewContext vc; + enum { + CURVE_DRAW_IDLE = 0, + CURVE_DRAW_PAINTING = 1, + } state; - /* StrokeElem */ - BLI_mempool *stroke_elem_pool; + /* StrokeElem */ + BLI_mempool *stroke_elem_pool; - void *draw_handle_view; + void *draw_handle_view; }; -static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd, const float pressure) +static float stroke_elem_radius_from_pressure(const struct CurveDrawData *cdd, + const float pressure) { - const Curve *cu = cdd->vc.obedit->data; - return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2; + const Curve *cu = cdd->vc.obedit->data; + return ((pressure * cdd->radius.range) + cdd->radius.min) * cu->ext2; } static float stroke_elem_radius(const struct CurveDrawData *cdd, const struct StrokeElem *selem) { - return stroke_elem_radius_from_pressure(cdd, selem->pressure); + return stroke_elem_radius_from_pressure(cdd, selem->pressure); } -static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, struct StrokeElem *selem, float pressure) +static void stroke_elem_pressure_set(const struct CurveDrawData *cdd, + struct StrokeElem *selem, + float pressure) { - if ((cdd->project.surface_offset != 0.0f) && - !cdd->project.use_surface_offset_absolute && - !is_zero_v3(selem->normal_local)) - { - const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) - - stroke_elem_radius_from_pressure(cdd, selem->pressure); - madd_v3_v3fl(selem->location_local, selem->normal_local, adjust); - mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local); - } - selem->pressure = pressure; + if ((cdd->project.surface_offset != 0.0f) && !cdd->project.use_surface_offset_absolute && + !is_zero_v3(selem->normal_local)) { + const float adjust = stroke_elem_radius_from_pressure(cdd, pressure) - + stroke_elem_radius_from_pressure(cdd, selem->pressure); + madd_v3_v3fl(selem->location_local, selem->normal_local, adjust); + mul_v3_m4v3(selem->location_world, cdd->vc.obedit->obmat, selem->location_local); + } + selem->pressure = pressure; } -static void stroke_elem_interp( - struct StrokeElem *selem_out, - const struct StrokeElem *selem_a, const struct StrokeElem *selem_b, float t) +static void stroke_elem_interp(struct StrokeElem *selem_out, + const struct StrokeElem *selem_a, + const struct StrokeElem *selem_b, + float t) { - interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t); - interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t); - interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t); - selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t); + interp_v2_v2v2(selem_out->mval, selem_a->mval, selem_b->mval, t); + interp_v3_v3v3(selem_out->location_world, selem_a->location_world, selem_b->location_world, t); + interp_v3_v3v3(selem_out->location_local, selem_a->location_local, selem_b->location_local, t); + selem_out->pressure = interpf(selem_a->pressure, selem_b->pressure, t); } - /** * Sets the depth from #StrokeElem.mval */ -static bool stroke_elem_project( - const struct CurveDrawData *cdd, - const int mval_i[2], const float mval_fl[2], - float surface_offset, const float radius, - float r_location_world[3], float r_normal_world[3]) +static bool stroke_elem_project(const struct CurveDrawData *cdd, + const int mval_i[2], + const float mval_fl[2], + float surface_offset, + const float radius, + float r_location_world[3], + float r_normal_world[3]) { - ARegion *ar = cdd->vc.ar; - RegionView3D *rv3d = cdd->vc.rv3d; - - bool is_location_world_set = false; - - /* project to 'location_world' */ - if (cdd->project.use_plane) { - /* get the view vector to 'location' */ - if (ED_view3d_win_to_3d_on_plane(ar, cdd->project.plane, mval_fl, true, r_location_world)) { - if (r_normal_world) { - zero_v3(r_normal_world); - } - is_location_world_set = true; - } - } - else { - const ViewDepths *depths = rv3d->depths; - if (depths && - ((unsigned int)mval_i[0] < depths->w) && - ((unsigned int)mval_i[1] < depths->h)) - { - const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i); - if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { - if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) { - is_location_world_set = true; - if (r_normal_world) { - zero_v3(r_normal_world); - } - - if (surface_offset != 0.0f) { - const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius; - float normal[3]; - if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) { - madd_v3_v3fl(r_location_world, normal, offset * surface_offset); - if (r_normal_world) { - copy_v3_v3(r_normal_world, normal); - } - } - } - } - } - } - } - - if (is_location_world_set) { - if (cdd->project.use_offset) { - add_v3_v3(r_location_world, cdd->project.offset); - } - } - - return is_location_world_set; + ARegion *ar = cdd->vc.ar; + RegionView3D *rv3d = cdd->vc.rv3d; + + bool is_location_world_set = false; + + /* project to 'location_world' */ + if (cdd->project.use_plane) { + /* get the view vector to 'location' */ + if (ED_view3d_win_to_3d_on_plane(ar, cdd->project.plane, mval_fl, true, r_location_world)) { + if (r_normal_world) { + zero_v3(r_normal_world); + } + is_location_world_set = true; + } + } + else { + const ViewDepths *depths = rv3d->depths; + if (depths && ((unsigned int)mval_i[0] < depths->w) && ((unsigned int)mval_i[1] < depths->h)) { + const double depth = (double)ED_view3d_depth_read_cached(&cdd->vc, mval_i); + if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) { + if (ED_view3d_depth_unproject(ar, mval_i, depth, r_location_world)) { + is_location_world_set = true; + if (r_normal_world) { + zero_v3(r_normal_world); + } + + if (surface_offset != 0.0f) { + const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius; + float normal[3]; + if (ED_view3d_depth_read_cached_normal(&cdd->vc, mval_i, normal)) { + madd_v3_v3fl(r_location_world, normal, offset * surface_offset); + if (r_normal_world) { + copy_v3_v3(r_normal_world, normal); + } + } + } + } + } + } + } + + if (is_location_world_set) { + if (cdd->project.use_offset) { + add_v3_v3(r_location_world, cdd->project.offset); + } + } + + return is_location_world_set; } -static bool stroke_elem_project_fallback( - const struct CurveDrawData *cdd, - const int mval_i[2], const float mval_fl[2], - const float surface_offset, const float radius, - const float location_fallback_depth[3], - float r_location_world[3], float r_location_local[3], - float r_normal_world[3], float r_normal_local[3]) +static bool stroke_elem_project_fallback(const struct CurveDrawData *cdd, + const int mval_i[2], + const float mval_fl[2], + const float surface_offset, + const float radius, + const float location_fallback_depth[3], + float r_location_world[3], + float r_location_local[3], + float r_normal_world[3], + float r_normal_local[3]) { - bool is_depth_found = stroke_elem_project( - cdd, mval_i, mval_fl, - surface_offset, radius, - r_location_world, r_normal_world); - if (is_depth_found == false) { - ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, location_fallback_depth, mval_fl, r_location_world); - zero_v3(r_normal_local); - } - mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world); - - if (!is_zero_v3(r_normal_world)) { - copy_v3_v3(r_normal_local, r_normal_world); - mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local); - normalize_v3(r_normal_local); - } - else { - zero_v3(r_normal_local); - } - - return is_depth_found; + bool is_depth_found = stroke_elem_project( + cdd, mval_i, mval_fl, surface_offset, radius, r_location_world, r_normal_world); + if (is_depth_found == false) { + ED_view3d_win_to_3d( + cdd->vc.v3d, cdd->vc.ar, location_fallback_depth, mval_fl, r_location_world); + zero_v3(r_normal_local); + } + mul_v3_m4v3(r_location_local, cdd->vc.obedit->imat, r_location_world); + + if (!is_zero_v3(r_normal_world)) { + copy_v3_v3(r_normal_local, r_normal_world); + mul_transposed_mat3_m4_v3(cdd->vc.obedit->obmat, r_normal_local); + normalize_v3(r_normal_local); + } + else { + zero_v3(r_normal_local); + } + + return is_depth_found; } /** * \note #StrokeElem.mval & #StrokeElem.pressure must be set first. */ -static bool stroke_elem_project_fallback_elem( - const struct CurveDrawData *cdd, - const float location_fallback_depth[3], - struct StrokeElem *selem) +static bool stroke_elem_project_fallback_elem(const struct CurveDrawData *cdd, + const float location_fallback_depth[3], + struct StrokeElem *selem) { - const int mval_i[2] = {UNPACK2(selem->mval)}; - const float radius = stroke_elem_radius(cdd, selem); - return stroke_elem_project_fallback( - cdd, mval_i, selem->mval, - cdd->project.surface_offset, radius, - location_fallback_depth, - selem->location_world, selem->location_local, - selem->normal_world, selem->normal_local); + const int mval_i[2] = {UNPACK2(selem->mval)}; + const float radius = stroke_elem_radius(cdd, selem); + return stroke_elem_project_fallback(cdd, + mval_i, + selem->mval, + cdd->project.surface_offset, + radius, + location_fallback_depth, + selem->location_world, + selem->location_local, + selem->normal_world, + selem->normal_local); } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Operator/Stroke Conversion * \{ */ -static void curve_draw_stroke_to_operator_elem( - wmOperator *op, const struct StrokeElem *selem) +static void curve_draw_stroke_to_operator_elem(wmOperator *op, const struct StrokeElem *selem) { - PointerRNA itemptr; - RNA_collection_add(op->ptr, "stroke", &itemptr); + PointerRNA itemptr; + RNA_collection_add(op->ptr, "stroke", &itemptr); - RNA_float_set_array(&itemptr, "mouse", selem->mval); - RNA_float_set_array(&itemptr, "location", selem->location_world); - RNA_float_set(&itemptr, "pressure", selem->pressure); + RNA_float_set_array(&itemptr, "mouse", selem->mval); + RNA_float_set_array(&itemptr, "location", selem->location_world); + RNA_float_set(&itemptr, "pressure", selem->pressure); } -static void curve_draw_stroke_from_operator_elem( - wmOperator *op, PointerRNA *itemptr) +static void curve_draw_stroke_from_operator_elem(wmOperator *op, PointerRNA *itemptr) { - struct CurveDrawData *cdd = op->customdata; + struct CurveDrawData *cdd = op->customdata; - struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); + struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); - RNA_float_get_array(itemptr, "mouse", selem->mval); - RNA_float_get_array(itemptr, "location", selem->location_world); - mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world); - selem->pressure = RNA_float_get(itemptr, "pressure"); + RNA_float_get_array(itemptr, "mouse", selem->mval); + RNA_float_get_array(itemptr, "location", selem->location_world); + mul_v3_m4v3(selem->location_local, cdd->vc.obedit->imat, selem->location_world); + selem->pressure = RNA_float_get(itemptr, "pressure"); } static void curve_draw_stroke_to_operator(wmOperator *op) { - struct CurveDrawData *cdd = op->customdata; + struct CurveDrawData *cdd = op->customdata; - BLI_mempool_iter iter; - const struct StrokeElem *selem; + BLI_mempool_iter iter; + const struct StrokeElem *selem; - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - curve_draw_stroke_to_operator_elem(op, selem); - } + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + curve_draw_stroke_to_operator_elem(op, selem); + } } static void curve_draw_stroke_from_operator(wmOperator *op) { - RNA_BEGIN (op->ptr, itemptr, "stroke") - { - curve_draw_stroke_from_operator_elem(op, &itemptr); - } - RNA_END; + RNA_BEGIN (op->ptr, itemptr, "stroke") { + curve_draw_stroke_from_operator_elem(op, &itemptr); + } + RNA_END; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Operator Callbacks & Helpers * \{ */ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg) { - wmOperator *op = arg; - struct CurveDrawData *cdd = op->customdata; - - const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); - - if (stroke_len == 0) { - return; - } - - Object *obedit = cdd->vc.obedit; - Curve *cu = obedit->data; - - if (cu->ext2 > 0.0f) { - BLI_mempool_iter iter; - const struct StrokeElem *selem; - - const float location_zero[3] = {0}; - const float *location_prev = location_zero; - - float color[3]; - UI_GetThemeColor3fv(TH_WIRE, color); - - GPUBatch *sphere = GPU_batch_preset_sphere(0); - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_uniform_3fv(sphere, "color", color); - - /* scale to edit-mode space */ - GPU_matrix_push(); - GPU_matrix_mul(obedit->obmat); - - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - GPU_matrix_translate_3f( - selem->location_local[0] - location_prev[0], - selem->location_local[1] - location_prev[1], - selem->location_local[2] - location_prev[2]); - location_prev = selem->location_local; - - const float radius = stroke_elem_radius(cdd, selem); - - GPU_matrix_push(); - GPU_matrix_scale_1f(radius); - GPU_batch_draw(sphere); - GPU_matrix_pop(); - - location_prev = selem->location_local; - } - - GPU_matrix_pop(); - } - - if (stroke_len > 1) { - float (*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__); - - { - BLI_mempool_iter iter; - const struct StrokeElem *selem; - int i; - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter), i = 0; selem; selem = BLI_mempool_iterstep(&iter), i++) { - copy_v3_v3(coord_array[i], selem->location_world); - } - } - - { - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - GPU_depth_test(false); - GPU_blend(true); - GPU_line_smooth(true); - GPU_line_width(3.0f); - - imm_cpack(0x0); - immBegin(GPU_PRIM_LINE_STRIP, stroke_len); - for (int i = 0; i < stroke_len; i++) { - immVertex3fv(pos, coord_array[i]); - } - immEnd(); - - GPU_line_width(1.0f); - - imm_cpack(0xffffffff); - immBegin(GPU_PRIM_LINE_STRIP, stroke_len); - for (int i = 0; i < stroke_len; i++) { - immVertex3fv(pos, coord_array[i]); - } - immEnd(); - - /* Reset defaults */ - GPU_depth_test(true); - GPU_blend(false); - GPU_line_smooth(false); - - immUnbindProgram(); - } - - MEM_freeN(coord_array); - } + wmOperator *op = arg; + struct CurveDrawData *cdd = op->customdata; + + const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); + + if (stroke_len == 0) { + return; + } + + Object *obedit = cdd->vc.obedit; + Curve *cu = obedit->data; + + if (cu->ext2 > 0.0f) { + BLI_mempool_iter iter; + const struct StrokeElem *selem; + + const float location_zero[3] = {0}; + const float *location_prev = location_zero; + + float color[3]; + UI_GetThemeColor3fv(TH_WIRE, color); + + GPUBatch *sphere = GPU_batch_preset_sphere(0); + GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); + GPU_batch_uniform_3fv(sphere, "color", color); + + /* scale to edit-mode space */ + GPU_matrix_push(); + GPU_matrix_mul(obedit->obmat); + + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + GPU_matrix_translate_3f(selem->location_local[0] - location_prev[0], + selem->location_local[1] - location_prev[1], + selem->location_local[2] - location_prev[2]); + location_prev = selem->location_local; + + const float radius = stroke_elem_radius(cdd, selem); + + GPU_matrix_push(); + GPU_matrix_scale_1f(radius); + GPU_batch_draw(sphere); + GPU_matrix_pop(); + + location_prev = selem->location_local; + } + + GPU_matrix_pop(); + } + + if (stroke_len > 1) { + float(*coord_array)[3] = MEM_mallocN(sizeof(*coord_array) * stroke_len, __func__); + + { + BLI_mempool_iter iter; + const struct StrokeElem *selem; + int i; + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter), i = 0; selem; + selem = BLI_mempool_iterstep(&iter), i++) { + copy_v3_v3(coord_array[i], selem->location_world); + } + } + + { + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + GPU_depth_test(false); + GPU_blend(true); + GPU_line_smooth(true); + GPU_line_width(3.0f); + + imm_cpack(0x0); + immBegin(GPU_PRIM_LINE_STRIP, stroke_len); + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } + immEnd(); + + GPU_line_width(1.0f); + + imm_cpack(0xffffffff); + immBegin(GPU_PRIM_LINE_STRIP, stroke_len); + for (int i = 0; i < stroke_len; i++) { + immVertex3fv(pos, coord_array[i]); + } + immEnd(); + + /* Reset defaults */ + GPU_depth_test(true); + GPU_blend(false); + GPU_line_smooth(false); + + immUnbindProgram(); + } + + MEM_freeN(coord_array); + } } static void curve_draw_event_add(wmOperator *op, const wmEvent *event) { - struct CurveDrawData *cdd = op->customdata; - Object *obedit = cdd->vc.obedit; - - invert_m4_m4(obedit->imat, obedit->obmat); - - struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); - - ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]); - - /* handle pressure sensitivity (which is supplied by tablets) */ - if (event->tablet_data) { - const wmTabletData *wmtab = event->tablet_data; - selem->pressure = wmtab->Pressure; - } - else { - selem->pressure = 1.0f; - } - - bool is_depth_found = stroke_elem_project_fallback_elem( - cdd, cdd->prev.location_world_valid, selem); - - if (is_depth_found) { - /* use the depth if a fallback wasn't used */ - copy_v3_v3(cdd->prev.location_world_valid, selem->location_world); - } - copy_v3_v3(cdd->prev.location_world, selem->location_world); - - float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval); - copy_v2_v2(cdd->prev.mouse, selem->mval); - - if (cdd->sample.use_substeps && cdd->prev.selem) { - const struct StrokeElem selem_target = *selem; - struct StrokeElem *selem_new_last = selem; - if (len_sq >= SQUARE(STROKE_SAMPLE_DIST_MAX_PX)) { - int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX ; - - for (int i = 1; i < n; i++) { - struct StrokeElem *selem_new = selem_new_last; - stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n); - - const bool is_depth_found_substep = stroke_elem_project_fallback_elem( - cdd, cdd->prev.location_world_valid, selem_new); - if (is_depth_found == false) { - if (is_depth_found_substep) { - copy_v3_v3(cdd->prev.location_world_valid, selem_new->location_world); - } - } - - selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool); - } - } - selem = selem_new_last; - *selem_new_last = selem_target; - } - - cdd->prev.selem = selem; - - ED_region_tag_redraw(cdd->vc.ar); + struct CurveDrawData *cdd = op->customdata; + Object *obedit = cdd->vc.obedit; + + invert_m4_m4(obedit->imat, obedit->obmat); + + struct StrokeElem *selem = BLI_mempool_calloc(cdd->stroke_elem_pool); + + ARRAY_SET_ITEMS(selem->mval, event->mval[0], event->mval[1]); + + /* handle pressure sensitivity (which is supplied by tablets) */ + if (event->tablet_data) { + const wmTabletData *wmtab = event->tablet_data; + selem->pressure = wmtab->Pressure; + } + else { + selem->pressure = 1.0f; + } + + bool is_depth_found = stroke_elem_project_fallback_elem( + cdd, cdd->prev.location_world_valid, selem); + + if (is_depth_found) { + /* use the depth if a fallback wasn't used */ + copy_v3_v3(cdd->prev.location_world_valid, selem->location_world); + } + copy_v3_v3(cdd->prev.location_world, selem->location_world); + + float len_sq = len_squared_v2v2(cdd->prev.mouse, selem->mval); + copy_v2_v2(cdd->prev.mouse, selem->mval); + + if (cdd->sample.use_substeps && cdd->prev.selem) { + const struct StrokeElem selem_target = *selem; + struct StrokeElem *selem_new_last = selem; + if (len_sq >= SQUARE(STROKE_SAMPLE_DIST_MAX_PX)) { + int n = (int)ceil(sqrt((double)len_sq)) / STROKE_SAMPLE_DIST_MAX_PX; + + for (int i = 1; i < n; i++) { + struct StrokeElem *selem_new = selem_new_last; + stroke_elem_interp(selem_new, cdd->prev.selem, &selem_target, (float)i / n); + + const bool is_depth_found_substep = stroke_elem_project_fallback_elem( + cdd, cdd->prev.location_world_valid, selem_new); + if (is_depth_found == false) { + if (is_depth_found_substep) { + copy_v3_v3(cdd->prev.location_world_valid, selem_new->location_world); + } + } + + selem_new_last = BLI_mempool_calloc(cdd->stroke_elem_pool); + } + } + selem = selem_new_last; + *selem_new_last = selem_target; + } + + cdd->prev.selem = selem; + + ED_region_tag_redraw(cdd->vc.ar); } static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event) { - struct CurveDrawData *cdd = op->customdata; - const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; - - /* add first point */ - curve_draw_event_add(op, event); - - if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && cdd->project.use_depth && - (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS)) - { - RegionView3D *rv3d = cdd->vc.rv3d; - - cdd->project.use_depth = false; - cdd->project.use_plane = true; - - float normal[3] = {0.0f}; - if (ELEM(cps->surface_plane, - CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW, - CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE)) - { - if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) { - if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) { - float cross_a[3], cross_b[3]; - cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal); - cross_v3_v3v3(cross_b, normal, cross_a); - copy_v3_v3(normal, cross_b); - } - } - } - - /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */ - if (is_zero_v3(normal)) { - copy_v3_v3(normal, rv3d->viewinv[2]); - } - - normalize_v3_v3(cdd->project.plane, normal); - cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, cdd->prev.location_world_valid); - - /* Special case for when we only have offset applied on the first-hit, - * the remaining stroke must be offset too. */ - if (cdd->project.surface_offset != 0.0f) { - const float mval_fl[2] = {UNPACK2(event->mval)}; - - float location_no_offset[3]; - - if (stroke_elem_project( - cdd, event->mval, mval_fl, 0.0f, 0.0f, - location_no_offset, NULL)) - { - sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset); - if (!is_zero_v3(cdd->project.offset)) { - cdd->project.use_offset = true; - } - } - } - /* end special case */ - - } - - cdd->init_event_type = event->type; - cdd->state = CURVE_DRAW_PAINTING; + struct CurveDrawData *cdd = op->customdata; + const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; + + /* add first point */ + curve_draw_event_add(op, event); + + if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && cdd->project.use_depth && + (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_ENDPOINTS)) { + RegionView3D *rv3d = cdd->vc.rv3d; + + cdd->project.use_depth = false; + cdd->project.use_plane = true; + + float normal[3] = {0.0f}; + if (ELEM(cps->surface_plane, + CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW, + CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE)) { + if (ED_view3d_depth_read_cached_normal(&cdd->vc, event->mval, normal)) { + if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) { + float cross_a[3], cross_b[3]; + cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal); + cross_v3_v3v3(cross_b, normal, cross_a); + copy_v3_v3(normal, cross_b); + } + } + } + + /* CURVE_PAINT_SURFACE_PLANE_VIEW or fallback */ + if (is_zero_v3(normal)) { + copy_v3_v3(normal, rv3d->viewinv[2]); + } + + normalize_v3_v3(cdd->project.plane, normal); + cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, cdd->prev.location_world_valid); + + /* Special case for when we only have offset applied on the first-hit, + * the remaining stroke must be offset too. */ + if (cdd->project.surface_offset != 0.0f) { + const float mval_fl[2] = {UNPACK2(event->mval)}; + + float location_no_offset[3]; + + if (stroke_elem_project(cdd, event->mval, mval_fl, 0.0f, 0.0f, location_no_offset, NULL)) { + sub_v3_v3v3(cdd->project.offset, cdd->prev.location_world_valid, location_no_offset); + if (!is_zero_v3(cdd->project.offset)) { + cdd->project.use_offset = true; + } + } + } + /* end special case */ + } + + cdd->init_event_type = event->type; + cdd->state = CURVE_DRAW_PAINTING; } static bool curve_draw_init(bContext *C, wmOperator *op, bool is_invoke) { - BLI_assert(op->customdata == NULL); + BLI_assert(op->customdata == NULL); - struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__); + struct CurveDrawData *cdd = MEM_callocN(sizeof(*cdd), __func__); - cdd->depsgraph = CTX_data_depsgraph(C); + cdd->depsgraph = CTX_data_depsgraph(C); - if (is_invoke) { - ED_view3d_viewcontext_init(C, &cdd->vc); - if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) { - MEM_freeN(cdd); - BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport"); - return false; - } - } - else { - cdd->vc.bmain = CTX_data_main(C); - cdd->vc.depsgraph = CTX_data_depsgraph(C); - cdd->vc.scene = CTX_data_scene(C); - cdd->vc.view_layer = CTX_data_view_layer(C); - cdd->vc.obedit = CTX_data_edit_object(C); - } + if (is_invoke) { + ED_view3d_viewcontext_init(C, &cdd->vc); + if (ELEM(NULL, cdd->vc.ar, cdd->vc.rv3d, cdd->vc.v3d, cdd->vc.win, cdd->vc.scene)) { + MEM_freeN(cdd); + BKE_report(op->reports, RPT_ERROR, "Unable to access 3D viewport"); + return false; + } + } + else { + cdd->vc.bmain = CTX_data_main(C); + cdd->vc.depsgraph = CTX_data_depsgraph(C); + cdd->vc.scene = CTX_data_scene(C); + cdd->vc.view_layer = CTX_data_view_layer(C); + cdd->vc.obedit = CTX_data_edit_object(C); + } - op->customdata = cdd; + op->customdata = cdd; - const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; + const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; - cdd->curve_type = cps->curve_type; + cdd->curve_type = cps->curve_type; - cdd->radius.min = cps->radius_min; - cdd->radius.max = cps->radius_max; - cdd->radius.range = cps->radius_max - cps->radius_min; - cdd->project.surface_offset = cps->surface_offset; - cdd->project.use_surface_offset_absolute = (cps->flag & CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS) != 0; + cdd->radius.min = cps->radius_min; + cdd->radius.max = cps->radius_max; + cdd->radius.range = cps->radius_max - cps->radius_min; + cdd->project.surface_offset = cps->surface_offset; + cdd->project.use_surface_offset_absolute = (cps->flag & + CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS) != 0; - cdd->stroke_elem_pool = BLI_mempool_create( - sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER); + cdd->stroke_elem_pool = BLI_mempool_create( + sizeof(struct StrokeElem), 0, 512, BLI_MEMPOOL_ALLOW_ITER); - return true; + return true; } - static void curve_draw_exit(wmOperator *op) { - struct CurveDrawData *cdd = op->customdata; - if (cdd) { - if (cdd->draw_handle_view) { - ED_region_draw_cb_exit(cdd->vc.ar->type, cdd->draw_handle_view); - WM_cursor_modal_restore(cdd->vc.win); - } - - if (cdd->stroke_elem_pool) { - BLI_mempool_destroy(cdd->stroke_elem_pool); - } - - MEM_freeN(cdd); - op->customdata = NULL; - } + struct CurveDrawData *cdd = op->customdata; + if (cdd) { + if (cdd->draw_handle_view) { + ED_region_draw_cb_exit(cdd->vc.ar->type, cdd->draw_handle_view); + WM_cursor_modal_restore(cdd->vc.win); + } + + if (cdd->stroke_elem_pool) { + BLI_mempool_destroy(cdd->stroke_elem_pool); + } + + MEM_freeN(cdd); + op->customdata = NULL; + } } /** @@ -645,583 +638,601 @@ static void curve_draw_exit(wmOperator *op) */ static void curve_draw_exec_precalc(wmOperator *op) { - struct CurveDrawData *cdd = op->customdata; - const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; - PropertyRNA *prop; - - prop = RNA_struct_find_property(op->ptr, "fit_method"); - if (!RNA_property_is_set(op->ptr, prop)) { - RNA_property_enum_set(op->ptr, prop, cps->fit_method); - } - - prop = RNA_struct_find_property(op->ptr, "corner_angle"); - if (!RNA_property_is_set(op->ptr, prop)) { - const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle : (float)M_PI; - RNA_property_float_set(op->ptr, prop, corner_angle); - } - - prop = RNA_struct_find_property(op->ptr, "error_threshold"); - if (!RNA_property_is_set(op->ptr, prop)) { - - /* error isnt set so we'll have to calculate it from the pixel values */ - BLI_mempool_iter iter; - const struct StrokeElem *selem, *selem_prev; - - float len_3d = 0.0f, len_2d = 0.0f; - float scale_px; /* pixel to local space scale */ - - int i = 0; - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - selem_prev = BLI_mempool_iterstep(&iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) { - len_3d += len_v3v3(selem->location_local, selem_prev->location_local); - len_2d += len_v2v2(selem->mval, selem_prev->mval); - selem_prev = selem; - } - scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f; - float error_threshold = (cps->error_threshold * U.pixelsize) * scale_px; - RNA_property_float_set(op->ptr, prop, error_threshold); - } - - prop = RNA_struct_find_property(op->ptr, "use_cyclic"); - if (!RNA_property_is_set(op->ptr, prop)) { - bool use_cyclic = false; - - if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) { - BLI_mempool_iter iter; - const struct StrokeElem *selem, *selem_first, *selem_last; - - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - selem_first = selem_last = BLI_mempool_iterstep(&iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - selem_last = selem; - } - - if (len_squared_v2v2( - selem_first->mval, - selem_last->mval) <= SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize)) - { - use_cyclic = true; - } - } - - RNA_property_boolean_set(op->ptr, prop, use_cyclic); - } - - - if ((cps->radius_taper_start != 0.0f) || - (cps->radius_taper_end != 0.0f)) - { - /* note, we could try to de-duplicate the length calculations above */ - const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); - - BLI_mempool_iter iter; - struct StrokeElem *selem, *selem_prev; - - float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__); - struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__); - lengths[0] = 0.0f; - - float len_3d = 0.0f; - - int i = 1; - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - selem_prev = BLI_mempool_iterstep(&iter); - selem_array[0] = selem_prev; - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) { - const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local); - len_3d += len_3d_segment; - lengths[i] = len_3d; - selem_array[i] = selem; - selem_prev = selem; - } - - if (cps->radius_taper_start != 0.0f) { - const float len_taper_max = cps->radius_taper_start * len_3d; - for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) { - const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max); - stroke_elem_pressure_set(cdd, selem_array[i], pressure_new); - } - } - - if (cps->radius_taper_end != 0.0f) { - const float len_taper_max = cps->radius_taper_end * len_3d; - const float len_taper_min = len_3d - len_taper_max; - for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) { - const float pressure_new = selem_array[i]->pressure * ((len_3d - lengths[i]) / len_taper_max); - stroke_elem_pressure_set(cdd, selem_array[i], pressure_new); - } - } - - MEM_freeN(lengths); - MEM_freeN(selem_array); - } + struct CurveDrawData *cdd = op->customdata; + const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; + PropertyRNA *prop; + + prop = RNA_struct_find_property(op->ptr, "fit_method"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_enum_set(op->ptr, prop, cps->fit_method); + } + + prop = RNA_struct_find_property(op->ptr, "corner_angle"); + if (!RNA_property_is_set(op->ptr, prop)) { + const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle : + (float)M_PI; + RNA_property_float_set(op->ptr, prop, corner_angle); + } + + prop = RNA_struct_find_property(op->ptr, "error_threshold"); + if (!RNA_property_is_set(op->ptr, prop)) { + + /* error isnt set so we'll have to calculate it from the pixel values */ + BLI_mempool_iter iter; + const struct StrokeElem *selem, *selem_prev; + + float len_3d = 0.0f, len_2d = 0.0f; + float scale_px; /* pixel to local space scale */ + + int i = 0; + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + selem_prev = BLI_mempool_iterstep(&iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) { + len_3d += len_v3v3(selem->location_local, selem_prev->location_local); + len_2d += len_v2v2(selem->mval, selem_prev->mval); + selem_prev = selem; + } + scale_px = ((len_3d > 0.0f) && (len_2d > 0.0f)) ? (len_3d / len_2d) : 0.0f; + float error_threshold = (cps->error_threshold * U.pixelsize) * scale_px; + RNA_property_float_set(op->ptr, prop, error_threshold); + } + + prop = RNA_struct_find_property(op->ptr, "use_cyclic"); + if (!RNA_property_is_set(op->ptr, prop)) { + bool use_cyclic = false; + + if (BLI_mempool_len(cdd->stroke_elem_pool) > 2) { + BLI_mempool_iter iter; + const struct StrokeElem *selem, *selem_first, *selem_last; + + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + selem_first = selem_last = BLI_mempool_iterstep(&iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + selem_last = selem; + } + + if (len_squared_v2v2(selem_first->mval, selem_last->mval) <= + SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize)) { + use_cyclic = true; + } + } + + RNA_property_boolean_set(op->ptr, prop, use_cyclic); + } + + if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) { + /* note, we could try to de-duplicate the length calculations above */ + const int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); + + BLI_mempool_iter iter; + struct StrokeElem *selem, *selem_prev; + + float *lengths = MEM_mallocN(sizeof(float) * stroke_len, __func__); + struct StrokeElem **selem_array = MEM_mallocN(sizeof(*selem_array) * stroke_len, __func__); + lengths[0] = 0.0f; + + float len_3d = 0.0f; + + int i = 1; + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + selem_prev = BLI_mempool_iterstep(&iter); + selem_array[0] = selem_prev; + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), i++) { + const float len_3d_segment = len_v3v3(selem->location_local, selem_prev->location_local); + len_3d += len_3d_segment; + lengths[i] = len_3d; + selem_array[i] = selem; + selem_prev = selem; + } + + if (cps->radius_taper_start != 0.0f) { + const float len_taper_max = cps->radius_taper_start * len_3d; + for (i = 0; i < stroke_len && lengths[i] < len_taper_max; i++) { + const float pressure_new = selem_array[i]->pressure * (lengths[i] / len_taper_max); + stroke_elem_pressure_set(cdd, selem_array[i], pressure_new); + } + } + + if (cps->radius_taper_end != 0.0f) { + const float len_taper_max = cps->radius_taper_end * len_3d; + const float len_taper_min = len_3d - len_taper_max; + for (i = stroke_len - 1; i > 0 && lengths[i] > len_taper_min; i--) { + const float pressure_new = selem_array[i]->pressure * + ((len_3d - lengths[i]) / len_taper_max); + stroke_elem_pressure_set(cdd, selem_array[i], pressure_new); + } + } + + MEM_freeN(lengths); + MEM_freeN(selem_array); + } } static int curve_draw_exec(bContext *C, wmOperator *op) { - if (op->customdata == NULL) { - if (!curve_draw_init(C, op, false)) { - return OPERATOR_CANCELLED; - } - } + if (op->customdata == NULL) { + if (!curve_draw_init(C, op, false)) { + return OPERATOR_CANCELLED; + } + } - struct CurveDrawData *cdd = op->customdata; + struct CurveDrawData *cdd = op->customdata; - const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; - Object *obedit = cdd->vc.obedit; - Curve *cu = obedit->data; - ListBase *nurblist = object_editcurve_get(obedit); + const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; + Object *obedit = cdd->vc.obedit; + Curve *cu = obedit->data; + ListBase *nurblist = object_editcurve_get(obedit); - int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); + int stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); - const bool is_3d = (cu->flag & CU_3D) != 0; - invert_m4_m4(obedit->imat, obedit->obmat); + const bool is_3d = (cu->flag & CU_3D) != 0; + invert_m4_m4(obedit->imat, obedit->obmat); - if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) { - curve_draw_stroke_from_operator(op); - stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); - } + if (BLI_mempool_len(cdd->stroke_elem_pool) == 0) { + curve_draw_stroke_from_operator(op); + stroke_len = BLI_mempool_len(cdd->stroke_elem_pool); + } - /* Deselect all existing curves. */ - ED_curve_deselect_all_multi(C); + /* Deselect all existing curves. */ + ED_curve_deselect_all_multi(C); - const float radius_min = cps->radius_min; - const float radius_max = cps->radius_max; - const float radius_range = cps->radius_max - cps->radius_min; + const float radius_min = cps->radius_min; + const float radius_max = cps->radius_max; + const float radius_range = cps->radius_max - cps->radius_min; - Nurb *nu = MEM_callocN(sizeof(Nurb), __func__); - nu->pntsv = 0; - nu->resolu = cu->resolu; - nu->resolv = cu->resolv; - nu->flag |= CU_SMOOTH; + Nurb *nu = MEM_callocN(sizeof(Nurb), __func__); + nu->pntsv = 0; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->flag |= CU_SMOOTH; - const bool use_pressure_radius = - (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) || - ((cps->radius_taper_start != 0.0f) || - (cps->radius_taper_end != 0.0f)); + const bool use_pressure_radius = (cps->flag & CURVE_PAINT_FLAG_PRESSURE_RADIUS) || + ((cps->radius_taper_start != 0.0f) || + (cps->radius_taper_end != 0.0f)); - if (cdd->curve_type == CU_BEZIER) { - nu->type = CU_BEZIER; + if (cdd->curve_type == CU_BEZIER) { + nu->type = CU_BEZIER; #ifdef USE_SPLINE_FIT - /* Allow to interpolate multiple channels */ - int dims = 3; - struct { - int radius; - } coords_indices; - coords_indices.radius = use_pressure_radius ? dims++ : -1; - - float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__); - - float *cubic_spline = NULL; - unsigned int cubic_spline_len = 0; - - /* error in object local space */ - const int fit_method = RNA_enum_get(op->ptr, "fit_method"); - const float error_threshold = RNA_float_get(op->ptr, "error_threshold"); - const float corner_angle = RNA_float_get(op->ptr, "corner_angle"); - const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic"); - - { - BLI_mempool_iter iter; - const struct StrokeElem *selem; - float *co = coords; - - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter), co += dims) { - copy_v3_v3(co, selem->location_local); - if (coords_indices.radius != -1) { - co[coords_indices.radius] = selem->pressure; - } - - /* remove doubles */ - if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) { - co -= dims; - stroke_len--; - } - } - } - - unsigned int *corners = NULL; - unsigned int corners_len = 0; - - if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) { - /* this could be configurable... */ - const float corner_radius_min = error_threshold / 8; - const float corner_radius_max = error_threshold * 2; - const unsigned int samples_max = 16; - - curve_fit_corners_detect_fl( - coords, stroke_len, dims, - corner_radius_min, corner_radius_max, - samples_max, corner_angle, - &corners, &corners_len); - } - - unsigned int *corners_index = NULL; - unsigned int corners_index_len = 0; - unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY; - - if ((stroke_len > 2) && use_cyclic) { - calc_flag |= CURVE_FIT_CALC_CYCLIC; - } - - int result; - if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) { - result = curve_fit_cubic_to_points_refit_fl( - coords, stroke_len, dims, error_threshold, calc_flag, - NULL, 0, corner_angle, - &cubic_spline, &cubic_spline_len, - NULL, - &corners_index, &corners_index_len); - } - else { - result = curve_fit_cubic_to_points_fl( - coords, stroke_len, dims, error_threshold, calc_flag, - corners, corners_len, - &cubic_spline, &cubic_spline_len, - NULL, - &corners_index, &corners_index_len); - } - - MEM_freeN(coords); - if (corners) { - free(corners); - } - - if (result == 0) { - nu->pntsu = cubic_spline_len; - nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__); - - float *co = cubic_spline; - BezTriple *bezt = nu->bezt; - for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) { - const float *handle_l = co + (dims * 0); - const float *pt = co + (dims * 1); - const float *handle_r = co + (dims * 2); - - copy_v3_v3(bezt->vec[0], handle_l); - copy_v3_v3(bezt->vec[1], pt); - copy_v3_v3(bezt->vec[2], handle_r); - - if (coords_indices.radius != -1) { - bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min; - } - else { - bezt->radius = radius_max; - } - - bezt->h1 = bezt->h2 = HD_ALIGN; /* will set to free in second pass */ - bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - } - - if (corners_index) { - /* ignore the first and last */ - unsigned int i_start = 0, i_end = corners_index_len; - - if ((corners_index_len >= 2) && - (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) - { - i_start += 1; - i_end -= 1; - } - - for (unsigned int i = i_start; i < i_end; i++) { - bezt = &nu->bezt[corners_index[i]]; - bezt->h1 = bezt->h2 = HD_FREE; - } - } - - if (calc_flag & CURVE_FIT_CALC_CYCLIC) { - nu->flagu |= CU_NURB_CYCLIC; - } - } - - if (corners_index) { - free(corners_index); - } - - if (cubic_spline) { - free(cubic_spline); - } + /* Allow to interpolate multiple channels */ + int dims = 3; + struct { + int radius; + } coords_indices; + coords_indices.radius = use_pressure_radius ? dims++ : -1; + + float *coords = MEM_mallocN(sizeof(*coords) * stroke_len * dims, __func__); + + float *cubic_spline = NULL; + unsigned int cubic_spline_len = 0; + + /* error in object local space */ + const int fit_method = RNA_enum_get(op->ptr, "fit_method"); + const float error_threshold = RNA_float_get(op->ptr, "error_threshold"); + const float corner_angle = RNA_float_get(op->ptr, "corner_angle"); + const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic"); + + { + BLI_mempool_iter iter; + const struct StrokeElem *selem; + float *co = coords; + + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter); selem; + selem = BLI_mempool_iterstep(&iter), co += dims) { + copy_v3_v3(co, selem->location_local); + if (coords_indices.radius != -1) { + co[coords_indices.radius] = selem->pressure; + } + + /* remove doubles */ + if ((co != coords) && UNLIKELY(memcmp(co, co - dims, sizeof(float) * dims) == 0)) { + co -= dims; + stroke_len--; + } + } + } + + unsigned int *corners = NULL; + unsigned int corners_len = 0; + + if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) { + /* this could be configurable... */ + const float corner_radius_min = error_threshold / 8; + const float corner_radius_max = error_threshold * 2; + const unsigned int samples_max = 16; + + curve_fit_corners_detect_fl(coords, + stroke_len, + dims, + corner_radius_min, + corner_radius_max, + samples_max, + corner_angle, + &corners, + &corners_len); + } + + unsigned int *corners_index = NULL; + unsigned int corners_index_len = 0; + unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY; + + if ((stroke_len > 2) && use_cyclic) { + calc_flag |= CURVE_FIT_CALC_CYCLIC; + } + + int result; + if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) { + result = curve_fit_cubic_to_points_refit_fl(coords, + stroke_len, + dims, + error_threshold, + calc_flag, + NULL, + 0, + corner_angle, + &cubic_spline, + &cubic_spline_len, + NULL, + &corners_index, + &corners_index_len); + } + else { + result = curve_fit_cubic_to_points_fl(coords, + stroke_len, + dims, + error_threshold, + calc_flag, + corners, + corners_len, + &cubic_spline, + &cubic_spline_len, + NULL, + &corners_index, + &corners_index_len); + } + + MEM_freeN(coords); + if (corners) { + free(corners); + } + + if (result == 0) { + nu->pntsu = cubic_spline_len; + nu->bezt = MEM_callocN(sizeof(BezTriple) * nu->pntsu, __func__); + + float *co = cubic_spline; + BezTriple *bezt = nu->bezt; + for (int j = 0; j < cubic_spline_len; j++, bezt++, co += (dims * 3)) { + const float *handle_l = co + (dims * 0); + const float *pt = co + (dims * 1); + const float *handle_r = co + (dims * 2); + + copy_v3_v3(bezt->vec[0], handle_l); + copy_v3_v3(bezt->vec[1], pt); + copy_v3_v3(bezt->vec[2], handle_r); + + if (coords_indices.radius != -1) { + bezt->radius = (pt[coords_indices.radius] * cdd->radius.range) + cdd->radius.min; + } + else { + bezt->radius = radius_max; + } + + bezt->h1 = bezt->h2 = HD_ALIGN; /* will set to free in second pass */ + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + } + + if (corners_index) { + /* ignore the first and last */ + unsigned int i_start = 0, i_end = corners_index_len; + + if ((corners_index_len >= 2) && (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) { + i_start += 1; + i_end -= 1; + } + + for (unsigned int i = i_start; i < i_end; i++) { + bezt = &nu->bezt[corners_index[i]]; + bezt->h1 = bezt->h2 = HD_FREE; + } + } + + if (calc_flag & CURVE_FIT_CALC_CYCLIC) { + nu->flagu |= CU_NURB_CYCLIC; + } + } + + if (corners_index) { + free(corners_index); + } + + if (cubic_spline) { + free(cubic_spline); + } #else - nu->pntsu = stroke_len; - nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__); - - BezTriple *bezt = nu->bezt; - - { - BLI_mempool_iter iter; - const struct StrokeElem *selem; - - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - copy_v3_v3(bezt->vec[1], selem->location_local); - if (!is_3d) { - bezt->vec[1][2] = 0.0f; - } - - if (use_pressure_radius) { - bezt->radius = selem->pressure; - } - else { - bezt->radius = radius_max; - } - - bezt->h1 = bezt->h2 = HD_AUTO; - - bezt->f1 |= SELECT; - bezt->f2 |= SELECT; - bezt->f3 |= SELECT; - - bezt++; - } - } + nu->pntsu = stroke_len; + nu->bezt = MEM_callocN(nu->pntsu * sizeof(BezTriple), __func__); + + BezTriple *bezt = nu->bezt; + + { + BLI_mempool_iter iter; + const struct StrokeElem *selem; + + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + copy_v3_v3(bezt->vec[1], selem->location_local); + if (!is_3d) { + bezt->vec[1][2] = 0.0f; + } + + if (use_pressure_radius) { + bezt->radius = selem->pressure; + } + else { + bezt->radius = radius_max; + } + + bezt->h1 = bezt->h2 = HD_AUTO; + + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; + + bezt++; + } + } #endif - BKE_nurb_handles_calc(nu); - } - else { /* CU_POLY */ - BLI_mempool_iter iter; - const struct StrokeElem *selem; + BKE_nurb_handles_calc(nu); + } + else { /* CU_POLY */ + BLI_mempool_iter iter; + const struct StrokeElem *selem; - nu->pntsu = stroke_len; - nu->pntsv = 1; - nu->type = CU_POLY; - nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__); + nu->pntsu = stroke_len; + nu->pntsv = 1; + nu->type = CU_POLY; + nu->bp = MEM_callocN(nu->pntsu * sizeof(BPoint), __func__); - /* Misc settings. */ - nu->resolu = cu->resolu; - nu->resolv = 1; - nu->orderu = 4; - nu->orderv = 1; + /* Misc settings. */ + nu->resolu = cu->resolu; + nu->resolv = 1; + nu->orderu = 4; + nu->orderv = 1; - BPoint *bp = nu->bp; + BPoint *bp = nu->bp; - BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); - for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { - copy_v3_v3(bp->vec, selem->location_local); - if (!is_3d) { - bp->vec[2] = 0.0f; - } + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + copy_v3_v3(bp->vec, selem->location_local); + if (!is_3d) { + bp->vec[2] = 0.0f; + } - if (use_pressure_radius) { - bp->radius = (selem->pressure * radius_range) + radius_min; - } - else { - bp->radius = cps->radius_max; - } - bp->f1 = SELECT; - bp->vec[3] = 1.0f; + if (use_pressure_radius) { + bp->radius = (selem->pressure * radius_range) + radius_min; + } + else { + bp->radius = cps->radius_max; + } + bp->f1 = SELECT; + bp->vec[3] = 1.0f; - bp++; - } + bp++; + } - BKE_nurb_knot_calc_u(nu); - } + BKE_nurb_knot_calc_u(nu); + } - BLI_addtail(nurblist, nu); + BLI_addtail(nurblist, nu); - BKE_curve_nurb_active_set(cu, nu); - cu->actvert = nu->pntsu - 1; + BKE_curve_nurb_active_set(cu, nu); + cu->actvert = nu->pntsu - 1; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DEG_id_tag_update(obedit->data, 0); - curve_draw_exit(op); + curve_draw_exit(op); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - if (RNA_struct_property_is_set(op->ptr, "stroke")) { - return curve_draw_exec(C, op); - } - - if (!curve_draw_init(C, op, true)) { - return OPERATOR_CANCELLED; - } - - struct CurveDrawData *cdd = op->customdata; - - const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; - - const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); - - /* fallback (incase we can't find the depth on first test) */ - { - const float mval_fl[2] = {UNPACK2(event->mval)}; - float center[3]; - negate_v3_v3(center, cdd->vc.rv3d->ofs); - ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, center, mval_fl, cdd->prev.location_world); - copy_v3_v3(cdd->prev.location_world_valid, cdd->prev.location_world); - } - - cdd->draw_handle_view = ED_region_draw_cb_activate( - cdd->vc.ar->type, curve_draw_stroke_3d, op, REGION_DRAW_POST_VIEW); - WM_cursor_modal_set(cdd->vc.win, BC_PAINTBRUSHCURSOR); - - { - View3D *v3d = cdd->vc.v3d; - RegionView3D *rv3d = cdd->vc.rv3d; - Object *obedit = cdd->vc.obedit; - Curve *cu = obedit->data; - - const float *plane_no = NULL; - const float *plane_co = NULL; - - if ((cu->flag & CU_3D) == 0) { - /* 2D overrides other options */ - plane_co = obedit->obmat[3]; - plane_no = obedit->obmat[2]; - cdd->project.use_plane = true; - } - else { - if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && - (v3d->shading.type > OB_WIRE)) - { - /* needed or else the draw matrix can be incorrect */ - view3d_operator_needs_opengl(C); - - ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0); - - if (cdd->vc.rv3d->depths) { - cdd->vc.rv3d->depths->damaged = true; - } - - ED_view3d_depth_update(cdd->vc.ar); - - if (cdd->vc.rv3d->depths != NULL) { - cdd->project.use_depth = true; - } - else { - BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane"); - cdd->project.use_depth = false; - } - } - - /* use view plane (when set or as fallback when surface can't be found) */ - if (cdd->project.use_depth == false) { - plane_co = cdd->vc.scene->cursor.location; - plane_no = rv3d->viewinv[2]; - cdd->project.use_plane = true; - } - - if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) { - cdd->sample.use_substeps = true; - } - } - - if (cdd->project.use_plane) { - normalize_v3_v3(cdd->project.plane, plane_no); - cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co); - } - } - - if (is_modal == false) { - curve_draw_event_add_first(op, event); - } - - /* add temp handler */ - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; + if (RNA_struct_property_is_set(op->ptr, "stroke")) { + return curve_draw_exec(C, op); + } + + if (!curve_draw_init(C, op, true)) { + return OPERATOR_CANCELLED; + } + + struct CurveDrawData *cdd = op->customdata; + + const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; + + const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); + + /* fallback (incase we can't find the depth on first test) */ + { + const float mval_fl[2] = {UNPACK2(event->mval)}; + float center[3]; + negate_v3_v3(center, cdd->vc.rv3d->ofs); + ED_view3d_win_to_3d(cdd->vc.v3d, cdd->vc.ar, center, mval_fl, cdd->prev.location_world); + copy_v3_v3(cdd->prev.location_world_valid, cdd->prev.location_world); + } + + cdd->draw_handle_view = ED_region_draw_cb_activate( + cdd->vc.ar->type, curve_draw_stroke_3d, op, REGION_DRAW_POST_VIEW); + WM_cursor_modal_set(cdd->vc.win, BC_PAINTBRUSHCURSOR); + + { + View3D *v3d = cdd->vc.v3d; + RegionView3D *rv3d = cdd->vc.rv3d; + Object *obedit = cdd->vc.obedit; + Curve *cu = obedit->data; + + const float *plane_no = NULL; + const float *plane_co = NULL; + + if ((cu->flag & CU_3D) == 0) { + /* 2D overrides other options */ + plane_co = obedit->obmat[3]; + plane_no = obedit->obmat[2]; + cdd->project.use_plane = true; + } + else { + if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) && (v3d->shading.type > OB_WIRE)) { + /* needed or else the draw matrix can be incorrect */ + view3d_operator_needs_opengl(C); + + ED_view3d_autodist_init(cdd->vc.depsgraph, cdd->vc.ar, cdd->vc.v3d, 0); + + if (cdd->vc.rv3d->depths) { + cdd->vc.rv3d->depths->damaged = true; + } + + ED_view3d_depth_update(cdd->vc.ar); + + if (cdd->vc.rv3d->depths != NULL) { + cdd->project.use_depth = true; + } + else { + BKE_report(op->reports, RPT_WARNING, "Unable to access depth buffer, using view plane"); + cdd->project.use_depth = false; + } + } + + /* use view plane (when set or as fallback when surface can't be found) */ + if (cdd->project.use_depth == false) { + plane_co = cdd->vc.scene->cursor.location; + plane_no = rv3d->viewinv[2]; + cdd->project.use_plane = true; + } + + if (cdd->project.use_depth && (cdd->curve_type != CU_POLY)) { + cdd->sample.use_substeps = true; + } + } + + if (cdd->project.use_plane) { + normalize_v3_v3(cdd->project.plane, plane_no); + cdd->project.plane[3] = -dot_v3v3(cdd->project.plane, plane_co); + } + } + + if (is_modal == false) { + curve_draw_event_add_first(op, event); + } + + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; } static void curve_draw_cancel(bContext *UNUSED(C), wmOperator *op) { - curve_draw_exit(op); + curve_draw_exit(op); } - /* Modal event handling of frame changing */ static int curve_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) { - int ret = OPERATOR_RUNNING_MODAL; - struct CurveDrawData *cdd = op->customdata; - - UNUSED_VARS(C, op); - - if (event->type == cdd->init_event_type) { - if (event->val == KM_RELEASE) { - ED_region_tag_redraw(cdd->vc.ar); - - curve_draw_exec_precalc(op); - - curve_draw_stroke_to_operator(op); - - curve_draw_exec(C, op); - - return OPERATOR_FINISHED; - } - } - else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) { - ED_region_tag_redraw(cdd->vc.ar); - curve_draw_cancel(C, op); - return OPERATOR_CANCELLED; - } - else if (ELEM(event->type, LEFTMOUSE)) { - if (event->val == KM_PRESS) { - curve_draw_event_add_first(op, event); - } - } - else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { - if (cdd->state == CURVE_DRAW_PAINTING) { - const float mval_fl[2] = {UNPACK2(event->mval)}; - if (len_squared_v2v2(mval_fl, cdd->prev.mouse) > SQUARE(STROKE_SAMPLE_DIST_MIN_PX)) { - curve_draw_event_add(op, event); - } - } - } - - return ret; + int ret = OPERATOR_RUNNING_MODAL; + struct CurveDrawData *cdd = op->customdata; + + UNUSED_VARS(C, op); + + if (event->type == cdd->init_event_type) { + if (event->val == KM_RELEASE) { + ED_region_tag_redraw(cdd->vc.ar); + + curve_draw_exec_precalc(op); + + curve_draw_stroke_to_operator(op); + + curve_draw_exec(C, op); + + return OPERATOR_FINISHED; + } + } + else if (ELEM(event->type, ESCKEY, RIGHTMOUSE)) { + ED_region_tag_redraw(cdd->vc.ar); + curve_draw_cancel(C, op); + return OPERATOR_CANCELLED; + } + else if (ELEM(event->type, LEFTMOUSE)) { + if (event->val == KM_PRESS) { + curve_draw_event_add_first(op, event); + } + } + else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + if (cdd->state == CURVE_DRAW_PAINTING) { + const float mval_fl[2] = {UNPACK2(event->mval)}; + if (len_squared_v2v2(mval_fl, cdd->prev.mouse) > SQUARE(STROKE_SAMPLE_DIST_MIN_PX)) { + curve_draw_event_add(op, event); + } + } + } + + return ret; } void CURVE_OT_draw(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Draw Curve"; - ot->idname = "CURVE_OT_draw"; - ot->description = "Draw a freehand spline"; - - /* api callbacks */ - ot->exec = curve_draw_exec; - ot->invoke = curve_draw_invoke; - ot->cancel = curve_draw_cancel; - ot->modal = curve_draw_modal; - ot->poll = ED_operator_editcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - PropertyRNA *prop; - - prop = RNA_def_float_distance( - ot->srna, "error_threshold", 0.0f, 0.0f, 10.0f, "Error", - "Error distance threshold (in object units)", - 0.0001f, 10.0f); - RNA_def_property_ui_range(prop, 0.0, 10, 1, 4); - - RNA_def_enum(ot->srna, "fit_method", rna_enum_curve_fit_method_items, CURVE_PAINT_FIT_METHOD_REFIT, - "Fit Method", ""); - - prop = RNA_def_float_distance( - ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI); - RNA_def_property_subtype(prop, PROP_ANGLE); - - prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - - prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); - RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + /* identifiers */ + ot->name = "Draw Curve"; + ot->idname = "CURVE_OT_draw"; + ot->description = "Draw a freehand spline"; + + /* api callbacks */ + ot->exec = curve_draw_exec; + ot->invoke = curve_draw_invoke; + ot->cancel = curve_draw_cancel; + ot->modal = curve_draw_modal; + ot->poll = ED_operator_editcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + PropertyRNA *prop; + + prop = RNA_def_float_distance(ot->srna, + "error_threshold", + 0.0f, + 0.0f, + 10.0f, + "Error", + "Error distance threshold (in object units)", + 0.0001f, + 10.0f); + RNA_def_property_ui_range(prop, 0.0, 10, 1, 4); + + RNA_def_enum(ot->srna, + "fit_method", + rna_enum_curve_fit_method_items, + CURVE_PAINT_FIT_METHOD_REFIT, + "Fit Method", + ""); + + prop = RNA_def_float_distance( + ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI); + RNA_def_property_subtype(prop, PROP_ANGLE); + + prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index d9392090166..d3f0ebfda3c 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -59,271 +59,272 @@ /* returns 1 in case (de)selection was successful */ bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden) { - if ((bezt->hide == 0) || (hidden == HIDDEN)) { - if (selstatus == SELECT) { /* selects */ - bezt->f1 |= flag; - bezt->f2 |= flag; - bezt->f3 |= flag; - return true; - } - else { /* deselects */ - bezt->f1 &= ~flag; - bezt->f2 &= ~flag; - bezt->f3 &= ~flag; - return true; - } - } - - return false; + if ((bezt->hide == 0) || (hidden == HIDDEN)) { + if (selstatus == SELECT) { /* selects */ + bezt->f1 |= flag; + bezt->f2 |= flag; + bezt->f3 |= flag; + return true; + } + else { /* deselects */ + bezt->f1 &= ~flag; + bezt->f2 &= ~flag; + bezt->f3 &= ~flag; + return true; + } + } + + return false; } /* returns 1 in case (de)selection was successful */ bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden) { - if ((bp->hide == 0) || (hidden == 1)) { - if (selstatus == SELECT) { - bp->f1 |= flag; - return true; - } - else { - bp->f1 &= ~flag; - return true; - } - } - - return false; + if ((bp->hide == 0) || (hidden == 1)) { + if (selstatus == SELECT) { + bp->f1 |= flag; + return true; + } + else { + bp->f1 &= ~flag; + return true; + } + } + + return false; } static bool swap_selection_beztriple(BezTriple *bezt) { - if (bezt->f2 & SELECT) { - return select_beztriple(bezt, DESELECT, SELECT, VISIBLE); - } - else { - return select_beztriple(bezt, SELECT, SELECT, VISIBLE); - } + if (bezt->f2 & SELECT) { + return select_beztriple(bezt, DESELECT, SELECT, VISIBLE); + } + else { + return select_beztriple(bezt, SELECT, SELECT, VISIBLE); + } } static bool swap_selection_bpoint(BPoint *bp) { - if (bp->f1 & SELECT) { - return select_bpoint(bp, DESELECT, SELECT, VISIBLE); - } - else { - return select_bpoint(bp, SELECT, SELECT, VISIBLE); - } + if (bp->f1 & SELECT) { + return select_bpoint(bp, DESELECT, SELECT, VISIBLE); + } + else { + return select_bpoint(bp, SELECT, SELECT, VISIBLE); + } } bool ED_curve_nurb_select_check(View3D *v3d, Nurb *nu) { - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - int i; - - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - return true; - } - } - } - else { - BPoint *bp; - int i; - - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (bp->f1 & SELECT) { - return true; - } - } - } - return false; + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + int i; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + return true; + } + } + } + else { + BPoint *bp; + int i; + + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (bp->f1 & SELECT) { + return true; + } + } + } + return false; } int ED_curve_nurb_select_count(View3D *v3d, Nurb *nu) { - int sel = 0; - - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - int i; - - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { - sel++; - } - } - } - else { - BPoint *bp; - int i; - - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (bp->f1 & SELECT) { - sel++; - } - } - } - - return sel; + int sel = 0; + + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + int i; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt)) { + sel++; + } + } + } + else { + BPoint *bp; + int i; + + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (bp->f1 & SELECT) { + sel++; + } + } + } + + return sel; } bool ED_curve_nurb_select_all(const Nurb *nu) { - bool changed = false; - int i; - if (nu->bezt) { - BezTriple *bezt; - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (bezt->hide == 0) { - if (BEZT_ISSEL_ALL(bezt) == false) { - BEZT_SEL_ALL(bezt); - changed = true; - } - } - } - } - else if (nu->bp) { - BPoint *bp; - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (bp->hide == 0) { - if ((bp->f1 & SELECT) == 0) { - bp->f1 |= SELECT; - changed = true; - } - } - } - } - return changed; + bool changed = false; + int i; + if (nu->bezt) { + BezTriple *bezt; + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (bezt->hide == 0) { + if (BEZT_ISSEL_ALL(bezt) == false) { + BEZT_SEL_ALL(bezt); + changed = true; + } + } + } + } + else if (nu->bp) { + BPoint *bp; + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (bp->hide == 0) { + if ((bp->f1 & SELECT) == 0) { + bp->f1 |= SELECT; + changed = true; + } + } + } + } + return changed; } bool ED_curve_select_all(EditNurb *editnurb) { - bool changed = false; - for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { - changed |= ED_curve_nurb_select_all(nu); - } - return changed; + bool changed = false; + for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { + changed |= ED_curve_nurb_select_all(nu); + } + return changed; } bool ED_curve_nurb_deselect_all(const Nurb *nu) { - bool changed = false; - int i; - if (nu->bezt) { - BezTriple *bezt; - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (BEZT_ISSEL_ANY(bezt)) { - BEZT_DESEL_ALL(bezt); - changed = true; - } - } - } - else if (nu->bp) { - BPoint *bp; - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (bp->f1 & SELECT) { - bp->f1 &= ~SELECT; - changed = true; - } - } - } - return changed; + bool changed = false; + int i; + if (nu->bezt) { + BezTriple *bezt; + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (BEZT_ISSEL_ANY(bezt)) { + BEZT_DESEL_ALL(bezt); + changed = true; + } + } + } + else if (nu->bp) { + BPoint *bp; + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (bp->f1 & SELECT) { + bp->f1 &= ~SELECT; + changed = true; + } + } + } + return changed; } int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) { - int sel = 0; - Nurb *nu; + int sel = 0; + Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - sel += ED_curve_nurb_select_count(v3d, nu); - } + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + sel += ED_curve_nurb_select_count(v3d, nu); + } - return sel; + return sel; } bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) { - Nurb *nu; + Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - return true; - } - } + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + return true; + } + } - return false; + return false; } bool ED_curve_deselect_all(EditNurb *editnurb) { - bool changed = false; - for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { - changed |= ED_curve_nurb_deselect_all(nu); - } - return changed; + bool changed = false; + for (Nurb *nu = editnurb->nurbs.first; nu; nu = nu->next) { + changed |= ED_curve_nurb_deselect_all(nu); + } + return changed; } bool ED_curve_deselect_all_multi_ex(Base **bases, int bases_len) { - bool changed_multi = false; - for (uint base_index = 0; base_index < bases_len; base_index++) { - Object *obedit = bases[base_index]->object; - Curve *cu = obedit->data; - changed_multi |= ED_curve_deselect_all(cu->editnurb); - DEG_id_tag_update(&cu->id, ID_RECALC_SELECT); - } - return changed_multi; + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Object *obedit = bases[base_index]->object; + Curve *cu = obedit->data; + changed_multi |= ED_curve_deselect_all(cu->editnurb); + DEG_id_tag_update(&cu->id, ID_RECALC_SELECT); + } + return changed_multi; } bool ED_curve_deselect_all_multi(struct bContext *C) { - ViewContext vc; - ED_view3d_viewcontext_init(C, &vc); - uint bases_len = 0; - Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc.view_layer, vc.v3d, &bases_len); - bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len); - MEM_freeN(bases); - return changed_multi; + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc.view_layer, vc.v3d, &bases_len); + bool changed_multi = ED_curve_deselect_all_multi_ex(bases, bases_len); + MEM_freeN(bases); + return changed_multi; } bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) { - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - bool changed = false; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (bezt->hide == 0) { - bezt->f2 ^= SELECT; /* always do the center point */ - if (!hide_handles) { - bezt->f1 ^= SELECT; - bezt->f3 ^= SELECT; - } - changed = true; - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - if (bp->hide == 0) { - swap_selection_bpoint(bp); - changed = true; - } - bp++; - } - } - } - return changed; + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + bool changed = false; + + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + if (bezt->hide == 0) { + bezt->f2 ^= SELECT; /* always do the center point */ + if (!hide_handles) { + bezt->f1 ^= SELECT; + bezt->f3 ^= SELECT; + } + changed = true; + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + if (bp->hide == 0) { + swap_selection_bpoint(bp); + changed = true; + } + bp++; + } + } + } + return changed; } /** @@ -331,77 +332,80 @@ bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) * \param cont: when true select continuously * \param selstatus: inverts behavior */ -static void select_adjacent_cp( - ListBase *editnurb, short next, - const bool cont, const bool selstatus) +static void select_adjacent_cp(ListBase *editnurb, + short next, + const bool cont, + const bool selstatus) { - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - bool lastsel = false; - - if (next == 0) { - return; - } - - for (nu = editnurb->first; nu; nu = nu->next) { - lastsel = false; - if (nu->type == CU_BEZIER) { - a = nu->pntsu; - bezt = nu->bezt; - if (next < 0) { - bezt = &nu->bezt[a - 1]; - } - while (a--) { - if (a - abs(next) < 0) { - break; - } - if ((lastsel == false) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { - bezt += next; - if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { - bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); - if (sel && !cont) { - lastsel = true; - } - } - } - else { - bezt += next; - lastsel = false; - } - /* move around in zigzag way so that we go through each */ - bezt -= (next - next / abs(next)); - } - } - else { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - if (next < 0) { - bp = &nu->bp[a - 1]; - } - while (a--) { - if (a - abs(next) < 0) { - break; - } - if ((lastsel == false) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) { - bp += next; - if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { - bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); - if (sel && !cont) { - lastsel = true; - } - } - } - else { - bp += next; - lastsel = false; - } - /* move around in zigzag way so that we go through each */ - bp -= (next - next / abs(next)); - } - } - } + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + bool lastsel = false; + + if (next == 0) { + return; + } + + for (nu = editnurb->first; nu; nu = nu->next) { + lastsel = false; + if (nu->type == CU_BEZIER) { + a = nu->pntsu; + bezt = nu->bezt; + if (next < 0) { + bezt = &nu->bezt[a - 1]; + } + while (a--) { + if (a - abs(next) < 0) { + break; + } + if ((lastsel == false) && (bezt->hide == 0) && + ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { + bezt += next; + if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { + bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); + if (sel && !cont) { + lastsel = true; + } + } + } + else { + bezt += next; + lastsel = false; + } + /* move around in zigzag way so that we go through each */ + bezt -= (next - next / abs(next)); + } + } + else { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + if (next < 0) { + bp = &nu->bp[a - 1]; + } + while (a--) { + if (a - abs(next) < 0) { + break; + } + if ((lastsel == false) && (bp->hide == 0) && + ((bp->f1 & SELECT) || (selstatus == DESELECT))) { + bp += next; + if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { + bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); + if (sel && !cont) { + lastsel = true; + } + } + } + else { + bp += next; + lastsel = false; + } + /* move around in zigzag way so that we go through each */ + bp -= (next - next / abs(next)); + } + } + } } /**************** select start/end operators **************/ @@ -413,570 +417,579 @@ static void select_adjacent_cp( */ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - Curve *cu; - int a; - - if (obedit == NULL) { - return; - } - - cu = (Curve *)obedit->data; - cu->actvert = CU_ACT_NONE; - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - a = nu->pntsu; - - /* which point? */ - if (selfirst == LAST) { /* select last */ - bezt = &nu->bezt[a - 1]; - } - else { /* select first */ - bezt = nu->bezt; - } - - while (a--) { - bool sel; - if (doswap) { - sel = swap_selection_beztriple(bezt); - } - else { - sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); - } - - if (sel == true) { - break; - } - } - } - else { - a = nu->pntsu * nu->pntsv; - - /* which point? */ - if (selfirst == LAST) { /* select last */ - bp = &nu->bp[a - 1]; - } - else { /* select first */ - bp = nu->bp; - } - - while (a--) { - if (bp->hide == 0) { - bool sel; - if (doswap) { - sel = swap_selection_bpoint(bp); - } - else { - sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); - } - - if (sel == true) { - break; - } - } - } - } - } + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + Curve *cu; + int a; + + if (obedit == NULL) { + return; + } + + cu = (Curve *)obedit->data; + cu->actvert = CU_ACT_NONE; + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + a = nu->pntsu; + + /* which point? */ + if (selfirst == LAST) { /* select last */ + bezt = &nu->bezt[a - 1]; + } + else { /* select first */ + bezt = nu->bezt; + } + + while (a--) { + bool sel; + if (doswap) { + sel = swap_selection_beztriple(bezt); + } + else { + sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); + } + + if (sel == true) { + break; + } + } + } + else { + a = nu->pntsu * nu->pntsv; + + /* which point? */ + if (selfirst == LAST) { /* select last */ + bp = &nu->bp[a - 1]; + } + else { /* select first */ + bp = nu->bp; + } + + while (a--) { + if (bp->hide == 0) { + bool sel; + if (doswap) { + sel = swap_selection_bpoint(bp); + } + else { + sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); + } + + if (sel == true) { + break; + } + } + } + } + } } static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - selectend_nurb(obedit, FIRST, true, DESELECT); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + selectend_nurb(obedit, FIRST, true, DESELECT); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + BKE_curve_nurb_vert_active_validate(obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_de_select_first(wmOperatorType *ot) { - /* identifiers */ - ot->name = "(De)select First"; - ot->idname = "CURVE_OT_de_select_first"; - ot->description = "(De)select first of visible part of each NURBS"; + /* identifiers */ + ot->name = "(De)select First"; + ot->idname = "CURVE_OT_de_select_first"; + ot->description = "(De)select first of visible part of each NURBS"; - /* api cfirstbacks */ - ot->exec = de_select_first_exec; - ot->poll = ED_operator_editcurve; + /* api cfirstbacks */ + ot->exec = de_select_first_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - selectend_nurb(obedit, LAST, true, DESELECT); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(obedit->data); - } - - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + selectend_nurb(obedit, LAST, true, DESELECT); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + BKE_curve_nurb_vert_active_validate(obedit->data); + } + + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_de_select_last(wmOperatorType *ot) { - /* identifiers */ - ot->name = "(De)select Last"; - ot->idname = "CURVE_OT_de_select_last"; - ot->description = "(De)select last of visible part of each NURBS"; + /* identifiers */ + ot->name = "(De)select Last"; + ot->idname = "CURVE_OT_de_select_last"; + ot->description = "(De)select last of visible part of each NURBS"; - /* api clastbacks */ - ot->exec = de_select_last_exec; - ot->poll = ED_operator_editcurve; + /* api clastbacks */ + ot->exec = de_select_last_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } static int de_select_all_exec(bContext *C, wmOperator *op) { - int action = RNA_enum_get(op->ptr, "action"); - - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - if (action == SEL_TOGGLE) { - action = SEL_SELECT; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (ED_curve_select_check(v3d, cu->editnurb)) { - action = SEL_DESELECT; - break; - } - } - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - bool changed = false; - - switch (action) { - case SEL_SELECT: - changed = ED_curve_select_all(cu->editnurb); - break; - case SEL_DESELECT: - changed = ED_curve_deselect_all(cu->editnurb); - break; - case SEL_INVERT: - changed = ED_curve_select_swap(cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0); - break; - } - - if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - BKE_curve_nurb_vert_active_validate(cu); - } - } - - MEM_freeN(objects); - return OPERATOR_FINISHED; + int action = RNA_enum_get(op->ptr, "action"); + + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + if (action == SEL_TOGGLE) { + action = SEL_SELECT; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (ED_curve_select_check(v3d, cu->editnurb)) { + action = SEL_DESELECT; + break; + } + } + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + bool changed = false; + + switch (action) { + case SEL_SELECT: + changed = ED_curve_select_all(cu->editnurb); + break; + case SEL_DESELECT: + changed = ED_curve_deselect_all(cu->editnurb); + break; + case SEL_INVERT: + changed = ED_curve_select_swap( + cu->editnurb, (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0); + break; + } + + if (changed) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + BKE_curve_nurb_vert_active_validate(cu); + } + } + + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "(De)select All"; - ot->idname = "CURVE_OT_select_all"; - ot->description = "(De)select all control points"; + /* identifiers */ + ot->name = "(De)select All"; + ot->idname = "CURVE_OT_select_all"; + ot->description = "(De)select all control points"; - /* api callbacks */ - ot->exec = de_select_all_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = de_select_all_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - WM_operator_properties_select_all(ot); + /* properties */ + WM_operator_properties_select_all(ot); } - - /***************** select linked operator ******************/ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - ListBase *nurbs = &editnurb->nurbs; - Nurb *nu; - bool changed = false; - - for (nu = nurbs->first; nu; nu = nu->next) { - if (ED_curve_nurb_select_check(v3d, nu)) { - changed |= ED_curve_nurb_select_all(nu); - } - } - - if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + ListBase *nurbs = &editnurb->nurbs; + Nurb *nu; + bool changed = false; + + for (nu = nurbs->first; nu; nu = nu->next) { + if (ED_curve_nurb_select_check(v3d, nu)) { + changed |= ED_curve_nurb_select_all(nu); + } + } + + if (changed) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + } + MEM_freeN(objects); + + return OPERATOR_FINISHED; } static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - return select_linked_exec(C, op); + return select_linked_exec(C, op); } void CURVE_OT_select_linked(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Linked All"; - ot->idname = "CURVE_OT_select_linked"; - ot->description = "Select all control points linked to the current selection"; + /* identifiers */ + ot->name = "Select Linked All"; + ot->idname = "CURVE_OT_select_linked"; + ot->description = "Select all control points linked to the current selection"; - /* api callbacks */ - ot->exec = select_linked_exec; - ot->invoke = select_linked_invoke; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = select_linked_exec; + ot->invoke = select_linked_invoke; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ + /* properties */ } - /***************** select linked pick operator ******************/ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewContext vc; - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - const bool select = !RNA_boolean_get(op->ptr, "deselect"); - Base *basact = NULL; - - view3d_operator_needs_opengl(C); - ED_view3d_viewcontext_init(C, &vc); - copy_v2_v2_int(vc.mval, event->mval); - - if (!ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, NULL, &basact)) { - return OPERATOR_CANCELLED; - } - - if (bezt) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - select_beztriple(bezt, select, SELECT, VISIBLE); - bezt++; - } - } - else if (bp) { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - select_bpoint(bp, select, SELECT, VISIBLE); - bp++; - } - } - - Object *obedit = basact->object; - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - if (!select) { - BKE_curve_nurb_vert_active_validate(obedit->data); - } - - return OPERATOR_FINISHED; + ViewContext vc; + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + const bool select = !RNA_boolean_get(op->ptr, "deselect"); + Base *basact = NULL; + + view3d_operator_needs_opengl(C); + ED_view3d_viewcontext_init(C, &vc); + copy_v2_v2_int(vc.mval, event->mval); + + if (!ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, NULL, &basact)) { + return OPERATOR_CANCELLED; + } + + if (bezt) { + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + select_beztriple(bezt, select, SELECT, VISIBLE); + bezt++; + } + } + else if (bp) { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + select_bpoint(bp, select, SELECT, VISIBLE); + bp++; + } + } + + Object *obedit = basact->object; + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + if (!select) { + BKE_curve_nurb_vert_active_validate(obedit->data); + } + + return OPERATOR_FINISHED; } void CURVE_OT_select_linked_pick(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Linked"; - ot->idname = "CURVE_OT_select_linked_pick"; - ot->description = "Select all control points linked to already selected ones"; - - /* api callbacks */ - ot->invoke = select_linked_pick_invoke; - ot->poll = ED_operator_editsurfcurve_region_view3d; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect linked control points rather than selecting them"); + /* identifiers */ + ot->name = "Select Linked"; + ot->idname = "CURVE_OT_select_linked_pick"; + ot->description = "Select all control points linked to already selected ones"; + + /* api callbacks */ + ot->invoke = select_linked_pick_invoke; + ot->poll = ED_operator_editsurfcurve_region_view3d; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, + "deselect", + 0, + "Deselect", + "Deselect linked control points rather than selecting them"); } /***************** select row operator **********************/ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - ListBase *editnurb = object_editcurve_get(obedit); - static BPoint *last = NULL; - static int direction = 0; - Nurb *nu = NULL; - BPoint *bp = NULL; - int u = 0, v = 0, a, b; - - if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp)) { - return OPERATOR_CANCELLED; - } - - if (last == bp) { - direction = 1 - direction; - BKE_nurbList_flag_set(editnurb, 0); - } - last = bp; - - u = cu->actvert % nu->pntsu; - v = cu->actvert / nu->pntsu; - bp = nu->bp; - for (a = 0; a < nu->pntsv; a++) { - for (b = 0; b < nu->pntsu; b++, bp++) { - if (direction) { - if (a == v) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); - } - } - else { - if (b == u) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); - } - } - } - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + ListBase *editnurb = object_editcurve_get(obedit); + static BPoint *last = NULL; + static int direction = 0; + Nurb *nu = NULL; + BPoint *bp = NULL; + int u = 0, v = 0, a, b; + + if (!BKE_curve_nurb_vert_active_get(cu, &nu, (void *)&bp)) { + return OPERATOR_CANCELLED; + } + + if (last == bp) { + direction = 1 - direction; + BKE_nurbList_flag_set(editnurb, 0); + } + last = bp; + + u = cu->actvert % nu->pntsu; + v = cu->actvert / nu->pntsu; + bp = nu->bp; + for (a = 0; a < nu->pntsv; a++) { + for (b = 0; b < nu->pntsu; b++, bp++) { + if (direction) { + if (a == v) { + select_bpoint(bp, SELECT, SELECT, VISIBLE); + } + } + else { + if (b == u) { + select_bpoint(bp, SELECT, SELECT, VISIBLE); + } + } + } + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; } void CURVE_OT_select_row(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Control Point Row"; - ot->idname = "CURVE_OT_select_row"; - ot->description = "Select a row of control points including active one"; + /* identifiers */ + ot->name = "Select Control Point Row"; + ot->idname = "CURVE_OT_select_row"; + ot->description = "Select a row of control points including active one"; - /* api callbacks */ - ot->exec = select_row_exec; - ot->poll = ED_operator_editsurf; + /* api callbacks */ + ot->exec = select_row_exec; + ot->poll = ED_operator_editsurf; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /***************** select next operator **********************/ static int select_next_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ListBase *editnurb = object_editcurve_get(obedit); - select_adjacent_cp(editnurb, 1, 0, SELECT); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + select_adjacent_cp(editnurb, 1, 0, SELECT); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_next(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Next"; - ot->idname = "CURVE_OT_select_next"; - ot->description = "Select control points following already selected ones along the curves"; + /* identifiers */ + ot->name = "Select Next"; + ot->idname = "CURVE_OT_select_next"; + ot->description = "Select control points following already selected ones along the curves"; - /* api callbacks */ - ot->exec = select_next_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = select_next_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /***************** select previous operator **********************/ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ListBase *editnurb = object_editcurve_get(obedit); - select_adjacent_cp(editnurb, -1, 0, SELECT); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + select_adjacent_cp(editnurb, -1, 0, SELECT); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_previous(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Previous"; - ot->idname = "CURVE_OT_select_previous"; - ot->description = "Select control points preceding already selected ones along the curves"; + /* identifiers */ + ot->name = "Select Previous"; + ot->idname = "CURVE_OT_select_previous"; + ot->description = "Select control points preceding already selected ones along the curves"; - /* api callbacks */ - ot->exec = select_previous_exec; - ot->poll = ED_operator_editcurve; + /* api callbacks */ + ot->exec = select_previous_exec; + ot->poll = ED_operator_editcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /***************** select more operator **********************/ static void curve_select_more(Object *obedit) { - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BPoint *bp, *tempbp; - int a; - short sel = 0; - - /* note that NURBS surface is a special case because we mimic */ - /* the behavior of "select more" of mesh tools. */ - /* The algorithm is designed to work in planar cases so it */ - /* may not be optimal always (example: end of NURBS sphere) */ - if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { - BLI_bitmap *selbpoints; - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - selbpoints = BLI_BITMAP_NEW(a, "selectlist"); - while (a > 0) { - if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) { - /* upper control point */ - if (a % nu->pntsu != 0) { - tempbp = bp - 1; - if (!(tempbp->f1 & SELECT)) { - select_bpoint(tempbp, SELECT, SELECT, VISIBLE); - } - } - - /* left control point. select only if it is not selected already */ - if (a - nu->pntsu > 0) { - sel = 0; - tempbp = bp + nu->pntsu; - if (!(tempbp->f1 & SELECT)) { - sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); - } - /* make sure selected bpoint is discarded */ - if (sel == 1) { - BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu); - } - } - - /* right control point */ - if (a + nu->pntsu < nu->pntsu * nu->pntsv) { - tempbp = bp - nu->pntsu; - if (!(tempbp->f1 & SELECT)) { - select_bpoint(tempbp, SELECT, SELECT, VISIBLE); - } - } - - /* lower control point. skip next bp in case selection was made */ - if (a % nu->pntsu != 1) { - sel = 0; - tempbp = bp + 1; - if (!(tempbp->f1 & SELECT)) { - sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); - } - if (sel) { - bp++; - a--; - } - } - } - - bp++; - a--; - } - - MEM_freeN(selbpoints); - } - } - else { - select_adjacent_cp(editnurb, 1, 0, SELECT); - select_adjacent_cp(editnurb, -1, 0, SELECT); - } + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BPoint *bp, *tempbp; + int a; + short sel = 0; + + /* note that NURBS surface is a special case because we mimic */ + /* the behavior of "select more" of mesh tools. */ + /* The algorithm is designed to work in planar cases so it */ + /* may not be optimal always (example: end of NURBS sphere) */ + if (obedit->type == OB_SURF) { + for (nu = editnurb->first; nu; nu = nu->next) { + BLI_bitmap *selbpoints; + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + selbpoints = BLI_BITMAP_NEW(a, "selectlist"); + while (a > 0) { + if ((!BLI_BITMAP_TEST(selbpoints, a)) && (bp->hide == 0) && (bp->f1 & SELECT)) { + /* upper control point */ + if (a % nu->pntsu != 0) { + tempbp = bp - 1; + if (!(tempbp->f1 & SELECT)) { + select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + } + } + + /* left control point. select only if it is not selected already */ + if (a - nu->pntsu > 0) { + sel = 0; + tempbp = bp + nu->pntsu; + if (!(tempbp->f1 & SELECT)) { + sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + } + /* make sure selected bpoint is discarded */ + if (sel == 1) { + BLI_BITMAP_ENABLE(selbpoints, a - nu->pntsu); + } + } + + /* right control point */ + if (a + nu->pntsu < nu->pntsu * nu->pntsv) { + tempbp = bp - nu->pntsu; + if (!(tempbp->f1 & SELECT)) { + select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + } + } + + /* lower control point. skip next bp in case selection was made */ + if (a % nu->pntsu != 1) { + sel = 0; + tempbp = bp + 1; + if (!(tempbp->f1 & SELECT)) { + sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); + } + if (sel) { + bp++; + a--; + } + } + } + + bp++; + a--; + } + + MEM_freeN(selbpoints); + } + } + else { + select_adjacent_cp(editnurb, 1, 0, SELECT); + select_adjacent_cp(editnurb, -1, 0, SELECT); + } } static int curve_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - curve_select_more(obedit); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + curve_select_more(obedit); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_more(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select More"; - ot->idname = "CURVE_OT_select_more"; - ot->description = "Select control points directly linked to already selected ones"; + /* identifiers */ + ot->name = "Select More"; + ot->idname = "CURVE_OT_select_more"; + ot->description = "Select control points directly linked to already selected ones"; - /* api callbacks */ - ot->exec = curve_select_more_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_select_more_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************** select less operator *****************/ @@ -984,437 +997,439 @@ void CURVE_OT_select_more(wmOperatorType *ot) /* basic method: deselect if control point doesn't have all neighbors selected */ static void curve_select_less(Object *obedit) { - ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - BPoint *bp; - BezTriple *bezt; - int a; - int sel = 0; - bool lastsel = false; - - if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { - BLI_bitmap *selbpoints; - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - selbpoints = BLI_BITMAP_NEW(a, "selectlist"); - while (a--) { - if ((bp->hide == 0) && (bp->f1 & SELECT)) { - sel = 0; - - /* check if neighbors have been selected */ - /* edges of surface are an exception */ - if ((a + 1) % nu->pntsu == 0) { - sel++; - } - else { - bp--; - if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) { - sel++; - } - bp++; - } - - if ((a + 1) % nu->pntsu == 1) { - sel++; - } - else { - bp++; - if ((bp->hide == 0) && (bp->f1 & SELECT)) { - sel++; - } - bp--; - } - - if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) { - sel++; - } - else { - bp -= nu->pntsu; - if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || ((bp->hide == 0) && (bp->f1 & SELECT))) { - sel++; - } - bp += nu->pntsu; - } - - if (a < nu->pntsu) { - sel++; - } - else { - bp += nu->pntsu; - if ((bp->hide == 0) && (bp->f1 & SELECT)) { - sel++; - } - bp -= nu->pntsu; - } - - if (sel != 4) { - select_bpoint(bp, DESELECT, SELECT, VISIBLE); - BLI_BITMAP_ENABLE(selbpoints, a); - } - } - else { - lastsel = false; - } - - bp++; - } - - MEM_freeN(selbpoints); - } - } - else { - for (nu = editnurb->first; nu; nu = nu->next) { - lastsel = false; - /* check what type of curve/nurb it is */ - if (nu->type == CU_BEZIER) { - a = nu->pntsu; - bezt = nu->bezt; - while (a--) { - if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { - sel = (lastsel == 1); - - /* check if neighbors have been selected */ - /* first and last are exceptions */ - if (a == nu->pntsu - 1) { - sel++; - } - else { - bezt--; - if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { - sel++; - } - bezt++; - } - - if (a == 0) { - sel++; - } - else { - bezt++; - if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { - sel++; - } - bezt--; - } - - if (sel != 2) { - select_beztriple(bezt, DESELECT, SELECT, VISIBLE); - lastsel = true; - } - else { - lastsel = false; - } - } - else { - lastsel = false; - } - - bezt++; - } - } - else { - a = nu->pntsu * nu->pntsv; - bp = nu->bp; - while (a--) { - if ((lastsel == false) && (bp->hide == 0) && (bp->f1 & SELECT)) { - sel = 0; - - /* first and last are exceptions */ - if (a == nu->pntsu * nu->pntsv - 1) { - sel++; - } - else { - bp--; - if ((bp->hide == 0) && (bp->f1 & SELECT)) { - sel++; - } - bp++; - } - - if (a == 0) { - sel++; - } - else { - bp++; - if ((bp->hide == 0) && (bp->f1 & SELECT)) { - sel++; - } - bp--; - } - - if (sel != 2) { - select_bpoint(bp, DESELECT, SELECT, VISIBLE); - lastsel = true; - } - else { - lastsel = false; - } - } - else { - lastsel = false; - } - - bp++; - } - } - } - } + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int a; + int sel = 0; + bool lastsel = false; + + if (obedit->type == OB_SURF) { + for (nu = editnurb->first; nu; nu = nu->next) { + BLI_bitmap *selbpoints; + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + selbpoints = BLI_BITMAP_NEW(a, "selectlist"); + while (a--) { + if ((bp->hide == 0) && (bp->f1 & SELECT)) { + sel = 0; + + /* check if neighbors have been selected */ + /* edges of surface are an exception */ + if ((a + 1) % nu->pntsu == 0) { + sel++; + } + else { + bp--; + if (BLI_BITMAP_TEST(selbpoints, a + 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) { + sel++; + } + bp++; + } + + if ((a + 1) % nu->pntsu == 1) { + sel++; + } + else { + bp++; + if ((bp->hide == 0) && (bp->f1 & SELECT)) { + sel++; + } + bp--; + } + + if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) { + sel++; + } + else { + bp -= nu->pntsu; + if (BLI_BITMAP_TEST(selbpoints, a + nu->pntsu) || + ((bp->hide == 0) && (bp->f1 & SELECT))) { + sel++; + } + bp += nu->pntsu; + } + + if (a < nu->pntsu) { + sel++; + } + else { + bp += nu->pntsu; + if ((bp->hide == 0) && (bp->f1 & SELECT)) { + sel++; + } + bp -= nu->pntsu; + } + + if (sel != 4) { + select_bpoint(bp, DESELECT, SELECT, VISIBLE); + BLI_BITMAP_ENABLE(selbpoints, a); + } + } + else { + lastsel = false; + } + + bp++; + } + + MEM_freeN(selbpoints); + } + } + else { + for (nu = editnurb->first; nu; nu = nu->next) { + lastsel = false; + /* check what type of curve/nurb it is */ + if (nu->type == CU_BEZIER) { + a = nu->pntsu; + bezt = nu->bezt; + while (a--) { + if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { + sel = (lastsel == 1); + + /* check if neighbors have been selected */ + /* first and last are exceptions */ + if (a == nu->pntsu - 1) { + sel++; + } + else { + bezt--; + if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { + sel++; + } + bezt++; + } + + if (a == 0) { + sel++; + } + else { + bezt++; + if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { + sel++; + } + bezt--; + } + + if (sel != 2) { + select_beztriple(bezt, DESELECT, SELECT, VISIBLE); + lastsel = true; + } + else { + lastsel = false; + } + } + else { + lastsel = false; + } + + bezt++; + } + } + else { + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + if ((lastsel == false) && (bp->hide == 0) && (bp->f1 & SELECT)) { + sel = 0; + + /* first and last are exceptions */ + if (a == nu->pntsu * nu->pntsv - 1) { + sel++; + } + else { + bp--; + if ((bp->hide == 0) && (bp->f1 & SELECT)) { + sel++; + } + bp++; + } + + if (a == 0) { + sel++; + } + else { + bp++; + if ((bp->hide == 0) && (bp->f1 & SELECT)) { + sel++; + } + bp--; + } + + if (sel != 2) { + select_bpoint(bp, DESELECT, SELECT, VISIBLE); + lastsel = true; + } + else { + lastsel = false; + } + } + else { + lastsel = false; + } + + bp++; + } + } + } + } } static int curve_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - curve_select_less(obedit); - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - MEM_freeN(objects); - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + curve_select_less(obedit); + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_less(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Less"; - ot->idname = "CURVE_OT_select_less"; - ot->description = "Reduce current selection by deselecting boundary elements"; + /* identifiers */ + ot->name = "Select Less"; + ot->idname = "CURVE_OT_select_less"; + ot->description = "Reduce current selection by deselecting boundary elements"; - /* api callbacks */ - ot->exec = curve_select_less_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_select_less_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /********************** select random *********************/ static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select) { - Nurb *nu; - BezTriple *bezt; - BPoint *bp; - int a; - - RNG *rng = BLI_rng_new_srandom(seed); - - for (nu = editnurb->first; nu; nu = nu->next) { - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - if (!bezt->hide) { - if (BLI_rng_get_float(rng) < randfac) { - select_beztriple(bezt, select, SELECT, VISIBLE); - } - } - bezt++; - } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - - while (a--) { - if (!bp->hide) { - if (BLI_rng_get_float(rng) < randfac) { - select_bpoint(bp, select, SELECT, VISIBLE); - } - } - bp++; - } - } - } - - BLI_rng_free(rng); + Nurb *nu; + BezTriple *bezt; + BPoint *bp; + int a; + + RNG *rng = BLI_rng_new_srandom(seed); + + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + if (!bezt->hide) { + if (BLI_rng_get_float(rng) < randfac) { + select_beztriple(bezt, select, SELECT, VISIBLE); + } + } + bezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + + while (a--) { + if (!bp->hide) { + if (BLI_rng_get_float(rng) < randfac) { + select_bpoint(bp, select, SELECT, VISIBLE); + } + } + bp++; + } + } + } + + BLI_rng_free(rng); } static int curve_select_random_exec(bContext *C, wmOperator *op) { - const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; - const int seed = WM_operator_properties_select_random_seed_increment_get(op); - - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - ListBase *editnurb = object_editcurve_get(obedit); - int seed_iter = seed; - - /* This gives a consistent result regardless of object order. */ - if (ob_index) { - seed_iter += BLI_ghashutil_strhash_p(obedit->id.name); - } - - curve_select_random(editnurb, randfac, seed_iter, select); - BKE_curve_nurb_vert_active_validate(obedit->data); - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - - MEM_freeN(objects); - return OPERATOR_FINISHED; + const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); + const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const int seed = WM_operator_properties_select_random_seed_increment_get(op); + + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + ListBase *editnurb = object_editcurve_get(obedit); + int seed_iter = seed; + + /* This gives a consistent result regardless of object order. */ + if (ob_index) { + seed_iter += BLI_ghashutil_strhash_p(obedit->id.name); + } + + curve_select_random(editnurb, randfac, seed_iter, select); + BKE_curve_nurb_vert_active_validate(obedit->data); + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + + MEM_freeN(objects); + return OPERATOR_FINISHED; } void CURVE_OT_select_random(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Random"; - ot->idname = "CURVE_OT_select_random"; - ot->description = "Randomly select some control points"; + /* identifiers */ + ot->name = "Select Random"; + ot->idname = "CURVE_OT_select_random"; + ot->description = "Randomly select some control points"; - /* api callbacks */ - ot->exec = curve_select_random_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = curve_select_random_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - WM_operator_properties_select_random(ot); + /* properties */ + WM_operator_properties_select_random(ot); } /********************* every nth number of point *******************/ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, const struct CheckerIntervalParams *params) { - int a, start; + int a, start; - start = bezt - nu->bezt; - a = nu->pntsu; - bezt = &nu->bezt[a - 1]; + start = bezt - nu->bezt; + a = nu->pntsu; + bezt = &nu->bezt[a - 1]; - while (a--) { - const int depth = abs(start - a); - if (WM_operator_properties_checker_interval_test(params, depth)) { - select_beztriple(bezt, DESELECT, SELECT, HIDDEN); - } + while (a--) { + const int depth = abs(start - a); + if (WM_operator_properties_checker_interval_test(params, depth)) { + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); + } - bezt--; - } + bezt--; + } } static void select_nth_bp(Nurb *nu, BPoint *bp, const struct CheckerIntervalParams *params) { - int a, startrow, startpnt; - int row, pnt; - - startrow = (bp - nu->bp) / nu->pntsu; - startpnt = (bp - nu->bp) % nu->pntsu; - - a = nu->pntsu * nu->pntsv; - bp = &nu->bp[a - 1]; - row = nu->pntsv - 1; - pnt = nu->pntsu - 1; - - while (a--) { - const int depth = abs(pnt - startpnt) + abs(row - startrow); - if (WM_operator_properties_checker_interval_test(params, depth)) { - select_bpoint(bp, DESELECT, SELECT, HIDDEN); - } - - pnt--; - if (pnt < 0) { - pnt = nu->pntsu - 1; - row--; - } - - bp--; - } + int a, startrow, startpnt; + int row, pnt; + + startrow = (bp - nu->bp) / nu->pntsu; + startpnt = (bp - nu->bp) % nu->pntsu; + + a = nu->pntsu * nu->pntsv; + bp = &nu->bp[a - 1]; + row = nu->pntsv - 1; + pnt = nu->pntsu - 1; + + while (a--) { + const int depth = abs(pnt - startpnt) + abs(row - startrow); + if (WM_operator_properties_checker_interval_test(params, depth)) { + select_bpoint(bp, DESELECT, SELECT, HIDDEN); + } + + pnt--; + if (pnt < 0) { + pnt = nu->pntsu - 1; + row--; + } + + bp--; + } } static bool ed_curve_select_nth(Curve *cu, const struct CheckerIntervalParams *params) { - Nurb *nu = NULL; - void *vert = NULL; + Nurb *nu = NULL; + void *vert = NULL; - if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { - return false; - } + if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) { + return false; + } - if (nu->bezt) { - select_nth_bezt(nu, vert, params); - } - else { - select_nth_bp(nu, vert, params); - } + if (nu->bezt) { + select_nth_bezt(nu, vert, params); + } + else { + select_nth_bp(nu, vert, params); + } - return true; + return true; } static int select_nth_exec(bContext *C, wmOperator *op) { - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obact = CTX_data_edit_object(C); - View3D *v3d = CTX_wm_view3d(C); - bool changed = false; - - struct CheckerIntervalParams op_params; - WM_operator_properties_checker_interval_from_op(op, &op_params); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - - if (!ED_curve_select_check(v3d, cu->editnurb)) { - continue; - } - - if (ed_curve_select_nth(obedit->data, &op_params) == true) { - changed = true; - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - } - MEM_freeN(objects); - - if (!changed) { - if (obact->type == OB_SURF) { - BKE_report(op->reports, RPT_ERROR, - (objects_len == 1 ? - "Surface has no active point" : - "Surfaces have no active point")); - } - else { - BKE_report(op->reports, RPT_ERROR, - (objects_len == 1 ? - "Curve has no active point" : - "Curves have no active point")); - } - return OPERATOR_CANCELLED; - } - return OPERATOR_FINISHED; + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = CTX_data_edit_object(C); + View3D *v3d = CTX_wm_view3d(C); + bool changed = false; + + struct CheckerIntervalParams op_params; + WM_operator_properties_checker_interval_from_op(op, &op_params); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + + if (!ED_curve_select_check(v3d, cu->editnurb)) { + continue; + } + + if (ed_curve_select_nth(obedit->data, &op_params) == true) { + changed = true; + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + } + MEM_freeN(objects); + + if (!changed) { + if (obact->type == OB_SURF) { + BKE_report( + op->reports, + RPT_ERROR, + (objects_len == 1 ? "Surface has no active point" : "Surfaces have no active point")); + } + else { + BKE_report(op->reports, + RPT_ERROR, + (objects_len == 1 ? "Curve has no active point" : "Curves have no active point")); + } + return OPERATOR_CANCELLED; + } + return OPERATOR_FINISHED; } void CURVE_OT_select_nth(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Checker Deselect"; - ot->description = "Deselect every other vertex"; - ot->idname = "CURVE_OT_select_nth"; + /* identifiers */ + ot->name = "Checker Deselect"; + ot->description = "Deselect every other vertex"; + ot->idname = "CURVE_OT_select_nth"; - /* api callbacks */ - ot->exec = select_nth_exec; - ot->poll = ED_operator_editsurfcurve; + /* api callbacks */ + ot->exec = select_nth_exec; + ot->poll = ED_operator_editsurfcurve; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - WM_operator_properties_checker_interval(ot, false); + WM_operator_properties_checker_interval(ot, false); } - /* -------------------------------------------------------------------- */ /* Select Similar */ @@ -1422,373 +1437,365 @@ void CURVE_OT_select_nth(wmOperatorType *ot) * \{ */ static const EnumPropertyItem curve_prop_similar_compare_types[] = { - {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, - {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, - {SIM_CMP_LT, "LESS", 0, "Less", ""}, + {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, + {SIM_CMP_GT, "GREATER", 0, "Greater", ""}, + {SIM_CMP_LT, "LESS", 0, "Less", ""}, - {0, NULL, 0, NULL, NULL}, + {0, NULL, 0, NULL, NULL}, }; enum { - SIMCURHAND_TYPE = 0, - SIMCURHAND_RADIUS, - SIMCURHAND_WEIGHT, - SIMCURHAND_DIRECTION, + SIMCURHAND_TYPE = 0, + SIMCURHAND_RADIUS, + SIMCURHAND_WEIGHT, + SIMCURHAND_DIRECTION, }; static const EnumPropertyItem curve_prop_similar_types[] = { - {SIMCURHAND_TYPE, "TYPE", 0, "Type", ""}, - {SIMCURHAND_RADIUS, "RADIUS", 0, "Radius", ""}, - {SIMCURHAND_WEIGHT, "WEIGHT", 0, "Weight", ""}, - {SIMCURHAND_DIRECTION, "DIRECTION", 0, "Direction", ""}, - {0, NULL, 0, NULL, NULL}, + {SIMCURHAND_TYPE, "TYPE", 0, "Type", ""}, + {SIMCURHAND_RADIUS, "RADIUS", 0, "Radius", ""}, + {SIMCURHAND_WEIGHT, "WEIGHT", 0, "Weight", ""}, + {SIMCURHAND_DIRECTION, "DIRECTION", 0, "Direction", ""}, + {0, NULL, 0, NULL, NULL}, }; -static void nurb_bezt_direction_worldspace_get(Object *ob, Nurb *nu, BezTriple *bezt, float r_dir[3]) +static void nurb_bezt_direction_worldspace_get(Object *ob, + Nurb *nu, + BezTriple *bezt, + float r_dir[3]) { - float rsmat[3][3]; - BKE_nurb_bezt_calc_normal(nu, bezt, r_dir); - copy_m3_m4(rsmat, ob->obmat); - mul_m3_v3(rsmat, r_dir); - normalize_v3(r_dir); + float rsmat[3][3]; + BKE_nurb_bezt_calc_normal(nu, bezt, r_dir); + copy_m3_m4(rsmat, ob->obmat); + mul_m3_v3(rsmat, r_dir); + normalize_v3(r_dir); } static void nurb_bpoint_direction_worldspace_get(Object *ob, Nurb *nu, BPoint *bp, float r_dir[3]) { - float rsmat[3][3]; - BKE_nurb_bpoint_calc_normal(nu, bp, r_dir); - copy_m3_m4(rsmat, ob->obmat); - mul_m3_v3(rsmat, r_dir); - normalize_v3(r_dir); + float rsmat[3][3]; + BKE_nurb_bpoint_calc_normal(nu, bp, r_dir); + copy_m3_m4(rsmat, ob->obmat); + mul_m3_v3(rsmat, r_dir); + normalize_v3(r_dir); } static void curve_nurb_selected_type_get( - Object *ob, Nurb *nu, const int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d) + Object *ob, Nurb *nu, const int type, KDTree_1d *tree_1d, KDTree_3d *tree_3d) { - float tree_entry[3] = {0.0f, 0.0f, 0.0f}; - - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - int i; - int tree_index = 0; - - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if ((!bezt->hide) && (bezt->f1 & SELECT)) { - - switch (type) { - case SIMCURHAND_RADIUS: - { - float radius_ref = bezt->radius; - tree_entry[0] = radius_ref; - break; - } - case SIMCURHAND_WEIGHT: - { - float weight_ref = bezt->weight; - tree_entry[0] = weight_ref; - break; - } - case SIMCURHAND_DIRECTION: - { - nurb_bezt_direction_worldspace_get(ob, nu, bezt, tree_entry); - break; - } - } - if (tree_1d) { - BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry); - } - else { - BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry); - } - } - } - } - else { - BPoint *bp; - int i; - int tree_index = 0; - - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (!bp->hide && bp->f1 & SELECT) { - switch (type) { - case SIMCURHAND_RADIUS: - { - float radius_ref = bp->radius; - tree_entry[0] = radius_ref; - break; - } - case SIMCURHAND_WEIGHT: - { - float weight_ref = bp->weight; - tree_entry[0] = weight_ref; - break; - } - case SIMCURHAND_DIRECTION: - { - nurb_bpoint_direction_worldspace_get(ob, nu, bp, tree_entry); - break; - } - } - if (tree_1d) { - BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry); - } - else { - BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry); - } - } - } - } + float tree_entry[3] = {0.0f, 0.0f, 0.0f}; + + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + int i; + int tree_index = 0; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if ((!bezt->hide) && (bezt->f1 & SELECT)) { + + switch (type) { + case SIMCURHAND_RADIUS: { + float radius_ref = bezt->radius; + tree_entry[0] = radius_ref; + break; + } + case SIMCURHAND_WEIGHT: { + float weight_ref = bezt->weight; + tree_entry[0] = weight_ref; + break; + } + case SIMCURHAND_DIRECTION: { + nurb_bezt_direction_worldspace_get(ob, nu, bezt, tree_entry); + break; + } + } + if (tree_1d) { + BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry); + } + else { + BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry); + } + } + } + } + else { + BPoint *bp; + int i; + int tree_index = 0; + + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (!bp->hide && bp->f1 & SELECT) { + switch (type) { + case SIMCURHAND_RADIUS: { + float radius_ref = bp->radius; + tree_entry[0] = radius_ref; + break; + } + case SIMCURHAND_WEIGHT: { + float weight_ref = bp->weight; + tree_entry[0] = weight_ref; + break; + } + case SIMCURHAND_DIRECTION: { + nurb_bpoint_direction_worldspace_get(ob, nu, bp, tree_entry); + break; + } + } + if (tree_1d) { + BLI_kdtree_1d_insert(tree_1d, tree_index++, tree_entry); + } + else { + BLI_kdtree_3d_insert(tree_3d, tree_index++, tree_entry); + } + } + } + } } -static bool curve_nurb_select_similar_type( - Object *ob, Nurb *nu, const int type, - const KDTree_1d *tree_1d, const KDTree_3d *tree_3d, - const float thresh, const int compare) +static bool curve_nurb_select_similar_type(Object *ob, + Nurb *nu, + const int type, + const KDTree_1d *tree_1d, + const KDTree_3d *tree_3d, + const float thresh, + const int compare) { - const float thresh_cos = cosf(thresh * (float)M_PI_2); - bool changed = false; - - if (nu->type == CU_BEZIER) { - BezTriple *bezt; - int i; - - for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { - if (!bezt->hide) { - bool select = false; - - switch (type) { - case SIMCURHAND_RADIUS: - { - float radius_ref = bezt->radius; - if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) { - select = true; - } - break; - } - case SIMCURHAND_WEIGHT: - { - float weight_ref = bezt->weight; - if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) { - select = true; - } - break; - } - case SIMCURHAND_DIRECTION: - { - float dir[3]; - nurb_bezt_direction_worldspace_get(ob, nu, bezt, dir); - KDTreeNearest_3d nearest; - if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) { - float orient = angle_normalized_v3v3(dir, nearest.co); - float delta = thresh_cos - fabsf(cosf(orient)); - if (ED_select_similar_compare_float(delta, thresh, compare)) { - select = true; - } - } - break; - } - } - - if (select) { - select_beztriple(bezt, SELECT, SELECT, VISIBLE); - changed = true; - } - } - } - } - else { - BPoint *bp; - int i; - - for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { - if (!bp->hide) { - bool select = false; - - switch (type) { - case SIMCURHAND_RADIUS: - { - float radius_ref = bp->radius; - if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) { - select = true; - } - break; - } - case SIMCURHAND_WEIGHT: - { - float weight_ref = bp->weight; - if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) { - select = true; - } - break; - } - case SIMCURHAND_DIRECTION: - { - float dir[3]; - nurb_bpoint_direction_worldspace_get(ob, nu, bp, dir); - KDTreeNearest_3d nearest; - if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) { - float orient = angle_normalized_v3v3(dir, nearest.co); - float delta = fabsf(cosf(orient)) - thresh_cos; - if (ED_select_similar_compare_float(delta, thresh, compare)) { - select = true; - } - } - break; - } - } - - if (select) { - select_bpoint(bp, SELECT, SELECT, VISIBLE); - changed = true; - } - } - } - } - return changed; + const float thresh_cos = cosf(thresh * (float)M_PI_2); + bool changed = false; + + if (nu->type == CU_BEZIER) { + BezTriple *bezt; + int i; + + for (i = nu->pntsu, bezt = nu->bezt; i--; bezt++) { + if (!bezt->hide) { + bool select = false; + + switch (type) { + case SIMCURHAND_RADIUS: { + float radius_ref = bezt->radius; + if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) { + select = true; + } + break; + } + case SIMCURHAND_WEIGHT: { + float weight_ref = bezt->weight; + if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) { + select = true; + } + break; + } + case SIMCURHAND_DIRECTION: { + float dir[3]; + nurb_bezt_direction_worldspace_get(ob, nu, bezt, dir); + KDTreeNearest_3d nearest; + if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) { + float orient = angle_normalized_v3v3(dir, nearest.co); + float delta = thresh_cos - fabsf(cosf(orient)); + if (ED_select_similar_compare_float(delta, thresh, compare)) { + select = true; + } + } + break; + } + } + + if (select) { + select_beztriple(bezt, SELECT, SELECT, VISIBLE); + changed = true; + } + } + } + } + else { + BPoint *bp; + int i; + + for (i = nu->pntsu * nu->pntsv, bp = nu->bp; i--; bp++) { + if (!bp->hide) { + bool select = false; + + switch (type) { + case SIMCURHAND_RADIUS: { + float radius_ref = bp->radius; + if (ED_select_similar_compare_float_tree(tree_1d, radius_ref, thresh, compare)) { + select = true; + } + break; + } + case SIMCURHAND_WEIGHT: { + float weight_ref = bp->weight; + if (ED_select_similar_compare_float_tree(tree_1d, weight_ref, thresh, compare)) { + select = true; + } + break; + } + case SIMCURHAND_DIRECTION: { + float dir[3]; + nurb_bpoint_direction_worldspace_get(ob, nu, bp, dir); + KDTreeNearest_3d nearest; + if (BLI_kdtree_3d_find_nearest(tree_3d, dir, &nearest) != -1) { + float orient = angle_normalized_v3v3(dir, nearest.co); + float delta = fabsf(cosf(orient)) - thresh_cos; + if (ED_select_similar_compare_float(delta, thresh, compare)) { + select = true; + } + } + break; + } + } + + if (select) { + select_bpoint(bp, SELECT, SELECT, VISIBLE); + changed = true; + } + } + } + } + return changed; } static int curve_select_similar_exec(bContext *C, wmOperator *op) { - /* Get props. */ - const int optype = RNA_enum_get(op->ptr, "type"); - const float thresh = RNA_float_get(op->ptr, "threshold"); - const int compare = RNA_enum_get(op->ptr, "compare"); - - ViewLayer *view_layer = CTX_data_view_layer(C); - View3D *v3d = CTX_wm_view3d(C); - int tot_nurbs_selected_all = 0; - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - tot_nurbs_selected_all += ED_curve_select_count(v3d, cu->editnurb); - } - - if (tot_nurbs_selected_all == 0) { - BKE_report(op->reports, RPT_ERROR, "No control point selected"); - MEM_freeN(objects); - return OPERATOR_CANCELLED; - } - - KDTree_1d *tree_1d = NULL; - KDTree_3d *tree_3d = NULL; - short type_ref = 0; - - switch (optype) { - case SIMCURHAND_RADIUS: - case SIMCURHAND_WEIGHT: - tree_1d = BLI_kdtree_1d_new(tot_nurbs_selected_all); - break; - case SIMCURHAND_DIRECTION: - tree_3d = BLI_kdtree_3d_new(tot_nurbs_selected_all); - break; - } - - /* Get type of selected control points. */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - if (!ED_curve_nurb_select_check(v3d, nu)) { - continue; - } - switch (optype) { - case SIMCURHAND_TYPE: - { - type_ref |= nu->type; - break; - } - case SIMCURHAND_RADIUS: - case SIMCURHAND_WEIGHT: - case SIMCURHAND_DIRECTION: - curve_nurb_selected_type_get(obedit, nu, optype, tree_1d, tree_3d); - break; - } - } - } - - if (tree_1d != NULL) { - BLI_kdtree_1d_deduplicate(tree_1d); - BLI_kdtree_1d_balance(tree_1d); - } - if (tree_3d != NULL) { - BLI_kdtree_3d_deduplicate(tree_3d); - BLI_kdtree_3d_balance(tree_3d); - } - - /* Select control points with desired type. */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - Curve *cu = obedit->data; - EditNurb *editnurb = cu->editnurb; - bool changed = false; - Nurb *nu; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { - switch (optype) { - case SIMCURHAND_TYPE: - { - if (nu->type & type_ref) { - changed |= ED_curve_nurb_select_all(nu); - } - break; - } - case SIMCURHAND_RADIUS: - case SIMCURHAND_WEIGHT: - case SIMCURHAND_DIRECTION: - changed = curve_nurb_select_similar_type( - obedit, nu, optype, tree_1d, tree_3d, thresh, compare); - break; - } - } - - if (changed) { - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - } - - MEM_freeN(objects); - - if (tree_1d != NULL) { - BLI_kdtree_1d_free(tree_1d); - } - if (tree_3d != NULL) { - BLI_kdtree_3d_free(tree_3d); - } - return OPERATOR_FINISHED; - + /* Get props. */ + const int optype = RNA_enum_get(op->ptr, "type"); + const float thresh = RNA_float_get(op->ptr, "threshold"); + const int compare = RNA_enum_get(op->ptr, "compare"); + + ViewLayer *view_layer = CTX_data_view_layer(C); + View3D *v3d = CTX_wm_view3d(C); + int tot_nurbs_selected_all = 0; + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + tot_nurbs_selected_all += ED_curve_select_count(v3d, cu->editnurb); + } + + if (tot_nurbs_selected_all == 0) { + BKE_report(op->reports, RPT_ERROR, "No control point selected"); + MEM_freeN(objects); + return OPERATOR_CANCELLED; + } + + KDTree_1d *tree_1d = NULL; + KDTree_3d *tree_3d = NULL; + short type_ref = 0; + + switch (optype) { + case SIMCURHAND_RADIUS: + case SIMCURHAND_WEIGHT: + tree_1d = BLI_kdtree_1d_new(tot_nurbs_selected_all); + break; + case SIMCURHAND_DIRECTION: + tree_3d = BLI_kdtree_3d_new(tot_nurbs_selected_all); + break; + } + + /* Get type of selected control points. */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + + Nurb *nu; + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + if (!ED_curve_nurb_select_check(v3d, nu)) { + continue; + } + switch (optype) { + case SIMCURHAND_TYPE: { + type_ref |= nu->type; + break; + } + case SIMCURHAND_RADIUS: + case SIMCURHAND_WEIGHT: + case SIMCURHAND_DIRECTION: + curve_nurb_selected_type_get(obedit, nu, optype, tree_1d, tree_3d); + break; + } + } + } + + if (tree_1d != NULL) { + BLI_kdtree_1d_deduplicate(tree_1d); + BLI_kdtree_1d_balance(tree_1d); + } + if (tree_3d != NULL) { + BLI_kdtree_3d_deduplicate(tree_3d); + BLI_kdtree_3d_balance(tree_3d); + } + + /* Select control points with desired type. */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + Curve *cu = obedit->data; + EditNurb *editnurb = cu->editnurb; + bool changed = false; + Nurb *nu; + + for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + switch (optype) { + case SIMCURHAND_TYPE: { + if (nu->type & type_ref) { + changed |= ED_curve_nurb_select_all(nu); + } + break; + } + case SIMCURHAND_RADIUS: + case SIMCURHAND_WEIGHT: + case SIMCURHAND_DIRECTION: + changed = curve_nurb_select_similar_type( + obedit, nu, optype, tree_1d, tree_3d, thresh, compare); + break; + } + } + + if (changed) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + } + + MEM_freeN(objects); + + if (tree_1d != NULL) { + BLI_kdtree_1d_free(tree_1d); + } + if (tree_3d != NULL) { + BLI_kdtree_3d_free(tree_3d); + } + return OPERATOR_FINISHED; } void CURVE_OT_select_similar(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select Similar"; - ot->idname = "CURVE_OT_select_similar"; - ot->description = "Select similar curve points by property type"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = curve_select_similar_exec; - ot->poll = ED_operator_editsurfcurve; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", curve_prop_similar_types, SIMCURHAND_WEIGHT, "Type", ""); - RNA_def_enum(ot->srna, "compare", curve_prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); - RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.0, 100.0); + /* identifiers */ + ot->name = "Select Similar"; + ot->idname = "CURVE_OT_select_similar"; + ot->description = "Select similar curve points by property type"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = curve_select_similar_exec; + ot->poll = ED_operator_editsurfcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum( + ot->srna, "type", curve_prop_similar_types, SIMCURHAND_WEIGHT, "Type", ""); + RNA_def_enum(ot->srna, "compare", curve_prop_similar_compare_types, SIM_CMP_EQ, "Compare", ""); + RNA_def_float(ot->srna, "threshold", 0.1, 0.0, FLT_MAX, "Threshold", "", 0.0, 100.0); } /** \} */ - /* -------------------------------------------------------------------- */ /* Select Shortest Path */ @@ -1797,232 +1804,230 @@ void CURVE_OT_select_similar(wmOperatorType *ot) static float curve_calc_dist_pair(const Nurb *nu, int a, int b) { - const float *a_fl, *b_fl; - - if (nu->type == CU_BEZIER) { - a_fl = nu->bezt[a].vec[1]; - b_fl = nu->bezt[b].vec[1]; - } - else { - a_fl = nu->bp[a].vec; - b_fl = nu->bp[b].vec; - } - - return len_v3v3(a_fl, b_fl); + const float *a_fl, *b_fl; + + if (nu->type == CU_BEZIER) { + a_fl = nu->bezt[a].vec[1]; + b_fl = nu->bezt[b].vec[1]; + } + else { + a_fl = nu->bp[a].vec; + b_fl = nu->bp[b].vec; + } + + return len_v3v3(a_fl, b_fl); } static float curve_calc_dist_span(Nurb *nu, int vert_src, int vert_dst) { - const int u = nu->pntsu; - int i_prev, i; - float dist = 0.0f; + const int u = nu->pntsu; + int i_prev, i; + float dist = 0.0f; - BLI_assert(nu->pntsv == 1); + BLI_assert(nu->pntsv == 1); - i_prev = vert_src; - i = (i_prev + 1) % u; + i_prev = vert_src; + i = (i_prev + 1) % u; - while (true) { - dist += curve_calc_dist_pair(nu, i_prev, i); + while (true) { + dist += curve_calc_dist_pair(nu, i_prev, i); - if (i == vert_dst) { - break; - } - i = (i + 1) % u; - } - return dist; + if (i == vert_dst) { + break; + } + i = (i + 1) % u; + } + return dist; } static void curve_select_shortest_path_curve(Nurb *nu, int vert_src, int vert_dst) { - const int u = nu->pntsu; - int i; - - if (vert_src > vert_dst) { - SWAP(int, vert_src, vert_dst); - } - - if (nu->flagu & CU_NURB_CYCLIC) { - if (curve_calc_dist_span(nu, vert_src, vert_dst) > - curve_calc_dist_span(nu, vert_dst, vert_src)) - { - SWAP(int, vert_src, vert_dst); - } - } - - i = vert_src; - while (true) { - if (nu->type & CU_BEZIER) { - select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN); - } - else { - select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN); - } - - if (i == vert_dst) { - break; - } - i = (i + 1) % u; - } + const int u = nu->pntsu; + int i; + + if (vert_src > vert_dst) { + SWAP(int, vert_src, vert_dst); + } + + if (nu->flagu & CU_NURB_CYCLIC) { + if (curve_calc_dist_span(nu, vert_src, vert_dst) > + curve_calc_dist_span(nu, vert_dst, vert_src)) { + SWAP(int, vert_src, vert_dst); + } + } + + i = vert_src; + while (true) { + if (nu->type & CU_BEZIER) { + select_beztriple(&nu->bezt[i], SELECT, SELECT, HIDDEN); + } + else { + select_bpoint(&nu->bp[i], SELECT, SELECT, HIDDEN); + } + + if (i == vert_dst) { + break; + } + i = (i + 1) % u; + } } static void curve_select_shortest_path_surf(Nurb *nu, int vert_src, int vert_dst) { - HeapSimple *heap; - - int i, vert_curr; - - int totu = nu->pntsu; - int totv = nu->pntsv; - int vert_num = totu * totv; - - /* custom data */ - struct PointAdj { - int vert, vert_prev; - float cost; - } *data; - - /* init connectivity data */ - data = MEM_mallocN(sizeof(*data) * vert_num, __func__); - for (i = 0; i < vert_num; i++) { - data[i].vert = i; - data[i].vert_prev = -1; - data[i].cost = FLT_MAX; - } - - /* init heap */ - heap = BLI_heapsimple_new(); - - vert_curr = data[vert_src].vert; - BLI_heapsimple_insert(heap, 0.0f, &data[vert_src].vert); - data[vert_src].cost = 0.0f; - data[vert_src].vert_prev = vert_src; /* nop */ - - while (!BLI_heapsimple_is_empty(heap)) { - int axis, sign; - int u, v; - - vert_curr = *((int *)BLI_heapsimple_pop_min(heap)); - if (vert_curr == vert_dst) { - break; - } - - BKE_nurb_index_to_uv(nu, vert_curr, &u, &v); - - /* loop over 4 adjacent verts */ - for (sign = -1; sign != 3; sign += 2) { - for (axis = 0; axis != 2; axis += 1) { - int uv_other[2] = {u, v}; - int vert_other; - - uv_other[axis] += sign; - - vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]); - if (vert_other != -1) { - const float dist = data[vert_curr].cost + curve_calc_dist_pair(nu, vert_curr, vert_other); - - if (data[vert_other].cost > dist) { - data[vert_other].cost = dist; - if (data[vert_other].vert_prev == -1) { - BLI_heapsimple_insert(heap, data[vert_other].cost, &data[vert_other].vert); - } - data[vert_other].vert_prev = vert_curr; - } - } - - } - } - - } - - BLI_heapsimple_free(heap, NULL); - - if (vert_curr == vert_dst) { - i = 0; - while (vert_curr != vert_src && i++ < vert_num) { - if (nu->type == CU_BEZIER) { - select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN); - } - else { - select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN); - } - vert_curr = data[vert_curr].vert_prev; - } - } - - MEM_freeN(data); + HeapSimple *heap; + + int i, vert_curr; + + int totu = nu->pntsu; + int totv = nu->pntsv; + int vert_num = totu * totv; + + /* custom data */ + struct PointAdj { + int vert, vert_prev; + float cost; + } * data; + + /* init connectivity data */ + data = MEM_mallocN(sizeof(*data) * vert_num, __func__); + for (i = 0; i < vert_num; i++) { + data[i].vert = i; + data[i].vert_prev = -1; + data[i].cost = FLT_MAX; + } + + /* init heap */ + heap = BLI_heapsimple_new(); + + vert_curr = data[vert_src].vert; + BLI_heapsimple_insert(heap, 0.0f, &data[vert_src].vert); + data[vert_src].cost = 0.0f; + data[vert_src].vert_prev = vert_src; /* nop */ + + while (!BLI_heapsimple_is_empty(heap)) { + int axis, sign; + int u, v; + + vert_curr = *((int *)BLI_heapsimple_pop_min(heap)); + if (vert_curr == vert_dst) { + break; + } + + BKE_nurb_index_to_uv(nu, vert_curr, &u, &v); + + /* loop over 4 adjacent verts */ + for (sign = -1; sign != 3; sign += 2) { + for (axis = 0; axis != 2; axis += 1) { + int uv_other[2] = {u, v}; + int vert_other; + + uv_other[axis] += sign; + + vert_other = BKE_nurb_index_from_uv(nu, uv_other[0], uv_other[1]); + if (vert_other != -1) { + const float dist = data[vert_curr].cost + + curve_calc_dist_pair(nu, vert_curr, vert_other); + + if (data[vert_other].cost > dist) { + data[vert_other].cost = dist; + if (data[vert_other].vert_prev == -1) { + BLI_heapsimple_insert(heap, data[vert_other].cost, &data[vert_other].vert); + } + data[vert_other].vert_prev = vert_curr; + } + } + } + } + } + + BLI_heapsimple_free(heap, NULL); + + if (vert_curr == vert_dst) { + i = 0; + while (vert_curr != vert_src && i++ < vert_num) { + if (nu->type == CU_BEZIER) { + select_beztriple(&nu->bezt[vert_curr], SELECT, SELECT, HIDDEN); + } + else { + select_bpoint(&nu->bp[vert_curr], SELECT, SELECT, HIDDEN); + } + vert_curr = data[vert_curr].vert_prev; + } + } + + MEM_freeN(data); } static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ViewContext vc; - Nurb *nu_dst; - BezTriple *bezt_dst; - BPoint *bp_dst; - int vert_dst; - void *vert_dst_p; - Base *basact = NULL; - - view3d_operator_needs_opengl(C); - ED_view3d_viewcontext_init(C, &vc); - copy_v2_v2_int(vc.mval, event->mval); - - if (!ED_curve_pick_vert(&vc, 1, &nu_dst, &bezt_dst, &bp_dst, NULL, &basact)) { - return OPERATOR_PASS_THROUGH; - } - - ED_view3d_viewcontext_init_object(&vc, basact->object); - Object *obedit = basact->object; - Curve *cu = obedit->data; - Nurb *nu_src = BKE_curve_nurb_active_get(cu); - int vert_src = cu->actvert; - - if (vert_src == CU_ACT_NONE) { - return OPERATOR_PASS_THROUGH; - } - - if (nu_src != nu_dst) { - BKE_report(op->reports, RPT_ERROR, "Control point belongs to another spline"); - return OPERATOR_CANCELLED; - } - - vert_dst_p = bezt_dst ? (void *)bezt_dst : (void *)bp_dst; - vert_dst = BKE_curve_nurb_vert_index_get(nu_dst, vert_dst_p); - if (vert_src == vert_dst) { - return OPERATOR_CANCELLED; - } - - if ((obedit->type == OB_SURF) && (nu_src->pntsv > 1)) { - curve_select_shortest_path_surf(nu_src, vert_src, vert_dst); - } - else { - curve_select_shortest_path_curve(nu_src, vert_src, vert_dst); - } - - BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p); - - if (vc.view_layer->basact != basact) { - ED_object_base_activate(C, basact); - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - return OPERATOR_FINISHED; + ViewContext vc; + Nurb *nu_dst; + BezTriple *bezt_dst; + BPoint *bp_dst; + int vert_dst; + void *vert_dst_p; + Base *basact = NULL; + + view3d_operator_needs_opengl(C); + ED_view3d_viewcontext_init(C, &vc); + copy_v2_v2_int(vc.mval, event->mval); + + if (!ED_curve_pick_vert(&vc, 1, &nu_dst, &bezt_dst, &bp_dst, NULL, &basact)) { + return OPERATOR_PASS_THROUGH; + } + + ED_view3d_viewcontext_init_object(&vc, basact->object); + Object *obedit = basact->object; + Curve *cu = obedit->data; + Nurb *nu_src = BKE_curve_nurb_active_get(cu); + int vert_src = cu->actvert; + + if (vert_src == CU_ACT_NONE) { + return OPERATOR_PASS_THROUGH; + } + + if (nu_src != nu_dst) { + BKE_report(op->reports, RPT_ERROR, "Control point belongs to another spline"); + return OPERATOR_CANCELLED; + } + + vert_dst_p = bezt_dst ? (void *)bezt_dst : (void *)bp_dst; + vert_dst = BKE_curve_nurb_vert_index_get(nu_dst, vert_dst_p); + if (vert_src == vert_dst) { + return OPERATOR_CANCELLED; + } + + if ((obedit->type == OB_SURF) && (nu_src->pntsv > 1)) { + curve_select_shortest_path_surf(nu_src, vert_src, vert_dst); + } + else { + curve_select_shortest_path_curve(nu_src, vert_src, vert_dst); + } + + BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p); + + if (vc.view_layer->basact != basact) { + ED_object_base_activate(C, basact); + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + return OPERATOR_FINISHED; } void CURVE_OT_shortest_path_pick(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Pick Shortest Path"; - ot->idname = "CURVE_OT_shortest_path_pick"; - ot->description = "Select shortest path between two selections"; + /* identifiers */ + ot->name = "Pick Shortest Path"; + ot->idname = "CURVE_OT_shortest_path_pick"; + ot->description = "Select shortest path between two selections"; - /* api callbacks */ - ot->invoke = edcu_shortest_path_pick_invoke; - ot->poll = ED_operator_editsurfcurve_region_view3d; + /* api callbacks */ + ot->invoke = edcu_shortest_path_pick_invoke; + ot->poll = ED_operator_editsurfcurve_region_view3d; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /** \} */ diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 6cde9abb33f..d0c2afcb1d2 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -58,133 +58,131 @@ static CLG_LogRef LOG = {"ed.undo.curve"}; * \{ */ typedef struct { - ListBase nubase; - int actvert; - GHash *undoIndex; - ListBase fcurves, drivers; - int actnu; - int flag; - - /* Stored in the object, needed since users may change the active key while in edit-mode. */ - struct { - short shapenr; - } obedit; - - size_t undo_size; + ListBase nubase; + int actvert; + GHash *undoIndex; + ListBase fcurves, drivers; + int actnu; + int flag; + + /* Stored in the object, needed since users may change the active key while in edit-mode. */ + struct { + short shapenr; + } obedit; + + size_t undo_size; } UndoCurve; static void undocurve_to_editcurve(Main *bmain, UndoCurve *ucu, Curve *cu, short *r_shapenr) { - ListBase *undobase = &ucu->nubase; - ListBase *editbase = BKE_curve_editNurbs_get(cu); - Nurb *nu, *newnu; - EditNurb *editnurb = cu->editnurb; - AnimData *ad = BKE_animdata_from_id(&cu->id); - - BKE_nurbList_free(editbase); - - if (ucu->undoIndex) { - BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex); - editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex); - } - - if (ad) { - if (ad->action) { - free_fcurves(&ad->action->curves); - copy_fcurves(&ad->action->curves, &ucu->fcurves); - } - - free_fcurves(&ad->drivers); - copy_fcurves(&ad->drivers, &ucu->drivers); - } - - /* copy */ - for (nu = undobase->first; nu; nu = nu->next) { - newnu = BKE_nurb_duplicate(nu); - - if (editnurb->keyindex) { - ED_curve_keyindex_update_nurb(editnurb, nu, newnu); - } - - BLI_addtail(editbase, newnu); - } - - cu->actvert = ucu->actvert; - cu->actnu = ucu->actnu; - cu->flag = ucu->flag; - *r_shapenr = ucu->obedit.shapenr; - ED_curve_updateAnimPaths(bmain, cu); + ListBase *undobase = &ucu->nubase; + ListBase *editbase = BKE_curve_editNurbs_get(cu); + Nurb *nu, *newnu; + EditNurb *editnurb = cu->editnurb; + AnimData *ad = BKE_animdata_from_id(&cu->id); + + BKE_nurbList_free(editbase); + + if (ucu->undoIndex) { + BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex); + editnurb->keyindex = ED_curve_keyindex_hash_duplicate(ucu->undoIndex); + } + + if (ad) { + if (ad->action) { + free_fcurves(&ad->action->curves); + copy_fcurves(&ad->action->curves, &ucu->fcurves); + } + + free_fcurves(&ad->drivers); + copy_fcurves(&ad->drivers, &ucu->drivers); + } + + /* copy */ + for (nu = undobase->first; nu; nu = nu->next) { + newnu = BKE_nurb_duplicate(nu); + + if (editnurb->keyindex) { + ED_curve_keyindex_update_nurb(editnurb, nu, newnu); + } + + BLI_addtail(editbase, newnu); + } + + cu->actvert = ucu->actvert; + cu->actnu = ucu->actnu; + cu->flag = ucu->flag; + *r_shapenr = ucu->obedit.shapenr; + ED_curve_updateAnimPaths(bmain, cu); } static void undocurve_from_editcurve(UndoCurve *ucu, Curve *cu, const short shapenr) { - BLI_assert(BLI_array_is_zeroed(ucu, 1)); - ListBase *nubase = BKE_curve_editNurbs_get(cu); - EditNurb *editnurb = cu->editnurb, tmpEditnurb; - Nurb *nu, *newnu; - AnimData *ad = BKE_animdata_from_id(&cu->id); - - /* TODO: include size of fcurve & undoIndex */ - // ucu->undo_size = 0; - - if (editnurb->keyindex) { - ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex); - tmpEditnurb.keyindex = ucu->undoIndex; - } - - if (ad) { - if (ad->action) { - copy_fcurves(&ucu->fcurves, &ad->action->curves); - } - - copy_fcurves(&ucu->drivers, &ad->drivers); - } - - /* copy */ - for (nu = nubase->first; nu; nu = nu->next) { - newnu = BKE_nurb_duplicate(nu); - - if (ucu->undoIndex) { - ED_curve_keyindex_update_nurb(&tmpEditnurb, nu, newnu); - } - - BLI_addtail(&ucu->nubase, newnu); - - ucu->undo_size += ( - (nu->bezt ? (sizeof(BezTriple) * nu->pntsu) : 0) + - (nu->bp ? (sizeof(BPoint) * (nu->pntsu * nu->pntsv)) : 0) + - (nu->knotsu ? (sizeof(float) * KNOTSU(nu)) : 0) + - (nu->knotsv ? (sizeof(float) * KNOTSV(nu)) : 0) + - sizeof(Nurb)); - } - - ucu->actvert = cu->actvert; - ucu->actnu = cu->actnu; - ucu->flag = cu->flag; - - ucu->obedit.shapenr = shapenr; + BLI_assert(BLI_array_is_zeroed(ucu, 1)); + ListBase *nubase = BKE_curve_editNurbs_get(cu); + EditNurb *editnurb = cu->editnurb, tmpEditnurb; + Nurb *nu, *newnu; + AnimData *ad = BKE_animdata_from_id(&cu->id); + + /* TODO: include size of fcurve & undoIndex */ + // ucu->undo_size = 0; + + if (editnurb->keyindex) { + ucu->undoIndex = ED_curve_keyindex_hash_duplicate(editnurb->keyindex); + tmpEditnurb.keyindex = ucu->undoIndex; + } + + if (ad) { + if (ad->action) { + copy_fcurves(&ucu->fcurves, &ad->action->curves); + } + + copy_fcurves(&ucu->drivers, &ad->drivers); + } + + /* copy */ + for (nu = nubase->first; nu; nu = nu->next) { + newnu = BKE_nurb_duplicate(nu); + + if (ucu->undoIndex) { + ED_curve_keyindex_update_nurb(&tmpEditnurb, nu, newnu); + } + + BLI_addtail(&ucu->nubase, newnu); + + ucu->undo_size += ((nu->bezt ? (sizeof(BezTriple) * nu->pntsu) : 0) + + (nu->bp ? (sizeof(BPoint) * (nu->pntsu * nu->pntsv)) : 0) + + (nu->knotsu ? (sizeof(float) * KNOTSU(nu)) : 0) + + (nu->knotsv ? (sizeof(float) * KNOTSV(nu)) : 0) + sizeof(Nurb)); + } + + ucu->actvert = cu->actvert; + ucu->actnu = cu->actnu; + ucu->flag = cu->flag; + + ucu->obedit.shapenr = shapenr; } static void undocurve_free_data(UndoCurve *uc) { - BKE_nurbList_free(&uc->nubase); + BKE_nurbList_free(&uc->nubase); - BKE_curve_editNurb_keyIndex_free(&uc->undoIndex); + BKE_curve_editNurb_keyIndex_free(&uc->undoIndex); - free_fcurves(&uc->fcurves); - free_fcurves(&uc->drivers); + free_fcurves(&uc->fcurves); + free_fcurves(&uc->drivers); } static Object *editcurve_object_from_context(bContext *C) { - Object *obedit = CTX_data_edit_object(C); - if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) { - Curve *cu = obedit->data; - if (BKE_curve_editNurbs_get(cu) != NULL) { - return obedit; - } - } - return NULL; + Object *obedit = CTX_data_edit_object(C); + if (obedit && ELEM(obedit->type, OB_CURVE, OB_SURF)) { + Curve *cu = obedit->data; + if (BKE_curve_editNurbs_get(cu) != NULL) { + return obedit; + } + } + return NULL; } /** \} */ @@ -196,113 +194,123 @@ static Object *editcurve_object_from_context(bContext *C) * \{ */ typedef struct CurveUndoStep_Elem { - UndoRefID_Object obedit_ref; - UndoCurve data; + UndoRefID_Object obedit_ref; + UndoCurve data; } CurveUndoStep_Elem; typedef struct CurveUndoStep { - UndoStep step; - CurveUndoStep_Elem *elems; - uint elems_len; + UndoStep step; + CurveUndoStep_Elem *elems; + uint elems_len; } CurveUndoStep; static bool curve_undosys_poll(bContext *C) { - Object *obedit = editcurve_object_from_context(C); - return (obedit != NULL); + Object *obedit = editcurve_object_from_context(C); + return (obedit != NULL); } -static bool curve_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p) +static bool curve_undosys_step_encode(struct bContext *C, + struct Main *UNUSED(bmain), + UndoStep *us_p) { - CurveUndoStep *us = (CurveUndoStep *)us_p; - - /* Important not to use the 3D view when getting objects because all objects - * outside of this list will be moved out of edit-mode when reading back undo steps. */ - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, NULL, &objects_len); - - us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); - us->elems_len = objects_len; - - for (uint i = 0; i < objects_len; i++) { - Object *ob = objects[i]; - CurveUndoStep_Elem *elem = &us->elems[i]; - - elem->obedit_ref.ptr = ob; - undocurve_from_editcurve(&elem->data, ob->data, ob->shapenr); - us->step.data_size += elem->data.undo_size; - } - MEM_freeN(objects); - return true; + CurveUndoStep *us = (CurveUndoStep *)us_p; + + /* Important not to use the 3D view when getting objects because all objects + * outside of this list will be moved out of edit-mode when reading back undo steps. */ + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, NULL, &objects_len); + + us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__); + us->elems_len = objects_len; + + for (uint i = 0; i < objects_len; i++) { + Object *ob = objects[i]; + CurveUndoStep_Elem *elem = &us->elems[i]; + + elem->obedit_ref.ptr = ob; + undocurve_from_editcurve(&elem->data, ob->data, ob->shapenr); + us->step.data_size += elem->data.undo_size; + } + MEM_freeN(objects); + return true; } -static void curve_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir)) +static void curve_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + int UNUSED(dir)) { - CurveUndoStep *us = (CurveUndoStep *)us_p; - - /* Load all our objects into edit-mode, clear everything else. */ - ED_undo_object_editmode_restore_helper( - C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems)); - - BLI_assert(curve_undosys_poll(C)); - - for (uint i = 0; i < us->elems_len; i++) { - CurveUndoStep_Elem *elem = &us->elems[i]; - Object *obedit = elem->obedit_ref.ptr; - Curve *cu = obedit->data; - if (cu->editnurb == NULL) { - /* Should never fail, may not crash but can give odd behavior. */ - CLOG_ERROR(&LOG, "name='%s', failed to enter edit-mode for object '%s', undo state invalid", - us_p->name, obedit->id.name); - continue; - } - undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - } - - /* The first element is always active */ - ED_undo_object_set_active_or_warn(CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); + CurveUndoStep *us = (CurveUndoStep *)us_p; + + /* Load all our objects into edit-mode, clear everything else. */ + ED_undo_object_editmode_restore_helper( + C, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems)); + + BLI_assert(curve_undosys_poll(C)); + + for (uint i = 0; i < us->elems_len; i++) { + CurveUndoStep_Elem *elem = &us->elems[i]; + Object *obedit = elem->obedit_ref.ptr; + Curve *cu = obedit->data; + if (cu->editnurb == NULL) { + /* Should never fail, may not crash but can give odd behavior. */ + CLOG_ERROR(&LOG, + "name='%s', failed to enter edit-mode for object '%s', undo state invalid", + us_p->name, + obedit->id.name); + continue; + } + undocurve_to_editcurve(bmain, &elem->data, obedit->data, &obedit->shapenr); + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + } + + /* The first element is always active */ + ED_undo_object_set_active_or_warn( + CTX_data_view_layer(C), us->elems[0].obedit_ref.ptr, us_p->name, &LOG); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } static void curve_undosys_step_free(UndoStep *us_p) { - CurveUndoStep *us = (CurveUndoStep *)us_p; + CurveUndoStep *us = (CurveUndoStep *)us_p; - for (uint i = 0; i < us->elems_len; i++) { - CurveUndoStep_Elem *elem = &us->elems[i]; - undocurve_free_data(&elem->data); - } - MEM_freeN(us->elems); + for (uint i = 0; i < us->elems_len; i++) { + CurveUndoStep_Elem *elem = &us->elems[i]; + undocurve_free_data(&elem->data); + } + MEM_freeN(us->elems); } -static void curve_undosys_foreach_ID_ref( - UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data) +static void curve_undosys_foreach_ID_ref(UndoStep *us_p, + UndoTypeForEachIDRefFn foreach_ID_ref_fn, + void *user_data) { - CurveUndoStep *us = (CurveUndoStep *)us_p; + CurveUndoStep *us = (CurveUndoStep *)us_p; - for (uint i = 0; i < us->elems_len; i++) { - CurveUndoStep_Elem *elem = &us->elems[i]; - foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref)); - } + for (uint i = 0; i < us->elems_len; i++) { + CurveUndoStep_Elem *elem = &us->elems[i]; + foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref)); + } } /* Export for ED_undo_sys. */ void ED_curve_undosys_type(UndoType *ut) { - ut->name = "Edit Curve"; - ut->poll = curve_undosys_poll; - ut->step_encode = curve_undosys_step_encode; - ut->step_decode = curve_undosys_step_decode; - ut->step_free = curve_undosys_step_free; + ut->name = "Edit Curve"; + ut->poll = curve_undosys_poll; + ut->step_encode = curve_undosys_step_encode; + ut->step_decode = curve_undosys_step_decode; + ut->step_free = curve_undosys_step_free; - ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref; + ut->step_foreach_ID_ref = curve_undosys_foreach_ID_ref; - ut->use_context = true; + ut->use_context = true; - ut->step_size = sizeof(CurveUndoStep); + ut->step_size = sizeof(CurveUndoStep); } /** \} */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 480819dd47a..d1b1f43d8dd 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -21,7 +21,6 @@ * \ingroup edcurve */ - #include #include #include @@ -76,1927 +75,2118 @@ static int kill_selection(Object *obedit, int ins); static char findaccent(char char1, unsigned int code) { - char new = 0; - - if (char1 == 'a') { - if (code == '`') { new = 224; } - else if (code == 39) { new = 225; } - else if (code == '^') { new = 226; } - else if (code == '~') { new = 227; } - else if (code == '"') { new = 228; } - else if (code == 'o') { new = 229; } - else if (code == 'e') { new = 230; } - else if (code == '-') { new = 170; } - } - else if (char1 == 'c') { - if (code == ',') { new = 231; } - else if (code == '|') { new = 162; } - else if (code == 'o') { new = 169; } - } - else if (char1 == 'e') { - if (code == '`') { new = 232; } - else if (code == 39) { new = 233; } - else if (code == '^') { new = 234; } - else if (code == '"') { new = 235; } - } - else if (char1 == 'i') { - if (code == '`') { new = 236; } - else if (code == 39) { new = 237; } - else if (code == '^') { new = 238; } - else if (code == '"') { new = 239; } - } - else if (char1 == 'n') { - if (code == '~') { new = 241; } - } - else if (char1 == 'o') { - if (code == '`') { new = 242; } - else if (code == 39) { new = 243; } - else if (code == '^') { new = 244; } - else if (code == '~') { new = 245; } - else if (code == '"') { new = 246; } - else if (code == '/') { new = 248; } - else if (code == '-') { new = 186; } - else if (code == 'e') { new = 143; } - else if (code == 'c') { new = 169; } - else if (code == 'r') { new = 174; } - } - else if (char1 == 'r') { - if (code == 'o') { new = 174; } - } - else if (char1 == 's') { - if (code == 's') { new = 167; } - } - else if (char1 == 't') { - if (code == 'm') { new = 153; } - } - else if (char1 == 'u') { - if (code == '`') { new = 249; } - else if (code == 39) { new = 250; } - else if (code == '^') { new = 251; } - else if (code == '"') { new = 252; } - } - else if (char1 == 'y') { - if (code == 39) { new = 253; } - else if (code == '"') { new = 255; } - } - else if (char1 == 'A') { - if (code == '`') { new = 192; } - else if (code == 39) { new = 193; } - else if (code == '^') { new = 194; } - else if (code == '~') { new = 195; } - else if (code == '"') { new = 196; } - else if (code == 'o') { new = 197; } - else if (code == 'e') { new = 198; } - } - else if (char1 == 'C') { - if (code == ',') { new = 199; } - } - else if (char1 == 'E') { - if (code == '`') { new = 200; } - else if (code == 39) { new = 201; } - else if (code == '^') { new = 202; } - else if (code == '"') { new = 203; } - } - else if (char1 == 'I') { - if (code == '`') { new = 204; } - else if (code == 39) { new = 205; } - else if (code == '^') { new = 206; } - else if (code == '"') { new = 207; } - } - else if (char1 == 'N') { - if (code == '~') { new = 209; } - } - else if (char1 == 'O') { - if (code == '`') { new = 210; } - else if (code == 39) { new = 211; } - else if (code == '^') { new = 212; } - else if (code == '~') { new = 213; } - else if (code == '"') { new = 214; } - else if (code == '/') { new = 216; } - else if (code == 'e') { new = 141; } - } - else if (char1 == 'U') { - if (code == '`') { new = 217; } - else if (code == 39) { new = 218; } - else if (code == '^') { new = 219; } - else if (code == '"') { new = 220; } - } - else if (char1 == 'Y') { - if (code == 39) { new = 221; } - } - else if (char1 == '1') { - if (code == '4') { new = 188; } - if (code == '2') { new = 189; } - } - else if (char1 == '3') { - if (code == '4') { new = 190; } - } - else if (char1 == ':') { - if (code == '-') { new = 247; } - } - else if (char1 == '-') { - if (code == ':') { new = 247; } - if (code == '|') { new = 135; } - if (code == '+') { new = 177; } - } - else if (char1 == '|') { - if (code == '-') { new = 135; } - if (code == '=') { new = 136; } - } - else if (char1 == '=') { - if (code == '|') { new = 136; } - } - else if (char1 == '+') { - if (code == '-') { new = 177; } - } - - if (new) { - return new; - } - else { - return char1; - } + char new = 0; + + if (char1 == 'a') { + if (code == '`') { + new = 224; + } + else if (code == 39) { + new = 225; + } + else if (code == '^') { + new = 226; + } + else if (code == '~') { + new = 227; + } + else if (code == '"') { + new = 228; + } + else if (code == 'o') { + new = 229; + } + else if (code == 'e') { + new = 230; + } + else if (code == '-') { + new = 170; + } + } + else if (char1 == 'c') { + if (code == ',') { + new = 231; + } + else if (code == '|') { + new = 162; + } + else if (code == 'o') { + new = 169; + } + } + else if (char1 == 'e') { + if (code == '`') { + new = 232; + } + else if (code == 39) { + new = 233; + } + else if (code == '^') { + new = 234; + } + else if (code == '"') { + new = 235; + } + } + else if (char1 == 'i') { + if (code == '`') { + new = 236; + } + else if (code == 39) { + new = 237; + } + else if (code == '^') { + new = 238; + } + else if (code == '"') { + new = 239; + } + } + else if (char1 == 'n') { + if (code == '~') { + new = 241; + } + } + else if (char1 == 'o') { + if (code == '`') { + new = 242; + } + else if (code == 39) { + new = 243; + } + else if (code == '^') { + new = 244; + } + else if (code == '~') { + new = 245; + } + else if (code == '"') { + new = 246; + } + else if (code == '/') { + new = 248; + } + else if (code == '-') { + new = 186; + } + else if (code == 'e') { + new = 143; + } + else if (code == 'c') { + new = 169; + } + else if (code == 'r') { + new = 174; + } + } + else if (char1 == 'r') { + if (code == 'o') { + new = 174; + } + } + else if (char1 == 's') { + if (code == 's') { + new = 167; + } + } + else if (char1 == 't') { + if (code == 'm') { + new = 153; + } + } + else if (char1 == 'u') { + if (code == '`') { + new = 249; + } + else if (code == 39) { + new = 250; + } + else if (code == '^') { + new = 251; + } + else if (code == '"') { + new = 252; + } + } + else if (char1 == 'y') { + if (code == 39) { + new = 253; + } + else if (code == '"') { + new = 255; + } + } + else if (char1 == 'A') { + if (code == '`') { + new = 192; + } + else if (code == 39) { + new = 193; + } + else if (code == '^') { + new = 194; + } + else if (code == '~') { + new = 195; + } + else if (code == '"') { + new = 196; + } + else if (code == 'o') { + new = 197; + } + else if (code == 'e') { + new = 198; + } + } + else if (char1 == 'C') { + if (code == ',') { + new = 199; + } + } + else if (char1 == 'E') { + if (code == '`') { + new = 200; + } + else if (code == 39) { + new = 201; + } + else if (code == '^') { + new = 202; + } + else if (code == '"') { + new = 203; + } + } + else if (char1 == 'I') { + if (code == '`') { + new = 204; + } + else if (code == 39) { + new = 205; + } + else if (code == '^') { + new = 206; + } + else if (code == '"') { + new = 207; + } + } + else if (char1 == 'N') { + if (code == '~') { + new = 209; + } + } + else if (char1 == 'O') { + if (code == '`') { + new = 210; + } + else if (code == 39) { + new = 211; + } + else if (code == '^') { + new = 212; + } + else if (code == '~') { + new = 213; + } + else if (code == '"') { + new = 214; + } + else if (code == '/') { + new = 216; + } + else if (code == 'e') { + new = 141; + } + } + else if (char1 == 'U') { + if (code == '`') { + new = 217; + } + else if (code == 39) { + new = 218; + } + else if (code == '^') { + new = 219; + } + else if (code == '"') { + new = 220; + } + } + else if (char1 == 'Y') { + if (code == 39) { + new = 221; + } + } + else if (char1 == '1') { + if (code == '4') { + new = 188; + } + if (code == '2') { + new = 189; + } + } + else if (char1 == '3') { + if (code == '4') { + new = 190; + } + } + else if (char1 == ':') { + if (code == '-') { + new = 247; + } + } + else if (char1 == '-') { + if (code == ':') { + new = 247; + } + if (code == '|') { + new = 135; + } + if (code == '+') { + new = 177; + } + } + else if (char1 == '|') { + if (code == '-') { + new = 135; + } + if (code == '=') { + new = 136; + } + } + else if (char1 == '=') { + if (code == '|') { + new = 136; + } + } + else if (char1 == '+') { + if (code == '-') { + new = 177; + } + } + + if (new) { + return new; + } + else { + return char1; + } } static int insert_into_textbuf(Object *obedit, uintptr_t c) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - - if (ef->len < MAXTEXT - 1) { - int x; - - for (x = ef->len; x > ef->pos; x--) { - ef->textbuf[x] = ef->textbuf[x - 1]; - } - for (x = ef->len; x > ef->pos; x--) { - ef->textbufinfo[x] = ef->textbufinfo[x - 1]; - } - ef->textbuf[ef->pos] = c; - ef->textbufinfo[ef->pos] = cu->curinfo; - ef->textbufinfo[ef->pos].kern = 0; - ef->textbufinfo[ef->pos].mat_nr = obedit->actcol; - - ef->pos++; - ef->len++; - ef->textbuf[ef->len] = '\0'; - - return 1; - } - else { - return 0; - } + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + + if (ef->len < MAXTEXT - 1) { + int x; + + for (x = ef->len; x > ef->pos; x--) { + ef->textbuf[x] = ef->textbuf[x - 1]; + } + for (x = ef->len; x > ef->pos; x--) { + ef->textbufinfo[x] = ef->textbufinfo[x - 1]; + } + ef->textbuf[ef->pos] = c; + ef->textbufinfo[ef->pos] = cu->curinfo; + ef->textbufinfo[ef->pos].kern = 0; + ef->textbufinfo[ef->pos].mat_nr = obedit->actcol; + + ef->pos++; + ef->len++; + ef->textbuf[ef->len] = '\0'; + + return 1; + } + else { + return 0; + } } static void text_update_edited(bContext *C, Object *obedit, int mode) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - - BLI_assert(ef->len >= 0); - - /* run update first since it can move the cursor */ - if (mode == FO_EDIT) { - /* re-tesselllate */ - DEG_id_tag_update(obedit->data, 0); - } - else { - /* depsgraph runs above, but since we're not tagging for update, call direct */ - /* We need evaluated data here. */ - BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), mode); - } - - cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; - - if (obedit->totcol > 0) { - obedit->actcol = cu->curinfo.mat_nr; - - /* since this array is calloc'd, it can be 0 even though we try ensure - * (mat_nr > 0) almost everywhere */ - if (obedit->actcol < 1) { - obedit->actcol = 1; - } - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + + BLI_assert(ef->len >= 0); + + /* run update first since it can move the cursor */ + if (mode == FO_EDIT) { + /* re-tesselllate */ + DEG_id_tag_update(obedit->data, 0); + } + else { + /* depsgraph runs above, but since we're not tagging for update, call direct */ + /* We need evaluated data here. */ + BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), mode); + } + + cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; + + if (obedit->totcol > 0) { + obedit->actcol = cu->curinfo.mat_nr; + + /* since this array is calloc'd, it can be 0 even though we try ensure + * (mat_nr > 0) almost everywhere */ + if (obedit->actcol < 1) { + obedit->actcol = 1; + } + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); } /* -------------------------------------------------------------------- */ /* Generic Paste Functions */ /* text_update_edited(C, scene, obedit, 1, FO_EDIT); */ -static bool font_paste_wchar(Object *obedit, const wchar_t *str, const size_t str_len, +static bool font_paste_wchar(Object *obedit, + const wchar_t *str, + const size_t str_len, /* optional */ struct CharInfo *str_info) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int selend, selstart; - - if (BKE_vfont_select_get(obedit, &selstart, &selend) == 0) { - selstart = selend = 0; - } - - /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */ - if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) { - - kill_selection(obedit, 0); - - if (str_len) { - int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t); - memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size); - memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t)); - - memmove(ef->textbufinfo + ef->pos + str_len, ef->textbufinfo + ef->pos, (ef->len - ef->pos + 1) * sizeof(CharInfo)); - if (str_info) { - memcpy(ef->textbufinfo + ef->pos, str_info, str_len * sizeof(CharInfo)); - } - else { - memset(ef->textbufinfo + ef->pos, '\0', str_len * sizeof(CharInfo)); - } - - ef->len += str_len; - ef->pos += str_len; - } - - return true; - } - - return false; + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int selend, selstart; + + if (BKE_vfont_select_get(obedit, &selstart, &selend) == 0) { + selstart = selend = 0; + } + + /* Verify that the copy buffer => [copy buffer len] + ef->len < MAXTEXT */ + if ((ef->len + str_len) - (selend - selstart) <= MAXTEXT) { + + kill_selection(obedit, 0); + + if (str_len) { + int size = (ef->len * sizeof(wchar_t)) - (ef->pos * sizeof(wchar_t)) + sizeof(wchar_t); + memmove(ef->textbuf + ef->pos + str_len, ef->textbuf + ef->pos, size); + memcpy(ef->textbuf + ef->pos, str, str_len * sizeof(wchar_t)); + + memmove(ef->textbufinfo + ef->pos + str_len, + ef->textbufinfo + ef->pos, + (ef->len - ef->pos + 1) * sizeof(CharInfo)); + if (str_info) { + memcpy(ef->textbufinfo + ef->pos, str_info, str_len * sizeof(CharInfo)); + } + else { + memset(ef->textbufinfo + ef->pos, '\0', str_len * sizeof(CharInfo)); + } + + ef->len += str_len; + ef->pos += str_len; + } + + return true; + } + + return false; } static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len) { - Object *obedit = CTX_data_edit_object(C); - bool retval; + Object *obedit = CTX_data_edit_object(C); + bool retval; - int tmplen; + int tmplen; - wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__); + wchar_t *mem = MEM_mallocN((sizeof(wchar_t) * (str_len + 1)), __func__); - tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1); + tmplen = BLI_strncpy_wchar_from_utf8(mem, str, str_len + 1); - retval = font_paste_wchar(obedit, mem, tmplen, NULL); + retval = font_paste_wchar(obedit, mem, tmplen, NULL); - MEM_freeN(mem); + MEM_freeN(mem); - return retval; + return retval; } - /* -------------------------------------------------------------------- */ /* Paste From File*/ static int paste_from_file(bContext *C, ReportList *reports, const char *filename) { - Object *obedit = CTX_data_edit_object(C); - char *strp; - size_t filelen; - int retval; - - strp = BLI_file_read_text_as_mem(filename, 1, &filelen); - if (strp == NULL) { - BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename); - return OPERATOR_CANCELLED; - } - strp[filelen] = 0; - - if (font_paste_utf8(C, strp, filelen)) { - text_update_edited(C, obedit, FO_EDIT); - retval = OPERATOR_FINISHED; - - } - else { - BKE_reportf(reports, RPT_ERROR, "File too long %s", filename); - retval = OPERATOR_CANCELLED; - } - - MEM_freeN(strp); - - return retval; + Object *obedit = CTX_data_edit_object(C); + char *strp; + size_t filelen; + int retval; + + strp = BLI_file_read_text_as_mem(filename, 1, &filelen); + if (strp == NULL) { + BKE_reportf(reports, RPT_ERROR, "Failed to open file '%s'", filename); + return OPERATOR_CANCELLED; + } + strp[filelen] = 0; + + if (font_paste_utf8(C, strp, filelen)) { + text_update_edited(C, obedit, FO_EDIT); + retval = OPERATOR_FINISHED; + } + else { + BKE_reportf(reports, RPT_ERROR, "File too long %s", filename); + retval = OPERATOR_CANCELLED; + } + + MEM_freeN(strp); + + return retval; } static int paste_from_file_exec(bContext *C, wmOperator *op) { - char *path; - int retval; + char *path; + int retval; - path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0); - retval = paste_from_file(C, op->reports, path); - MEM_freeN(path); + path = RNA_string_get_alloc(op->ptr, "filepath", NULL, 0); + retval = paste_from_file(C, op->reports, path); + MEM_freeN(path); - return retval; + return retval; } static int paste_from_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - if (RNA_struct_property_is_set(op->ptr, "filepath")) { - return paste_from_file_exec(C, op); - } + if (RNA_struct_property_is_set(op->ptr, "filepath")) { + return paste_from_file_exec(C, op); + } - WM_event_add_fileselect(C, op); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void FONT_OT_text_paste_from_file(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste File"; - ot->description = "Paste contents from file"; - ot->idname = "FONT_OT_text_paste_from_file"; - - /* api callbacks */ - ot->exec = paste_from_file_exec; - ot->invoke = paste_from_file_invoke; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_TEXT, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + /* identifiers */ + ot->name = "Paste File"; + ot->description = "Paste contents from file"; + ot->idname = "FONT_OT_text_paste_from_file"; + + /* api callbacks */ + ot->exec = paste_from_file_exec; + ot->invoke = paste_from_file_invoke; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_TEXT, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); } /******************* text to object operator ********************/ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3]) { - Main *bmain = CTX_data_main(C); - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Curve *cu; - Object *obedit; - Base *base; - struct TextLine *tmp; - int nchars = 0, nbytes = 0; - char *s; - int a; - float rot[3] = {0.f, 0.f, 0.f}; - - obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL); - base = view_layer->basact; + Main *bmain = CTX_data_main(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Curve *cu; + Object *obedit; + Base *base; + struct TextLine *tmp; + int nchars = 0, nbytes = 0; + char *s; + int a; + float rot[3] = {0.f, 0.f, 0.f}; - /* seems to assume view align ? TODO - look into this, could be an operator option */ - ED_object_base_init_transform(C, base, NULL, rot); + obedit = BKE_object_add(bmain, scene, view_layer, OB_FONT, NULL); + base = view_layer->basact; - BKE_object_where_is_calc(depsgraph, scene, obedit); + /* seems to assume view align ? TODO - look into this, could be an operator option */ + ED_object_base_init_transform(C, base, NULL, rot); - add_v3_v3(obedit->loc, offset); + BKE_object_where_is_calc(depsgraph, scene, obedit); - cu = obedit->data; - cu->vfont = BKE_vfont_builtin_get(); - id_us_plus(&cu->vfont->id); + add_v3_v3(obedit->loc, offset); - for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) { - size_t nchars_line, nbytes_line; - nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line); - nchars += nchars_line + 1; - nbytes += nbytes_line + 1; - } + cu = obedit->data; + cu->vfont = BKE_vfont_builtin_get(); + id_us_plus(&cu->vfont->id); - if (cu->str) { - MEM_freeN(cu->str); - } - if (cu->strinfo) { - MEM_freeN(cu->strinfo); - } + for (tmp = firstline, a = 0; nbytes < MAXTEXT && a < totline; tmp = tmp->next, a++) { + size_t nchars_line, nbytes_line; + nchars_line = BLI_strlen_utf8_ex(tmp->line, &nbytes_line); + nchars += nchars_line + 1; + nbytes += nbytes_line + 1; + } - cu->str = MEM_mallocN(nbytes + 4, "str"); - cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo"); + if (cu->str) { + MEM_freeN(cu->str); + } + if (cu->strinfo) { + MEM_freeN(cu->strinfo); + } - cu->len = 0; - cu->len_wchar = nchars - 1; - cu->pos = 0; + cu->str = MEM_mallocN(nbytes + 4, "str"); + cu->strinfo = MEM_callocN((nchars + 4) * sizeof(CharInfo), "strinfo"); - s = cu->str; + cu->len = 0; + cu->len_wchar = nchars - 1; + cu->pos = 0; - for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) { - size_t nbytes_line; + s = cu->str; - nbytes_line = BLI_strcpy_rlen(s, tmp->line); + for (tmp = firstline, a = 0; cu->len < MAXTEXT && a < totline; tmp = tmp->next, a++) { + size_t nbytes_line; - s += nbytes_line; - cu->len += nbytes_line; + nbytes_line = BLI_strcpy_rlen(s, tmp->line); - if (tmp->next) { - nbytes_line = BLI_strcpy_rlen(s, "\n"); + s += nbytes_line; + cu->len += nbytes_line; - s += nbytes_line; - cu->len += nbytes_line; - } + if (tmp->next) { + nbytes_line = BLI_strcpy_rlen(s, "\n"); - } + s += nbytes_line; + cu->len += nbytes_line; + } + } - cu->pos = cu->len_wchar; - *s = '\0'; + cu->pos = cu->len_wchar; + *s = '\0'; - WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit); + WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit); } void ED_text_to_object(bContext *C, Text *text, const bool split_lines) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); - TextLine *line; - float offset[3]; - int linenum = 0; - - if (!text || !text->lines.first) { - return; - } - - if (split_lines) { - for (line = text->lines.first; line; line = line->next) { - /* skip lines with no text, but still make space for them */ - if (line->line[0] == '\0') { - linenum++; - continue; - } - - /* do the translation */ - offset[0] = 0; - offset[1] = -linenum; - offset[2] = 0; - - if (rv3d) { - mul_mat3_m4_v3(rv3d->viewinv, offset); - } - - txt_add_object(C, line, 1, offset); - - linenum++; - } - } - else { - offset[0] = 0.0f; - offset[1] = 0.0f; - offset[2] = 0.0f; - - txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset); - } + RegionView3D *rv3d = CTX_wm_region_view3d(C); + TextLine *line; + float offset[3]; + int linenum = 0; + + if (!text || !text->lines.first) { + return; + } + + if (split_lines) { + for (line = text->lines.first; line; line = line->next) { + /* skip lines with no text, but still make space for them */ + if (line->line[0] == '\0') { + linenum++; + continue; + } + + /* do the translation */ + offset[0] = 0; + offset[1] = -linenum; + offset[2] = 0; + + if (rv3d) { + mul_mat3_m4_v3(rv3d->viewinv, offset); + } + + txt_add_object(C, line, 1, offset); + + linenum++; + } + } + else { + offset[0] = 0.0f; + offset[1] = 0.0f; + offset[2] = 0.0f; + + txt_add_object(C, text->lines.first, BLI_listbase_count(&text->lines), offset); + } } /********************** utilities ***************************/ -static int kill_selection(Object *obedit, int ins) /* 1 == new character */ +static int kill_selection(Object *obedit, int ins) /* 1 == new character */ { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int selend, selstart, direction; - int offset = 0; - int getfrom; - - direction = BKE_vfont_select_get(obedit, &selstart, &selend); - if (direction) { - int size; - if (ins) { - offset = 1; - } - if (ef->pos >= selstart) { - ef->pos = selstart + offset; - } - if ((direction == -1) && ins) { - selstart++; - selend++; - } - getfrom = selend + offset; - if (ins == 0) { - getfrom++; - } - size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t)); - memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size); - memmove(ef->textbufinfo + selstart, ef->textbufinfo + getfrom, ((ef->len - selstart) + offset) * sizeof(CharInfo)); - ef->len -= ((selend - selstart) + 1); - ef->selstart = ef->selend = 0; - } - - return(direction); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int selend, selstart, direction; + int offset = 0; + int getfrom; + + direction = BKE_vfont_select_get(obedit, &selstart, &selend); + if (direction) { + int size; + if (ins) { + offset = 1; + } + if (ef->pos >= selstart) { + ef->pos = selstart + offset; + } + if ((direction == -1) && ins) { + selstart++; + selend++; + } + getfrom = selend + offset; + if (ins == 0) { + getfrom++; + } + size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t)); + memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size); + memmove(ef->textbufinfo + selstart, + ef->textbufinfo + getfrom, + ((ef->len - selstart) + offset) * sizeof(CharInfo)); + ef->len -= ((selend - selstart) + 1); + ef->selstart = ef->selend = 0; + } + + return (direction); } /******************* set style operator ********************/ static const EnumPropertyItem style_items[] = { - {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""}, - {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""}, - {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""}, - {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""}, - {0, NULL, 0, NULL, NULL}, + {CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""}, + {CU_CHINFO_ITALIC, "ITALIC", 0, "Italic", ""}, + {CU_CHINFO_UNDERLINE, "UNDERLINE", 0, "Underline", ""}, + {CU_CHINFO_SMALLCAPS, "SMALL_CAPS", 0, "Small Caps", ""}, + {0, NULL, 0, NULL, NULL}, }; static int set_style(bContext *C, const int style, const bool clear) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int i, selstart, selend; - - if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { - return OPERATOR_CANCELLED; - } - - for (i = selstart; i <= selend; i++) { - if (clear) { - ef->textbufinfo[i].flag &= ~style; - } - else { - ef->textbufinfo[i].flag |= style; - } - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int i, selstart, selend; + + if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { + return OPERATOR_CANCELLED; + } + + for (i = selstart; i <= selend; i++) { + if (clear) { + ef->textbufinfo[i].flag &= ~style; + } + else { + ef->textbufinfo[i].flag |= style; + } + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; } static int set_style_exec(bContext *C, wmOperator *op) { - const int style = RNA_enum_get(op->ptr, "style"); - const bool clear = RNA_boolean_get(op->ptr, "clear"); + const int style = RNA_enum_get(op->ptr, "style"); + const bool clear = RNA_boolean_get(op->ptr, "clear"); - return set_style(C, style, clear); + return set_style(C, style, clear); } void FONT_OT_style_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Style"; - ot->description = "Set font style"; - ot->idname = "FONT_OT_style_set"; - - /* api callbacks */ - ot->exec = set_style_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to"); - RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it"); + /* identifiers */ + ot->name = "Set Style"; + ot->description = "Set font style"; + ot->idname = "FONT_OT_style_set"; + + /* api callbacks */ + ot->exec = set_style_exec; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_enum( + ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to"); + RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it"); } /******************* toggle style operator ********************/ static int toggle_style_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - int style, clear, selstart, selend; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + int style, clear, selstart, selend; - if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { - return OPERATOR_CANCELLED; - } + if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { + return OPERATOR_CANCELLED; + } - style = RNA_enum_get(op->ptr, "style"); + style = RNA_enum_get(op->ptr, "style"); - cu->curinfo.flag ^= style; - clear = (cu->curinfo.flag & style) == 0; + cu->curinfo.flag ^= style; + clear = (cu->curinfo.flag & style) == 0; - return set_style(C, style, clear); + return set_style(C, style, clear); } void FONT_OT_style_toggle(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Toggle Style"; - ot->description = "Toggle font style"; - ot->idname = "FONT_OT_style_toggle"; + /* identifiers */ + ot->name = "Toggle Style"; + ot->description = "Toggle font style"; + ot->idname = "FONT_OT_style_toggle"; - /* api callbacks */ - ot->exec = toggle_style_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = toggle_style_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to"); + /* properties */ + RNA_def_enum( + ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to"); } - /* -------------------------------------------------------------------- */ /* Select All */ static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - - if (ef->len) { - ef->selstart = 1; - ef->selend = ef->len; - ef->pos = ef->len; - - text_update_edited(C, obedit, FO_SELCHANGE); - - return OPERATOR_FINISHED; - } - else { - return OPERATOR_CANCELLED; - } - + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + + if (ef->len) { + ef->selstart = 1; + ef->selend = ef->len; + ef->pos = ef->len; + + text_update_edited(C, obedit, FO_SELCHANGE); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void FONT_OT_select_all(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Select All"; - ot->description = "Select all text"; - ot->idname = "FONT_OT_select_all"; + /* identifiers */ + ot->name = "Select All"; + ot->description = "Select all text"; + ot->idname = "FONT_OT_select_all"; - /* api callbacks */ - ot->exec = font_select_all_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = font_select_all_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } - /******************* copy text operator ********************/ static void copy_selection(Object *obedit) { - int selstart, selend; - - if (BKE_vfont_select_get(obedit, &selstart, &selend)) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - char *buf = NULL; - wchar_t *text_buf; - size_t len_utf8; - - /* internal clipboard (for style) */ - BKE_vfont_clipboard_set(ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1); - BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL); - - /* system clipboard */ - buf = MEM_mallocN(len_utf8 + 1, __func__); - if (buf) { - BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1); - WM_clipboard_text_set(buf, false); - MEM_freeN(buf); - } - } + int selstart, selend; + + if (BKE_vfont_select_get(obedit, &selstart, &selend)) { + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + char *buf = NULL; + wchar_t *text_buf; + size_t len_utf8; + + /* internal clipboard (for style) */ + BKE_vfont_clipboard_set( + ef->textbuf + selstart, ef->textbufinfo + selstart, selend - selstart + 1); + BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL); + + /* system clipboard */ + buf = MEM_mallocN(len_utf8 + 1, __func__); + if (buf) { + BLI_strncpy_wchar_as_utf8(buf, text_buf, len_utf8 + 1); + WM_clipboard_text_set(buf, false); + MEM_freeN(buf); + } + } } static int copy_text_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); + Object *obedit = CTX_data_edit_object(C); - copy_selection(obedit); + copy_selection(obedit); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_text_copy(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Copy Text"; - ot->description = "Copy selected text to clipboard"; - ot->idname = "FONT_OT_text_copy"; - - /* api callbacks */ - ot->exec = copy_text_exec; - ot->poll = ED_operator_editfont; + /* identifiers */ + ot->name = "Copy Text"; + ot->description = "Copy selected text to clipboard"; + ot->idname = "FONT_OT_text_copy"; + + /* api callbacks */ + ot->exec = copy_text_exec; + ot->poll = ED_operator_editfont; } /******************* cut text operator ********************/ static int cut_text_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - int selstart, selend; + Object *obedit = CTX_data_edit_object(C); + int selstart, selend; - if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { - return OPERATOR_CANCELLED; - } + if (!BKE_vfont_select_get(obedit, &selstart, &selend)) { + return OPERATOR_CANCELLED; + } - copy_selection(obedit); - kill_selection(obedit, 0); + copy_selection(obedit); + kill_selection(obedit, 0); - text_update_edited(C, obedit, FO_EDIT); + text_update_edited(C, obedit, FO_EDIT); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_text_cut(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Cut Text"; - ot->description = "Cut selected text to clipboard"; - ot->idname = "FONT_OT_text_cut"; + /* identifiers */ + ot->name = "Cut Text"; + ot->description = "Cut selected text to clipboard"; + ot->idname = "FONT_OT_text_cut"; - /* api callbacks */ - ot->exec = cut_text_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = cut_text_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************* paste text operator ********************/ static bool paste_selection(Object *obedit, ReportList *reports) { - wchar_t *text_buf; - CharInfo *info_buf; - size_t len; - - BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len); - - if (font_paste_wchar(obedit, text_buf, len, info_buf)) { - return true; - } - else { - BKE_report(reports, RPT_WARNING, "Text too long"); - return false; - } + wchar_t *text_buf; + CharInfo *info_buf; + size_t len; + + BKE_vfont_clipboard_get(&text_buf, &info_buf, NULL, &len); + + if (font_paste_wchar(obedit, text_buf, len, info_buf)) { + return true; + } + else { + BKE_report(reports, RPT_WARNING, "Text too long"); + return false; + } } static int paste_text_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - int retval; - size_t len_utf8; - wchar_t *text_buf; - - /* Store both clipboards as utf8 for comparison, - * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles - * as long as its synchronized with the systems clipboard. */ - struct { - char *buf; - int len; - } clipboard_system = {NULL}, clipboard_vfont = {NULL}; - - clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len); - - if (clipboard_system.buf == NULL) { - return OPERATOR_CANCELLED; - } - - BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL); - - if (text_buf) { - clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__); - - if (clipboard_vfont.buf == NULL) { - MEM_freeN(clipboard_system.buf); - return OPERATOR_CANCELLED; - } - - BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1); - } - - if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) { - retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; - } - else { - if ((clipboard_system.len <= MAXTEXT) && - font_paste_utf8(C, clipboard_system.buf, clipboard_system.len)) - { - text_update_edited(C, obedit, FO_EDIT); - retval = OPERATOR_FINISHED; - } - else { - BKE_report(op->reports, RPT_ERROR, "Clipboard too long"); - retval = OPERATOR_CANCELLED; - } - - /* free the existent clipboard buffer */ - BKE_vfont_clipboard_free(); - } - - if (retval != OPERATOR_CANCELLED) { - text_update_edited(C, obedit, FO_EDIT); - } - - /* cleanup */ - if (clipboard_vfont.buf) { - MEM_freeN(clipboard_vfont.buf); - } - - MEM_freeN(clipboard_system.buf); - - return retval; + Object *obedit = CTX_data_edit_object(C); + int retval; + size_t len_utf8; + wchar_t *text_buf; + + /* Store both clipboards as utf8 for comparison, + * Give priority to the internal 'vfont' clipboard with its 'CharInfo' text styles + * as long as its synchronized with the systems clipboard. */ + struct { + char *buf; + int len; + } clipboard_system = {NULL}, clipboard_vfont = {NULL}; + + clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len); + + if (clipboard_system.buf == NULL) { + return OPERATOR_CANCELLED; + } + + BKE_vfont_clipboard_get(&text_buf, NULL, &len_utf8, NULL); + + if (text_buf) { + clipboard_vfont.buf = MEM_mallocN(len_utf8 + 1, __func__); + + if (clipboard_vfont.buf == NULL) { + MEM_freeN(clipboard_system.buf); + return OPERATOR_CANCELLED; + } + + BLI_strncpy_wchar_as_utf8(clipboard_vfont.buf, text_buf, len_utf8 + 1); + } + + if (clipboard_vfont.buf && STREQ(clipboard_vfont.buf, clipboard_system.buf)) { + retval = paste_selection(obedit, op->reports) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + } + else { + if ((clipboard_system.len <= MAXTEXT) && + font_paste_utf8(C, clipboard_system.buf, clipboard_system.len)) { + text_update_edited(C, obedit, FO_EDIT); + retval = OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "Clipboard too long"); + retval = OPERATOR_CANCELLED; + } + + /* free the existent clipboard buffer */ + BKE_vfont_clipboard_free(); + } + + if (retval != OPERATOR_CANCELLED) { + text_update_edited(C, obedit, FO_EDIT); + } + + /* cleanup */ + if (clipboard_vfont.buf) { + MEM_freeN(clipboard_vfont.buf); + } + + MEM_freeN(clipboard_system.buf); + + return retval; } void FONT_OT_text_paste(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Paste Text"; - ot->description = "Paste text from clipboard"; - ot->idname = "FONT_OT_text_paste"; + /* identifiers */ + ot->name = "Paste Text"; + ot->description = "Paste text from clipboard"; + ot->idname = "FONT_OT_text_paste"; - /* api callbacks */ - ot->exec = paste_text_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = paste_text_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /************************ move operator ************************/ static const EnumPropertyItem move_type_items[] = { - {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, - {LINE_END, "LINE_END", 0, "Line End", ""}, - {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, - {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, - {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, - {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, - {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""}, - {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""}, - {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""}, - {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, - {0, NULL, 0, NULL, NULL}, + {LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""}, + {LINE_END, "LINE_END", 0, "Line End", ""}, + {PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, + {NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, + {PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, + {NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, + {PREV_LINE, "PREVIOUS_LINE", 0, "Previous Line", ""}, + {NEXT_LINE, "NEXT_LINE", 0, "Next Line", ""}, + {PREV_PAGE, "PREVIOUS_PAGE", 0, "Previous Page", ""}, + {NEXT_PAGE, "NEXT_PAGE", 0, "Next Page", ""}, + {0, NULL, 0, NULL, NULL}, }; static int move_cursor(bContext *C, int type, const bool select) { - Depsgraph *depsgraph = CTX_data_depsgraph(C); - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int cursmove = -1; - - if ((select) && (ef->selstart == 0)) { - ef->selstart = ef->selend = ef->pos + 1; - } - - switch (type) { - case LINE_BEGIN: - while (ef->pos > 0) { - if (ef->textbuf[ef->pos - 1] == '\n') { - break; - } - if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) { - break; - } - ef->pos--; - } - cursmove = FO_CURS; - break; - - case LINE_END: - while (ef->pos < ef->len) { - if (ef->textbuf[ef->pos] == 0) { - break; - } - if (ef->textbuf[ef->pos] == '\n') { - break; - } - if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) { - break; - } - ef->pos++; - } - cursmove = FO_CURS; - break; - - case PREV_WORD: - { - int pos = ef->pos; - BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); - ef->pos = pos; - cursmove = FO_CURS; - break; - } - - case NEXT_WORD: - { - int pos = ef->pos; - BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); - ef->pos = pos; - cursmove = FO_CURS; - break; - } - - case PREV_CHAR: - ef->pos--; - cursmove = FO_CURS; - break; - - case NEXT_CHAR: - ef->pos++; - cursmove = FO_CURS; - - break; - - case PREV_LINE: - cursmove = FO_CURSUP; - break; - - case NEXT_LINE: - cursmove = FO_CURSDOWN; - break; - - case PREV_PAGE: - cursmove = FO_PAGEUP; - break; - - case NEXT_PAGE: - cursmove = FO_PAGEDOWN; - break; - } - - if (cursmove == -1) { - return OPERATOR_CANCELLED; - } - - if (ef->pos > ef->len) { ef->pos = ef->len; } - else if (ef->pos >= MAXTEXT) { ef->pos = MAXTEXT; } - else if (ef->pos < 0) { ef->pos = 0; } - - /* apply vertical cursor motion to position immediately - * otherwise the selection will lag behind */ - if (FO_CURS_IS_MOTION(cursmove)) { - BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), cursmove); - cursmove = FO_CURS; - } - - if (select == 0) { - if (ef->selstart) { - ef->selstart = ef->selend = 0; - BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), FO_SELCHANGE); - } - } - - if (select) { - ef->selend = ef->pos; - } - - text_update_edited(C, obedit, cursmove); - - return OPERATOR_FINISHED; + Depsgraph *depsgraph = CTX_data_depsgraph(C); + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int cursmove = -1; + + if ((select) && (ef->selstart == 0)) { + ef->selstart = ef->selend = ef->pos + 1; + } + + switch (type) { + case LINE_BEGIN: + while (ef->pos > 0) { + if (ef->textbuf[ef->pos - 1] == '\n') { + break; + } + if (ef->textbufinfo[ef->pos - 1].flag & CU_CHINFO_WRAP) { + break; + } + ef->pos--; + } + cursmove = FO_CURS; + break; + + case LINE_END: + while (ef->pos < ef->len) { + if (ef->textbuf[ef->pos] == 0) { + break; + } + if (ef->textbuf[ef->pos] == '\n') { + break; + } + if (ef->textbufinfo[ef->pos].flag & CU_CHINFO_WRAP) { + break; + } + ef->pos++; + } + cursmove = FO_CURS; + break; + + case PREV_WORD: { + int pos = ef->pos; + BLI_str_cursor_step_wchar( + ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); + ef->pos = pos; + cursmove = FO_CURS; + break; + } + + case NEXT_WORD: { + int pos = ef->pos; + BLI_str_cursor_step_wchar( + ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); + ef->pos = pos; + cursmove = FO_CURS; + break; + } + + case PREV_CHAR: + ef->pos--; + cursmove = FO_CURS; + break; + + case NEXT_CHAR: + ef->pos++; + cursmove = FO_CURS; + + break; + + case PREV_LINE: + cursmove = FO_CURSUP; + break; + + case NEXT_LINE: + cursmove = FO_CURSDOWN; + break; + + case PREV_PAGE: + cursmove = FO_PAGEUP; + break; + + case NEXT_PAGE: + cursmove = FO_PAGEDOWN; + break; + } + + if (cursmove == -1) { + return OPERATOR_CANCELLED; + } + + if (ef->pos > ef->len) { + ef->pos = ef->len; + } + else if (ef->pos >= MAXTEXT) { + ef->pos = MAXTEXT; + } + else if (ef->pos < 0) { + ef->pos = 0; + } + + /* apply vertical cursor motion to position immediately + * otherwise the selection will lag behind */ + if (FO_CURS_IS_MOTION(cursmove)) { + BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), cursmove); + cursmove = FO_CURS; + } + + if (select == 0) { + if (ef->selstart) { + ef->selstart = ef->selend = 0; + BKE_vfont_to_curve(DEG_get_evaluated_object(depsgraph, obedit), FO_SELCHANGE); + } + } + + if (select) { + ef->selend = ef->pos; + } + + text_update_edited(C, obedit, cursmove); + + return OPERATOR_FINISHED; } static int move_exec(bContext *C, wmOperator *op) { - int type = RNA_enum_get(op->ptr, "type"); + int type = RNA_enum_get(op->ptr, "type"); - return move_cursor(C, type, false); + return move_cursor(C, type, false); } void FONT_OT_move(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Cursor"; - ot->description = "Move cursor to position type"; - ot->idname = "FONT_OT_move"; + /* identifiers */ + ot->name = "Move Cursor"; + ot->description = "Move cursor to position type"; + ot->idname = "FONT_OT_move"; - /* api callbacks */ - ot->exec = move_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = move_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); + /* properties */ + RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to"); } /******************* move select operator ********************/ static int move_select_exec(bContext *C, wmOperator *op) { - int type = RNA_enum_get(op->ptr, "type"); + int type = RNA_enum_get(op->ptr, "type"); - return move_cursor(C, type, true); + return move_cursor(C, type, true); } void FONT_OT_move_select(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Move Select"; - ot->description = "Move the cursor while selecting"; - ot->idname = "FONT_OT_move_select"; - - /* api callbacks */ - ot->exec = move_select_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to, to make a selection"); + /* identifiers */ + ot->name = "Move Select"; + ot->description = "Move the cursor while selecting"; + ot->idname = "FONT_OT_move_select"; + + /* api callbacks */ + ot->exec = move_select_exec; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, + "type", + move_type_items, + LINE_BEGIN, + "Type", + "Where to move cursor to, to make a selection"); } /************************* change spacing **********************/ static int change_spacing_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int kern, delta = RNA_int_get(op->ptr, "delta"); + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int kern, delta = RNA_int_get(op->ptr, "delta"); - kern = ef->textbufinfo[ef->pos - 1].kern; - kern += delta; - CLAMP(kern, -20, 20); + kern = ef->textbufinfo[ef->pos - 1].kern; + kern += delta; + CLAMP(kern, -20, 20); - if (ef->textbufinfo[ef->pos - 1].kern == kern) { - return OPERATOR_CANCELLED; - } + if (ef->textbufinfo[ef->pos - 1].kern == kern) { + return OPERATOR_CANCELLED; + } - ef->textbufinfo[ef->pos - 1].kern = kern; + ef->textbufinfo[ef->pos - 1].kern = kern; - text_update_edited(C, obedit, FO_EDIT); + text_update_edited(C, obedit, FO_EDIT); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_change_spacing(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Change Spacing"; - ot->description = "Change font spacing"; - ot->idname = "FONT_OT_change_spacing"; - - /* api callbacks */ - ot->exec = change_spacing_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_int(ot->srna, "delta", 1, -20, 20, "Delta", "Amount to decrease or increase character spacing with", -20, 20); + /* identifiers */ + ot->name = "Change Spacing"; + ot->description = "Change font spacing"; + ot->idname = "FONT_OT_change_spacing"; + + /* api callbacks */ + ot->exec = change_spacing_exec; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, + "delta", + 1, + -20, + 20, + "Delta", + "Amount to decrease or increase character spacing with", + -20, + 20); } /************************* change character **********************/ static int change_character_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int character, delta = RNA_int_get(op->ptr, "delta"); + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int character, delta = RNA_int_get(op->ptr, "delta"); - if (ef->pos <= 0) { - return OPERATOR_CANCELLED; - } + if (ef->pos <= 0) { + return OPERATOR_CANCELLED; + } - character = ef->textbuf[ef->pos - 1]; - character += delta; - CLAMP(character, 0, 255); + character = ef->textbuf[ef->pos - 1]; + character += delta; + CLAMP(character, 0, 255); - if (character == ef->textbuf[ef->pos - 1]) { - return OPERATOR_CANCELLED; - } + if (character == ef->textbuf[ef->pos - 1]) { + return OPERATOR_CANCELLED; + } - ef->textbuf[ef->pos - 1] = character; + ef->textbuf[ef->pos - 1] = character; - text_update_edited(C, obedit, FO_EDIT); + text_update_edited(C, obedit, FO_EDIT); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_change_character(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Change Character"; - ot->description = "Change font character code"; - ot->idname = "FONT_OT_change_character"; - - /* api callbacks */ - ot->exec = change_character_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_int(ot->srna, "delta", 1, -255, 255, "Delta", "Number to increase or decrease character code with", -255, 255); + /* identifiers */ + ot->name = "Change Character"; + ot->description = "Change font character code"; + ot->idname = "FONT_OT_change_character"; + + /* api callbacks */ + ot->exec = change_character_exec; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_int(ot->srna, + "delta", + 1, + -255, + 255, + "Delta", + "Number to increase or decrease character code with", + -255, + 255); } /******************* line break operator ********************/ static int line_break_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; - insert_into_textbuf(obedit, '\n'); + insert_into_textbuf(obedit, '\n'); - ef->selstart = ef->selend = 0; + ef->selstart = ef->selend = 0; - text_update_edited(C, obedit, FO_EDIT); + text_update_edited(C, obedit, FO_EDIT); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_line_break(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Line Break"; - ot->description = "Insert line break at cursor position"; - ot->idname = "FONT_OT_line_break"; + /* identifiers */ + ot->name = "Line Break"; + ot->description = "Insert line break at cursor position"; + ot->idname = "FONT_OT_line_break"; - /* api callbacks */ - ot->exec = line_break_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = line_break_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /******************* delete operator **********************/ static const EnumPropertyItem delete_type_items[] = { - {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, - {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, - {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, - {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, - {DEL_SELECTION, "SELECTION", 0, "Selection", ""}, - {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""}, - {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""}, - {0, NULL, 0, NULL, NULL}, + {DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""}, + {DEL_PREV_CHAR, "PREVIOUS_CHARACTER", 0, "Previous Character", ""}, + {DEL_NEXT_WORD, "NEXT_WORD", 0, "Next Word", ""}, + {DEL_PREV_WORD, "PREVIOUS_WORD", 0, "Previous Word", ""}, + {DEL_SELECTION, "SELECTION", 0, "Selection", ""}, + {DEL_NEXT_SEL, "NEXT_OR_SELECTION", 0, "Next or Selection", ""}, + {DEL_PREV_SEL, "PREVIOUS_OR_SELECTION", 0, "Previous or Selection", ""}, + {0, NULL, 0, NULL, NULL}, }; static int delete_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int selstart, selend, type = RNA_enum_get(op->ptr, "type"); - int range[2] = {0, 0}; - bool has_select = false; - - if (ef->len == 0) { - return OPERATOR_CANCELLED; - } - - if (BKE_vfont_select_get(obedit, &selstart, &selend)) { - if (type == DEL_NEXT_SEL) { - type = DEL_SELECTION; - } - else if (type == DEL_PREV_SEL) { - type = DEL_SELECTION; - } - has_select = true; - } - else { - if (type == DEL_NEXT_SEL) { - type = DEL_NEXT_CHAR; - } - else if (type == DEL_PREV_SEL) { - type = DEL_PREV_CHAR; - } - } - - switch (type) { - case DEL_SELECTION: - if (!kill_selection(obedit, 0)) { - return OPERATOR_CANCELLED; - } - break; - case DEL_PREV_CHAR: - if (ef->pos <= 0) { - return OPERATOR_CANCELLED; - } - - range[0] = ef->pos - 1; - range[1] = ef->pos; - - ef->pos--; - break; - case DEL_NEXT_CHAR: - if (ef->pos >= ef->len) { - return OPERATOR_CANCELLED; - } - - range[0] = ef->pos; - range[1] = ef->pos + 1; - break; - case DEL_NEXT_WORD: - { - int pos = ef->pos; - BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); - range[0] = ef->pos; - range[1] = pos; - break; - } - - case DEL_PREV_WORD: - { - int pos = ef->pos; - BLI_str_cursor_step_wchar(ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); - range[0] = pos; - range[1] = ef->pos; - ef->pos = pos; - break; - } - default: - return OPERATOR_CANCELLED; - } - - if (range[0] != range[1]) { - BLI_assert(range[0] < range[1]); - int len_remove = range[1] - range[0]; - int len_tail = ef->len - range[1]; - if (has_select) { - for (int i = 0; i < 2; i++) { - int *sel = i ? &ef->selend : &ef->selstart; - if (*sel <= range[0]) { - /* pass */ - } - else if (*sel >= range[1]) { - *sel -= len_remove; - } - else if (*sel < range[1]) { - /* pass */ - *sel = range[0]; - } - } - } - - memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail); - memmove(&ef->textbufinfo[range[0]], &ef->textbufinfo[range[1]], sizeof(*ef->textbufinfo) * len_tail); - - ef->len -= len_remove; - ef->textbuf[ef->len] = '\0'; - - BKE_vfont_select_clamp(obedit); - } - - text_update_edited(C, obedit, FO_EDIT); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int selstart, selend, type = RNA_enum_get(op->ptr, "type"); + int range[2] = {0, 0}; + bool has_select = false; + + if (ef->len == 0) { + return OPERATOR_CANCELLED; + } + + if (BKE_vfont_select_get(obedit, &selstart, &selend)) { + if (type == DEL_NEXT_SEL) { + type = DEL_SELECTION; + } + else if (type == DEL_PREV_SEL) { + type = DEL_SELECTION; + } + has_select = true; + } + else { + if (type == DEL_NEXT_SEL) { + type = DEL_NEXT_CHAR; + } + else if (type == DEL_PREV_SEL) { + type = DEL_PREV_CHAR; + } + } + + switch (type) { + case DEL_SELECTION: + if (!kill_selection(obedit, 0)) { + return OPERATOR_CANCELLED; + } + break; + case DEL_PREV_CHAR: + if (ef->pos <= 0) { + return OPERATOR_CANCELLED; + } + + range[0] = ef->pos - 1; + range[1] = ef->pos; + + ef->pos--; + break; + case DEL_NEXT_CHAR: + if (ef->pos >= ef->len) { + return OPERATOR_CANCELLED; + } + + range[0] = ef->pos; + range[1] = ef->pos + 1; + break; + case DEL_NEXT_WORD: { + int pos = ef->pos; + BLI_str_cursor_step_wchar( + ef->textbuf, ef->len, &pos, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM, true); + range[0] = ef->pos; + range[1] = pos; + break; + } + + case DEL_PREV_WORD: { + int pos = ef->pos; + BLI_str_cursor_step_wchar( + ef->textbuf, ef->len, &pos, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM, true); + range[0] = pos; + range[1] = ef->pos; + ef->pos = pos; + break; + } + default: + return OPERATOR_CANCELLED; + } + + if (range[0] != range[1]) { + BLI_assert(range[0] < range[1]); + int len_remove = range[1] - range[0]; + int len_tail = ef->len - range[1]; + if (has_select) { + for (int i = 0; i < 2; i++) { + int *sel = i ? &ef->selend : &ef->selstart; + if (*sel <= range[0]) { + /* pass */ + } + else if (*sel >= range[1]) { + *sel -= len_remove; + } + else if (*sel < range[1]) { + /* pass */ + *sel = range[0]; + } + } + } + + memmove(&ef->textbuf[range[0]], &ef->textbuf[range[1]], sizeof(*ef->textbuf) * len_tail); + memmove(&ef->textbufinfo[range[0]], + &ef->textbufinfo[range[1]], + sizeof(*ef->textbufinfo) * len_tail); + + ef->len -= len_remove; + ef->textbuf[ef->len] = '\0'; + + BKE_vfont_select_clamp(obedit); + } + + text_update_edited(C, obedit, FO_EDIT); + + return OPERATOR_FINISHED; } void FONT_OT_delete(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Delete"; - ot->description = "Delete text by cursor position"; - ot->idname = "FONT_OT_delete"; - - /* api callbacks */ - ot->exec = delete_exec; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_enum(ot->srna, "type", delete_type_items, DEL_PREV_CHAR, "Type", "Which part of the text to delete"); + /* identifiers */ + ot->name = "Delete"; + ot->description = "Delete text by cursor position"; + ot->idname = "FONT_OT_delete"; + + /* api callbacks */ + ot->exec = delete_exec; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_enum(ot->srna, + "type", + delete_type_items, + DEL_PREV_CHAR, + "Type", + "Which part of the text to delete"); } /*********************** insert text operator *************************/ static int insert_text_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_edit_object(C); - char *inserted_utf8; - wchar_t *inserted_text; - int a, len; + Object *obedit = CTX_data_edit_object(C); + char *inserted_utf8; + wchar_t *inserted_text; + int a, len; - if (!RNA_struct_property_is_set(op->ptr, "text")) { - return OPERATOR_CANCELLED; - } + if (!RNA_struct_property_is_set(op->ptr, "text")) { + return OPERATOR_CANCELLED; + } - inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0); - len = BLI_strlen_utf8(inserted_utf8); + inserted_utf8 = RNA_string_get_alloc(op->ptr, "text", NULL, 0); + len = BLI_strlen_utf8(inserted_utf8); - inserted_text = MEM_callocN(sizeof(wchar_t) * (len + 1), "FONT_insert_text"); - BLI_strncpy_wchar_from_utf8(inserted_text, inserted_utf8, len + 1); + inserted_text = MEM_callocN(sizeof(wchar_t) * (len + 1), "FONT_insert_text"); + BLI_strncpy_wchar_from_utf8(inserted_text, inserted_utf8, len + 1); - for (a = 0; a < len; a++) { - insert_into_textbuf(obedit, inserted_text[a]); - } + for (a = 0; a < len; a++) { + insert_into_textbuf(obedit, inserted_text[a]); + } - MEM_freeN(inserted_text); - MEM_freeN(inserted_utf8); + MEM_freeN(inserted_text); + MEM_freeN(inserted_utf8); - kill_selection(obedit, 1); - text_update_edited(C, obedit, FO_EDIT); + kill_selection(obedit, 1); + text_update_edited(C, obedit, FO_EDIT); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - static int accentcode = 0; - uintptr_t ascii = event->ascii; - int alt = event->alt, shift = event->shift, ctrl = event->ctrl; - int event_type = event->type, event_val = event->val; - wchar_t inserted_text[2] = {0}; - - if (RNA_struct_property_is_set(op->ptr, "text")) { - return insert_text_exec(C, op); - } - - if (RNA_struct_property_is_set(op->ptr, "accent")) { - if (ef->len != 0 && ef->pos > 0) { - accentcode = 1; - } - return OPERATOR_FINISHED; - } - - /* tab should exit editmode, but we allow it to be typed using modifier keys */ - if (event_type == TABKEY) { - if ((alt || ctrl || shift) == 0) { - return OPERATOR_PASS_THROUGH; - } - else { - ascii = 9; - } - } - - if (event_type == BACKSPACEKEY) { - if (alt && ef->len != 0 && ef->pos > 0) { - accentcode = 1; - } - return OPERATOR_PASS_THROUGH; - } - - if (event_val && (ascii || event->utf8_buf[0])) { - /* handle case like TAB (== 9) */ - if ( (ascii > 31 && ascii < 254 && ascii != 127) || - (ascii == 13) || - (ascii == 10) || - (ascii == 8) || - (event->utf8_buf[0])) - { - - if (accentcode) { - if (ef->pos > 0) { - inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii); - ef->textbuf[ef->pos - 1] = inserted_text[0]; - } - accentcode = 0; - } - else if (event->utf8_buf[0]) { - inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf); - ascii = inserted_text[0]; - insert_into_textbuf(obedit, ascii); - accentcode = 0; - } - else if (ascii) { - insert_into_textbuf(obedit, ascii); - accentcode = 0; - } - else { - BLI_assert(0); - } - - kill_selection(obedit, 1); - text_update_edited(C, obedit, FO_EDIT); - } - else { - inserted_text[0] = ascii; - insert_into_textbuf(obedit, ascii); - text_update_edited(C, obedit, FO_EDIT); - } - } - else { - return OPERATOR_PASS_THROUGH; - } - - if (inserted_text[0]) { - /* store as utf8 in RNA string */ - char inserted_utf8[8] = {0}; - - BLI_strncpy_wchar_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8)); - RNA_string_set(op->ptr, "text", inserted_utf8); - } - - /* reset property? */ - if (event_val == 0) { - accentcode = 0; - } - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + static int accentcode = 0; + uintptr_t ascii = event->ascii; + int alt = event->alt, shift = event->shift, ctrl = event->ctrl; + int event_type = event->type, event_val = event->val; + wchar_t inserted_text[2] = {0}; + + if (RNA_struct_property_is_set(op->ptr, "text")) { + return insert_text_exec(C, op); + } + + if (RNA_struct_property_is_set(op->ptr, "accent")) { + if (ef->len != 0 && ef->pos > 0) { + accentcode = 1; + } + return OPERATOR_FINISHED; + } + + /* tab should exit editmode, but we allow it to be typed using modifier keys */ + if (event_type == TABKEY) { + if ((alt || ctrl || shift) == 0) { + return OPERATOR_PASS_THROUGH; + } + else { + ascii = 9; + } + } + + if (event_type == BACKSPACEKEY) { + if (alt && ef->len != 0 && ef->pos > 0) { + accentcode = 1; + } + return OPERATOR_PASS_THROUGH; + } + + if (event_val && (ascii || event->utf8_buf[0])) { + /* handle case like TAB (== 9) */ + if ((ascii > 31 && ascii < 254 && ascii != 127) || (ascii == 13) || (ascii == 10) || + (ascii == 8) || (event->utf8_buf[0])) { + + if (accentcode) { + if (ef->pos > 0) { + inserted_text[0] = findaccent(ef->textbuf[ef->pos - 1], ascii); + ef->textbuf[ef->pos - 1] = inserted_text[0]; + } + accentcode = 0; + } + else if (event->utf8_buf[0]) { + inserted_text[0] = BLI_str_utf8_as_unicode(event->utf8_buf); + ascii = inserted_text[0]; + insert_into_textbuf(obedit, ascii); + accentcode = 0; + } + else if (ascii) { + insert_into_textbuf(obedit, ascii); + accentcode = 0; + } + else { + BLI_assert(0); + } + + kill_selection(obedit, 1); + text_update_edited(C, obedit, FO_EDIT); + } + else { + inserted_text[0] = ascii; + insert_into_textbuf(obedit, ascii); + text_update_edited(C, obedit, FO_EDIT); + } + } + else { + return OPERATOR_PASS_THROUGH; + } + + if (inserted_text[0]) { + /* store as utf8 in RNA string */ + char inserted_utf8[8] = {0}; + + BLI_strncpy_wchar_as_utf8(inserted_utf8, inserted_text, sizeof(inserted_utf8)); + RNA_string_set(op->ptr, "text", inserted_utf8); + } + + /* reset property? */ + if (event_val == 0) { + accentcode = 0; + } + + return OPERATOR_FINISHED; } void FONT_OT_text_insert(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Insert Text"; - ot->description = "Insert text at cursor position"; - ot->idname = "FONT_OT_text_insert"; - - /* api callbacks */ - ot->exec = insert_text_exec; - ot->invoke = insert_text_invoke; - ot->poll = ED_operator_editfont; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position"); - RNA_def_boolean(ot->srna, "accent", 0, "Accent mode", "Next typed character will strike through previous, for special character input"); + /* identifiers */ + ot->name = "Insert Text"; + ot->description = "Insert text at cursor position"; + ot->idname = "FONT_OT_text_insert"; + + /* api callbacks */ + ot->exec = insert_text_exec; + ot->invoke = insert_text_invoke; + ot->poll = ED_operator_editfont; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "text", NULL, 0, "Text", "Text to insert at the cursor position"); + RNA_def_boolean( + ot->srna, + "accent", + 0, + "Accent mode", + "Next typed character will strike through previous, for special character input"); } - /*********************** textbox add operator *************************/ static int textbox_add_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_active_object(C); - Curve *cu = obedit->data; - int i; - - if (cu->totbox < 256) { - for (i = cu->totbox; i > cu->actbox; i--) { - cu->tb[i] = cu->tb[i - 1]; - } - cu->tb[cu->actbox] = cu->tb[cu->actbox - 1]; - cu->actbox++; - cu->totbox++; - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - return OPERATOR_FINISHED; + Object *obedit = CTX_data_active_object(C); + Curve *cu = obedit->data; + int i; + + if (cu->totbox < 256) { + for (i = cu->totbox; i > cu->actbox; i--) { + cu->tb[i] = cu->tb[i - 1]; + } + cu->tb[cu->actbox] = cu->tb[cu->actbox - 1]; + cu->actbox++; + cu->totbox++; + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + return OPERATOR_FINISHED; } void FONT_OT_textbox_add(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Add Textbox"; - ot->description = "Add a new text box"; - ot->idname = "FONT_OT_textbox_add"; - - /* api callbacks */ - ot->exec = textbox_add_exec; - ot->poll = ED_operator_object_active_editable_font; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* identifiers */ + ot->name = "Add Textbox"; + ot->description = "Add a new text box"; + ot->idname = "FONT_OT_textbox_add"; + /* api callbacks */ + ot->exec = textbox_add_exec; + ot->poll = ED_operator_object_active_editable_font; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } - - /*********************** textbox remove operator *************************/ - - static int textbox_remove_exec(bContext *C, wmOperator *op) { - Object *obedit = CTX_data_active_object(C); - Curve *cu = obedit->data; - int i; - int index = RNA_int_get(op->ptr, "index"); - - - if (cu->totbox > 1) { - for (i = index; i < cu->totbox; i++) { - cu->tb[i] = cu->tb[i + 1]; - } - cu->totbox--; - if (cu->actbox >= index) { - cu->actbox--; - } - } - - DEG_id_tag_update(obedit->data, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_active_object(C); + Curve *cu = obedit->data; + int i; + int index = RNA_int_get(op->ptr, "index"); + + if (cu->totbox > 1) { + for (i = index; i < cu->totbox; i++) { + cu->tb[i] = cu->tb[i + 1]; + } + cu->totbox--; + if (cu->actbox >= index) { + cu->actbox--; + } + } + + DEG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; } void FONT_OT_textbox_remove(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Remove Textbox"; - ot->description = "Remove the textbox"; - ot->idname = "FONT_OT_textbox_remove"; + /* identifiers */ + ot->name = "Remove Textbox"; + ot->description = "Remove the textbox"; + ot->idname = "FONT_OT_textbox_remove"; - /* api callbacks */ - ot->exec = textbox_remove_exec; - ot->poll = ED_operator_object_active_editable_font; + /* api callbacks */ + ot->exec = textbox_remove_exec; + ot->poll = ED_operator_object_active_editable_font; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX); + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX); } - - /***************** editmode enter/exit ********************/ void ED_curve_editfont_make(Object *obedit) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - int len_wchar; + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + int len_wchar; - if (ef == NULL) { - ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont"); + if (ef == NULL) { + ef = cu->editfont = MEM_callocN(sizeof(EditFont), "editfont"); - ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf"); - ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo"); - } + ef->textbuf = MEM_callocN((MAXTEXT + 4) * sizeof(wchar_t), "texteditbuf"); + ef->textbufinfo = MEM_callocN((MAXTEXT + 4) * sizeof(CharInfo), "texteditbufinfo"); + } - /* Convert the original text to wchar_t */ - len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4); - BLI_assert(len_wchar == cu->len_wchar); - ef->len = len_wchar; - BLI_assert(ef->len >= 0); + /* Convert the original text to wchar_t */ + len_wchar = BLI_strncpy_wchar_from_utf8(ef->textbuf, cu->str, MAXTEXT + 4); + BLI_assert(len_wchar == cu->len_wchar); + ef->len = len_wchar; + BLI_assert(ef->len >= 0); - memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo)); + memcpy(ef->textbufinfo, cu->strinfo, ef->len * sizeof(CharInfo)); - if (ef->pos > ef->len) { - ef->pos = ef->len; - } + if (ef->pos > ef->len) { + ef->pos = ef->len; + } - cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; + cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0]; - /* Other vars */ - ef->pos = cu->pos; - ef->selstart = cu->selstart; - ef->selend = cu->selend; + /* Other vars */ + ef->pos = cu->pos; + ef->selstart = cu->selstart; + ef->selend = cu->selend; - /* text may have been modified by Python */ - BKE_vfont_select_clamp(obedit); + /* text may have been modified by Python */ + BKE_vfont_select_clamp(obedit); } void ED_curve_editfont_load(Object *obedit) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; - /* Free the old curve string */ - MEM_freeN(cu->str); + /* Free the old curve string */ + MEM_freeN(cu->str); - /* Calculate the actual string length in UTF-8 variable characters */ - cu->len_wchar = ef->len; - cu->len = BLI_wstrlen_utf8(ef->textbuf); + /* Calculate the actual string length in UTF-8 variable characters */ + cu->len_wchar = ef->len; + cu->len = BLI_wstrlen_utf8(ef->textbuf); - /* Alloc memory for UTF-8 variable char length string */ - cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str"); + /* Alloc memory for UTF-8 variable char length string */ + cu->str = MEM_mallocN(cu->len + sizeof(wchar_t), "str"); - /* Copy the wchar to UTF-8 */ - BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1); + /* Copy the wchar to UTF-8 */ + BLI_strncpy_wchar_as_utf8(cu->str, ef->textbuf, cu->len + 1); - if (cu->strinfo) { - MEM_freeN(cu->strinfo); - } - cu->strinfo = MEM_callocN((cu->len_wchar + 4) * sizeof(CharInfo), "texteditinfo"); - memcpy(cu->strinfo, ef->textbufinfo, cu->len_wchar * sizeof(CharInfo)); + if (cu->strinfo) { + MEM_freeN(cu->strinfo); + } + cu->strinfo = MEM_callocN((cu->len_wchar + 4) * sizeof(CharInfo), "texteditinfo"); + memcpy(cu->strinfo, ef->textbufinfo, cu->len_wchar * sizeof(CharInfo)); - /* Other vars */ - cu->pos = ef->pos; - cu->selstart = ef->selstart; - cu->selend = ef->selend; + /* Other vars */ + cu->pos = ef->pos; + cu->selstart = ef->selstart; + cu->selend = ef->selend; } void ED_curve_editfont_free(Object *obedit) { - BKE_curve_editfont_free((Curve *)obedit->data); + BKE_curve_editfont_free((Curve *)obedit->data); } /********************** set case operator *********************/ static const EnumPropertyItem case_items[] = { - {CASE_LOWER, "LOWER", 0, "Lower", ""}, - {CASE_UPPER, "UPPER", 0, "Upper", ""}, - {0, NULL, 0, NULL, NULL}, + {CASE_LOWER, "LOWER", 0, "Lower", ""}, + {CASE_UPPER, "UPPER", 0, "Upper", ""}, + {0, NULL, 0, NULL, NULL}, }; static int set_case(bContext *C, int ccase) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - wchar_t *str; - int len; - int selstart, selend; - - if (BKE_vfont_select_get(obedit, &selstart, &selend)) { - len = (selend - selstart) + 1; - str = &ef->textbuf[selstart]; - while (len) { - if (*str >= 'a' && *str <= 'z') { - *str -= 32; - } - len--; - str++; - } - - if (ccase == CASE_LOWER) { - len = (selend - selstart) + 1; - str = &ef->textbuf[selstart]; - while (len) { - if (*str >= 'A' && *str <= 'Z') { - *str += 32; - } - len--; - str++; - } - } - - text_update_edited(C, obedit, FO_EDIT); - } - - return OPERATOR_FINISHED; + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + wchar_t *str; + int len; + int selstart, selend; + + if (BKE_vfont_select_get(obedit, &selstart, &selend)) { + len = (selend - selstart) + 1; + str = &ef->textbuf[selstart]; + while (len) { + if (*str >= 'a' && *str <= 'z') { + *str -= 32; + } + len--; + str++; + } + + if (ccase == CASE_LOWER) { + len = (selend - selstart) + 1; + str = &ef->textbuf[selstart]; + while (len) { + if (*str >= 'A' && *str <= 'Z') { + *str += 32; + } + len--; + str++; + } + } + + text_update_edited(C, obedit, FO_EDIT); + } + + return OPERATOR_FINISHED; } static int set_case_exec(bContext *C, wmOperator *op) { - return set_case(C, RNA_enum_get(op->ptr, "case")); + return set_case(C, RNA_enum_get(op->ptr, "case")); } void FONT_OT_case_set(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Set Case"; - ot->description = "Set font case"; - ot->idname = "FONT_OT_case_set"; + /* identifiers */ + ot->name = "Set Case"; + ot->description = "Set font case"; + ot->idname = "FONT_OT_case_set"; - /* api callbacks */ - ot->exec = set_case_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = set_case_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* properties */ - RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case"); + /* properties */ + RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case"); } /********************** toggle case operator *********************/ static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op)) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - wchar_t *str; - int len, ccase = CASE_UPPER; - - len = wcslen(ef->textbuf); - str = ef->textbuf; - while (len) { - if (*str >= 'a' && *str <= 'z') { - ccase = CASE_LOWER; - break; - } - - len--; - str++; - } - - return set_case(C, ccase); + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + wchar_t *str; + int len, ccase = CASE_UPPER; + + len = wcslen(ef->textbuf); + str = ef->textbuf; + while (len) { + if (*str >= 'a' && *str <= 'z') { + ccase = CASE_LOWER; + break; + } + + len--; + str++; + } + + return set_case(C, ccase); } void FONT_OT_case_toggle(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Toggle Case"; - ot->description = "Toggle font case"; - ot->idname = "FONT_OT_case_toggle"; + /* identifiers */ + ot->name = "Toggle Case"; + ot->description = "Toggle font case"; + ot->idname = "FONT_OT_case_toggle"; - /* api callbacks */ - ot->exec = toggle_case_exec; - ot->poll = ED_operator_editfont; + /* api callbacks */ + ot->exec = toggle_case_exec; + ot->poll = ED_operator_editfont; - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* **************** Open Font ************** */ static void font_ui_template_init(bContext *C, wmOperator *op) { - PropertyPointerRNA *pprop; + PropertyPointerRNA *pprop; - op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"); - UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop); + op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA"); + UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop); } static void font_open_cancel(bContext *UNUSED(C), wmOperator *op) { - MEM_freeN(op->customdata); - op->customdata = NULL; + MEM_freeN(op->customdata); + op->customdata = NULL; } static int font_open_exec(bContext *C, wmOperator *op) { - struct Main *bmain = CTX_data_main(C); - VFont *font; - PropertyPointerRNA *pprop; - PointerRNA idptr; - char filepath[FILE_MAX]; - RNA_string_get(op->ptr, "filepath", filepath); - - font = BKE_vfont_load(bmain, filepath); - - if (!font) { - if (op->customdata) { - MEM_freeN(op->customdata); - } - return OPERATOR_CANCELLED; - } - - if (!op->customdata) { - font_ui_template_init(C, op); - } - - /* hook into UI */ - pprop = op->customdata; - - if (pprop->prop) { - /* when creating new ID blocks, use is already 1, but RNA - * pointer use also increases user, so this compensates it */ - id_us_min(&font->id); - - RNA_id_pointer_create(&font->id, &idptr); - RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); - RNA_property_update(C, &pprop->ptr, pprop->prop); - } - - MEM_freeN(op->customdata); - - return OPERATOR_FINISHED; + struct Main *bmain = CTX_data_main(C); + VFont *font; + PropertyPointerRNA *pprop; + PointerRNA idptr; + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + font = BKE_vfont_load(bmain, filepath); + + if (!font) { + if (op->customdata) { + MEM_freeN(op->customdata); + } + return OPERATOR_CANCELLED; + } + + if (!op->customdata) { + font_ui_template_init(C, op); + } + + /* hook into UI */ + pprop = op->customdata; + + if (pprop->prop) { + /* when creating new ID blocks, use is already 1, but RNA + * pointer use also increases user, so this compensates it */ + id_us_min(&font->id); + + RNA_id_pointer_create(&font->id, &idptr); + RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr); + RNA_property_update(C, &pprop->ptr, pprop->prop); + } + + MEM_freeN(op->customdata); + + return OPERATOR_FINISHED; } static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { - VFont *vfont = NULL; - const char *path; + VFont *vfont = NULL; + const char *path; - PointerRNA idptr; - PropertyPointerRNA *pprop; + PointerRNA idptr; + PropertyPointerRNA *pprop; - font_ui_template_init(C, op); + font_ui_template_init(C, op); - /* hook into UI */ - pprop = op->customdata; + /* hook into UI */ + pprop = op->customdata; - if (pprop->prop) { - idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop); - vfont = idptr.id.data; - } + if (pprop->prop) { + idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop); + vfont = idptr.id.data; + } - path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir; + path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir; - if (RNA_struct_property_is_set(op->ptr, "filepath")) { - return font_open_exec(C, op); - } + if (RNA_struct_property_is_set(op->ptr, "filepath")) { + return font_open_exec(C, op); + } - RNA_string_set(op->ptr, "filepath", path); - WM_event_add_fileselect(C, op); + RNA_string_set(op->ptr, "filepath", path); + WM_event_add_fileselect(C, op); - return OPERATOR_RUNNING_MODAL; + return OPERATOR_RUNNING_MODAL; } void FONT_OT_open(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Open Font"; - ot->idname = "FONT_OT_open"; - ot->description = "Load a new font from a file"; - - /* api callbacks */ - ot->exec = font_open_exec; - ot->invoke = open_invoke; - ot->cancel = font_open_cancel; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_filesel( - ot, FILE_TYPE_FOLDER | FILE_TYPE_FTFONT, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); + /* identifiers */ + ot->name = "Open Font"; + ot->idname = "FONT_OT_open"; + ot->description = "Load a new font from a file"; + + /* api callbacks */ + ot->exec = font_open_exec; + ot->invoke = open_invoke; + ot->cancel = font_open_cancel; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, + FILE_TYPE_FOLDER | FILE_TYPE_FTFONT, + FILE_SPECIAL, + FILE_OPENFILE, + WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, + FILE_DEFAULTDISPLAY, + FILE_SORT_ALPHA); } /******************* delete operator *********************/ static int font_unlink_exec(bContext *C, wmOperator *op) { - VFont *builtin_font; + VFont *builtin_font; - PointerRNA idptr; - PropertyPointerRNA pprop; + PointerRNA idptr; + PropertyPointerRNA pprop; - UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop); + UI_context_active_but_prop_get_templateID(C, &pprop.ptr, &pprop.prop); - if (pprop.prop == NULL) { - BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink"); - return OPERATOR_CANCELLED; - } + if (pprop.prop == NULL) { + BKE_report(op->reports, RPT_ERROR, "Incorrect context for running font unlink"); + return OPERATOR_CANCELLED; + } - builtin_font = BKE_vfont_builtin_get(); + builtin_font = BKE_vfont_builtin_get(); - RNA_id_pointer_create(&builtin_font->id, &idptr); - RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr); - RNA_property_update(C, &pprop.ptr, pprop.prop); + RNA_id_pointer_create(&builtin_font->id, &idptr); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr); + RNA_property_update(C, &pprop.ptr, pprop.prop); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; } void FONT_OT_unlink(wmOperatorType *ot) { - /* identifiers */ - ot->name = "Unlink"; - ot->idname = "FONT_OT_unlink"; - ot->description = "Unlink active font data-block"; + /* identifiers */ + ot->name = "Unlink"; + ot->idname = "FONT_OT_unlink"; + ot->description = "Unlink active font data-block"; - /* api callbacks */ - ot->exec = font_unlink_exec; + /* api callbacks */ + ot->exec = font_unlink_exec; } /** * TextBox selection */ -bool ED_curve_editfont_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) +bool ED_curve_editfont_select_pick( + bContext *C, const int mval[2], bool extend, bool deselect, bool toggle) { - Object *obedit = CTX_data_edit_object(C); - Curve *cu = obedit->data; - ViewContext vc; - /* bias against the active, in pixels, allows cycling */ - const float active_bias_px = 4.0f; - const float mval_fl[2] = {UNPACK2(mval)}; - const int i_actbox = max_ii(0, cu->actbox - 1); - int i_iter, actbox_select = -1; - const float dist = ED_view3d_select_dist_px(); - float dist_sq_best = dist * dist; - - ED_view3d_viewcontext_init(C, &vc); - - ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); - - /* currently only select active */ - (void)extend; - (void)deselect; - (void)toggle; - - for (i_iter = 0; i_iter < cu->totbox; i_iter++) { - int i = (i_iter + i_actbox) % cu->totbox; - float dist_sq_min; - int j, j_prev; - - float obedit_co[4][3]; - float screen_co[4][2]; - rctf rect; - int project_ok = 0; - - - BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect); - - copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f); - copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f); - copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f); - copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f); - - for (j = 0; j < 4; j++) { - if (ED_view3d_project_float_object(vc.ar, obedit_co[j], screen_co[j], - V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK) - { - project_ok |= (1 << j); - } - } - - dist_sq_min = dist_sq_best; - for (j = 0, j_prev = 3; j < 4; j_prev = j++) { - if ((project_ok & (1 << j)) && - (project_ok & (1 << j_prev))) - { - const float dist_test_sq = dist_squared_to_line_segment_v2(mval_fl, screen_co[j_prev], screen_co[j]); - if (dist_sq_min > dist_test_sq) { - dist_sq_min = dist_test_sq; - } - } - } - - /* bias in pixels to cycle seletion */ - if (i_iter == 0) { - dist_sq_min += active_bias_px; - } - - if (dist_sq_min < dist_sq_best) { - dist_sq_best = dist_sq_min; - actbox_select = i + 1; - } - } - - if (actbox_select != -1) { - if (cu->actbox != actbox_select) { - cu->actbox = actbox_select; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - } - return true; - } - else { - return false; - } + Object *obedit = CTX_data_edit_object(C); + Curve *cu = obedit->data; + ViewContext vc; + /* bias against the active, in pixels, allows cycling */ + const float active_bias_px = 4.0f; + const float mval_fl[2] = {UNPACK2(mval)}; + const int i_actbox = max_ii(0, cu->actbox - 1); + int i_iter, actbox_select = -1; + const float dist = ED_view3d_select_dist_px(); + float dist_sq_best = dist * dist; + + ED_view3d_viewcontext_init(C, &vc); + + ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); + + /* currently only select active */ + (void)extend; + (void)deselect; + (void)toggle; + + for (i_iter = 0; i_iter < cu->totbox; i_iter++) { + int i = (i_iter + i_actbox) % cu->totbox; + float dist_sq_min; + int j, j_prev; + + float obedit_co[4][3]; + float screen_co[4][2]; + rctf rect; + int project_ok = 0; + + BKE_curve_rect_from_textbox(cu, &cu->tb[i], &rect); + + copy_v3_fl3(obedit_co[0], rect.xmin, rect.ymin, 0.0f); + copy_v3_fl3(obedit_co[1], rect.xmin, rect.ymax, 0.0f); + copy_v3_fl3(obedit_co[2], rect.xmax, rect.ymax, 0.0f); + copy_v3_fl3(obedit_co[3], rect.xmax, rect.ymin, 0.0f); + + for (j = 0; j < 4; j++) { + if (ED_view3d_project_float_object( + vc.ar, obedit_co[j], screen_co[j], V3D_PROJ_TEST_CLIP_BB) == V3D_PROJ_RET_OK) { + project_ok |= (1 << j); + } + } + + dist_sq_min = dist_sq_best; + for (j = 0, j_prev = 3; j < 4; j_prev = j++) { + if ((project_ok & (1 << j)) && (project_ok & (1 << j_prev))) { + const float dist_test_sq = dist_squared_to_line_segment_v2( + mval_fl, screen_co[j_prev], screen_co[j]); + if (dist_sq_min > dist_test_sq) { + dist_sq_min = dist_test_sq; + } + } + } + + /* bias in pixels to cycle seletion */ + if (i_iter == 0) { + dist_sq_min += active_bias_px; + } + + if (dist_sq_min < dist_sq_best) { + dist_sq_best = dist_sq_min; + actbox_select = i + 1; + } + } + + if (actbox_select != -1) { + if (cu->actbox != actbox_select) { + cu->actbox = actbox_select; + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + } + return true; + } + else { + return false; + } } diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index 13cbea77ab8..82c19db7a4a 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -27,7 +27,6 @@ #include "BLI_utildefines.h" #include "BLI_array_utils.h" - #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -60,33 +59,32 @@ * \{ */ typedef struct UndoFont { - wchar_t *textbuf; - struct CharInfo *textbufinfo; + wchar_t *textbuf; + struct CharInfo *textbufinfo; - int len, pos; + int len, pos; #ifdef USE_ARRAY_STORE - struct { - BArrayState *textbuf; - BArrayState *textbufinfo; - } store; + struct { + BArrayState *textbuf; + BArrayState *textbufinfo; + } store; #endif - size_t undo_size; + size_t undo_size; } UndoFont; - #ifdef USE_ARRAY_STORE /** \name Array Store * \{ */ static struct { - struct BArrayStore_AtSize bs_stride; - int users; + struct BArrayStore_AtSize bs_stride; + int users; - /* We could have the undo API pass in the previous state, for now store a local list */ - ListBase local_links; + /* We could have the undo API pass in the previous state, for now store a local list */ + ListBase local_links; } uf_arraystore = {{NULL}}; @@ -95,33 +93,33 @@ static struct { * This is done since when reading from an undo state, they must be temporarily expanded. * then discarded afterwards, having this argument avoids having 2x code paths. */ -static void uf_arraystore_compact_ex( - UndoFont *uf, const UndoFont *uf_ref, - bool create) +static void uf_arraystore_compact_ex(UndoFont *uf, const UndoFont *uf_ref, bool create) { -#define STATE_COMPACT(uf, id, len) \ - if ((uf)->id) { \ - BLI_assert(create == ((uf)->store.id == NULL)); \ - if (create) { \ - BArrayState *state_reference = uf_ref ? uf_ref->store.id : NULL; \ - const size_t stride = sizeof(*(uf)->id); \ - BArrayStore *bs = BLI_array_store_at_size_ensure(&uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \ - (uf)->store.id = BLI_array_store_state_add( \ - bs, (uf)->id, (size_t)(len) * stride, state_reference); \ - } \ - /* keep uf->len for validation */ \ - MEM_freeN((uf)->id); \ - (uf)->id = NULL; \ - } ((void)0) - - STATE_COMPACT(uf, textbuf, uf->len + 1); - STATE_COMPACT(uf, textbufinfo, uf->len + 1); - -#undef STATE_COMPACT - - if (create) { - uf_arraystore.users += 1; - } +# define STATE_COMPACT(uf, id, len) \ + if ((uf)->id) { \ + BLI_assert(create == ((uf)->store.id == NULL)); \ + if (create) { \ + BArrayState *state_reference = uf_ref ? uf_ref->store.id : NULL; \ + const size_t stride = sizeof(*(uf)->id); \ + BArrayStore *bs = BLI_array_store_at_size_ensure( \ + &uf_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE); \ + (uf)->store.id = BLI_array_store_state_add( \ + bs, (uf)->id, (size_t)(len)*stride, state_reference); \ + } \ + /* keep uf->len for validation */ \ + MEM_freeN((uf)->id); \ + (uf)->id = NULL; \ + } \ + ((void)0) + + STATE_COMPACT(uf, textbuf, uf->len + 1); + STATE_COMPACT(uf, textbufinfo, uf->len + 1); + +# undef STATE_COMPACT + + if (create) { + uf_arraystore.users += 1; + } } /** @@ -129,35 +127,40 @@ static void uf_arraystore_compact_ex( */ static void uf_arraystore_compact(UndoFont *um, const UndoFont *uf_ref) { - uf_arraystore_compact_ex(um, uf_ref, true); + uf_arraystore_compact_ex(um, uf_ref, true); } static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref) { -#ifdef DEBUG_PRINT - size_t size_expanded_prev, size_compacted_prev; - BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev); -#endif - - uf_arraystore_compact(um, uf_ref); - -#ifdef DEBUG_PRINT - { - size_t size_expanded, size_compacted; - BLI_array_store_at_size_calc_memory_usage(&uf_arraystore.bs_stride, &size_expanded, &size_compacted); - - const double percent_total = size_expanded ? - (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0; - - size_t size_expanded_step = size_expanded - size_expanded_prev; - size_t size_compacted_step = size_compacted - size_compacted_prev; - const double percent_step = size_expanded_step ? - (((double)size_compacted_step / (double)size_expanded_step) * 100.0) : -1.0; - - printf("overall memory use: %.8f%% of expanded size\n", percent_total); - printf("step memory use: %.8f%% of expanded size\n", percent_step); - } -#endif +# ifdef DEBUG_PRINT + size_t size_expanded_prev, size_compacted_prev; + BLI_array_store_at_size_calc_memory_usage( + &uf_arraystore.bs_stride, &size_expanded_prev, &size_compacted_prev); +# endif + + uf_arraystore_compact(um, uf_ref); + +# ifdef DEBUG_PRINT + { + size_t size_expanded, size_compacted; + BLI_array_store_at_size_calc_memory_usage( + &uf_arraystore.bs_stride, &size_expanded, &size_compacted); + + const double percent_total = size_expanded ? + (((double)size_compacted / (double)size_expanded) * 100.0) : + -1.0; + + size_t size_expanded_step = size_expanded - size_expanded_prev; + size_t size_compacted_step = size_compacted - size_compacted_prev; + const double percent_step = size_expanded_step ? + (((double)size_compacted_step / (double)size_expanded_step) * + 100.0) : + -1.0; + + printf("overall memory use: %.8f%% of expanded size\n", percent_total); + printf("step memory use: %.8f%% of expanded size\n", percent_step); + } +# endif } /** @@ -165,156 +168,159 @@ static void uf_arraystore_compact_with_info(UndoFont *um, const UndoFont *uf_ref */ static void uf_arraystore_expand_clear(UndoFont *um) { - uf_arraystore_compact_ex(um, NULL, false); + uf_arraystore_compact_ex(um, NULL, false); } static void uf_arraystore_expand(UndoFont *uf) { -#define STATE_EXPAND(uf, id, len) \ - if ((uf)->store.id) { \ - const size_t stride = sizeof(*(uf)->id); \ - BArrayState *state = (uf)->store.id; \ - size_t state_len; \ - (uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \ - BLI_assert((len) == (state_len / stride)); \ - UNUSED_VARS_NDEBUG(stride); \ - } ((void)0) - - STATE_EXPAND(uf, textbuf, uf->len + 1); - STATE_EXPAND(uf, textbufinfo, uf->len + 1); - -#undef STATE_EXPAND +# define STATE_EXPAND(uf, id, len) \ + if ((uf)->store.id) { \ + const size_t stride = sizeof(*(uf)->id); \ + BArrayState *state = (uf)->store.id; \ + size_t state_len; \ + (uf)->id = BLI_array_store_state_data_get_alloc(state, &state_len); \ + BLI_assert((len) == (state_len / stride)); \ + UNUSED_VARS_NDEBUG(stride); \ + } \ + ((void)0) + + STATE_EXPAND(uf, textbuf, uf->len + 1); + STATE_EXPAND(uf, textbufinfo, uf->len + 1); + +# undef STATE_EXPAND } static void uf_arraystore_free(UndoFont *uf) { -#define STATE_FREE(uf, id) \ - if ((uf)->store.id) { \ - const size_t stride = sizeof(*(uf)->id); \ - BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \ - BArrayState *state = (uf)->store.id; \ - BLI_array_store_state_remove(bs, state); \ - (uf)->store.id = NULL; \ - } ((void)0) +# define STATE_FREE(uf, id) \ + if ((uf)->store.id) { \ + const size_t stride = sizeof(*(uf)->id); \ + BArrayStore *bs = BLI_array_store_at_size_get(&uf_arraystore.bs_stride, stride); \ + BArrayState *state = (uf)->store.id; \ + BLI_array_store_state_remove(bs, state); \ + (uf)->store.id = NULL; \ + } \ + ((void)0) - STATE_FREE(uf, textbuf); - STATE_FREE(uf, textbufinfo); + STATE_FREE(uf, textbuf); + STATE_FREE(uf, textbufinfo); -#undef STATE_FREE +# undef STATE_FREE - uf_arraystore.users -= 1; + uf_arraystore.users -= 1; - BLI_assert(uf_arraystore.users >= 0); + BLI_assert(uf_arraystore.users >= 0); - if (uf_arraystore.users == 0) { -#ifdef DEBUG_PRINT - printf("editfont undo store: freeing all data!\n"); -#endif + if (uf_arraystore.users == 0) { +# ifdef DEBUG_PRINT + printf("editfont undo store: freeing all data!\n"); +# endif - BLI_array_store_at_size_clear(&uf_arraystore.bs_stride); - } + BLI_array_store_at_size_clear(&uf_arraystore.bs_stride); + } } /** \} */ -#endif /* USE_ARRAY_STORE */ +#endif /* USE_ARRAY_STORE */ static void undofont_to_editfont(UndoFont *uf, Curve *cu) { - EditFont *ef = cu->editfont; + EditFont *ef = cu->editfont; - size_t final_size; + size_t final_size; #ifdef USE_ARRAY_STORE - uf_arraystore_expand(uf); + uf_arraystore_expand(uf); #endif - final_size = sizeof(wchar_t) * (uf->len + 1); - memcpy(ef->textbuf, uf->textbuf, final_size); + final_size = sizeof(wchar_t) * (uf->len + 1); + memcpy(ef->textbuf, uf->textbuf, final_size); - final_size = sizeof(CharInfo) * (uf->len + 1); - memcpy(ef->textbufinfo, uf->textbufinfo, final_size); + final_size = sizeof(CharInfo) * (uf->len + 1); + memcpy(ef->textbufinfo, uf->textbufinfo, final_size); - ef->pos = uf->pos; - ef->len = uf->len; + ef->pos = uf->pos; + ef->len = uf->len; - ef->selstart = ef->selend = 0; + ef->selstart = ef->selend = 0; #ifdef USE_ARRAY_STORE - uf_arraystore_expand_clear(uf); + uf_arraystore_expand_clear(uf); #endif } static void *undofont_from_editfont(UndoFont *uf, Curve *cu) { - BLI_assert(BLI_array_is_zeroed(uf, 1)); + BLI_assert(BLI_array_is_zeroed(uf, 1)); - EditFont *ef = cu->editfont; + EditFont *ef = cu->editfont; - size_t mem_used_prev = MEM_get_memory_in_use(); + size_t mem_used_prev = MEM_get_memory_in_use(); - size_t final_size; + size_t final_size; - final_size = sizeof(wchar_t) * (ef->len + 1); - uf->textbuf = MEM_mallocN(final_size, __func__); - memcpy(uf->textbuf, ef->textbuf, final_size); + final_size = sizeof(wchar_t) * (ef->len + 1); + uf->textbuf = MEM_mallocN(final_size, __func__); + memcpy(uf->textbuf, ef->textbuf, final_size); - final_size = sizeof(CharInfo) * (ef->len + 1); - uf->textbufinfo = MEM_mallocN(final_size, __func__); - memcpy(uf->textbufinfo, ef->textbufinfo, final_size); + final_size = sizeof(CharInfo) * (ef->len + 1); + uf->textbufinfo = MEM_mallocN(final_size, __func__); + memcpy(uf->textbufinfo, ef->textbufinfo, final_size); - uf->pos = ef->pos; - uf->len = ef->len; + uf->pos = ef->pos; + uf->len = ef->len; #ifdef USE_ARRAY_STORE - { - const UndoFont *uf_ref = uf_arraystore.local_links.last ? - ((LinkData *)uf_arraystore.local_links.last)->data : NULL; + { + const UndoFont *uf_ref = uf_arraystore.local_links.last ? + ((LinkData *)uf_arraystore.local_links.last)->data : + NULL; - /* add oursrlves */ - BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf)); + /* add oursrlves */ + BLI_addtail(&uf_arraystore.local_links, BLI_genericNodeN(uf)); - uf_arraystore_compact_with_info(uf, uf_ref); - } + uf_arraystore_compact_with_info(uf, uf_ref); + } #endif - size_t mem_used_curr = MEM_get_memory_in_use(); + size_t mem_used_curr = MEM_get_memory_in_use(); - uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont); + uf->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev : sizeof(UndoFont); - return uf; + return uf; } static void undofont_free_data(UndoFont *uf) { #ifdef USE_ARRAY_STORE - { - LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data)); - BLI_remlink(&uf_arraystore.local_links, link); - MEM_freeN(link); - } - uf_arraystore_free(uf); + { + LinkData *link = BLI_findptr(&uf_arraystore.local_links, uf, offsetof(LinkData, data)); + BLI_remlink(&uf_arraystore.local_links, link); + MEM_freeN(link); + } + uf_arraystore_free(uf); #endif - if (uf->textbuf) { - MEM_freeN(uf->textbuf); - } - if (uf->textbufinfo) { - MEM_freeN(uf->textbufinfo); - } + if (uf->textbuf) { + MEM_freeN(uf->textbuf); + } + if (uf->textbufinfo) { + MEM_freeN(uf->textbufinfo); + } } static Object *editfont_object_from_context(bContext *C) { - Object *obedit = CTX_data_edit_object(C); - if (obedit && obedit->type == OB_FONT) { - Curve *cu = obedit->data; - EditFont *ef = cu->editfont; - if (ef != NULL) { - return obedit; - } - } - return NULL; + Object *obedit = CTX_data_edit_object(C); + if (obedit && obedit->type == OB_FONT) { + Curve *cu = obedit->data; + EditFont *ef = cu->editfont; + if (ef != NULL) { + return obedit; + } + } + return NULL; } /** \} */ @@ -324,68 +330,74 @@ static Object *editfont_object_from_context(bContext *C) * \{ */ typedef struct FontUndoStep { - UndoStep step; - /* note: will split out into list for multi-object-editmode. */ - UndoRefID_Object obedit_ref; - UndoFont data; + UndoStep step; + /* note: will split out into list for multi-object-editmode. */ + UndoRefID_Object obedit_ref; + UndoFont data; } FontUndoStep; static bool font_undosys_poll(bContext *C) { - return editfont_object_from_context(C) != NULL; + return editfont_object_from_context(C) != NULL; } -static bool font_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p) +static bool font_undosys_step_encode(struct bContext *C, + struct Main *UNUSED(bmain), + UndoStep *us_p) { - FontUndoStep *us = (FontUndoStep *)us_p; - us->obedit_ref.ptr = editfont_object_from_context(C); - Curve *cu = us->obedit_ref.ptr->data; - undofont_from_editfont(&us->data, cu); - us->step.data_size = us->data.undo_size; - return true; + FontUndoStep *us = (FontUndoStep *)us_p; + us->obedit_ref.ptr = editfont_object_from_context(C); + Curve *cu = us->obedit_ref.ptr->data; + undofont_from_editfont(&us->data, cu); + us->step.data_size = us->data.undo_size; + return true; } -static void font_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int UNUSED(dir)) +static void font_undosys_step_decode(struct bContext *C, + struct Main *UNUSED(bmain), + UndoStep *us_p, + int UNUSED(dir)) { - /* TODO(campbell): undo_system: use low-level API to set mode. */ - ED_object_mode_set(C, OB_MODE_EDIT); - BLI_assert(font_undosys_poll(C)); - - FontUndoStep *us = (FontUndoStep *)us_p; - Object *obedit = us->obedit_ref.ptr; - Curve *cu = obedit->data; - undofont_to_editfont(&us->data, cu); - DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); + /* TODO(campbell): undo_system: use low-level API to set mode. */ + ED_object_mode_set(C, OB_MODE_EDIT); + BLI_assert(font_undosys_poll(C)); + + FontUndoStep *us = (FontUndoStep *)us_p; + Object *obedit = us->obedit_ref.ptr; + Curve *cu = obedit->data; + undofont_to_editfont(&us->data, cu); + DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); } static void font_undosys_step_free(UndoStep *us_p) { - FontUndoStep *us = (FontUndoStep *)us_p; - undofont_free_data(&us->data); + FontUndoStep *us = (FontUndoStep *)us_p; + undofont_free_data(&us->data); } -static void font_undosys_foreach_ID_ref( - UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data) +static void font_undosys_foreach_ID_ref(UndoStep *us_p, + UndoTypeForEachIDRefFn foreach_ID_ref_fn, + void *user_data) { - FontUndoStep *us = (FontUndoStep *)us_p; - foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref)); + FontUndoStep *us = (FontUndoStep *)us_p; + foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref)); } /* Export for ED_undo_sys. */ void ED_font_undosys_type(UndoType *ut) { - ut->name = "Edit Font"; - ut->poll = font_undosys_poll; - ut->step_encode = font_undosys_step_encode; - ut->step_decode = font_undosys_step_decode; - ut->step_free = font_undosys_step_free; + ut->name = "Edit Font"; + ut->poll = font_undosys_poll; + ut->step_encode = font_undosys_step_encode; + ut->step_decode = font_undosys_step_decode; + ut->step_free = font_undosys_step_free; - ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref; + ut->step_foreach_ID_ref = font_undosys_foreach_ID_ref; - ut->use_context = true; + ut->use_context = true; - ut->step_size = sizeof(FontUndoStep); + ut->step_size = sizeof(FontUndoStep); } /** \} */ -- cgit v1.2.3