Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c13
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h23
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c27
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c330
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c867
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c282
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_stroke.c274
8 files changed, 984 insertions, 833 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 870b66cdbbd..465aa281e25 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -3707,7 +3707,7 @@ static void *do_projectpaint_thread(void *ph_v)
ProjPaintImage *last_projIma= NULL;
ImagePaintPartialRedraw *last_partial_redraw_cell;
- float rgba[4], alpha, dist_nosqrt, dist;
+ float rgba[4], alpha, dist_nosqrt;
float brush_size_sqared;
float falloff;
@@ -3721,7 +3721,6 @@ static void *do_projectpaint_thread(void *ph_v)
float co[2];
float mask = 1.0f; /* airbrush wont use mask */
unsigned short mask_short;
- float size_half = ((float)ps->brush->size) * 0.5f;
LinkNode *smearPixels = NULL;
LinkNode *smearPixels_f = NULL;
@@ -3756,8 +3755,8 @@ static void *do_projectpaint_thread(void *ph_v)
dist_nosqrt = Vec2Lenf_nosqrt(projPixel->projCoSS, pos);
/*if (dist < s->brush->size) {*/ /* correct but uses a sqrtf */
- if (dist_nosqrt < brush_size_sqared && (dist=sqrtf(dist_nosqrt)) < size_half) {
- falloff = brush_curve_strength(ps->brush, dist, size_half);
+ if (dist_nosqrt < brush_size_sqared) {
+ falloff = brush_sample_falloff_noalpha(ps->brush, sqrtf(dist_nosqrt));
if (falloff > 0.0f) {
if (ps->is_texbrush) {
brush_sample_tex(ps->brush, projPixel->projCoSS, rgba);
@@ -4720,7 +4719,7 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event)
tablet= (wmtab->Active != EVT_TABLET_NONE);
pressure= wmtab->Pressure;
if(wmtab->Active == EVT_TABLET_ERASER)
- pop->s.blend= IMB_BLEND_ERASE_ALPHA;
+ pop->s.blend= BRUSH_BLEND_ERASE_ALPHA;
}
else
pressure= 1.0f;
@@ -5175,7 +5174,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT,
NULL, me->totface);
- paint_init(&scene->toolsettings->imapaint.paint, PAINT_CURSOR_TEXTURE_PAINT);
+ paint_init(&scene->toolsettings->imapaint.paint, "Brush");
if(U.glreslimit != 0)
GPU_free_images();
@@ -5184,7 +5183,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
toggle_paint_cursor(C, 1);
}
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index ba1b57a1bef..40423e17fe4 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -29,37 +29,14 @@
#ifndef ED_PAINT_INTERN_H
#define ED_PAINT_INTERN_H
-struct bContext;
struct Scene;
struct Object;
struct Mesh;
-struct PaintStroke;
-struct PointerRNA;
struct ViewContext;
-struct wmEvent;
-struct wmOperator;
struct wmOperatorType;
struct ARegion;
-/* paint_stroke.c */
-typedef int (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-typedef void (*StrokeUpdateStep)(struct bContext *C, struct PaintStroke *stroke, struct PointerRNA *itemptr);
-typedef void (*StrokeDone)(struct bContext *C, struct PaintStroke *stroke);
-
-struct PaintStroke *paint_stroke_new(bContext *C, StrokeTestStart test_start,
- StrokeUpdateStep update_step, StrokeDone done);
-int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event);
-int paint_stroke_exec(struct bContext *C, struct wmOperator *op);
-struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
-void *paint_stroke_mode_data(struct PaintStroke *stroke);
-void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
-int paint_poll(bContext *C);
-void paint_cursor_start(struct bContext *C, int (*poll)(struct bContext *C));
-
/* paint_vertex.c */
-int vertex_paint_mode_poll(bContext *C);
-void clear_vpaint(Scene *scene, int selected);
-
void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_weight_paint_radial_control(struct wmOperatorType *ot);
void PAINT_OT_weight_paint(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index c38b36007e9..63a6591d057 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -77,30 +77,10 @@ void BRUSH_OT_add(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", brush_type_items, OB_MODE_VERTEX_PAINT, "Type", "Which paint mode to create the brush for.");
}
-static int vertex_color_set_exec(bContext *C, wmOperator *op)
+/* Paint operators */
+static int paint_poll(bContext *C)
{
- int selected = RNA_boolean_get(op->ptr, "selected");
- Scene *scene = CTX_data_scene(C);
-
- clear_vpaint(scene, selected);
-
- return OPERATOR_FINISHED;
-}
-
-void PAINT_OT_vertex_color_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Set Vertex Colors";
- ot->idname= "PAINT_OT_vertex_color_set";
-
- /* api callbacks */
- ot->exec= vertex_color_set_exec;
- ot->poll= vertex_paint_mode_poll;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "selected", 0, "Type", "Only color selected faces.");
+ return !!paint_get_active(CTX_data_scene(C));
}
/**************************** registration **********************************/
@@ -129,6 +109,5 @@ void ED_operatortypes_paint(void)
WM_operatortype_append(PAINT_OT_vertex_paint_radial_control);
WM_operatortype_append(PAINT_OT_vertex_paint_toggle);
WM_operatortype_append(PAINT_OT_vertex_paint);
- WM_operatortype_append(PAINT_OT_vertex_color_set);
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
deleted file mode 100644
index bd9ea50e0f8..00000000000
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2009 by Nicholas Bishop
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_brush_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-
-#include "RNA_access.h"
-
-#include "BKE_context.h"
-#include "BKE_paint.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "BLI_arithb.h"
-
-#include "PIL_time.h"
-
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
-#include "ED_screen.h"
-#include "ED_view3d.h"
-
-#include "paint_intern.h"
-
-#include <float.h>
-#include <math.h>
-
-typedef struct PaintStroke {
- void *mode_data;
- void *smooth_stroke_cursor;
- wmTimer *timer;
-
- /* Cached values */
- ViewContext vc;
- bglMats mats;
- Brush *brush;
-
- float last_mouse_position[2];
-
- /* Set whether any stroke step has yet occured
- e.g. in sculpt mode, stroke doesn't start until cursor
- passes over the mesh */
- int stroke_started;
-
- StrokeTestStart test_start;
- StrokeUpdateStep update_step;
- StrokeDone done;
-} PaintStroke;
-
-/*** Cursor ***/
-static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata)
-{
- Brush *brush = paint_brush(paint_get_active(CTX_data_scene(C)));
- PaintStroke *stroke = customdata;
-
- glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
- if(stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
- ARegion *ar = CTX_wm_region(C);
- sdrawline(x, y, (int)stroke->last_mouse_position[0] - ar->winrct.xmin,
- (int)stroke->last_mouse_position[1] - ar->winrct.ymin);
- }
-
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
-}
-
-static void paint_draw_cursor(bContext *C, int x, int y, void *customdata)
-{
- Brush *brush = paint_brush(paint_get_active(CTX_data_scene(C)));
-
- glColor4ubv(paint_get_active(CTX_data_scene(C))->paint_cursor_col);
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
-
- glTranslatef((float)x, (float)y, 0.0f);
- glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
- glTranslatef((float)-x, (float)-y, 0.0f);
-
- glDisable(GL_BLEND);
- glDisable(GL_LINE_SMOOTH);
-}
-
-/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
-static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse[2])
-{
- PointerRNA itemptr;
- float cur_depth, pressure = 1;
- float center[3];
- PaintStroke *stroke = op->customdata;
-
- cur_depth = read_cached_depth(&stroke->vc, mouse[0], mouse[1]);
- view3d_unproject(&stroke->mats, center, mouse[0], mouse[1], cur_depth);
-
- /* Tablet */
- if(event->custom == EVT_DATA_TABLET) {
- wmTabletData *wmtab= event->customdata;
- if(wmtab->Active != EVT_TABLET_NONE)
- pressure= wmtab->Pressure;
- }
-
- /* Add to stroke */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
- RNA_float_set_array(&itemptr, "location", center);
- RNA_float_set_array(&itemptr, "mouse", mouse);
- RNA_boolean_set(&itemptr, "flip", event->shift);
- RNA_float_set(&itemptr, "pressure", pressure);
-
- stroke->last_mouse_position[0] = mouse[0];
- stroke->last_mouse_position[1] = mouse[1];
-
- stroke->update_step(C, stroke, &itemptr);
-}
-
-/* Returns zero if no sculpt changes should be made, non-zero otherwise */
-static int paint_smooth_stroke(PaintStroke *stroke, float output[2], wmEvent *event)
-{
- output[0] = event->x;
- output[1] = event->y;
-
- if(stroke->brush->flag & BRUSH_SMOOTH_STROKE && stroke->brush->sculpt_tool != SCULPT_TOOL_GRAB) {
- float u = stroke->brush->smooth_stroke_factor, v = 1.0 - u;
- float dx = stroke->last_mouse_position[0] - event->x, dy = stroke->last_mouse_position[1] - event->y;
-
- /* If the mouse is moving within the radius of the last move,
- don't update the mouse position. This allows sharp turns. */
- if(dx*dx + dy*dy < stroke->brush->smooth_stroke_radius * stroke->brush->smooth_stroke_radius)
- return 0;
-
- output[0] = event->x * v + stroke->last_mouse_position[0] * u;
- output[1] = event->y * v + stroke->last_mouse_position[1] * u;
- }
-
- return 1;
-}
-
-/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
-static int paint_space_stroke_enabled(Brush *br)
-{
- return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB);
-}
-
-/* For brushes with stroke spacing enabled, moves mouse in steps
- towards the final mouse location. */
-static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const float final_mouse[2])
-{
- PaintStroke *stroke = op->customdata;
- int cnt = 0;
-
- if(paint_space_stroke_enabled(stroke->brush)) {
- float mouse[2] = {stroke->last_mouse_position[0], stroke->last_mouse_position[1]};
- float vec[2] = {final_mouse[0] - mouse[0], final_mouse[1] - mouse[1]};
- float length, scale;
- int steps = 0, i;
-
- /* Normalize the vector between the last stroke dot and the goal */
- length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
-
- if(length > FLT_EPSILON) {
- scale = stroke->brush->spacing / length;
- vec[0] *= scale;
- vec[1] *= scale;
-
- steps = (int)(length / stroke->brush->spacing);
- for(i = 0; i < steps; ++i, ++cnt) {
- mouse[0] += vec[0];
- mouse[1] += vec[1];
- paint_brush_stroke_add_step(C, op, event, mouse);
- }
- }
- }
-
- return cnt;
-}
-
-/**** Public API ****/
-
-PaintStroke *paint_stroke_new(bContext *C, StrokeTestStart test_start,
- StrokeUpdateStep update_step, StrokeDone done)
-{
- PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
-
- stroke->brush = paint_brush(paint_get_active(CTX_data_scene(C)));
- view3d_set_viewcontext(C, &stroke->vc);
- view3d_get_transformation(&stroke->vc, stroke->vc.obact, &stroke->mats);
-
- stroke->test_start = test_start;
- stroke->update_step = update_step;
- stroke->done = done;
-
- return stroke;
-}
-
-int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
- ARegion *ar = CTX_wm_region(C);
- PaintStroke *stroke = op->customdata;
- float mouse[2];
-
- if(event->type == TIMER && (event->customdata != stroke->timer))
- return OPERATOR_RUNNING_MODAL;
-
- if(!stroke->stroke_started) {
- stroke->last_mouse_position[0] = event->x;
- stroke->last_mouse_position[1] = event->y;
- stroke->stroke_started = stroke->test_start(C, op, event);
-
- if(stroke->stroke_started) {
- stroke->smooth_stroke_cursor =
- WM_paint_cursor_activate(CTX_wm_manager(C), paint_poll, paint_draw_smooth_stroke, stroke);
-
- if(stroke->brush->flag & BRUSH_AIRBRUSH)
- stroke->timer = WM_event_add_window_timer(CTX_wm_window(C), TIMER, stroke->brush->rate);
- }
-
- ED_region_tag_redraw(ar);
- }
-
- if(stroke->stroke_started) {
- if(paint_smooth_stroke(stroke, mouse, event)) {
- if(paint_space_stroke_enabled(stroke->brush)) {
- if(!paint_space_stroke(C, op, event, mouse))
- ED_region_tag_redraw(ar);
- }
- else
- paint_brush_stroke_add_step(C, op, event, mouse);
- }
- else
- ED_region_tag_redraw(ar);
- }
-
- /* TODO: fix hardcoded event here */
- if(event->type == LEFTMOUSE && event->val == 0) {
- /* Exit stroke, free data */
-
- if(stroke->smooth_stroke_cursor)
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->smooth_stroke_cursor);
-
- if(stroke->timer)
- WM_event_remove_window_timer(CTX_wm_window(C), stroke->timer);
-
- stroke->done(C, stroke);
- MEM_freeN(stroke);
- return OPERATOR_FINISHED;
- }
- else
- return OPERATOR_RUNNING_MODAL;
-}
-
-int paint_stroke_exec(bContext *C, wmOperator *op)
-{
- PaintStroke *stroke = op->customdata;
-
- RNA_BEGIN(op->ptr, itemptr, "stroke") {
- stroke->update_step(C, stroke, &itemptr);
- }
- RNA_END;
-
- MEM_freeN(stroke);
- op->customdata = NULL;
-
- return OPERATOR_FINISHED;
-}
-
-ViewContext *paint_stroke_view_context(PaintStroke *stroke)
-{
- return &stroke->vc;
-}
-
-void *paint_stroke_mode_data(struct PaintStroke *stroke)
-{
- return stroke->mode_data;
-}
-
-void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
-{
- stroke->mode_data = mode_data;
-}
-
-int paint_poll(bContext *C)
-{
- Paint *p = paint_get_active(CTX_data_scene(C));
- Object *ob = CTX_data_active_object(C);
-
- return p && ob && paint_brush(p) &&
- CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
- CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
-}
-
-void paint_cursor_start(bContext *C, int (*poll)(bContext *C))
-{
- Paint *p = paint_get_active(CTX_data_scene(C));
-
- if(p && !p->paint_cursor)
- p->paint_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), poll, paint_draw_cursor, NULL);
-}
-
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 25ff57ca87f..1a548708ec8 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -43,7 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
-
+#include "MTC_matrixops.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
@@ -62,7 +62,6 @@
#include "DNA_userdef_types.h"
#include "RNA_access.h"
-#include "RNA_define.h"
#include "BKE_armature.h"
#include "BKE_brush.h"
@@ -92,8 +91,6 @@
#include "ED_util.h"
#include "ED_view3d.h"
-#include "paint_intern.h"
-
/* vp->mode */
#define VP_MIX 0
#define VP_ADD 1
@@ -110,18 +107,11 @@ static void error() {}
/* polling - retrieve whether cursor should be set or operator should be done */
-
-/* Returns true if vertex paint mode is active */
-int vertex_paint_mode_poll(bContext *C)
+static int vp_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- return ob && ob->mode == OB_MODE_VERTEX_PAINT;
-}
-
-static int vp_poll(bContext *C)
-{
- if(vertex_paint_mode_poll(C) &&
+ if(ob && ob->mode & OB_MODE_VERTEX_PAINT &&
paint_brush(&CTX_data_tool_settings(C)->vpaint->paint)) {
ScrArea *sa= CTX_wm_area(C);
if(sa->spacetype==SPACE_VIEW3D) {
@@ -149,6 +139,56 @@ static int wp_poll(bContext *C)
return 0;
}
+
+/* Cursors */
+static void vp_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ Brush *brush = paint_brush(&CTX_data_tool_settings(C)->vpaint->paint);
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(255, 255, 255, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glTranslatef((float)-x, (float)-y, 0.0f);
+}
+
+static void wp_drawcursor(bContext *C, int x, int y, void *customdata)
+{
+ Brush *brush = paint_brush(&CTX_data_tool_settings(C)->wpaint->paint);
+
+ glTranslatef((float)x, (float)y, 0.0f);
+
+ glColor4ub(200, 200, 255, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+
+ glTranslatef((float)-x, (float)-y, 0.0f);
+}
+
+static void toggle_paint_cursor(bContext *C, int wpaint)
+{
+ ToolSettings *ts = CTX_data_scene(C)->toolsettings;
+ VPaint *vp = wpaint ? ts->wpaint : ts->vpaint;
+
+ if(vp->paintcursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), vp->paintcursor);
+ vp->paintcursor = NULL;
+ }
+ else {
+ vp->paintcursor = wpaint ?
+ WM_paint_cursor_activate(CTX_wm_manager(C), wp_poll, wp_drawcursor, NULL) :
+ WM_paint_cursor_activate(CTX_wm_manager(C), vp_poll, vp_drawcursor, NULL);
+ }
+}
+
static VPaint *new_vpaint(int wpaint)
{
VPaint *vp= MEM_callocN(sizeof(VPaint), "VPaint");
@@ -295,7 +335,7 @@ void make_vertexcol(Scene *scene, int shade) /* single ob */
else
memset(me->mcol, 255, 4*sizeof(MCol)*me->totface);
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
@@ -330,7 +370,34 @@ static void copy_wpaint_prev (VPaint *wp, MDeformVert *dverts, int dcount)
}
-void clear_vpaint(Scene *scene, int selected)
+void clear_vpaint(Scene *scene)
+{
+ Mesh *me;
+ Object *ob;
+ unsigned int *to, paintcol;
+ int a;
+
+ ob= OBACT;
+ me= get_mesh(ob);
+ if(!ob || ob->id.lib) return;
+
+ if(!(ob->mode & OB_MODE_VERTEX_PAINT)) return;
+
+ if(me==0 || me->mcol==0 || me->totface==0) return;
+
+ paintcol= vpaint_get_current_col(scene->toolsettings->vpaint);
+
+ to= (unsigned int *)me->mcol;
+ a= 4*me->totface;
+ while(a--) {
+ *to= paintcol;
+ to++;
+ }
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+}
+
+void clear_vpaint_selectedfaces(Scene *scene)
{
Mesh *me;
MFace *mf;
@@ -350,7 +417,7 @@ void clear_vpaint(Scene *scene, int selected)
mf = me->mface;
mcol = (unsigned int*)me->mcol;
for (i = 0; i < me->totface; i++, mf++, mcol+=4) {
- if (!selected || mf->flag & ME_FACE_SEL) {
+ if (mf->flag & ME_FACE_SEL) {
mcol[0] = paintcol;
mcol[1] = paintcol;
mcol[2] = paintcol;
@@ -358,7 +425,7 @@ void clear_vpaint(Scene *scene, int selected)
}
}
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
@@ -408,8 +475,8 @@ void clear_wpaint_selectedfaces(Scene *scene)
if (!strcmp(curdef->name, name))
break;
if(curdef==NULL) {
- int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
- curdef= ED_vgroup_add_name (ob, name);
+ int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
+ curdef= add_defgroup_name (ob, name);
ob->actdef= olddef;
}
@@ -431,9 +498,9 @@ void clear_wpaint_selectedfaces(Scene *scene)
faceverts[3]= mface->v4;
for (i=0; i<3 || faceverts[i]; i++) {
if(!((me->dvert+faceverts[i])->flag)) {
- dw= ED_vgroup_weight_verify(me->dvert+faceverts[i], vgroup);
+ dw= verify_defweight(me->dvert+faceverts[i], vgroup);
if(dw) {
- uw= ED_vgroup_weight_verify(wp->wpaint_prev+faceverts[i], vgroup);
+ uw= verify_defweight(wp->wpaint_prev+faceverts[i], vgroup);
uw->weight= dw->weight; /* set the undo weight */
dw->weight= paintweight;
@@ -442,11 +509,11 @@ void clear_wpaint_selectedfaces(Scene *scene)
if(j>=0) {
/* copy, not paint again */
if(vgroup_mirror != -1) {
- dw= ED_vgroup_weight_verify(me->dvert+j, vgroup_mirror);
- uw= ED_vgroup_weight_verify(wp->wpaint_prev+j, vgroup_mirror);
+ dw= verify_defweight(me->dvert+j, vgroup_mirror);
+ uw= verify_defweight(wp->wpaint_prev+j, vgroup_mirror);
} else {
- dw= ED_vgroup_weight_verify(me->dvert+j, vgroup);
- uw= ED_vgroup_weight_verify(wp->wpaint_prev+j, vgroup);
+ dw= verify_defweight(me->dvert+j, vgroup);
+ uw= verify_defweight(wp->wpaint_prev+j, vgroup);
}
uw->weight= dw->weight; /* set the undo weight */
dw->weight= paintweight;
@@ -468,7 +535,7 @@ void clear_wpaint_selectedfaces(Scene *scene)
MEM_freeN(indexar);
copy_wpaint_prev(wp, NULL, 0);
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
@@ -740,7 +807,7 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x
return tot;
}
-static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, float *mval)
+static int calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, float vpimat[][3], float *vert_nor, short *mval)
{
Brush *brush = paint_brush(&vp->paint);
float fac, dx, dy;
@@ -923,7 +990,7 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
val= 0; // XXX pupmenu(str);
if(val>=0) {
ob->actdef= val+1;
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
MEM_freeN(str);
}
@@ -963,20 +1030,20 @@ void sample_wpaint(Scene *scene, ARegion *ar, View3D *v3d, int mode)
fac= MIN4(w1, w2, w3, w4);
if(w1==fac) {
- dw= ED_vgroup_weight_get(me->dvert+mface->v1, ob->actdef-1);
+ dw= get_defweight(me->dvert+mface->v1, ob->actdef-1);
if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
}
else if(w2==fac) {
- dw= ED_vgroup_weight_get(me->dvert+mface->v2, ob->actdef-1);
+ dw= get_defweight(me->dvert+mface->v2, ob->actdef-1);
if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
}
else if(w3==fac) {
- dw= ED_vgroup_weight_get(me->dvert+mface->v3, ob->actdef-1);
+ dw= get_defweight(me->dvert+mface->v3, ob->actdef-1);
if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
}
else if(w4==fac) {
if(mface->v4) {
- dw= ED_vgroup_weight_get(me->dvert+mface->v4, ob->actdef-1);
+ dw= get_defweight(me->dvert+mface->v4, ob->actdef-1);
if(dw) ts->vgroup_weight= dw->weight; else ts->vgroup_weight= 0.0f;
}
}
@@ -995,12 +1062,12 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha,
int vgroup= ob->actdef-1;
if(wp->flag & VP_ONLYVGROUP) {
- dw= ED_vgroup_weight_get(me->dvert+index, vgroup);
- uw= ED_vgroup_weight_get(wp->wpaint_prev+index, vgroup);
+ dw= get_defweight(me->dvert+index, vgroup);
+ uw= get_defweight(wp->wpaint_prev+index, vgroup);
}
else {
- dw= ED_vgroup_weight_verify(me->dvert+index, vgroup);
- uw= ED_vgroup_weight_verify(wp->wpaint_prev+index, vgroup);
+ dw= verify_defweight(me->dvert+index, vgroup);
+ uw= verify_defweight(wp->wpaint_prev+index, vgroup);
}
if(dw==NULL || uw==NULL)
return;
@@ -1012,9 +1079,9 @@ static void do_weight_paint_vertex(VPaint *wp, Object *ob, int index, int alpha,
if(j>=0) {
/* copy, not paint again */
if(vgroup_mirror != -1)
- uw= ED_vgroup_weight_verify(me->dvert+j, vgroup_mirror);
+ uw= verify_defweight(me->dvert+j, vgroup_mirror);
else
- uw= ED_vgroup_weight_verify(me->dvert+j, vgroup);
+ uw= verify_defweight(me->dvert+j, vgroup);
uw->weight= dw->weight;
}
@@ -1049,7 +1116,7 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */
* exit (exit needs doing regardless because we
* should redeform).
*/
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
if(ob->mode & OB_MODE_WEIGHT_PAINT) {
Object *par;
@@ -1057,8 +1124,9 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */
if(wp==NULL)
wp= scene->toolsettings->wpaint= new_vpaint(1);
- paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT);
- paint_cursor_start(C, wp_poll);
+ paint_init(&wp->paint, "Brush");
+
+ toggle_paint_cursor(C, 1);
mesh_octree_table(ob, NULL, NULL, 's');
@@ -1070,10 +1138,13 @@ static int set_wpaint(bContext *C, wmOperator *op) /* toggle */
if(pchan->bone->flag & BONE_ACTIVE)
break;
if(pchan)
- ED_vgroup_select_by_name(ob, pchan->name);
+ vertexgroup_select_by_name(ob, pchan->name);
}
}
else {
+ if(wp)
+ toggle_paint_cursor(C, 1);
+
mesh_octree_table(ob, NULL, NULL, 'e');
}
@@ -1114,11 +1185,9 @@ void PAINT_OT_weight_paint_toggle(wmOperatorType *ot)
static int vpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- Paint *p = paint_get_active(CTX_data_scene(C));
- Brush *brush = paint_brush(p);
-
- WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
- p->paint_cursor = NULL;
+ Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->vpaint->paint);
+
+ toggle_paint_cursor(C, 0);
brush_radial_control_invoke(op, brush, 1);
return WM_radial_control_invoke(C, op, event);
}
@@ -1127,7 +1196,7 @@ static int vpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve
{
int ret = WM_radial_control_modal(C, op, event);
if(ret != OPERATOR_RUNNING_MODAL)
- paint_cursor_start(C, vp_poll);
+ toggle_paint_cursor(C, 0);
return ret;
}
@@ -1139,11 +1208,8 @@ static int vpaint_radial_control_exec(bContext *C, wmOperator *op)
static int wpaint_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- Paint *p = paint_get_active(CTX_data_scene(C));
- Brush *brush = paint_brush(p);
-
- WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
- p->paint_cursor = NULL;
+ Brush *brush = paint_brush(&CTX_data_scene(C)->toolsettings->wpaint->paint);
+ toggle_paint_cursor(C, 1);
brush_radial_control_invoke(op, brush, 1);
return WM_radial_control_invoke(C, op, event);
}
@@ -1152,7 +1218,7 @@ static int wpaint_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve
{
int ret = WM_radial_control_modal(C, op, event);
if(ret != OPERATOR_RUNNING_MODAL)
- paint_cursor_start(C, wp_poll);
+ toggle_paint_cursor(C, 1);
return ret;
}
@@ -1204,10 +1270,207 @@ struct WPaintData {
float wpimat[3][3];
};
-static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
+static void wpaint_exit(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ Object *ob= CTX_data_active_object(C);
+ struct WPaintData *wpd= op->customdata;
+
+ if(wpd->vertexcosnos)
+ MEM_freeN(wpd->vertexcosnos);
+ MEM_freeN(wpd->indexar);
+
+ /* frees prev buffer */
+ copy_wpaint_prev(ts->wpaint, NULL, 0);
+
+ /* and particles too */
+ if(ob->particlesystem.first) {
+ ParticleSystem *psys;
+ int i;
+
+ for(psys= ob->particlesystem.first; psys; psys= psys->next) {
+ for(i=0; i<PSYS_TOT_VG; i++) {
+ if(psys->vgroup[i]==ob->actdef) {
+ psys->recalc |= PSYS_RECALC_RESET;
+ break;
+ }
+ }
+ }
+ }
+
+ DAG_object_flush_update(CTX_data_scene(C), ob, OB_RECALC_DATA);
+
+ MEM_freeN(wpd);
+ op->customdata= NULL;
+}
+
+
+static int wpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *wp= ts->wpaint;
+ Brush *brush = paint_brush(&wp->paint);
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ if(event->val==0) { /* release */
+ wpaint_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ /* pass on, first press gets painted too */
+
+ case MOUSEMOVE:
+ {
+ struct WPaintData *wpd= op->customdata;
+ ViewContext *vc= &wpd->vc;
+ Object *ob= vc->obact;
+ Mesh *me= ob->data;
+ float mat[4][4];
+ float paintweight= ts->vgroup_weight;
+ int *indexar= wpd->indexar;
+ int totindex, index, alpha, totw;
+ short mval[2];
+
+ view3d_operator_needs_opengl(C);
+
+ /* load projection matrix */
+ wmMultMatrix(ob->obmat);
+ wmGetSingleMatrix(mat);
+ wmLoadMatrix(wpd->vc.rv3d->viewmat);
+
+ MTC_Mat4SwapMat4(wpd->vc.rv3d->persmat, mat);
+
+ mval[0]= event->x - vc->ar->winrct.xmin;
+ mval[1]= event->y - vc->ar->winrct.ymin;
+
+ /* which faces are involved */
+ if(wp->flag & VP_AREA) {
+ totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size);
+ }
+ else {
+ indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ if(wp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ if((G.f & G_FACESELECT) && me->mface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if((mface->flag & ME_FACE_SEL)==0) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+
+ /* make sure each vertex gets treated only once */
+ /* and calculate filter weight */
+ totw= 0;
+ if(wp->mode==VP_BLUR)
+ paintweight= 0.0f;
+ else
+ paintweight= ts->vgroup_weight;
+
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= me->mface + (indexar[index]-1);
+
+ (me->dvert+mface->v1)->flag= 1;
+ (me->dvert+mface->v2)->flag= 1;
+ (me->dvert+mface->v3)->flag= 1;
+ if(mface->v4) (me->dvert+mface->v4)->flag= 1;
+
+ if(wp->mode==VP_BLUR) {
+ MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = verify_defweight;
+
+ if(wp->flag & VP_ONLYVGROUP)
+ dw_func= get_defweight;
+
+ dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ if(mface->v4) {
+ dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
+ if(dw) {paintweight+= dw->weight; totw++;}
+ }
+ }
+ }
+ }
+
+ if(wp->mode==VP_BLUR)
+ paintweight/= (float)totw;
+
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= me->mface + (indexar[index]-1);
+
+ if((me->dvert+mface->v1)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v1)->flag= 0;
+ }
+
+ if((me->dvert+mface->v2)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v2)->flag= 0;
+ }
+
+ if((me->dvert+mface->v3)->flag) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v3)->flag= 0;
+ }
+
+ if((me->dvert+mface->v4)->flag) {
+ if(mface->v4) {
+ alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval);
+ if(alpha) {
+ do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror);
+ }
+ (me->dvert+mface->v4)->flag= 0;
+ }
+ }
+ }
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+ ED_region_tag_redraw(vc->ar);
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Scene *scene= CTX_data_scene(C);
- struct PaintStroke *stroke = op->customdata;
ToolSettings *ts= CTX_data_tool_settings(C);
VPaint *wp= ts->wpaint;
Object *ob= CTX_data_active_object(C);
@@ -1216,17 +1479,17 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
float mat[4][4], imat[4][4];
if(scene->obedit) return OPERATOR_CANCELLED;
+ // XXX if(multires_level1_test()) return;
me= get_mesh(ob);
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
/* if nothing was added yet, we make dverts and a vertex deform group */
if (!me->dvert)
- ED_vgroup_data_create(&me->id);
+ create_dverts(&me->id);
- /* make mode data storage */
- wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
- paint_stroke_set_mode_data(stroke, wpd);
+ /* make customdata storage */
+ op->customdata= wpd= MEM_callocN(sizeof(struct WPaintData), "WPaintData");
view3d_set_viewcontext(C, &wpd->vc);
wpd->vgroup_mirror= -1;
@@ -1256,14 +1519,14 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
if(pchan) {
bDeformGroup *dg= get_named_vertexgroup(ob, pchan->name);
if(dg==NULL)
- dg= ED_vgroup_add_name(ob, pchan->name); /* sets actdef */
+ dg= add_defgroup_name(ob, pchan->name); /* sets actdef */
else
ob->actdef= get_defgroup_num(ob, dg);
}
}
}
if(ob->defbase.first==NULL) {
- ED_vgroup_add(ob);
+ add_defgroup(ob);
}
// if(ob->lay & v3d->lay); else error("Active object is not in this layer");
@@ -1288,8 +1551,8 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
if (!strcmp(curdef->name, name))
break;
if(curdef==NULL) {
- int olddef= ob->actdef; /* tsk, ED_vgroup_add sets the active defgroup */
- curdef= ED_vgroup_add_name (ob, name);
+ int olddef= ob->actdef; /* tsk, add_defgroup sets the active defgroup */
+ curdef= add_defgroup_name (ob, name);
ob->actdef= olddef;
}
@@ -1298,203 +1561,11 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, wmEvent *event)
}
}
- return 1;
-}
-
-static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- VPaint *wp= ts->wpaint;
- Brush *brush = paint_brush(&wp->paint);
- struct WPaintData *wpd= paint_stroke_mode_data(stroke);
- ViewContext *vc= &wpd->vc;
- Object *ob= vc->obact;
- Mesh *me= ob->data;
- float mat[4][4];
- float paintweight= ts->vgroup_weight;
- int *indexar= wpd->indexar;
- int totindex, index, alpha, totw;
- float mval[2];
-
- view3d_operator_needs_opengl(C);
-
- /* load projection matrix */
- wmMultMatrix(ob->obmat);
- wmGetSingleMatrix(mat);
- wmLoadMatrix(wpd->vc.rv3d->viewmat);
-
- RNA_float_get_array(itemptr, "mouse", mval);
- mval[0]-= vc->ar->winrct.xmin;
- mval[1]-= vc->ar->winrct.ymin;
-
- Mat4SwapMat4(wpd->vc.rv3d->persmat, mat);
-
- /* which faces are involved */
- if(wp->flag & VP_AREA) {
- totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size);
- }
- else {
- indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
- if(indexar[0]) totindex= 1;
- else totindex= 0;
- }
-
- if(wp->flag & VP_COLINDEX) {
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
-
- if(mface->mat_nr!=ob->actcol-1) {
- indexar[index]= 0;
- }
- }
- }
- }
-
- if((G.f & G_FACESELECT) && me->mface) {
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
-
- if((mface->flag & ME_FACE_SEL)==0) {
- indexar[index]= 0;
- }
- }
- }
- }
-
- /* make sure each vertex gets treated only once */
- /* and calculate filter weight */
- totw= 0;
- if(wp->mode==VP_BLUR)
- paintweight= 0.0f;
- else
- paintweight= ts->vgroup_weight;
-
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
-
- (me->dvert+mface->v1)->flag= 1;
- (me->dvert+mface->v2)->flag= 1;
- (me->dvert+mface->v3)->flag= 1;
- if(mface->v4) (me->dvert+mface->v4)->flag= 1;
-
- if(wp->mode==VP_BLUR) {
- MDeformWeight *dw, *(*dw_func)(MDeformVert *, int) = ED_vgroup_weight_verify;
-
- if(wp->flag & VP_ONLYVGROUP)
- dw_func= ED_vgroup_weight_get;
-
- dw= dw_func(me->dvert+mface->v1, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- dw= dw_func(me->dvert+mface->v2, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- dw= dw_func(me->dvert+mface->v3, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- if(mface->v4) {
- dw= dw_func(me->dvert+mface->v4, ob->actdef-1);
- if(dw) {paintweight+= dw->weight; totw++;}
- }
- }
- }
- }
-
- if(wp->mode==VP_BLUR)
- paintweight/= (float)totw;
-
- for(index=0; index<totindex; index++) {
-
- if(indexar[index] && indexar[index]<=me->totface) {
- MFace *mface= me->mface + (indexar[index]-1);
-
- if((me->dvert+mface->v1)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v1, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v1, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v1)->flag= 0;
- }
-
- if((me->dvert+mface->v2)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v2, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v2, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v2)->flag= 0;
- }
-
- if((me->dvert+mface->v3)->flag) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v3, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v3, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v3)->flag= 0;
- }
-
- if((me->dvert+mface->v4)->flag) {
- if(mface->v4) {
- alpha= calc_vp_alpha_dl(wp, vc, wpd->wpimat, wpd->vertexcosnos+6*mface->v4, mval);
- if(alpha) {
- do_weight_paint_vertex(wp, ob, mface->v4, alpha, paintweight, wpd->vgroup_mirror);
- }
- (me->dvert+mface->v4)->flag= 0;
- }
- }
- }
- }
-
- Mat4SwapMat4(vc->rv3d->persmat, mat);
-
- DAG_id_flush_update(ob->data, OB_RECALC_DATA);
- ED_region_tag_redraw(vc->ar);
-}
-
-static void wpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- Object *ob= CTX_data_active_object(C);
- struct WPaintData *wpd= paint_stroke_mode_data(stroke);
-
- if(wpd->vertexcosnos)
- MEM_freeN(wpd->vertexcosnos);
- MEM_freeN(wpd->indexar);
-
- /* frees prev buffer */
- copy_wpaint_prev(ts->wpaint, NULL, 0);
-
- /* and particles too */
- if(ob->particlesystem.first) {
- ParticleSystem *psys;
- int i;
-
- for(psys= ob->particlesystem.first; psys; psys= psys->next) {
- for(i=0; i<PSYS_TOT_VG; i++) {
- if(psys->vgroup[i]==ob->actdef) {
- psys->recalc |= PSYS_RECALC_RESET;
- break;
- }
- }
- }
- }
-
- DAG_id_flush_update(ob->data, OB_RECALC_DATA);
-
- MEM_freeN(wpd);
-}
-
-
-static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
- op->customdata = paint_stroke_new(C, wpaint_stroke_test_start,
- wpaint_stroke_update_step,
- wpaint_stroke_done);
+ /* do paint once for click only paint */
+ wpaint_modal(C, op, event);
/* add modal handler */
WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
-
- op->type->modal(C, op, event);
return OPERATOR_RUNNING_MODAL;
}
@@ -1508,14 +1579,13 @@ void PAINT_OT_weight_paint(wmOperatorType *ot)
/* api callbacks */
ot->invoke= wpaint_invoke;
- ot->modal= paint_stroke_modal;
+ ot->modal= wpaint_modal;
/* ot->exec= vpaint_exec; <-- needs stroke property */
ot->poll= wp_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
+
}
/* ************ set / clear vertex paint mode ********** */
@@ -1547,6 +1617,11 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
if(ob->mode & OB_MODE_VERTEX_PAINT) {
ob->mode &= ~OB_MODE_VERTEX_PAINT;
+
+ if(vp) {
+ toggle_paint_cursor(C, 0);
+ vp->paintcursor= NULL;
+ }
}
else {
ob->mode |= OB_MODE_VERTEX_PAINT;
@@ -1557,14 +1632,14 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */
if(vp==NULL)
vp= scene->toolsettings->vpaint= new_vpaint(0);
- paint_cursor_start(C, vp_poll);
+ toggle_paint_cursor(C, 0);
- paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT);
+ paint_init(&vp->paint, "Brush");
}
if (me)
/* update modifier stack for mapping requirements */
- DAG_id_flush_update(&me->id, OB_RECALC_DATA);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_SCENE|ND_MODE, scene);
@@ -1610,24 +1685,158 @@ For future:
*/
-typedef struct VPaintData {
+struct VPaintData {
ViewContext vc;
unsigned int paintcol;
int *indexar;
float *vertexcosnos;
float vpimat[3][3];
-} VPaintData;
+};
+
+static void vpaint_exit(bContext *C, wmOperator *op)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ struct VPaintData *vpd= op->customdata;
+
+ if(vpd->vertexcosnos)
+ MEM_freeN(vpd->vertexcosnos);
+ MEM_freeN(vpd->indexar);
+
+ /* frees prev buffer */
+ copy_vpaint_prev(ts->vpaint, NULL, 0);
+
+ MEM_freeN(vpd);
+ op->customdata= NULL;
+}
+
+static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ ToolSettings *ts= CTX_data_tool_settings(C);
+ VPaint *vp= ts->vpaint;
+ Brush *brush = paint_brush(&vp->paint);
+
+ switch(event->type) {
+ case LEFTMOUSE:
+ if(event->val==0) { /* release */
+ vpaint_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ /* pass on, first press gets painted too */
+
+ case MOUSEMOVE:
+ {
+ struct VPaintData *vpd= op->customdata;
+ ViewContext *vc= &vpd->vc;
+ Object *ob= vc->obact;
+ Mesh *me= ob->data;
+ float mat[4][4];
+ int *indexar= vpd->indexar;
+ int totindex, index;
+ short mval[2];
+
+ view3d_operator_needs_opengl(C);
+
+ /* load projection matrix */
+ wmMultMatrix(ob->obmat);
+ wmGetSingleMatrix(mat);
+ wmLoadMatrix(vc->rv3d->viewmat);
+
+ mval[0]= event->x - vc->ar->winrct.xmin;
+ mval[1]= event->y - vc->ar->winrct.ymin;
+
+ /* which faces are involved */
+ if(vp->flag & VP_AREA) {
+ totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size);
+ }
+ else {
+ indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
+ if(indexar[0]) totindex= 1;
+ else totindex= 0;
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ if(vp->flag & VP_COLINDEX) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if(mface->mat_nr!=ob->actcol-1) {
+ indexar[index]= 0;
+ }
+ }
+ }
+ }
+ if((G.f & G_FACESELECT) && me->mface) {
+ for(index=0; index<totindex; index++) {
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+
+ if((mface->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ }
+ }
+ }
+
+ for(index=0; index<totindex; index++) {
+
+ if(indexar[index] && indexar[index]<=me->totface) {
+ MFace *mface= ((MFace *)me->mface) + (indexar[index]-1);
+ unsigned int *mcol= ( (unsigned int *)me->mcol) + 4*(indexar[index]-1);
+ unsigned int *mcolorig= ( (unsigned int *)vp->vpaint_prev) + 4*(indexar[index]-1);
+ int alpha;
+
+ if(vp->mode==VP_BLUR) {
+ unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
+ if(mface->v4) {
+ unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
+ vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
+ }
+ else {
+ vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
+ }
+
+ }
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v1, mval);
+ if(alpha) vpaint_blend(vp, mcol, mcolorig, vpd->paintcol, alpha);
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v2, mval);
+ if(alpha) vpaint_blend(vp, mcol+1, mcolorig+1, vpd->paintcol, alpha);
+
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v3, mval);
+ if(alpha) vpaint_blend(vp, mcol+2, mcolorig+2, vpd->paintcol, alpha);
+
+ if(mface->v4) {
+ alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*mface->v4, mval);
+ if(alpha) vpaint_blend(vp, mcol+3, mcolorig+3, vpd->paintcol, alpha);
+ }
+ }
+ }
+
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
+
+ do_shared_vertexcol(me);
+
+ ED_region_tag_redraw(vc->ar);
+
+ DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+ }
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
-static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event)
+static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
ToolSettings *ts= CTX_data_tool_settings(C);
- struct PaintStroke *stroke = op->customdata;
VPaint *vp= ts->vpaint;
struct VPaintData *vpd;
Object *ob= CTX_data_active_object(C);
Mesh *me;
float mat[4][4], imat[4][4];
-
+
/* context checks could be a poll() */
me= get_mesh(ob);
if(me==NULL || me->totface==0) return OPERATOR_PASS_THROUGH;
@@ -1635,9 +1844,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
if(me->mcol==NULL) make_vertexcol(CTX_data_scene(C), 0);
if(me->mcol==NULL) return OPERATOR_CANCELLED;
- /* make mode data storage */
- vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
- paint_stroke_set_mode_data(stroke, vpd);
+ /* make customdata storage */
+ op->customdata= vpd= MEM_callocN(sizeof(struct VPaintData), "VPaintData");
view3d_set_viewcontext(C, &vpd->vc);
vpd->vertexcosnos= mesh_get_mapped_verts_nors(vpd->vc.scene, ob);
@@ -1651,119 +1859,12 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent
Mat4MulMat4(mat, ob->obmat, vpd->vc.rv3d->viewmat);
Mat4Invert(imat, mat);
Mat3CpyMat4(vpd->vpimat, imat);
-
- return 1;
-}
-
-static void vpaint_paint_face(VPaint *vp, VPaintData *vpd, Object *ob, int index, float mval[2])
-{
- ViewContext *vc = &vpd->vc;
- Mesh *me = get_mesh(ob);
- MFace *mface= ((MFace*)me->mface) + index;
- unsigned int *mcol= ((unsigned int*)me->mcol) + 4*index;
- unsigned int *mcolorig= ((unsigned int*)vp->vpaint_prev) + 4*index;
- int alpha, i;
-
- if((vp->flag & VP_COLINDEX && mface->mat_nr!=ob->actcol-1) ||
- (G.f & G_FACESELECT && !(mface->flag & ME_FACE_SEL)))
- return;
-
- if(vp->mode==VP_BLUR) {
- unsigned int fcol1= mcol_blend( mcol[0], mcol[1], 128);
- if(mface->v4) {
- unsigned int fcol2= mcol_blend( mcol[2], mcol[3], 128);
- vpd->paintcol= mcol_blend( fcol1, fcol2, 128);
- }
- else {
- vpd->paintcol= mcol_blend( mcol[2], fcol1, 170);
- }
-
- }
-
- for(i = 0; i < (mface->v4 ? 4 : 3); ++i) {
- alpha= calc_vp_alpha_dl(vp, vc, vpd->vpimat, vpd->vertexcosnos+6*(&mface->v1)[i], mval);
- if(alpha)
- vpaint_blend(vp, mcol+i, mcolorig+i, vpd->paintcol, alpha);
- }
-}
-
-static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- struct VPaintData *vpd = paint_stroke_mode_data(stroke);
- VPaint *vp= ts->vpaint;
- Brush *brush = paint_brush(&vp->paint);
- ViewContext *vc= &vpd->vc;
- Object *ob= vc->obact;
- Mesh *me= ob->data;
- float mat[4][4];
- int *indexar= vpd->indexar;
- int totindex, index;
- float mval[2];
-
- RNA_float_get_array(itemptr, "mouse", mval);
-
- view3d_operator_needs_opengl(C);
-
- /* load projection matrix */
- wmMultMatrix(ob->obmat);
- wmGetSingleMatrix(mat);
- wmLoadMatrix(vc->rv3d->viewmat);
-
- mval[0]-= vc->ar->winrct.xmin;
- mval[1]-= vc->ar->winrct.ymin;
-
-
- /* which faces are involved */
- if(vp->flag & VP_AREA) {
- totindex= sample_backbuf_area(vc, indexar, me->totface, mval[0], mval[1], brush->size);
- }
- else {
- indexar[0]= view3d_sample_backbuf(vc, mval[0], mval[1]);
- if(indexar[0]) totindex= 1;
- else totindex= 0;
- }
-
- Mat4SwapMat4(vc->rv3d->persmat, mat);
-
- for(index=0; index<totindex; index++) {
- if(indexar[index] && indexar[index]<=me->totface)
- vpaint_paint_face(vp, vpd, ob, indexar[index]-1, mval);
- }
-
- Mat4SwapMat4(vc->rv3d->persmat, mat);
-
- ED_region_tag_redraw(vc->ar);
-
- DAG_id_flush_update(ob->data, OB_RECALC_DATA);
-}
-
-static void vpaint_stroke_done(bContext *C, struct PaintStroke *stroke)
-{
- ToolSettings *ts= CTX_data_tool_settings(C);
- struct VPaintData *vpd= paint_stroke_mode_data(stroke);
- if(vpd->vertexcosnos)
- MEM_freeN(vpd->vertexcosnos);
- MEM_freeN(vpd->indexar);
-
- /* frees prev buffer */
- copy_vpaint_prev(ts->vpaint, NULL, 0);
-
- MEM_freeN(vpd);
-}
-
-static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
- op->customdata = paint_stroke_new(C, vpaint_stroke_test_start,
- vpaint_stroke_update_step,
- vpaint_stroke_done);
+ /* do paint once for click only paint */
+ vpaint_modal(C, op, event);
/* add modal handler */
WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
-
- op->type->modal(C, op, event);
return OPERATOR_RUNNING_MODAL;
}
@@ -1776,13 +1877,11 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot)
/* api callbacks */
ot->invoke= vpaint_invoke;
- ot->modal= paint_stroke_modal;
+ ot->modal= vpaint_modal;
/* ot->exec= vpaint_exec; <-- needs stroke property */
ot->poll= vp_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
-
- RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index b08e8ab5c2b..f7f72d611dc 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -65,6 +65,7 @@
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_paint.h"
+#include "BKE_sculpt.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_colortools.h"
@@ -79,7 +80,6 @@
#include "ED_space_api.h"
#include "ED_util.h"
#include "ED_view3d.h"
-#include "paint_intern.h"
#include "sculpt_intern.h"
#include "RNA_access.h"
@@ -144,6 +144,7 @@ typedef struct StrokeCache {
int first_time; /* Beginning of stroke may do some things special */
+ ViewContext vc;
bglMats *mats;
short (*orig_norms)[3]; /* Copy of the mesh vertices' normals */
@@ -177,6 +178,19 @@ typedef struct ProjVert {
* Simple functions to get data from the GL
*/
+/* Uses window coordinates (x,y) and depth component z to find a point in
+ modelspace */
+static void unproject(bglMats *mats, float out[3], const short x, const short y, const float z)
+{
+ double ux, uy, uz;
+
+ gluUnProject(x,y,z, mats->modelview, mats->projection,
+ (GLint *)mats->viewport, &ux, &uy, &uz );
+ out[0] = ux;
+ out[1] = uy;
+ out[2] = uz;
+}
+
/* Convert a point in model coordinates to 2D screen coordinates. */
static void projectf(bglMats *mats, const float v[3], float p[2])
{
@@ -533,7 +547,7 @@ static void do_flatten_clay_brush(Sculpt *sd, SculptSession *ss, const ListBase
ActiveData *node= active_verts->first;
/* area_normal and cntr define the plane towards which vertices are squashed */
float area_normal[3];
- float cntr[3], cntr2[3], bstr = 0;
+ float cntr[3], cntr2[3], bstr;
int flip = 0;
calc_area_normal(sd, ss, area_normal, active_verts);
@@ -1041,7 +1055,47 @@ static int sculpt_mode_poll(bContext *C)
static int sculpt_poll(bContext *C)
{
- return sculpt_mode_poll(C) && paint_poll(C);
+ return sculpt_mode_poll(C) && paint_brush(&CTX_data_tool_settings(C)->sculpt->paint) &&
+ CTX_wm_area(C)->spacetype == SPACE_VIEW3D &&
+ CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
+}
+
+/*** Sculpt Cursor ***/
+static void draw_paint_cursor(bContext *C, int x, int y, void *customdata)
+{
+ Sculpt *sd= CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss= CTX_data_active_object(C)->sculpt;
+ Brush *brush = paint_brush(&sd->paint);
+
+ glColor4ub(255, 100, 100, 128);
+ glEnable( GL_LINE_SMOOTH );
+ glEnable(GL_BLEND);
+
+ glTranslatef((float)x, (float)y, 0.0f);
+ glutil_draw_lined_arc(0.0, M_PI*2.0, brush->size, 40);
+ glTranslatef((float)-x, (float)-y, 0.0f);
+
+ if(ss && ss->cache && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) {
+ ARegion *ar = CTX_wm_region(C);
+ sdrawline(x, y, (int)ss->cache->mouse[0] - ar->winrct.xmin, (int)ss->cache->mouse[1] - ar->winrct.ymin);
+ }
+
+ glDisable(GL_BLEND);
+ glDisable( GL_LINE_SMOOTH );
+}
+
+static void toggle_paint_cursor(bContext *C)
+{
+ Sculpt *s = CTX_data_scene(C)->toolsettings->sculpt;
+
+ if(s->cursor) {
+ WM_paint_cursor_end(CTX_wm_manager(C), s->cursor);
+ s->cursor = NULL;
+ }
+ else {
+ s->cursor =
+ WM_paint_cursor_activate(CTX_wm_manager(C), sculpt_poll, draw_paint_cursor, NULL);
+ }
}
static void sculpt_undo_push(bContext *C, Sculpt *sd)
@@ -1071,11 +1125,8 @@ static void sculpt_undo_push(bContext *C, Sculpt *sd)
/**** Radial control ****/
static int sculpt_radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
- Paint *p = paint_get_active(CTX_data_scene(C));
- Brush *brush = paint_brush(p);
-
- WM_paint_cursor_end(CTX_wm_manager(C), p->paint_cursor);
- p->paint_cursor = NULL;
+ Brush *brush = paint_brush(&CTX_data_tool_settings(C)->sculpt->paint);
+ toggle_paint_cursor(C);
brush_radial_control_invoke(op, brush, 1);
return WM_radial_control_invoke(C, op, event);
}
@@ -1084,7 +1135,7 @@ static int sculpt_radial_control_modal(bContext *C, wmOperator *op, wmEvent *eve
{
int ret = WM_radial_control_modal(C, op, event);
if(ret != OPERATOR_RUNNING_MODAL)
- paint_cursor_start(C, sculpt_poll);
+ toggle_paint_cursor(C);
return ret;
}
@@ -1118,7 +1169,7 @@ static float unproject_brush_radius(SculptSession *ss, float offset)
float brush_edge[3];
/* In anchored mode, brush size changes with mouse loc, otherwise it's fixed using the brush radius */
- view3d_unproject(ss->cache->mats, brush_edge, ss->cache->initial_mouse[0] + offset,
+ unproject(ss->cache->mats, brush_edge, ss->cache->initial_mouse[0] + offset,
ss->cache->initial_mouse[1], ss->cache->depth);
return VecLenf(ss->cache->true_location, brush_edge);
@@ -1143,7 +1194,6 @@ static void sculpt_update_cache_invariants(Sculpt *sd, SculptSession *ss, bConte
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
Brush *brush = paint_brush(&sd->paint);
- ViewContext *vc = paint_stroke_view_context(op->customdata);
int i;
ss->cache = cache;
@@ -1159,8 +1209,10 @@ static void sculpt_update_cache_invariants(Sculpt *sd, SculptSession *ss, bConte
/* Truly temporary data that isn't stored in properties */
+ view3d_set_viewcontext(C, &cache->vc);
+
cache->mats = MEM_callocN(sizeof(bglMats), "sculpt bglMats");
- view3d_get_transformation(vc, vc->obact, cache->mats);
+ view3d_get_transformation(&cache->vc, cache->vc.obact, cache->mats);
sculpt_update_mesh_elements(C);
@@ -1200,7 +1252,7 @@ static void sculpt_update_cache_invariants(Sculpt *sd, SculptSession *ss, bConte
}
}
- view3d_unproject(cache->mats, cache->true_location, cache->initial_mouse[0], cache->initial_mouse[1], cache->depth);
+ unproject(cache->mats, cache->true_location, cache->initial_mouse[0], cache->initial_mouse[1], cache->depth);
cache->initial_radius = unproject_brush_radius(ss, brush->size);
cache->rotation = 0;
cache->first_time = 1;
@@ -1260,7 +1312,7 @@ static void sculpt_update_cache_variants(Sculpt *sd, SculptSession *ss, PointerR
/* Find the grab delta */
if(brush->sculpt_tool == SCULPT_TOOL_GRAB) {
- view3d_unproject(cache->mats, grab_location, cache->mouse[0], cache->mouse[1], cache->depth);
+ unproject(cache->mats, grab_location, cache->mouse[0], cache->mouse[1], cache->depth);
if(!cache->first_time)
VecSubf(cache->grab_delta, grab_location, cache->old_grab_location);
VecCopyf(cache->old_grab_location, grab_location);
@@ -1273,6 +1325,7 @@ static void sculpt_brush_stroke_init_properties(bContext *C, wmOperator *op, wmE
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
Object *ob= CTX_data_active_object(C);
ModifierData *md;
+ ViewContext vc;
float scale[3], clip_tolerance[3] = {0,0,0};
float mouse[2];
int flag = 0;
@@ -1305,12 +1358,13 @@ static void sculpt_brush_stroke_init_properties(bContext *C, wmOperator *op, wmE
RNA_float_set_array(op->ptr, "initial_mouse", mouse);
/* Initial screen depth under the mouse */
- RNA_float_set(op->ptr, "depth", read_cached_depth(paint_stroke_view_context(op->customdata), event->x, event->y));
+ view3d_set_viewcontext(C, &vc);
+ RNA_float_set(op->ptr, "depth", read_cached_depth(&vc, event->x, event->y));
sculpt_update_cache_invariants(sd, ss, C, op);
}
-static void sculpt_brush_stroke_init(bContext *C)
+static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
@@ -1322,7 +1376,10 @@ static void sculpt_brush_stroke_init(bContext *C)
changes are made to the texture. */
sculpt_update_tex(sd, ss);
- sculpt_update_mesh_elements(C);
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
+ return OPERATOR_RUNNING_MODAL;
}
static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
@@ -1378,69 +1435,157 @@ static void sculpt_flush_update(bContext *C)
ED_region_tag_redraw(ar);
}
-static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event)
+/* Returns zero if no sculpt changes should be made, non-zero otherwise */
+static int sculpt_smooth_stroke(Sculpt *s, SculptSession *ss, float output[2], wmEvent *event)
{
- ViewContext vc;
- float cur_depth;
+ Brush *brush = paint_brush(&s->paint);
- view3d_set_viewcontext(C, &vc);
- cur_depth = read_cached_depth(&vc, event->x, event->y);
-
- /* Don't start the stroke until a valid depth is found */
- if(cur_depth < 1.0 - FLT_EPSILON) {
- SculptSession *ss = CTX_data_active_object(C)->sculpt;
+ output[0] = event->x;
+ output[1] = event->y;
- sculpt_brush_stroke_init_properties(C, op, event, ss);
- sculptmode_update_all_projverts(ss);
+ if(brush->flag & BRUSH_SMOOTH_STROKE && brush->sculpt_tool != SCULPT_TOOL_GRAB) {
+ StrokeCache *cache = ss->cache;
+ float u = brush->smooth_stroke_factor, v = 1.0 - u;
+ float dx = cache->mouse[0] - event->x, dy = cache->mouse[1] - event->y;
- return 1;
+ /* If the mouse is moving within the radius of the last move,
+ don't update the mouse position. This allows sharp turns. */
+ if(dx*dx + dy*dy < brush->smooth_stroke_radius * brush->smooth_stroke_radius)
+ return 0;
+
+ output[0] = event->x * v + cache->mouse[0] * u;
+ output[1] = event->y * v + cache->mouse[1] * u;
}
- else
- return 0;
+
+ return 1;
}
-static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
+/* Returns zero if the stroke dots should not be spaced, non-zero otherwise */
+int sculpt_space_stroke_enabled(Sculpt *s)
+{
+ Brush *br = paint_brush(&s->paint);
+ return (br->flag & BRUSH_SPACE) && !(br->flag & BRUSH_ANCHORED) && (br->sculpt_tool != SCULPT_TOOL_GRAB);
+}
+
+/* Put the location of the next sculpt stroke dot into the stroke RNA and apply it to the mesh */
+static void sculpt_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, float mouse[2])
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
-
- sculpt_update_cache_variants(sd, ss, itemptr);
+ StrokeCache *cache = ss->cache;
+ PointerRNA itemptr;
+ float cur_depth, pressure = 1;
+ float center[3];
+
+ cur_depth = read_cached_depth(&cache->vc, mouse[0], mouse[1]);
+ unproject(ss->cache->mats, center, mouse[0], mouse[1], cur_depth);
+
+ /* Tablet */
+ if(event->custom == EVT_DATA_TABLET) {
+ wmTabletData *wmtab= event->customdata;
+ if(wmtab->Active != EVT_TABLET_NONE)
+ pressure= wmtab->Pressure;
+ }
+
+ /* Add to stroke */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+ RNA_float_set_array(&itemptr, "location", center);
+ RNA_float_set_array(&itemptr, "mouse", mouse);
+ RNA_boolean_set(&itemptr, "flip", event->shift);
+ RNA_float_set(&itemptr, "pressure", pressure);
+ sculpt_update_cache_variants(sd, ss, &itemptr);
+
sculpt_restore_mesh(sd, ss);
do_symmetrical_brush_actions(sd, ss);
+}
- /* Cleanup */
- sculpt_flush_update(C);
- sculpt_post_stroke_free(ss);
+/* For brushes with stroke spacing enabled, moves mouse in steps
+ towards the final mouse location. */
+static int sculpt_space_stroke(bContext *C, wmOperator *op, wmEvent *event, Sculpt *s, SculptSession *ss, const float final_mouse[2])
+{
+ StrokeCache *cache = ss->cache;
+ Brush *brush = paint_brush(&s->paint);
+ int cnt = 0;
+
+ if(sculpt_space_stroke_enabled(s)) {
+ float vec[2] = {final_mouse[0] - cache->mouse[0], final_mouse[1] - cache->mouse[1]};
+ float mouse[2] = {cache->mouse[0], cache->mouse[1]};
+ float length, scale;
+ int steps = 0, i;
+
+ /* Normalize the vector between the last stroke dot and the goal */
+ length = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
+
+ if(length > FLT_EPSILON) {
+ scale = brush->spacing / length;
+ vec[0] *= scale;
+ vec[1] *= scale;
+
+ steps = (int)(length / brush->spacing);
+ for(i = 0; i < steps; ++i, ++cnt) {
+ mouse[0] += vec[0];
+ mouse[1] += vec[1];
+ sculpt_brush_stroke_add_step(C, op, event, mouse);
+ }
+ }
+ }
+
+ return cnt;
}
-static void sculpt_stroke_done(bContext *C, struct PaintStroke *stroke)
+static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
{
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
+ ARegion *ar = CTX_wm_region(C);
+ float cur_depth;
- /* Finished */
- if(ss->cache) {
- Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ sculpt_update_mesh_elements(C);
+
+ if(!ss->cache) {
+ ViewContext vc;
+ view3d_set_viewcontext(C, &vc);
+ cur_depth = read_cached_depth(&vc, event->x, event->y);
- request_depth_update(paint_stroke_view_context(stroke)->rv3d);
- sculpt_cache_free(ss->cache);
- ss->cache = NULL;
- sculpt_undo_push(C, sd);
+ /* Don't start the stroke until a valid depth is found */
+ if(cur_depth < 1.0 - FLT_EPSILON) {
+ sculpt_brush_stroke_init_properties(C, op, event, ss);
+ sculptmode_update_all_projverts(ss);
+ }
+
+ ED_region_tag_redraw(ar);
}
-}
-static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- sculpt_brush_stroke_init(C);
+ if(ss->cache) {
+ float mouse[2];
- op->customdata = paint_stroke_new(C, sculpt_stroke_test_start,
- sculpt_stroke_update_step,
- sculpt_stroke_done);
+ if(sculpt_smooth_stroke(sd, ss, mouse, event)) {
+ if(sculpt_space_stroke_enabled(sd)) {
+ if(!sculpt_space_stroke(C, op, event, sd, ss, mouse))
+ ED_region_tag_redraw(ar);
+ }
+ else
+ sculpt_brush_stroke_add_step(C, op, event, mouse);
- /* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+ sculpt_flush_update(C);
+ sculpt_post_stroke_free(ss);
+ }
+ else
+ ED_region_tag_redraw(ar);
+ }
+
+ /* Finished */
+ if(event->type == LEFTMOUSE && event->val == 0) {
+ if(ss->cache) {
+ request_depth_update(ss->cache->vc.rv3d);
+ sculpt_cache_free(ss->cache);
+ ss->cache = NULL;
+ sculpt_undo_push(C, sd);
+ }
+
+ return OPERATOR_FINISHED;
+ }
- op->type->modal(C, op, event);
-
return OPERATOR_RUNNING_MODAL;
}
@@ -1449,14 +1594,20 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
- op->customdata = paint_stroke_new(C, sculpt_stroke_test_start, sculpt_stroke_update_step, sculpt_stroke_done);
-
- sculpt_brush_stroke_init(C);
-
+ view3d_operator_needs_opengl(C);
sculpt_update_cache_invariants(sd, ss, C, op);
sculptmode_update_all_projverts(ss);
+ sculpt_update_tex(sd, ss);
- paint_stroke_exec(C, op);
+ RNA_BEGIN(op->ptr, itemptr, "stroke") {
+ sculpt_update_cache_variants(sd, ss, &itemptr);
+
+ sculpt_restore_mesh(sd, ss);
+ do_symmetrical_brush_actions(sd, ss);
+
+ sculpt_post_stroke_free(ss);
+ }
+ RNA_END;
sculpt_flush_update(C);
sculpt_cache_free(ss->cache);
@@ -1476,7 +1627,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
/* api callbacks */
ot->invoke= sculpt_brush_stroke_invoke;
- ot->modal= paint_stroke_modal;
+ ot->modal= sculpt_brush_stroke_modal;
ot->exec= sculpt_brush_stroke_exec;
ot->poll= sculpt_poll;
@@ -1563,9 +1714,10 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *op)
free_sculptsession(&ob->sculpt);
ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- paint_init(&ts->sculpt->paint, PAINT_CURSOR_SCULPT);
-
- paint_cursor_start(C, sculpt_poll);
+ if(!ts->sculpt->cursor)
+ toggle_paint_cursor(C);
+
+ paint_init(&ts->sculpt->paint, "Brush");
WM_event_add_notifier(C, NC_SCENE|ND_MODE, CTX_data_scene(C));
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 25f97b862e6..febca301939 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -32,6 +32,7 @@
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
+#include "BKE_sculpt.h"
struct Brush;
struct Mesh;
diff --git a/source/blender/editors/sculpt_paint/sculpt_stroke.c b/source/blender/editors/sculpt_paint/sculpt_stroke.c
new file mode 100644
index 00000000000..554ff580358
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_stroke.c
@@ -0,0 +1,274 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Storage and manipulation of sculptmode brush strokes.
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_sculpt.h"
+#include "BLI_blenlib.h"
+#include "BIF_gl.h"
+
+#include "sculpt_intern.h"
+
+#include <math.h>
+
+/* Temporary storage of input stroke control points */
+typedef struct StrokePoint {
+ struct StrokePoint *next, *prev;
+ short x, y;
+} StrokePoint;
+typedef struct SculptStroke {
+ short (*loc)[2];
+ int max;
+ int index;
+ float length;
+ ListBase final;
+ StrokePoint *final_mem;
+ float offset;
+} SculptStroke;
+
+SculptStroke *sculpt_stroke_new(const int max)
+{
+ SculptStroke *stroke = MEM_callocN(sizeof(SculptStroke), "SculptStroke");
+ stroke->loc = MEM_callocN(sizeof(short) * 4 * max, "SculptStroke.loc");
+ stroke->max = max;
+ stroke->index = -1;
+ return stroke;
+}
+
+void sculpt_stroke_free(SculptStroke *stroke)
+{
+ if(stroke) {
+ if(stroke->loc) MEM_freeN(stroke->loc);
+ if(stroke->final_mem) MEM_freeN(stroke->final_mem);
+
+ MEM_freeN(stroke);
+ }
+}
+
+void sculpt_stroke_add_point(SculptStroke *stroke, const short x, const short y)
+{
+ const int next = stroke->index + 1;
+
+ if(stroke->index == -1) {
+ stroke->loc[0][0] = x;
+ stroke->loc[0][1] = y;
+ stroke->index = 0;
+ }
+ else if(next < stroke->max) {
+ const int dx = x - stroke->loc[stroke->index][0];
+ const int dy = y - stroke->loc[stroke->index][1];
+ stroke->loc[next][0] = x;
+ stroke->loc[next][1] = y;
+ stroke->length += sqrt(dx*dx + dy*dy);
+ stroke->index = next;
+ }
+}
+
+static void sculpt_stroke_smooth(SculptStroke *stroke)
+{
+ /* Apply smoothing (exclude the first and last points)*/
+ StrokePoint *p = stroke->final.first;
+ if(p && p->next && p->next->next) {
+ for(p = p->next->next; p && p->next && p->next->next; p = p->next) {
+ p->x = p->prev->prev->x*0.1 + p->prev->x*0.2 + p->x*0.4 + p->next->x*0.2 + p->next->next->x*0.1;
+ p->y = p->prev->prev->y*0.1 + p->prev->y*0.2 + p->y*0.4 + p->next->y*0.2 + p->next->next->y*0.1;
+ }
+ }
+}
+
+static void sculpt_stroke_create_final(SculptStroke *stroke)
+{
+ if(stroke) {
+ StrokePoint *p, *pnext;
+ int i;
+
+ /* Copy loc into final */
+ if(stroke->final_mem)
+ MEM_freeN(stroke->final_mem);
+ stroke->final_mem = MEM_callocN(sizeof(StrokePoint) * (stroke->index + 1) * 2, "SculptStroke.final");
+ stroke->final.first = stroke->final.last = NULL;
+ for(i = 0; i <= stroke->index; ++i) {
+ p = &stroke->final_mem[i];
+ p->x = stroke->loc[i][0];
+ p->y = stroke->loc[i][1];
+ BLI_addtail(&stroke->final, p);
+ }
+
+ /* Remove shortest edges */
+ if(stroke->final.first) {
+ for(p = ((StrokePoint*)stroke->final.first)->next; p && p->next; p = pnext) {
+ const int dx = p->x - p->prev->x;
+ const int dy = p->y - p->prev->y;
+ const float len = sqrt(dx*dx + dy*dy);
+ pnext = p->next;
+ if(len < 10) {
+ BLI_remlink(&stroke->final, p);
+ }
+ }
+ }
+
+ sculpt_stroke_smooth(stroke);
+
+ /* Subdivide edges */
+ for(p = stroke->final.first; p && p->next; p = pnext) {
+ StrokePoint *np = &stroke->final_mem[i++];
+
+ pnext = p->next;
+ np->x = (p->x + p->next->x) / 2;
+ np->y = (p->y + p->next->y) / 2;
+ BLI_insertlink(&stroke->final, p, np);
+ }
+
+ sculpt_stroke_smooth(stroke);
+ }
+}
+
+static float sculpt_stroke_seglen(StrokePoint *p1, StrokePoint *p2)
+{
+ int dx = p2->x - p1->x;
+ int dy = p2->y - p1->y;
+ return sqrt(dx*dx + dy*dy);
+}
+
+static float sculpt_stroke_final_length(SculptStroke *stroke)
+{
+ StrokePoint *p;
+ float len = 0;
+ for(p = stroke->final.first; p && p->next; ++p)
+ len += sculpt_stroke_seglen(p, p->next);
+ return len;
+}
+
+/* If partial is nonzero, cuts off apply after that length has been processed */
+static StrokePoint *sculpt_stroke_apply_generic(Sculpt *sd, SculptStroke *stroke, const int partial)
+{
+ const int sdspace = 0; //XXX: sd->spacing;
+ const short spacing = sdspace > 0 ? sdspace : 2;
+ const int dots = sculpt_stroke_final_length(stroke) / spacing;
+ int i;
+ StrokePoint *p = stroke->final.first;
+ float startloc = stroke->offset;
+
+ for(i = 0; i < dots && p && p->next; ++i) {
+ const float dotloc = spacing * i;
+ short co[2];
+ float len = sculpt_stroke_seglen(p, p->next);
+ float u, v;
+
+ /* Find edge containing dot */
+ while(dotloc > startloc + len && p && p->next && p->next->next) {
+ p = p->next;
+ startloc += len;
+ len = sculpt_stroke_seglen(p, p->next);
+ }
+
+ if(!p || !p->next || dotloc > startloc + len)
+ break;
+
+ if(partial && startloc > partial) {
+ /* Calculate offset for next stroke segment */
+ stroke->offset = startloc + len - dotloc;
+ break;
+ }
+
+ u = (dotloc - startloc) / len;
+ v = 1 - u;
+
+ co[0] = p->x*v + p->next->x*u;
+ co[1] = p->y*v + p->next->y*u;
+
+ //do_symmetrical_brush_actions(sd, a, co, NULL);
+ }
+
+ return p ? p->next : NULL;
+}
+
+void sculpt_stroke_apply(Sculpt *sd, SculptStroke *stroke)
+{
+ /* TODO: make these values user-modifiable? */
+ const int partial_len = 100;
+ const int min_len = 200;
+
+ if(stroke) {
+ sculpt_stroke_create_final(stroke);
+
+ if(sculpt_stroke_final_length(stroke) > min_len) {
+ StrokePoint *p = sculpt_stroke_apply_generic(sd, stroke, partial_len);
+
+ /* Replace remaining values in stroke->loc with remaining stroke->final values */
+ stroke->index = -1;
+ stroke->length = 0;
+ for(; p; p = p->next) {
+ ++stroke->index;
+ stroke->loc[stroke->index][0] = p->x;
+ stroke->loc[stroke->index][1] = p->y;
+ if(p->next) {
+ stroke->length += sculpt_stroke_seglen(p, p->next);
+ }
+ }
+ }
+ }
+}
+
+void sculpt_stroke_apply_all(Sculpt *sd, SculptStroke *stroke)
+{
+ sculpt_stroke_create_final(stroke);
+
+ if(stroke) {
+ sculpt_stroke_apply_generic(sd, stroke, 0);
+ }
+}
+
+/* XXX: drawing goes elsewhere */
+void sculpt_stroke_draw(SculptStroke *stroke)
+{
+ if(stroke) {
+ StrokePoint *p;
+
+ /* Draws the original stroke */
+ /*glColor3f(1, 0, 0);
+ glBegin(GL_LINE_STRIP);
+ for(i = 0; i <= stroke->index; ++i)
+ glVertex2s(stroke->loc[i][0], stroke->loc[i][1]);
+ glEnd();*/
+
+ /* Draws the smoothed stroke */
+ glColor3f(0, 1, 0);
+ glBegin(GL_LINE_STRIP);
+ for(p = stroke->final.first; p; p = p->next)
+ glVertex2s(p->x, p->y);
+ glEnd();
+ }
+}