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:
-rw-r--r--source/blender/editors/include/ED_view3d.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h15
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c224
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c175
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c209
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c13
6 files changed, 391 insertions, 246 deletions
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 07aa44cadd8..fd1b7e1351d 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -70,6 +70,7 @@ float *give_cursor(struct Scene *scene, struct View3D *v3d);
void initgrabz(struct RegionView3D *rv3d, float x, float y, float z);
void window_to_3d(struct ARegion *ar, float *vec, short mx, short my);
void window_to_3d_delta(struct ARegion *ar, float *vec, short mx, short my);
+void view3d_unproject(struct bglMats *mats, float out[3], const short x, const short y, const float z);
/* Depth buffer */
float read_cached_depth(struct ViewContext *vc, int x, int y);
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 40423e17fe4..41764a70686 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -29,13 +29,28 @@
#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);
+struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
+
/* paint_vertex.c */
void PAINT_OT_weight_paint_toggle(struct wmOperatorType *ot);
void PAINT_OT_weight_paint_radial_control(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
new file mode 100644
index 00000000000..634b82674b5
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -0,0 +1,224 @@
+/*
+ * ***** 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 "BIF_glutil.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "paint_intern.h"
+
+#include <float.h>
+#include <math.h>
+
+typedef struct PaintStroke {
+ /* 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;
+
+/* 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(!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);
+ 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) {
+ stroke->done(C, stroke);
+ MEM_freeN(stroke);
+ return OPERATOR_FINISHED;
+ }
+ else
+ return OPERATOR_RUNNING_MODAL;
+}
+
+ViewContext *paint_stroke_view_context(PaintStroke *stroke)
+{
+ return &stroke->vc;
+}
+
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 1a548708ec8..05faa47e0f4 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1709,122 +1709,123 @@ static void vpaint_exit(bContext *C, wmOperator *op)
op->customdata= NULL;
}
-static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+static void vpaint_dot(bContext *C, struct VPaintData *vpd, 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];
+ 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);
+ view3d_operator_needs_opengl(C);
- /* load projection matrix */
- wmMultMatrix(ob->obmat);
- wmGetSingleMatrix(mat);
- wmLoadMatrix(vc->rv3d->viewmat);
+ /* 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;
+ 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;
- }
+ /* 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);
+ 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(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(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((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;
- }
- }
- }
+ if((mface->flag & ME_FACE_SEL)==0)
+ indexar[index]= 0;
+ }
+ }
+ }
- for(index=0; index<totindex; index++) {
+ 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(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);
- }
+ 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->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->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);
+ 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);
- }
- }
+ 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);
+ MTC_Mat4SwapMat4(vc->rv3d->persmat, mat);
- do_shared_vertexcol(me);
+ do_shared_vertexcol(me);
- ED_region_tag_redraw(vc->ar);
+ ED_region_tag_redraw(vc->ar);
- DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+ DAG_object_flush_update(vc->scene, ob, OB_RECALC_DATA);
+}
+
+static int vpaint_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+ 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:
+ vpaint_dot(C, op->customdata, event);
break;
}
-
+
return OPERATOR_RUNNING_MODAL;
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index f7f72d611dc..c01004f5b7e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -80,6 +80,7 @@
#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,7 +145,6 @@ 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 */
@@ -178,19 +178,6 @@ 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])
{
@@ -547,7 +534,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;
+ float cntr[3], cntr2[3], bstr = 0;
int flip = 0;
calc_area_normal(sd, ss, area_normal, active_verts);
@@ -1169,7 +1156,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 */
- unproject(ss->cache->mats, brush_edge, ss->cache->initial_mouse[0] + offset,
+ view3d_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);
@@ -1194,6 +1181,7 @@ 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;
@@ -1209,10 +1197,8 @@ 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(&cache->vc, cache->vc.obact, cache->mats);
+ view3d_get_transformation(vc, vc->obact, cache->mats);
sculpt_update_mesh_elements(C);
@@ -1252,7 +1238,7 @@ static void sculpt_update_cache_invariants(Sculpt *sd, SculptSession *ss, bConte
}
}
- unproject(cache->mats, cache->true_location, cache->initial_mouse[0], cache->initial_mouse[1], cache->depth);
+ view3d_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;
@@ -1312,7 +1298,7 @@ static void sculpt_update_cache_variants(Sculpt *sd, SculptSession *ss, PointerR
/* Find the grab delta */
if(brush->sculpt_tool == SCULPT_TOOL_GRAB) {
- unproject(cache->mats, grab_location, cache->mouse[0], cache->mouse[1], cache->depth);
+ view3d_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);
@@ -1325,7 +1311,6 @@ 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;
@@ -1358,13 +1343,12 @@ 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 */
- view3d_set_viewcontext(C, &vc);
- RNA_float_set(op->ptr, "depth", read_cached_depth(&vc, event->x, event->y));
+ RNA_float_set(op->ptr, "depth", read_cached_depth(paint_stroke_view_context(op->customdata), event->x, event->y));
sculpt_update_cache_invariants(sd, ss, C, op);
}
-static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static void sculpt_brush_stroke_init(bContext *C)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
@@ -1376,10 +1360,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even
changes are made to the texture. */
sculpt_update_tex(sd, ss);
- /* add modal handler */
- WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
-
- return OPERATOR_RUNNING_MODAL;
+ sculpt_update_mesh_elements(C);
}
static void sculpt_restore_mesh(Sculpt *sd, SculptSession *ss)
@@ -1435,157 +1416,67 @@ static void sculpt_flush_update(bContext *C)
ED_region_tag_redraw(ar);
}
-/* 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)
+static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, wmEvent *event)
{
- Brush *brush = paint_brush(&s->paint);
-
- output[0] = event->x;
- output[1] = event->y;
+ ViewContext vc;
+ float cur_depth;
- 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;
+ 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;
- /* 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;
+ sculpt_brush_stroke_init_properties(C, op, event, ss);
+ sculptmode_update_all_projverts(ss);
- output[0] = event->x * v + cache->mouse[0] * u;
- output[1] = event->y * v + cache->mouse[1] * u;
+ return 1;
}
-
- return 1;
-}
-
-/* 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);
+ else
+ return 0;
}
-/* 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])
+static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr)
{
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
SculptSession *ss = CTX_data_active_object(C)->sculpt;
- 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_update_cache_variants(sd, ss, itemptr);
sculpt_restore_mesh(sd, ss);
do_symmetrical_brush_actions(sd, 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;
+ /* Cleanup */
+ sculpt_flush_update(C); // XXX: during exec, shouldn't do this every time
+ sculpt_post_stroke_free(ss);
}
-static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
+static void sculpt_stroke_done(bContext *C, struct PaintStroke *stroke)
{
- 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;
-
- 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);
-
- /* 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);
- }
+ /* Finished */
if(ss->cache) {
- float mouse[2];
-
- 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);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
- sculpt_flush_update(C);
- sculpt_post_stroke_free(ss);
- }
- else
- ED_region_tag_redraw(ar);
+ request_depth_update(paint_stroke_view_context(stroke)->rv3d);
+ sculpt_cache_free(ss->cache);
+ ss->cache = NULL;
+ sculpt_undo_push(C, sd);
}
+}
- /* 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);
- }
+static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ sculpt_brush_stroke_init(C);
- return OPERATOR_FINISHED;
- }
+ op->customdata = paint_stroke_new(C, sculpt_stroke_test_start,
+ sculpt_stroke_update_step,
+ sculpt_stroke_done);
+ /* add modal handler */
+ WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
+
return OPERATOR_RUNNING_MODAL;
}
@@ -1594,10 +1485,10 @@ 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;
- view3d_operator_needs_opengl(C);
+ sculpt_brush_stroke_init(C);
+
sculpt_update_cache_invariants(sd, ss, C, op);
sculptmode_update_all_projverts(ss);
- sculpt_update_tex(sd, ss);
RNA_BEGIN(op->ptr, itemptr, "stroke") {
sculpt_update_cache_variants(sd, ss, &itemptr);
@@ -1627,7 +1518,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot)
/* api callbacks */
ot->invoke= sculpt_brush_stroke_invoke;
- ot->modal= sculpt_brush_stroke_modal;
+ ot->modal= paint_stroke_modal;
ot->exec= sculpt_brush_stroke_exec;
ot->poll= sculpt_poll;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 58b7a70a128..ce7b6ba454d 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -63,6 +63,7 @@
#include "RE_pipeline.h" // make_stars
#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -543,6 +544,18 @@ void view3d_get_object_project_mat(RegionView3D *rv3d, Object *ob, float pmat[4]
Mat4MulMat4(pmat, vmat, rv3d->winmat);
}
+/* Uses window coordinates (x,y) and depth component z to find a point in
+ modelspace */
+void view3d_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;
+}
/* use above call to get projecting mat */
void view3d_project_float(ARegion *ar, float *vec, float *adr, float mat[4][4])