[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29539] branches/soc-2010-kwk/source/ blender/editors/sculpt_paint: Attempt: Stroke system in texture painting

Konrad Kleine konrad at konradwilhelm.de
Fri Jun 18 10:04:17 CEST 2010


Revision: 29539
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29539
Author:   kwk
Date:     2010-06-18 10:04:15 +0200 (Fri, 18 Jun 2010)

Log Message:
-----------
Attempt: Stroke system in texture painting

This is my first step to integrate the new stroke system into the texture painting. The results are far away from perfect but I'm happy that the code compiles again and you can at least paint textures in 3D space AND in 2D space (inside UV/Texture Editor). It appears like there is a zoom dependend offset between the mouse pointer and the paint stroke. The round brush pointer follows the mouse pointer correctly in 3D View.

Switching spaces (e.g. from 3D to 2D) somehow breaks the functionality.

Painting sometimes is slower than before my changes, probably because of too many RNA queries?

The stroke system didn't distinguish between different spaces and only works with 3D Space. Now I added a stub condition to check if one is painting in 2D mode. There need to be made some changes to stroke->mats maybe but for now I couldn't find a place in paint_stroke.c where these matrices are actually used. This problem requires more research.

Modified Paths:
--------------
    branches/soc-2010-kwk/source/blender/editors/sculpt_paint/paint_image.c
    branches/soc-2010-kwk/source/blender/editors/sculpt_paint/paint_stroke.c

Modified: branches/soc-2010-kwk/source/blender/editors/sculpt_paint/paint_image.c
===================================================================
--- branches/soc-2010-kwk/source/blender/editors/sculpt_paint/paint_image.c	2010-06-18 05:18:46 UTC (rev 29538)
+++ branches/soc-2010-kwk/source/blender/editors/sculpt_paint/paint_image.c	2010-06-18 08:04:15 UTC (rev 29539)
@@ -4514,7 +4514,7 @@
 
 	int first;
 	int prevmouse[2];
-	float prev_pressure; /* need this since we dont get tablet events for pressure change */
+//	float prev_pressure; /* need this since we dont get tablet events for pressure change */
 	int brush_size_orig;
 	double starttime;
 
@@ -4616,7 +4616,7 @@
 		ps->do_mask_normal = 0; /* no need to do blending */
 }
 
