[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59115] branches/soc-2013-paint: Curved strokes for paint modes.

Antony Riakiotakis kalast at gmail.com
Tue Aug 13 19:57:58 CEST 2013


Revision: 59115
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59115
Author:   psy-fi
Date:     2013-08-13 17:57:58 +0000 (Tue, 13 Aug 2013)
Log Message:
-----------
Curved strokes for paint modes.

This commmit introduves a first rough implementation of strokes guided
by screen space curves for artist review. This is somewhat limited
because it does not allow panning (which in 3d viewport wouldn't help
anyway).

To use select Curve under the stroke menu, or press the A key
By dragging, the user can define the first bezier control points. It is
also possible to select and edit the bezier handles independently. To
constrain the handles to follow each other (similar to aligned bezier
curves), use shift before selecting and dragging a handle. To avoid
accidentally adding a curve point, the user needs to explicitly use
Ctrl-Click to add another bezier point. To confirm the stroke use either
enter or spacebar.

TODOs: No pressure simulation or dynamic curve subdivision is done in
this first implementation. Also the draw calls for the bezier could be
optimized better.

Modified Paths:
--------------
    branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py
    branches/soc-2013-paint/release/scripts/startup/bl_ui/space_view3d_toolbar.py
    branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_stroke.c
    branches/soc-2013-paint/source/blender/makesdna/DNA_brush_types.h
    branches/soc-2013-paint/source/blender/makesrna/intern/rna_brush.c

Modified: branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py
===================================================================
--- branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py	2013-08-13 15:27:49 UTC (rev 59114)
+++ branches/soc-2013-paint/release/scripts/startup/bl_ui/space_image.py	2013-08-13 17:57:58 UTC (rev 59115)
@@ -875,7 +875,7 @@
             row.prop(brush, "spacing", text="Spacing")
             row.prop(brush, "use_pressure_spacing", toggle=True, text="")
             
-        if brush.use_line or brush.use_polyline:
+        if brush.use_line or brush.use_polyline or brush.use_curve:
             col.separator()
             row = col.row(align=True)
             row.prop(brush, "spacing", text="Spacing")

Modified: branches/soc-2013-paint/release/scripts/startup/bl_ui/space_view3d_toolbar.py
===================================================================
--- branches/soc-2013-paint/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2013-08-13 15:27:49 UTC (rev 59114)
+++ branches/soc-2013-paint/release/scripts/startup/bl_ui/space_view3d_toolbar.py	2013-08-13 17:57:58 UTC (rev 59115)
@@ -904,7 +904,7 @@
             row.prop(brush, "spacing", text="Spacing")
             row.prop(brush, "use_pressure_spacing", toggle=True, text="")
 
-        if brush.use_line or brush.use_polyline:
+        if brush.use_line or brush.use_polyline or brush.use_curve:
             col.separator()
             row = col.row(align=True)
             row.prop(brush, "spacing", text="Spacing")

Modified: branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_stroke.c
===================================================================
--- branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_stroke.c	2013-08-13 15:27:49 UTC (rev 59114)
+++ branches/soc-2013-paint/source/blender/editors/sculpt_paint/paint_stroke.c	2013-08-13 17:57:58 UTC (rev 59115)
@@ -41,12 +41,14 @@
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_brush_types.h"
+#include "DNA_curve_types.h"
 
 #include "RNA_access.h"
 
 #include "BKE_context.h"
 #include "BKE_paint.h"
 #include "BKE_brush.h"
+#include "BKE_curve.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -72,6 +74,20 @@
 	float pos[2];
 } LinePoint;
 
+typedef struct CurvePoint {
+	struct CurvePoint *next, *prev;
+	BezTriple bez;
+} CurvePoint;
+
+/* stroke->curve_edited */
+enum {
+	CURVE_HANDLE_CENTER = 1,
+	CURVE_HANDLE_PREV = 2,
+	CURVE_HANDLE_NEXT = 3,
+	CURVE_HANDLE_PREV_CONSTRAINED = 4,
+	CURVE_HANDLE_NEXT_CONSTRAINED = 5
+};
+
 typedef struct PaintStroke {
 	void *mode_data;
 	void *stroke_cursor;
@@ -82,7 +98,15 @@
 	bglMats mats;
 	Brush *brush;
 	UnifiedPaintSettings *ups;
+
+	/* used for lines and curves */
 	ListBase line;
+	/* type of curve handle being edited */
+	unsigned char curve_edited;
+	/* curve handle being edited */
+	CurvePoint *edited;
+	/* original handle coordinate */
+	BezTriple curve_orig;
 
 	/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
 	 * to smooth the stroke */
@@ -192,6 +216,129 @@
 	}
 }
 
