[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