-static int texture_paint_init(bContext *C, wmOperator *op)
+static int texture_paint_init(bContext *C, wmOperator *op, struct PaintStroke *stroke)
 {
 	Scene *scene= CTX_data_scene(C);
 	ToolSettings *settings= scene->toolsettings;
@@ -4624,7 +4624,8 @@
 	PaintOperation *pop= MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */
 
 	pop->first= 1;
-	op->customdata= pop;
+	paint_stroke_set_mode_data(stroke, pop);
+//	op->customdata= pop;
 	
 	/* initialize from context */
 	if(CTX_wm_region_view3d(C)) {
@@ -4700,9 +4701,9 @@
 	return 1;
 }
 
-static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
+static void paint_apply(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
 {
-	PaintOperation *pop= op->customdata;
+	PaintOperation *pop= paint_stroke_mode_data(stroke);
 	float time, mousef[2];
 	float pressure;
 	int mouse[2], redraw;
@@ -4737,11 +4738,110 @@
 	pop->first= 0;
 }
 
-static void paint_exit(bContext *C, wmOperator *op)
+//static void paint_exit(bContext *C, wmOperator *op)
+//{
+//	Scene *scene= CTX_data_scene(C);
+//	ToolSettings *settings= scene->toolsettings;
+//	PaintOperation *pop= op->customdata;
+//
+//	if(pop->timer)
+//		WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
+//
+//	settings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+//	imapaint_canvas_free(&pop->s);
+//	brush_painter_free(pop->painter);
+//
+//	if(pop->mode == PAINT_MODE_3D_PROJECT) {
+//		pop->ps.brush->size = pop->brush_size_orig;
+//		project_paint_end(&pop->ps);
+//	}
+//	
+//	paint_redraw(C, &pop->s, 1);
+//	undo_paint_push_end(UNDO_PAINT_IMAGE);
+//	
+//	if(pop->s.warnmultifile)
+//		BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
+//	if(pop->s.warnpackedfile)
+//		BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
+//
+//	MEM_freeN(pop);
+//}
+
+// XXX: (kwk) comment back in when ready.
+//static int paint_exec(bContext *C, wmOperator *op)
+//{
+//	struct PaintStroke *stroke = op->customdata;
+//	
+//	if(!texture_paint_init(C, op, stroke)) {
+//		MEM_freeN(op->customdata);
+//		return OPERATOR_CANCELLED;
+//	}
+//
+//	RNA_BEGIN(op->ptr, itemptr, "stroke") {
+//		paint_apply(C, stroke, &itemptr);
+//	}
+//	RNA_END;
+//
+//	paint_exit(C, op);
+//
+//	return OPERATOR_FINISHED;
+//}
+
+static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
 {
+	ARegion *ar= CTX_wm_region(C);
+	PaintOperation *pop= paint_stroke_mode_data(stroke);
+	float pressure, mousef[2];
+	double time;
+	int mouse[2];
+	int flip; // 1: Eraser, 0: Normal pen
+
+	// XXX +1 matches brush location better but
+	// still not exact, find out why and fix ..
+//	mouse[0]= event->x - ar->winrct.xmin + 1;
+//	mouse[1]= event->y - ar->winrct.ymin + 1;
+	// XXX: (kwk) for now we use the location from paint stroke but it probably needs to be fixed.
+	RNA_float_get_array(itemptr, "location", mousef);
+	mouse[0] = (int) mousef[0] - ar->winrct.xmin + 1;
+	mouse[1] = (int) mousef[1] - ar->winrct.ymin + 1;
+	
+	time= PIL_check_seconds_timer();
+
+	pop->s.blend= pop->s.brush->blend;
+
+	// XXX: (kwk) cache these values when everything works or get rid of them.
+	flip =  RNA_boolean_get(itemptr, "flip");
+	pressure =  RNA_float_get(itemptr, "pressure");
+	
+	if (flip) {
+		pop->s.blend = IMB_BLEND_ERASE_ALPHA;
+	}
+
+	if(pop->first) {
+		pop->prevmouse[0]= mouse[0];
+		pop->prevmouse[1]= mouse[1];
+		pop->starttime= time;
+
+		/* special exception here for too high pressure values on first touch in
+		   windows for some tablets, then we just skip first touch ..  */
+		if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|BRUSH_SPACING_PRESSURE)) && (pressure >= 0.99f))
+			return;
+	}
+
+	// XXX: (kwk) ok to add time to existing RNA stroke collection from paint_stroke.c?
+	RNA_float_set(itemptr, "time", (float)(time - pop->starttime));
+
+	/* apply */
+//	paint_apply(C, op, &itemptr);
+	paint_apply(C, stroke, itemptr);
+}
+
+// XXX: (kwk) mainly copied from paint_exit(). Needs to be modified!
+static void paint_stroke_done(bContext *C, struct PaintStroke *stroke)
+{
 	Scene *scene= CTX_data_scene(C);
 	ToolSettings *settings= scene->toolsettings;
-	PaintOperation *pop= op->customdata;
+	PaintOperation *pop= paint_stroke_mode_data(stroke);
 
 	if(pop->timer)
 		WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer);
@@ -4755,102 +4855,48 @@
 		project_paint_end(&pop->ps);
 	}
 	
+	// XXX: (kwk) Think about how to get rid of these to lines. Undo/Redo is available via new stroke system (RNA) now.
 	paint_redraw(C, &pop->s, 1);
 	undo_paint_push_end(UNDO_PAINT_IMAGE);
 	
+	// XXX: (kwk) Since there is no longer a ReportList from op->reports we solely print the reports but do not store them for now.
 	if(pop->s.warnmultifile)
-		BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
+		BKE_reportf(NULL, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile);
 	if(pop->s.warnpackedfile)
-		BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
+		BKE_reportf(NULL, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile);
 
 	MEM_freeN(pop);
 }
 