+BLI_INLINE void draw_rect_line(float *co, float width)
+{
+	float w = width/2.0;
+	glColor4f(0.5, 1.0, 0.5, 0.5);
+	glLineWidth(4.0);
+
+	glBegin(GL_LINE_STRIP);
+	glVertex2f(co[0] + w, co[1] + w);
+	glVertex2f(co[0] - w, co[1] + w);
+	glVertex2f(co[0] - w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] + w);
+	glEnd();
+
+	glColor4f(1.0, 1.0, 1.0, 0.5);
+	glLineWidth(2.0);
+
+	glBegin(GL_LINE_STRIP);
+	glVertex2f(co[0] + w, co[1] + w);
+	glVertex2f(co[0] - w, co[1] + w);
+	glVertex2f(co[0] - w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] + w);
+	glEnd();
+}
+
+BLI_INLINE void draw_tri_line(float *co, float width)
+{
+	float w = width/2.0;
+	glColor4f(1.0, 0.5, 0.5, 0.5);
+	glLineWidth(4.0);
+
+	glBegin(GL_LINE_STRIP);
+	glVertex2f(co[0], co[1] + w);
+	glVertex2f(co[0] - w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] - w);
+	glVertex2f(co[0], co[1] + w);
+	glEnd();
+
+	glColor4f(1.0, 1.0, 1.0, 0.5);
+	glLineWidth(2.0);
+
+	glBegin(GL_LINE_STRIP);
+	glVertex2f(co[0], co[1] + w);
+	glVertex2f(co[0] - w, co[1] - w);
+	glVertex2f(co[0] + w, co[1] - w);
+	glVertex2f(co[0], co[1] + w);
+	glEnd();
+}
+
+BLI_INLINE void draw_bezier_lines(BezTriple *bez)
+{
+	glColor4f(0.0, 0.0, 0.0, 0.5);
+	glLineWidth(4.0);
+	glBegin(GL_LINES);
+	glVertex2fv(&bez->vec[1][0]);
+	glVertex2fv(&bez->vec[0][0]);
+	glVertex2fv(&bez->vec[1][0]);
+	glVertex2fv(&bez->vec[2][0]);
+	glEnd();
+
+	glColor4f(1.0, 1.0, 1.0, 0.5);
+	glLineWidth(2.0);
+	glBegin(GL_LINES);
+	glVertex2fv(&bez->vec[1][0]);
+	glVertex2fv(&bez->vec[0][0]);
+	glVertex2fv(&bez->vec[1][0]);
+	glVertex2fv(&bez->vec[2][0]);
+	glEnd();
+}
+
+#define NUM_SEGMENTS 40
+#define MOUSE_THRESHOLD 6.0
+
+static void paint_draw_curve_cursor(bContext *C, int UNUSED(x), int UNUSED(y), void *customdata)
+{
+	Paint *paint = BKE_paint_get_active_from_context(C);
+	Brush *brush = BKE_paint_brush(paint);
+	PaintStroke *stroke = customdata;
+
+	if (stroke && brush) {
+		CurvePoint *cp = stroke->line.first;
+
+		glEnable(GL_LINE_SMOOTH);
+		glEnable(GL_BLEND);
+
+		/* draw the bezier handles and the curve segment between the current and next point */
+		while (cp->next) {
+			int j;
+			float data[(NUM_SEGMENTS + 1) * 2];
+			/* use color coding to distinguish handles vs curve segments  */
+			draw_bezier_lines(&cp->bez);
+			draw_tri_line(&cp->bez.vec[1][0], 10.0);
+			draw_rect_line(&cp->bez.vec[0][0], 8.0);
+			draw_rect_line(&cp->bez.vec[2][0], 8.0);
+
+			for (j = 0; j < 2; j++)
+				BKE_curve_forward_diff_bezier(cp->bez.vec[1][j],
+							                  cp->bez.vec[2][j],
+							                  cp->next->bez.vec[0][j],
+							                  cp->next->bez.vec[1][j],
+							                  data + j, NUM_SEGMENTS, 2 * sizeof(float));
+
+			glBegin(GL_LINE_STRIP);
+			for (j = 0; j < NUM_SEGMENTS; j++)
+				glVertex2fv(data + j * 2);
+			glEnd();
+			cp = cp->next;
+		}
+
+		/* draw last line segment */
+		draw_bezier_lines(&cp->bez);
+		draw_tri_line(&cp->bez.vec[1][0], 10.0);
+		draw_rect_line(&cp->bez.vec[0][0], 8.0);
+		draw_rect_line(&cp->bez.vec[2][0], 8.0);
+
+		glLineWidth(1.0);
+
+		glDisable(GL_BLEND);
+		glDisable(GL_LINE_SMOOTH);
+	}
+}
+
 /* if this is a tablet event, return tablet pressure and set *pen_flip
  * to 1 if the eraser tool is being used, 0 otherwise */
 static float event_tablet_data(const wmEvent *event, int *pen_flip)
