Commit: 98b15d9a7cb195ca8afee8ffee39efafd38c460c
Author: Lukas Tönne
Date:   Sat Nov 29 16:15:51 2014 +0100
Branches: strand_editmode
https://developer.blender.org/rB98b15d9a7cb195ca8afee8ffee39efafd38c460c

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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to