[Bf-blender-cvs] [563026e] hair_immediate_fixes: Copied high-level operator code from the paint/sculpt system as a basis for brush-stroke operators in hair edit mode.

Lukas Tönne noreply at git.blender.org
Sat Nov 29 16:17:31 CET 2014


Commit: 563026ea6f902067afde98853275c0eedd9c74e8
Author: Lukas Tönne
Date:   Sat Nov 29 16:15:51 2014 +0100
Branches: hair_immediate_fixes
https://developer.blender.org/rB563026ea6f902067afde98853275c0eedd9c74e8

Copied high-level operator code from the paint/sculpt system as a basis
for brush-stroke operators in hair edit mode.

Hopefully this can help avoid some redundant code and ensure consistent
keymapping etc.

===================================================================

M	source/blender/bmesh/intern/bmesh_strands_conv.c
M	source/blender/editors/hair/CMakeLists.txt
M	source/blender/editors/hair/hair_edit.c
M	source/blender/editors/hair/hair_intern.h
M	source/blender/editors/hair/hair_ops.c
M	source/blender/editors/space_view3d/space_view3d.c

===================================================================

diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.c b/source/blender/bmesh/intern/bmesh_strands_conv.c
index 411d5ed..0c3a047 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.c
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.c
@@ -462,11 +462,6 @@ static void make_particle_hair(BMesh *bm, BMVert *root, Object *ob, ParticleSyst
 	pa->lifetime = 100.0f;
 	pa->dietime = 100.0f;
 	
-	pa->fuv[0] = 1.0f;
-	pa->fuv[1] = 0.0f;
-	pa->fuv[2] = 0.0f;
-	pa->fuv[3] = 0.0f;
-	
 	pa->size = psys->part->size;
 	
 	// TODO define other particle stuff ...
diff --git a/source/blender/editors/hair/CMakeLists.txt b/source/blender/editors/hair/CMakeLists.txt
index 9456184..f299b6e 100644
--- a/source/blender/editors/hair/CMakeLists.txt
+++ b/source/blender/editors/hair/CMakeLists.txt
@@ -20,6 +20,7 @@
 
 set(INC
 	../include
+	../sculpt_paint
 	../../blenfont
 	../../blenkernel
 	../../blenlib
diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c
index 611259b..44e2dcf 100644
--- a/source/blender/editors/hair/hair_edit.c
+++ b/source/blender/editors/hair/hair_edit.c
@@ -34,14 +34,18 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_utildefines.h"
+#include "BLI_math.h"
 
+#include "DNA_brush_types.h"
 #include "DNA_object_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
 
+#include "BKE_brush.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
 #include "BKE_edithair.h"
+#include "BKE_paint.h"
 #include "BKE_particle.h"
 
 #include "RNA_access.h"
@@ -51,8 +55,10 @@
 
 #include "ED_object.h"
 #include "ED_physics.h"
+#include "ED_view3d.h"
 
 #include "hair_intern.h"
+#include "paint_intern.h"
 
 static bool has_hair_data(Object *ob)
 {
@@ -99,7 +105,7 @@ static bool apply_hair_edit(Object *ob)
 
 /* ==== edit mode toggle ==== */
 
-static int hair_edit_toggle_poll(bContext *C)
+int hair_edit_toggle_poll(bContext *C)
 {
 	Object *ob = CTX_data_active_object(C);
 
@@ -159,3 +165,269 @@ void HAIR_OT_hair_edit_toggle(wmOperatorType *ot)
 	/* flags */
 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
+
+
+/* ==== brush stroke ==== */
+
+typedef struct HairStrokeOperation {
+	void *custom_paint;
+
+	float prevmouse[2];
+	float startmouse[2];
+	double starttime;
+
+	void *cursor;
+	ViewContext vc;
+} HairStrokeOperation;
+
+static HairStrokeOperation *hair_stroke_init(bContext *C, wmOperator *op, const float mouse[2])
+{
+	Scene *scene = CTX_data_scene(C);
+//	ToolSettings *settings = scene->toolsettings;
+	HairStrokeOperation *pop = MEM_callocN(sizeof(HairStrokeOperation), "PaintOperation"); /* caller frees */
+//	Brush *brush = BKE_paint_brush(&settings->imapaint.paint);
+	int mode = RNA_enum_get(op->ptr, "mode");
+	view3d_set_viewcontext(C, &pop->vc);
+
+	copy_v2_v2(pop->prevmouse, mouse);
+	copy_v2_v2(pop->startmouse, mouse);
+
+	/* initialize from context */
+	if (CTX_wm_region_view3d(C)) {
+		Object *ob = OBACT;
+		
+		pop->custom_paint = paint_proj_new_stroke(C, ob, mouse, mode);
+	}
+
+	if (!pop->custom_paint) {
+		MEM_freeN(pop);
+		return NULL;
+	}
+
+//	if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
+//		pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), image_paint_poll, gradient_draw_line, pop);
+//	}
+	
+//	ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
+//	                         ED_image_undo_restore, ED_image_undo_free, NULL);
+
+	return pop;
+}
+
+/* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
+static void hair_stroke_restore(void)
+{
+	/* XXX TODO */
+//	ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+//	image_undo_restore_runtime(lb);
+//	image_undo_invalidate();
+}
+
+static void hair_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
+{
+	HairStrokeOperation *pop = paint_stroke_mode_data(stroke);
+	Scene *scene = CTX_data_scene(C);
+	ToolSettings *toolsettings = CTX_data_tool_settings(C);
+	UnifiedPaintSettings *ups = &toolsettings->unified_paint_settings;
+	Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+	float alphafac = (brush->flag & BRUSH_ACCUMULATE) ? ups->overlap_factor : 1.0f;
+
+	/* initial brush values. Maybe it should be considered moving these to stroke system */
+	float startalpha = BKE_brush_alpha_get(scene, brush);
+
+	float mouse[2];
+	float pressure;
+	float size;
+	float distance = paint_stroke_distance_get(stroke);
+	int eraser;
+
+	RNA_float_get_array(itemptr, "mouse", mouse);
+	pressure = RNA_float_get(itemptr, "pressure");
+	eraser = RNA_boolean_get(itemptr, "pen_flip");
+	size = max_ff(1.0f, RNA_float_get(itemptr, "size"));
+
+	/* stroking with fill tool only acts on stroke end */
+	if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+		copy_v2_v2(pop->prevmouse, mouse);
+		return;
+	}
+
+	if (BKE_brush_use_alpha_pressure(scene, brush))
+		BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
+	else
+		BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * alphafac));
+
+	if ((brush->flag & BRUSH_DRAG_DOT) || (brush->flag & BRUSH_ANCHORED)) {
+		hair_stroke_restore();
+	}
+
+	paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse, eraser, pressure, distance, size);
+
+	copy_v2_v2(pop->prevmouse, mouse);
+
+	/* restore brush values */
+	BKE_brush_alpha_set(scene, brush, startalpha);
+}
+
+static void hair_stroke_redraw(const bContext *C, struct PaintStroke *stroke, bool final)
+{
+	HairStrokeOperation *pop = paint_stroke_mode_data(stroke);
+
+	paint_proj_redraw(C, pop->custom_paint, final);
+}
+
+static void hair_stroke_done(const bContext *C, struct PaintStroke *stroke)
+{
+	Scene *scene = CTX_data_scene(C);
+	ToolSettings *toolsettings = scene->toolsettings;
+	HairStrokeOperation *pop = paint_stroke_mode_data(stroke);
+	Brush *brush = BKE_paint_brush(&toolsettings->imapaint.paint);
+
+	toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
+
+	if (brush->imagepaint_tool == PAINT_TOOL_FILL) {
+		if (brush->flag & BRUSH_USE_GRADIENT) {
+			paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
+			                  1.0, 0.0, BKE_brush_size_get(scene, brush));
+			/* two redraws, one for GPU update, one for notification */
+			paint_proj_redraw(C, pop->custom_paint, false);
+			paint_proj_redraw(C, pop->custom_paint, true);
+		}
+		else {
+			paint_proj_stroke(C, pop->custom_paint, pop->startmouse, pop->prevmouse, paint_stroke_flipped(stroke),
+			                  1.0, 0.0, BKE_brush_size_get(scene, brush));
+			/* two redraws, one for GPU update, one for notification */
+			paint_proj_redraw(C, pop->custom_paint, false);
+			paint_proj_redraw(C, pop->custom_paint, true);
+		}
+	}
+	paint_proj_stroke_done(pop->custom_paint);
+
+	if (pop->cursor) {
+		WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+	}
+
+	// XXX TODO
+//	image_undo_end();
+
+	/* duplicate warning, see texpaint_init */
+#if 0
+	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);
+#endif
+	MEM_freeN(pop);
+}
+
+static bool hair_stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
+{
+	HairStrokeOperation *pop;
+
+	/* TODO Should avoid putting this here. Instead, last position should be requested
+	 * from stroke system. */
+
+//	if (!(pop = texture_paint_init(C, op, mouse))) {
+		return false;
+//	}
+
+	paint_stroke_set_mode_data(op->customdata, pop);
+
+	return true;
+}
+
+/* ------------------------------------------------------------------------- */
+
+static Brush *hair_stroke_brush(bContext *C)
+{
+	Scene *scene = CTX_data_scene(C);
+	ToolSettings *settings = scene->toolsettings;
+
+	return BKE_paint_brush(&settings->imapaint.paint);
+}
+
+static int hair_stroke_poll(bContext *C)
+{
+	Object *obact;
+
+	if (!hair_stroke_brush(C))
+		return false;
+
+	obact = CTX_data_active_object(C);
+	if ((obact && obact->mode & OB_MODE_HAIR_EDIT) && CTX_wm_region_view3d(C)) {
+		return true;
+	}
+
+	return false;
+}
+
+static int hair_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+	int retval;
+
+	op->customdata = paint_stroke_new(C, op, NULL, hair_stroke_test_start,
+	                                  hair_stroke_update_step,
+	                                  hair_stroke_redraw,
+	                                  hair_stroke_done, event->type);
+
+	if ((retval = op->type->modal(C, op, event)) == OPERATOR_FINISHED) {
+		paint_stroke_data_free(op);
+		return OPERATOR_FINISHED;
+	}
+	/* add modal handler */
+	WM_event_add_modal_handler(C, op);
+
+	OPERATOR_RETVAL_CHECK(retval);
+	BLI_assert(retval == OPERATOR_RUNNING_MODAL);
+
+	return OPERATOR_RUNNING_MODAL;
+}
+
+static int hair_stroke_exec(bContext *C, wmOperator *op)
+{
+	HairStrokeOperation *pop;
+	PropertyRNA *strokeprop;
+	PointerRNA firstpoint;
+	float mouse[2];
+
+	strokeprop = RNA_struct_find_property(op->ptr, "stroke");
+
+	if (!RNA_property_collection_lookup_int(op->ptr, strokeprop, 0, &firstpoint))
+		return OPERATOR_CANCELLED;
+
+	RNA_float_get_array(&firstpoint, "mouse", mouse);
+
+	if (!(pop = hair_stroke_init(C, op, mouse))) {
+		return OPERATOR_CANCELLED;
+	}
+
+	op->customdata = paint_stroke_new(C, op, NULL, hair_stroke_test_start,
+	                                  hair_stroke_update_step,
+	                                  hair_stroke_redraw,
+	                                  hair_stroke_done, 0);
+	/* frees op->customdata */
+	paint_stroke_exec(C, op);
+
+	return OPERATOR_FINISHED;
+}
+
+void HAIR_OT_stroke(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Brush Stroke";
+	ot->idname = "HAIR_OT_stroke";
+	ot->description = "Use a brush tool on hair";
+
+	/* api callbacks */
+	ot->invoke = hair_stroke_invoke;
+	ot->modal = paint_stroke_modal;
+	ot->exec = hair_stroke_exec;
+	ot->poll = hair_stroke_poll;
+	ot->cancel = paint_stroke_cancel;
+
+	/* flags */
+	ot->flag = OPTYPE_BLOCKING;
+
+	paint_stroke_operator_properties(ot);
+}
diff --git a/source/blender/editors/hair/hair_intern.h b/sour

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list