@@ -796,6 +943,50 @@
 	/*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/
 }
 
+/* slightly different version of spacing for line/curve strokes, makes sure the dabs stay on the line path */
+static void paint_line_strokes_spacing(bContext *C, wmOperator *op, PaintStroke *stroke, float spacing, float *length_residue, float old_pos[2], float new_pos[2])
+{
+	UnifiedPaintSettings *ups = stroke->ups;
+
+	float mouse[2], dmouse[2];
+	float length;
+
+	sub_v2_v2v2(dmouse, new_pos, old_pos);
+	copy_v2_v2(stroke->last_mouse_position, old_pos);
+
+	length = normalize_v2(dmouse);
+
+	BLI_assert(length >= 0.0);
+
+	if (length == 0.0)
+		return;
+
+	while (length > 0.0f) {
+		float spacing_final = spacing - *length_residue;
+		length += *length_residue;
+		*length_residue = 0.0;
+
+		if (length >= spacing) {
+			mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
+			mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
+
+			ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing/stroke->zoom_2d);
+
+			stroke->stroke_distance += spacing / stroke->zoom_2d;
+			paint_brush_stroke_add_step(C, op, mouse, 1.0);
+
+			length -= spacing;
+			spacing_final = spacing;
+		}
+		else {
+			break;
+		}
+	}
+
+	*length_residue = length;
+}
+
+
 static void paint_stroke_polyline_end(bContext *C, wmOperator *op, PaintStroke *stroke)
 {
 	Brush *br = stroke->brush;
@@ -818,43 +1009,45 @@
 			paint_brush_stroke_add_step(C, op, p->pos, 1.0);
 
 		for (p = p->next; p; p = p->next) {
-			UnifiedPaintSettings *ups = stroke->ups;
+			paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, p->prev->pos, p->pos);
+		}
+	}
+}
 
-			float mouse[2], dmouse[2];
-			float length;
+static void paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *stroke)
+{
+	Brush *br = stroke->brush;
+	if (stroke->stroke_started && (br->flag & BRUSH_CURVE)) {
+		const Scene *scene = CTX_data_scene(C);
+		const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+		CurvePoint *cp = stroke->line.first;
+		float length_residue = 0.0f;
 
-			sub_v2_v2v2(dmouse, p->pos, p->prev->pos);
-			copy_v2_v2(stroke->last_mouse_position, p->prev->pos);
+		stroke->ups->overlap_factor = paint_stroke_integrate_overlap(br, br->spacing);
 
-			length = normalize_v2(dmouse) + length_residue;
+		if (cp->next)
+			paint_brush_stroke_add_step(C, op, &cp->bez.vec[1][0], 1.0);
 
-			while (length > 0.0f) {
-				float spacing_final = spacing - length_residue;
-				length_residue = 0.0;
+		while (cp->next) {
+			int j;
+			float data[(NUM_SEGMENTS + 1) * 2];
+			for (j = 0; j < 2; j++)
+				BKE_curve_forward_diff_bezier(cp->bez.vec[1][j],
+							                  cp->bez.vec[2][j],
+							                  cp->next->bez.vec[0][j],
+							                  cp->next->bez.vec[1][j],
+							                  data + j, NUM_SEGMENTS, 2 * sizeof(float));
 
-				if (length >= spacing) {
-					mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
-					mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
 
-					ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, spacing/stroke->zoom_2d);
+			for (j = 0; j < NUM_SEGMENTS; j++)
+				paint_line_strokes_spacing(C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
 
-					stroke->stroke_distance += spacing / stroke->zoom_2d;
-					paint_brush_stroke_add_step(C, op, mouse, 1.0);
-
-					length -= spacing;
-					spacing_final = spacing;
-				}
-				else {
-					break;
-				}
-			}
-
-			/* length residue helps to correctly */
-			length_residue = length;
+			cp = cp->next;
 		}
 	}
 }
 
+
 int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
 {
 	Paint *p = BKE_paint_get_active_from_context(C);
@@ -912,6 +1105,20 @@
 				p = MEM_callocN(sizeof(*p), "line_stroke_point");
 				BLI_addtail(&stroke->line, p);
 				copy_v2_v2(p->pos, sample_average.mouse);
+			} else if (br->flag & BRUSH_CURVE) {

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list