diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_image.py | 21 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_curve.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.cpp | 17 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 1 | ||||
-rw-r--r-- | source/blender/editors/include/ED_screen.h | 1 | ||||
-rw-r--r-- | source/blender/editors/io/io_rhino_import.cpp | 3 | ||||
-rw-r--r-- | source/blender/editors/screen/screen_ops.c | 9 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_draw.c | 19 | ||||
-rw-r--r-- | source/blender/editors/uvedit/uvedit_ops.c | 172 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 13 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_curve.c | 253 |
11 files changed, 483 insertions, 27 deletions
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 96fc0ef658e..2828d6d3ba6 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -139,6 +139,13 @@ class IMAGE_MT_select(Menu): layout.operator("uv.select_split") +class IMAGE_MT_trim(Menu): + bl_label = "Trim" + def draw(self, context): + layout = self.layout + layout.operator("uv.nurbsuv_add_square", text="Square Trim", icon='MESH_PLANE') + layout.operator("uv.nurbsuv_add_circle", text="Circular Trim", icon='SURFACE_NCIRCLE') + layout.operator("uv.nurbsuv_delete_trim", text="Delete Trim") class IMAGE_MT_image(Menu): bl_label = "Image" @@ -460,11 +467,14 @@ class MASK_MT_editor_menus(Menu): show_uvedit = sima.show_uvedit show_maskedit = sima.show_maskedit + show_nurbsuv = sima.show_nurbsuv layout.menu("IMAGE_MT_view") if show_uvedit: layout.menu("IMAGE_MT_select") + if show_nurbsuv: + layout.menu("IMAGE_MT_trim") if show_maskedit: layout.menu("MASK_MT_select") @@ -617,6 +627,17 @@ class IMAGE_PT_view_properties(Panel): col.label("Cursor Location:") col.row().prop(sima, "cursor_location", text="") + if show_nurbsuv: + col.separator() + if context.edit_object.data.active_breakpt: + col.label(text="Active Breakpoint:") + col.prop(context.edit_object.data.active_breakpt, "loc", text="Location") + col.prop(context.edit_object.data.active_breakpt, "multiplicity", text="Multiplicity") + if context.edit_object.data.active_trim: + col.label(text="Active Trim:") + sub = col.column() + sub.row().prop(context.edit_object.data.active_trim, "type", expand=True) + if show_uvedit: col.separator() diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 44fe516215f..78ef2345615 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -176,6 +176,7 @@ void BKE_nurbList_flag_set(ListBase *editnurb, short flag); void BKE_nurbTrim_free(struct NurbTrim *nt); struct NurbTrim *BKE_nurbTrim_duplicate(struct NurbTrim *nt); int BKE_nurbTrim_tess(struct NurbTrim *nt, int resolution, float (**uv)[2]); // Returns: # verts in uv +void BKE_nurbTrim_update_data(struct NurbTrim *nt); void BKE_nurb_free(struct Nurb *nu); struct Nurb *BKE_nurb_duplicate(struct Nurb *nu); diff --git a/source/blender/blenkernel/intern/curve.cpp b/source/blender/blenkernel/intern/curve.cpp index 65a0f7a3e77..699a5943495 100644 --- a/source/blender/blenkernel/intern/curve.cpp +++ b/source/blender/blenkernel/intern/curve.cpp @@ -541,8 +541,6 @@ void BKE_nurbs_editKnot_propagate_nurb2ek(struct Nurb *nu) { if (nu->pntsv==1) { ek->num_breaksv = 0; /* This is a curve. There are no breakpoints in v direction. */ ek->breaksv = NULL; - ek->flagv = NULL; - ek->multiplicityv = NULL; } else { int capv = ek->capv = KNOTSV(nu); ek->breaksv = (NurbBreakpt*)MEM_callocN(capv*sizeof(NurbBreakpt), "NURBS_editknot_v"); @@ -746,6 +744,7 @@ Nurb *BKE_nurb_duplicate(Nurb *nu) newnu->trims.first = newnu->trims.last = NULL; for (NurbTrim *nt = (NurbTrim*)nu->trims.first; nt; nt=nt->next) { NurbTrim *dup_nt = BKE_nurbTrim_duplicate(nt); + dup_nt->parent_nurb = newnu; BLI_addtail(&newnu->trims, dup_nt); } BKE_nurbs_cached_UV_mesh_clear(newnu,false); @@ -786,18 +785,22 @@ NurbTrim *BKE_nurbTrim_duplicate(NurbTrim *nt) { NurbTrim *ret = (NurbTrim*)MEM_callocN(sizeof(NurbTrim), "duplicateNurbTrim"); BKE_nurbList_duplicate(&ret->nurb_list, &nt->nurb_list); ret->type = nt->type; + ret->parent_nurb = nt->parent_nurb; return ret; } int BKE_nurbTrim_tess(struct NurbTrim *nt, int resolution, float (**uv_out)[2]) { int tot_tess_pts = 0; for (Nurb* nu = (Nurb*)nt->nurb_list.first; nu; nu=nu->next) { - tot_tess_pts += nu->pntsu * resolution + 1; + int tess_pts = nu->pntsu * resolution + 1; + if (nu->flagu&CU_NURB_ENDPOINT) tess_pts = (nu->pntsu+2-nu->orderu)*resolution; + tot_tess_pts += tess_pts; } float (*uv)[2] = (float(*)[2])MEM_mallocN(sizeof(*uv)*tot_tess_pts, "BKE_nurbTrim_tess"); *uv_out = uv; for (Nurb* nu = (Nurb*)nt->nurb_list.first; nu; nu=nu->next) { int tess_pts = nu->pntsu * resolution + 1; + if (nu->flagu&CU_NURB_ENDPOINT) tess_pts = (nu->pntsu+2-nu->orderu)*resolution; float *U = nu->knotsu; int pntsu = nu->pntsu; BPoint *bp = nu->bp; @@ -817,6 +820,10 @@ int BKE_nurbTrim_tess(struct NurbTrim *nt, int resolution, float (**uv_out)[2]) return tot_tess_pts; } +void BKE_nurbTrim_update_data(struct NurbTrim *nt) { + BKE_nurbs_cached_UV_mesh_clear((Nurb*)nt->parent_nurb, true); +} + void BKE_nurbList_duplicate(ListBase *lb1, ListBase *lb2) { Nurb *nu, *nun; @@ -4248,10 +4255,10 @@ GridMesh *BKE_nurb_compute_trimmed_GridMesh(struct Nurb* nu) { int num_trimpts = BKE_nurbTrim_tess(nt, nu->resol_trim, &trim_uv_pts); int trim_poly = gm->poly_new((float*)trim_uv_pts, num_trimpts*2); switch (nt->type) { - case CU_TRIM_EXTERIOR: + case CU_TRIM_AND: gm->bool_AND(trim_poly); break; - case CU_TRIM_INTERIOR: + case CU_TRIM_SUB: gm->bool_SUB(trim_poly); break; default: diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ae535a9758d..a1ccb83b9e4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3365,6 +3365,7 @@ static void direct_link_nurblist(FileData *fd, ListBase *nurblist) if (nu->flag & CU_TRIMMED) { link_list(fd, &nu->trims); for (nt=nu->trims.first; nt; nt=nt->next) { + nt->parent_nurb = nu; direct_link_nurblist(fd, &nt->nurb_list); } } diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 97c6b3cb251..0967f46ac09 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -172,6 +172,7 @@ int ED_operator_editfont(struct bContext *C); int ED_operator_editlattice(struct bContext *C); int ED_operator_editmball(struct bContext *C); int ED_operator_uvedit(struct bContext *C); +int ED_operator_nurbsuv(struct bContext *C); int ED_operator_uvedit_or_nurbsuv(struct bContext *C); int ED_operator_uvedit_space_image(struct bContext *C); int ED_operator_uvedit_or_nurbsuv_space_image(struct bContext *C); diff --git a/source/blender/editors/io/io_rhino_import.cpp b/source/blender/editors/io/io_rhino_import.cpp index 1976e7e60c8..e7dccfc0795 100644 --- a/source/blender/editors/io/io_rhino_import.cpp +++ b/source/blender/editors/io/io_rhino_import.cpp @@ -755,7 +755,8 @@ static void rhino_import_brep_face(bContext *C, int trim_count = loop->TrimCount(); printf(" loop: 0x%lx\n",long(loop)); NurbTrim *trim = (NurbTrim*)MEM_callocN(sizeof(NurbTrim),"NURBS_imported_trim"); - trim->type = (loop==outer_loop)? CU_TRIM_EXTERIOR : CU_TRIM_INTERIOR; + trim->type = (loop==outer_loop)? CU_TRIM_AND : CU_TRIM_SUB; + trim->parent_nurb = nu; ListBase *nurb_list = &trim->nurb_list; for (int trimnum=0; trimnum<trim_count; trimnum++) { ON_BrepTrim *trim = loop->Trim(trimnum); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index a723b329527..9c17f5d8004 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -440,7 +440,14 @@ int ED_operator_uvedit(bContext *C) { SpaceImage *sima = CTX_wm_space_image(C); Object *obedit = CTX_data_edit_object(C); - return ED_space_image_show_uvedit(sima, obedit) || ED_space_image_show_nurbsuv(sima, obedit); + return ED_space_image_show_uvedit(sima, obedit); +} + +int ED_operator_nurbsuv(bContext *C) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Object *obedit = CTX_data_edit_object(C); + return ED_space_image_show_nurbsuv(sima, obedit); } int ED_operator_uvedit_or_nurbsuv(bContext *C) diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 25dc9a0d3cd..b9a453eb020 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -1094,12 +1094,12 @@ static void draw_nurbuv(const struct bContext *C, ARegion *ar, Object *obedit) /******* (Normalized Coordinates) draw trim control polygon *********/ UI_view2d_view_ortho(&ar->v2d); glShadeModel(GL_SMOOTH); - glBegin(GL_LINE_STRIP); - UI_ThemeColor(TH_WIRE); for (nu=cu->editnurb->nurbs.first; nu; nu=nu->next) { if (!(nu->flag2&CU_SELECTED2)) continue; resoltrim = nu->resol_trim; for (nt=nu->trims.first; nt; nt=nt->next) { + glBegin(GL_LINE_STRIP); + UI_ThemeColor(TH_WIRE); /* if (!(nt->flag & SELECT)) continue; */ for (trimnu=nt->nurb_list.first; trimnu; trimnu=trimnu->next) { j = trimnu->pntsu; @@ -1110,26 +1110,26 @@ static void draw_nurbuv(const struct bContext *C, ARegion *ar, Object *obedit) UI_ThemeColor((trimnu->bp[0].f1&SELECT)? TH_VERTEX_SELECT : TH_VERTEX); glVertex2f(trimnu->bp[0].vec[0], trimnu->bp[0].vec[1]); } + glEnd(); } } - glEnd(); glShadeModel(GL_FLAT); /******* (Normalized Coordinates) draw trim curves *********/ - glBegin(GL_LINE_STRIP); - UI_ThemeColor(TH_WIRE); for (nu=cu->editnurb->nurbs.first; nu; nu=nu->next) { if (!(nu->flag2&CU_SELECTED2)) continue; resoltrim = nu->resol_trim; for (nt=nu->trims.first; nt; nt=nt->next) { + glBegin(GL_LINE_STRIP); + UI_ThemeColor(TH_WIRE); switch (nt->type) { - case CU_TRIM_INTERIOR: + case CU_TRIM_SUB: UI_ThemeColor((nt->flag&SELECT)? TH_NURB_SEL_TRIM_SUB : TH_NURB_TRIM_SUB); break; - case CU_TRIM_EXTERIOR: + case CU_TRIM_AND: UI_ThemeColor((nt->flag&SELECT)? TH_NURB_SEL_TRIM_AND : TH_NURB_TRIM_AND); break; - case CU_TRIM_ISLAND: + case CU_TRIM_ADD: UI_ThemeColor((nt->flag&SELECT)? TH_NURB_SEL_TRIM_ADD : TH_NURB_TRIM_ADD); break; } @@ -1137,10 +1137,11 @@ static void draw_nurbuv(const struct bContext *C, ARegion *ar, Object *obedit) for (i=0; i<j; i++) { glVertex2f(trim_uv_pnts[i][0], trim_uv_pnts[i][1]); } + glVertex2f(trim_uv_pnts[0][0], trim_uv_pnts[0][1]); MEM_freeN(trim_uv_pnts); + glEnd(); } } - glEnd(); /******* (Normalized Coordinates) draw handles for control polygon *********/ glPointSize(3); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 8a6e50027c7..c45c0230474 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1957,7 +1957,6 @@ static int uv_select_all_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); - Curve *cu; Image *ima = CTX_data_edit_image(C); BMEditMesh *em; int action = RNA_enum_get(op->ptr, "action"); @@ -2343,7 +2342,6 @@ static void nurbsuv_invert_selection(bContext *C) { struct Object *editobj; Curve *cu; Nurb *nu, *trimnu; - NurbEditKnot *ek; NurbTrim *nt; int i,numbp; @@ -2483,7 +2481,7 @@ static int nurbsuv_mouse_select(bContext *C, const float co[2], bool extend) { NurbTrim *nt; /* Smallest difference between co[0] and a {u,v} breakpoint / trim */ double u=INFINITY,v=INFINITY,trimcp=INFINITY,trim=INFINITY; - Nurb *nearest_u, *nearest_v, *nearest_trimcp_nu, *nearest_trim_nu, *trimnu; + Nurb *nearest_u, *nearest_v, *nearest_trimcp_nu, *trimnu; NurbTrim *nearest_trimcp_nt=NULL, *nearest_trim_nt=NULL; int nearest_trim_cp,cp,num_bp; /* A trim ctrlpt is defined by: nearest_trim_nt > nearest_trim_nu > nearest_trim_cp */ /* The index of said nearest breakpoint or trim*/ @@ -4080,6 +4078,127 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +static int nurbsuv_add_square(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + SpaceImage *sima = CTX_wm_space_image(C); + ARegion *ar = CTX_wm_region(C); + Curve *cu; + Nurb *nu, *new_trimnu; + NurbTrim *new_nt; + BPoint *bp; + float ls = BLI_rctf_size_x(&ar->v2d.cur)/10; /* length of a side */ + float ll[4]={0,0,0,1}, lr[4]={ls,0,0,1}, ur[4]={ls,ls,0,1}, ul[4]={0,ls,0,1}; + + if (obedit->type != OB_SURF) return OPERATOR_CANCELLED; + if (!sima) return OPERATOR_CANCELLED; + cu = (Curve*)obedit->data; + nu = BKE_curve_nurb_active_get(cu); + + new_trimnu = (Nurb*)MEM_callocN(sizeof(Nurb),"nurbsuv_add_square.Nurb"); + new_trimnu->flag = CU_2D; + new_trimnu->flagu = CU_NURB_ENDPOINT; + new_trimnu->type = CU_NURBS; + new_trimnu->resolu = 1; + new_trimnu->resolv = 1; + new_trimnu->pntsu = 4; + new_trimnu->pntsv = 1; + new_trimnu->orderu = 2; + new_trimnu->orderv = 1; + bp = (BPoint*)MEM_callocN(sizeof(BPoint)*new_trimnu->pntsu,"nurbsuv_add_square.BPoint"); + add_v4_v4v4(bp[0].vec, sima->cursor, ll); + add_v4_v4v4(bp[1].vec, sima->cursor, lr); + add_v4_v4v4(bp[2].vec, sima->cursor, ur); + add_v4_v4v4(bp[3].vec, sima->cursor, ul); + new_trimnu->bp = bp; + BKE_nurb_knot_calc_u(new_trimnu); + + new_nt = (NurbTrim*)MEM_callocN(sizeof(NurbTrim),"nurbsuv_add_square.NurbTrim"); + new_nt->type = CU_TRIM_SUB; + new_nt->parent_nurb = new_trimnu; + BLI_addtail(&new_nt->nurb_list, new_trimnu); + + BLI_addtail(&nu->trims, new_nt); + BKE_nurbs_cached_UV_mesh_clear(nu, true); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, cu); + return OPERATOR_FINISHED; +} + +static int nurbsuv_add_circle(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + SpaceImage *sima = CTX_wm_space_image(C); + Curve *cu; + Nurb *nu, *new_trimnu; + NurbTrim *new_nt; + BPoint *bp; + float ls = 0.1; /* length of a side */ + float lr[2]={ls,0.0}, ur[2]={ls,ls}, ul[2]={0.0,ls}; + + if (obedit->type != OB_SURF) return OPERATOR_CANCELLED; + if (!sima) return OPERATOR_CANCELLED; + cu = (Curve*)obedit->data; + nu = BKE_curve_nurb_active_get(cu); + + new_trimnu = (Nurb*)MEM_callocN(sizeof(Nurb),"nurbsuv_add_circle.Nurb"); + new_trimnu->flag = CU_2D | CU_NURB_ENDPOINT; + new_trimnu->type = CU_NURBS; + new_trimnu->resolu = 1; + new_trimnu->resolv = 1; + new_trimnu->pntsu = 4; + new_trimnu->pntsv = 1; + new_trimnu->orderu = 2; + new_trimnu->orderv = 1; + bp = (BPoint*)MEM_callocN(sizeof(BPoint)*new_trimnu->pntsu,"nurbsuv_add_cicrcle.BPoint"); + copy_v2_v2(bp[0].vec, sima->cursor); + add_v2_v2v2(bp[1].vec, sima->cursor, lr); + add_v2_v2v2(bp[2].vec, sima->cursor, ur); + add_v2_v2v2(bp[3].vec, sima->cursor, ul); + new_trimnu->bp = bp; + BKE_nurb_knot_calc_u(new_trimnu); + + new_nt = (NurbTrim*)MEM_callocN(sizeof(NurbTrim),"nurbsuv_add_circle.NurbTrim"); + new_nt->type = CU_TRIM_SUB; + new_nt->parent_nurb = new_trimnu; + BLI_addtail(&new_nt->nurb_list, new_trimnu); + + BLI_addtail(&nu->trims, new_nt); + BKE_nurbs_cached_UV_mesh_clear(nu, true); + return OPERATOR_FINISHED; +} + +static int nurbsuv_delete_trim(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + SpaceImage *sima = CTX_wm_space_image(C); + Curve *cu; + Nurb *nu; + NurbTrim *nt; + bool finished = false; + + if (obedit->type != OB_SURF) return OPERATOR_CANCELLED; + if (!sima) return OPERATOR_CANCELLED; + cu = (Curve*)obedit->data; + nu = BKE_curve_nurb_active_get(cu); + + while (nu->trims.first && !finished) { + for (nt=nu->trims.first; nt; nt=nt->next) { + if (nt->flag & SELECT) { + BLI_remlink_safe(&nu->trims, nt); + BKE_nurbTrim_free(nt); + break; + } + if (!nt->next) { + finished = true; + break; + } + } + } + + BKE_nurbs_cached_UV_mesh_clear(nu, true); + return OPERATOR_FINISHED; +} + static void UV_OT_select_pinned(wmOperatorType *ot) { /* identifiers */ @@ -4093,6 +4212,45 @@ static void UV_OT_select_pinned(wmOperatorType *ot) ot->poll = ED_operator_uvedit; } +static void UV_OT_nurbsuv_add_square(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Square"; + ot->description = "Add a square (degree 2, i.e. polyline) NURBS 'curve' to the trims of the active NURBS surface"; + ot->idname = "UV_OT_nurbsuv_add_square"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = nurbsuv_add_square; + ot->poll = ED_operator_nurbsuv; +} + +static void UV_OT_nurbsuv_add_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Circle"; + ot->description = "Add a circular NURBS 'curve' to the trims of the active NURBS surface"; + ot->idname = "UV_OT_nurbsuv_add_circle"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = nurbsuv_add_circle; + ot->poll = ED_operator_nurbsuv; +} + +static void UV_OT_nurbsuv_delete_trim(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete Trim"; + ot->description = "Deletes all selected trim curves from the active NURBS surface"; + ot->idname = "UV_OT_nurbsuv_delete_trim"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = nurbsuv_delete_trim; + ot->poll = ED_operator_nurbsuv; +} + /********************** hide operator *********************/ /* check if we are selected or unselected based on 'bool_test' arg, @@ -4672,6 +4830,9 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_select_linked_pick); WM_operatortype_append(UV_OT_select_split); WM_operatortype_append(UV_OT_select_pinned); + WM_operatortype_append(UV_OT_nurbsuv_add_square); + WM_operatortype_append(UV_OT_nurbsuv_add_circle); + WM_operatortype_append(UV_OT_nurbsuv_delete_trim); WM_operatortype_append(UV_OT_select_border); WM_operatortype_append(UV_OT_select_lasso); WM_operatortype_append(UV_OT_circle_select); @@ -4791,6 +4952,11 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf) WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_snap", SKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_menu(keymap, "IMAGE_MT_uvs_select_mode", TABKEY, KM_PRESS, KM_CTRL, 0); + /* NURBS UV Editor */ + WM_keymap_add_menu(keymap, "UV_OT_nurbsuv_add_square", AKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_menu(keymap, "UV_OT_nurbsuv_add_circle", AKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_menu(keymap, "UV_OT_nurbsuv_delete_trim", XKEY, KM_PRESS, 0, 0); + ED_keymap_proportional_cycle(keyconf, keymap); ED_keymap_proportional_editmode(keyconf, keymap, false); diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 0cb45e8bb26..136f0d42c5b 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -135,11 +135,12 @@ typedef struct BPoint { } BPoint; typedef struct NurbTrim { - struct NurbTrim *prev, *next; + struct NurbTrim *next, *prev; ListBase nurb_list; /* A list of Nurb objects that define the trim when concatenated (implicit lines connect discontinuous endpoints) */ - short type; /* CU_TRIM_EXTERIOR (AND), CU_TRIM_INTERIOR (SUB), CU_TRIM_ISLAND (ADD) */ + short type; /* CU_TRIM_AND (AND), CU_TRIM_SUB (SUB), CU_TRIM_ADD (ADD) */ short flag; /* SELECTED */ short pad[2]; + void *parent_nurb; /* DNA doesn't like forward declarations? */ } NurbTrim; /* A breakpoint is a unique knot with multiplicitly stored explicitly rather @@ -165,8 +166,6 @@ typedef struct NurbEditKnot { int capu, capv; /* length of breaks{u,v}, multiplicity{u,v}, and flag{u,v} arrays */ int num_breaksu, num_breaksv; /* the set of breakpoints is the set of unique knots */ NurbBreakpt *breaksu, *breaksv; - int *multiplicityu, *multiplicityv; - int *flagu, *flagv; } NurbEditKnot; /** @@ -379,9 +378,9 @@ enum { #define CU_TYPE (CU_POLY|CU_BEZIER|CU_BSPLINE|CU_CARDINAL|CU_NURBS) /* trim curve type */ -#define CU_TRIM_INTERIOR 1 /* boolean SUB */ -#define CU_TRIM_EXTERIOR 2 /* boolean AND */ -#define CU_TRIM_ISLAND 3 /* boolean ADD */ +#define CU_TRIM_SUB 1 /* boolean SUB */ +#define CU_TRIM_AND 2 /* boolean AND */ +#define CU_TRIM_ADD 3 /* boolean ADD */ /* only for adding */ #define CU_PRIMITIVE 0xF00 diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 2e5792bb8b7..1fffc9758e3 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -48,6 +48,7 @@ #include "BKE_curve.h" #include "ED_curve.h" +#include "ED_types.h" #ifndef RNA_RUNTIME static EnumPropertyItem beztriple_handle_type_items[] = { @@ -750,6 +751,133 @@ static int rna_Curve_is_editmode_get(PointerRNA *ptr) } } +static void rna_NurbTrim_nurb_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + NurbTrim *nt = (NurbTrim*)ptr->id.data; + rna_iterator_listbase_begin(iter, &nt->nurb_list, NULL); +} + +static void rna_NurbTrim_type_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr) +{ + Object *editobj = scene->obedit; + NurbTrim *nt = (NurbTrim *)ptr->data; + BLI_assert(editobj->type == OB_SURF); + DAG_id_tag_update(&editobj->id, OB_RECALC_DATA); + BKE_nurbs_cached_UV_mesh_clear(nt->parent_nurb, true); +} + +static void rna_NurbTrim_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Nurb *nu = (Nurb*)ptr->data; + rna_iterator_listbase_begin(iter, &nu->trims, NULL); +} + +static void rna_editknot_breaksu_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + NurbEditKnot *ek = (NurbEditKnot*)ptr->data; + rna_iterator_array_begin(iter, (void *)ek->breaksu, sizeof(NurbBreakpt), + ek->num_breaksu, 0, NULL); +} + +static void rna_editknot_breaksv_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + NurbEditKnot *ek = (NurbEditKnot*)ptr->data; + rna_iterator_array_begin(iter, (void *)ek->breaksv, sizeof(NurbBreakpt), + ek->num_breaksv, 0, NULL); +} + +static PointerRNA rna_nurbs_active_breakpt_get(PointerRNA *ptr) +{ + Nurb *nu = (Nurb *)ptr->data; + NurbEditKnot *ek = nu->editknot; + int i; + + if (!ek) { + return rna_pointer_inherit_refine(ptr, NULL, NULL); + } + + for (i=0; i<ek->num_breaksu; i++) { + if (ek->breaksu[i].flag&SELECT) { + return rna_pointer_inherit_refine(ptr, &RNA_NurbBreakpt, &ek->breaksu[i]); + } + } + for (i=0; i<ek->num_breaksv; i++) { + if (ek->breaksv[i].flag&SELECT) { + return rna_pointer_inherit_refine(ptr, &RNA_NurbBreakpt, &ek->breaksv[i]); + } + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static PointerRNA rna_nurbs_active_trim_get(PointerRNA *ptr) +{ + Nurb *nu = (Nurb *)ptr->data; + NurbTrim *nt; + + for (nt=nu->trims.first; nt; nt=nt->next) { + if (nt->flag&SELECT) + return rna_pointer_inherit_refine(ptr, &RNA_NurbTrim, nt); + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static PointerRNA rna_curve_active_breakpt_get(PointerRNA *ptr) +{ + Curve *cu = (Curve *)ptr->data; + Nurb *nu; + NurbEditKnot *ek; + int i; + + if (!cu->editnurb || !cu->editnurb->nurbs.first) { + return rna_pointer_inherit_refine(ptr, NULL, NULL); + } + + for (nu=cu->editnurb->nurbs.first; nu; nu=nu->next) { + ek = nu->editknot; + if (!ek) continue; + for (i=0; i<ek->num_breaksu; i++) { + if (ek->breaksu[i].flag&SELECT) { + return rna_pointer_inherit_refine(ptr, &RNA_NurbBreakpt, &ek->breaksu[i]); + } + } + for (i=0; i<ek->num_breaksv; i++) { + if (ek->breaksv[i].flag&SELECT) { + return rna_pointer_inherit_refine(ptr, &RNA_NurbBreakpt, &ek->breaksv[i]); + } + } + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static PointerRNA rna_curve_active_trim_get(PointerRNA *ptr) +{ + Curve *cu = (Curve *)ptr->data; + Nurb *nu; + NurbTrim *nt; + + if (!cu->editnurb || !cu->editnurb->nurbs.first) { + return rna_pointer_inherit_refine(ptr, NULL, NULL); + } + + for (nu=cu->editnurb->nurbs.first; nu; nu=nu->next) { + for (nt=nu->trims.first; nt; nt=nt->next) { + if (nt->flag&SELECT) + return rna_pointer_inherit_refine(ptr, &RNA_NurbTrim, nt); + } + } + + return rna_pointer_inherit_refine(ptr, NULL, NULL); +} + +static void rna_Trim_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + NurbTrim *nt = (NurbTrim*) ptr->data; + BKE_nurbTrim_update_data(nt); +} + #else static void rna_def_bpoint(BlenderRNA *brna) @@ -1579,9 +1707,105 @@ static void rna_def_curve(BlenderRNA *brna) rna_def_animdata_common(srna); + prop = RNA_def_property(srna, "active_breakpt", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "NurbBreakpt"); + RNA_def_property_pointer_funcs(prop, "rna_curve_active_breakpt_get", NULL, NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Breakpoint", "Breakpoint to be edited in the property editor"); + + prop = RNA_def_property(srna, "active_trim", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "NurbTrim"); + RNA_def_property_pointer_funcs(prop, "rna_curve_active_trim_get", NULL, NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Trim", "Trim to be edited in the property editor"); + RNA_api_curve(srna); } +static EnumPropertyItem nurbsuv_trim_types[] = { + {CU_TRIM_SUB, "SUB", 0, "Subtract", "Punch a hole. Interior of trim curve (closed with a line if necessary) subtracts from NURBS surface."}, + {CU_TRIM_AND, "AND", 0, "Mask", "Define the outline of the NURBS surface. Interior of trim curve (closed with line if necessary) is boolean ANDed with the NURBS surface."}, + /* {CU_TRIM_ADD, "ADD", 0, "Island", "Create an island. Add visible NURBS surface back in a region where it was previously SUBed or ANDed away."},*/ + {0, NULL, 0, NULL, NULL} +}; + +static void rna_def_curve_nurb_trim(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "NurbTrim", NULL); + RNA_def_struct_sdna(srna, "NurbTrim"); + RNA_def_struct_ui_text(srna, "NurbTrim", "2D NURBS curve that defines a region in the UV parameter space of a parent 3D NURBS curve to be trimmed, outlined, or added."); + + prop = RNA_def_property(srna, "nurb_list", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_NurbTrim_nurb_list_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "Spline"); + RNA_def_property_ui_text(prop, "TrimCurves", "Collection of 2D NURBS curves that define the trim boundary when connected end-to-end with line segments."); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, nurbsuv_trim_types); + RNA_def_property_ui_text(prop, "Type", "The boolean operation with which the interior of this trim is to be combined with the UV-space tessellation of the surface."); + RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_NurbTrim_type_update"); + + prop = RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_ui_text(prop, "Selected", "Has this trim been selected?"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); +} + +static void rna_def_curve_nurb_breakpt(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "NurbBreakpt", NULL); + RNA_def_struct_sdna(srna, "NurbBreakpt"); + RNA_def_struct_ui_text(srna, "NurbBreakpt", "Breakpoints are unique knots which encode repetition in the 'multiplicity' attribute."); + + prop = RNA_def_property(srna, "selected", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SELECT); + RNA_def_property_ui_text(prop, "Selected", "Has this breakpoint been selected?"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); + + prop = RNA_def_property(srna, "multiplicity", PROP_INT, PROP_UNSIGNED); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* editing this needs knot recalc*/ + RNA_def_property_int_sdna(prop, NULL, "multiplicity"); + RNA_def_property_ui_text(prop, "Multiplicity", "Number of times the knot %loc% is repeated in the knot array."); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); + + prop = RNA_def_property(srna, "loc", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "loc"); + RNA_def_property_ui_text(prop, "KnotLocation", "The floating-point value of this knot in the knot array."); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); +} + +static void rna_def_curve_nurb_editknot(BlenderRNA *brna) { + StructRNA *srna; + PropertyRNA *prop; + srna = RNA_def_struct(brna, "NurbEditKnot", NULL); + RNA_def_struct_sdna(srna, "NurbEditKnot"); + RNA_def_struct_ui_text(srna, "NurbEditKnot", + "Representation of a NURBS surface's knots that uses breakpoints (unique knot values) and multiplicities rather than repeated knots."); + + prop = RNA_def_property(srna, "breaksu", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "breaksu", NULL); + RNA_def_property_struct_type(prop, "NurbBreakpt"); + RNA_def_property_collection_funcs(prop, "rna_editknot_breaksu_begin", "rna_iterator_array_next", + "rna_iterator_array_end", "rna_iterator_array_get", NULL, + NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "BreakpointsU", "Collection of breakpoints (unique knots) in the U direction."); + + prop = RNA_def_property(srna, "breaksv", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "breaksv", NULL); + RNA_def_property_struct_type(prop, "NurbBreakpt"); + RNA_def_property_collection_funcs(prop, "rna_editknot_breaksv_begin", "rna_iterator_array_next", + "rna_iterator_array_end", "rna_iterator_array_get", NULL, + NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "BreakpointsV", "Collection of breakpoints (unique knots) in the U direction."); +} + static void rna_def_curve_nurb(BlenderRNA *brna) { static EnumPropertyItem spline_interpolation_items[] = { @@ -1615,7 +1839,6 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bezier Points", "Collection of points for Bezier curves only"); rna_def_curve_spline_bezpoints(brna, prop); - prop = RNA_def_property(srna, "tilt_interpolation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "tilt_interp"); RNA_def_property_enum_items(prop, spline_interpolation_items); @@ -1750,6 +1973,34 @@ static void rna_def_curve_nurb(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Curve_update_data"); RNA_def_struct_path_func(srna, "rna_Curve_spline_path"); + + rna_def_curve_nurb_breakpt(brna); + rna_def_curve_nurb_editknot(brna); + rna_def_curve_nurb_trim(brna); + + prop = RNA_def_property(srna, "editknot", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "NurbEditKnot"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "EditKnot", + "Representation of knots as (unique value, multiplicity) used during knot editing"); + RNA_def_property_update(prop, NC_IMAGE | ND_DRAW, NULL); + + prop = RNA_def_property(srna, "active_breakpt", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "NurbBreakpt"); + RNA_def_property_pointer_funcs(prop, "rna_nurbs_active_breakpt_get", NULL, NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Breakpoint", "Breakpoint to be edited in the property editor"); + + prop = RNA_def_property(srna, "active_trim", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "NurbTrim"); + RNA_def_property_pointer_funcs(prop, "rna_nurbs_active_trim_get", NULL, NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Active Trim", "Trim to be edited in the property editor"); + + prop = RNA_def_property(srna, "trims", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, "rna_NurbTrim_list_begin", "rna_iterator_listbase_next", "rna_iterator_listbase_end", "rna_iterator_listbase_get", NULL, NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "NurbTrim"); + RNA_def_property_ui_text(prop, "TrimCurves", "Collection of trims (regions to boolean AND/OR/etc with the visible UV region of a NURBS curve)."); } void RNA_def_curve(BlenderRNA *brna) |