-static int paint_exec(bContext *C, wmOperator *op)
+static int paint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event)
 {
-	if(!texture_paint_init(C, op)) {
-		MEM_freeN(op->customdata);
+	struct PaintStroke *stroke = op->customdata;
+	
+	if(!texture_paint_init(C, op, stroke)) {		
+		MEM_freeN(paint_stroke_mode_data(stroke));
 		return OPERATOR_CANCELLED;
 	}
-
-	RNA_BEGIN(op->ptr, itemptr, "stroke") {
-		paint_apply(C, op, &itemptr);
-	}
-	RNA_END;
-
-	paint_exit(C, op);
-
-	return OPERATOR_FINISHED;
+	
+	return 1;
 }
 
-static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
-{
-	ARegion *ar= CTX_wm_region(C);
-	PaintOperation *pop= op->customdata;
-	wmTabletData *wmtab;
-	PointerRNA itemptr;
-	float pressure, mousef[2];
-	double time;
-	int tablet, mouse[2];
-
-	// XXX +1 matches brush location better but
-	// still not exact, find out why and fix ..
-	mouse[0]= event->x - ar->winrct.xmin + 1;
-	mouse[1]= event->y - ar->winrct.ymin + 1;
-
-	time= PIL_check_seconds_timer();
-
-	tablet= 0;
-	pressure= 0;
-	pop->s.blend= pop->s.brush->blend;
-
-	if(event->custom == EVT_DATA_TABLET) {
-		wmtab= event->customdata;
-
-		tablet= (wmtab->Active != EVT_TABLET_NONE);
-		pressure= wmtab->Pressure;
-		if(wmtab->Active == EVT_TABLET_ERASER)
-			pop->s.blend= IMB_BLEND_ERASE_ALPHA;
-	}
-	else /* otherwise airbrush becomes 1.0 pressure instantly */
-		pressure= pop->prev_pressure ? pop->prev_pressure : 1.0f;
-
-	if(pop->first) {
-		pop->prevmouse[0]= mouse[0];
-		pop->prevmouse[1]= mouse[1];
-		pop->starttime= time;
-
-		/* special exception here for too high pressure values on first touch in
-		   windows for some tablets, then we just skip first touch ..  */
-		if ((pop->s.brush->flag & (BRUSH_ALPHA_PRESSURE|BRUSH_SIZE_PRESSURE|BRUSH_SPACING_PRESSURE)) && tablet && (pressure >= 0.99f))
-			return;
-	}
-
-	/* fill in stroke */
-	RNA_collection_add(op->ptr, "stroke", &itemptr);
-
-	mousef[0] = mouse[0];
-	mousef[1] = mouse[1];
-	RNA_float_set_array(&itemptr, "mouse", mousef);
-	RNA_float_set(&itemptr, "time", (float)(time - pop->starttime));
-	RNA_float_set(&itemptr, "pressure", pressure);
-
-	/* apply */
-	paint_apply(C, op, &itemptr);
-
-	pop->prev_pressure= pressure;
-}
-
 static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
 	PaintOperation *pop;
 
-	if(!texture_paint_init(C, op)) {
-		MEM_freeN(op->customdata);
-		return OPERATOR_CANCELLED;
-	}
+	op->customdata = paint_stroke_new(C,
+									  NULL,
+									  paint_stroke_test_start,
+									  paint_stroke_update_step,
+									  paint_stroke_done);
 	
-	paint_apply_event(C, op, event);
+//	if(!texture_paint_init(C, op)) {
+//		MEM_freeN(op->customdata);
+//		return OPERATOR_CANCELLED;
+//	}
+	
+	// XXX: (kwk) This function is now mostly in paint_update_step() which gets called automatically.
+	//paint_apply_event(C, op, event);
 
 	pop= op->customdata;
 	WM_event_add_modal_handler(C, op);
@@ -4858,38 +4904,21 @@
 	if(pop->s.brush->flag & BRUSH_AIRBRUSH)
 		pop->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
 
+	/* XXX (kwk) copied from vpaint_stroke_invoke() and not sure what it does :( */
+	op->type->modal(C, op, event);
+	
 	return OPERATOR_RUNNING_MODAL;
 }
 
-static int paint_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-	PaintOperation *pop= op->customdata;
+// XXX: (kwk) ot->cancel not needed with new stroke system? like in PAINT_OT_vertex_paint() ?
+//static int paint_cancel(bContext *C, wmOperator *op)
+//{
+//	struct PaintStroke *stroke = op->customdata;
+//	paint_stroke_done(C, stroke); /* XXX (kwk) OK to call directly? */
+//
+//	return OPERATOR_CANCELLED;
+//}
 
-	switch(event->type) {
-		case LEFTMOUSE:
-		case MIDDLEMOUSE:
-		case RIGHTMOUSE: // XXX hardcoded
-			paint_exit(C, op);
-			return OPERATOR_FINISHED;
-		case MOUSEMOVE:
-			paint_apply_event(C, op, event);
-			break;
-		case TIMER:
-			if(event->customdata == pop->timer)
-				paint_apply_event(C, op, event);
-			break;
-	}
-
-	return OPERATOR_RUNNING_MODAL;
-}
-
-static int paint_cancel(bContext *C, wmOperator *op)
-{
-	paint_exit(C, op);
-
-	return OPERATOR_CANCELLED;
-}
-
 void PAINT_OT_image_paint(wmOperatorType *ot)
 {
 	/* identifiers */
@@ -4897,10 +4926,12 @@
 	ot->idname= "PAINT_OT_image_paint";
 	
 	/* api callbacks */
-	ot->exec= paint_exec;
 	ot->invoke= paint_invoke;
-	ot->modal= paint_modal;
-	ot->cancel= paint_cancel;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list