Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/space_image.py21
-rw-r--r--source/blender/blenkernel/BKE_curve.h1
-rw-r--r--source/blender/blenkernel/intern/curve.cpp17
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/io/io_rhino_import.cpp3
-rw-r--r--source/blender/editors/screen/screen_ops.c9
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c19
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c172
-rw-r--r--source/blender/makesdna/DNA_curve_types.h13
-rw-r--r--source/blender/makesrna/intern/rna_curve.c253
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)