Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gpencil/gpencil_paint.c
| Show First 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | typedef struct tGPsdata { | ||||
| char *align_flag; /* projection-mode flags (toolsettings - eGPencil_Placement_Flags) */ | char *align_flag; /* projection-mode flags (toolsettings - eGPencil_Placement_Flags) */ | ||||
| eGPencil_PaintStatus status; /* current status of painting */ | eGPencil_PaintStatus status; /* current status of painting */ | ||||
| eGPencil_PaintModes paintmode; /* mode for painting */ | eGPencil_PaintModes paintmode; /* mode for painting */ | ||||
| eGPencil_PaintFlags flags; /* flags that can get set during runtime (eGPencil_PaintFlags) */ | eGPencil_PaintFlags flags; /* flags that can get set during runtime (eGPencil_PaintFlags) */ | ||||
| short radius; /* radius of influence for eraser */ | short radius; /* radius of influence for eraser */ | ||||
| int mval[2]; /* current mouse-position */ | float mval[2]; /* current mouse-position */ | ||||
| int mvalo[2]; /* previous recorded mouse-position */ | float mvalo[2]; /* previous recorded mouse-position */ | ||||
| float pressure; /* current stylus pressure */ | float pressure; /* current stylus pressure */ | ||||
| float opressure; /* previous stylus pressure */ | float opressure; /* previous stylus pressure */ | ||||
| /* These need to be doubles, as (at least under unix) they are in seconds since epoch, | /* These need to be doubles, as (at least under unix) they are in seconds since epoch, | ||||
| * float (and its 7 digits precision) is definitively not enough here! | * float (and its 7 digits precision) is definitively not enough here! | ||||
| * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. | * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | static void gp_get_3d_reference(tGPsdata *p, float vec[3]) | ||||
| if (p->ownerPtr.type == &RNA_Object) { | if (p->ownerPtr.type == &RNA_Object) { | ||||
| ob = (Object *)p->ownerPtr.data; | ob = (Object *)p->ownerPtr.data; | ||||
| } | } | ||||
| ED_gp_get_drawing_reference(p->scene, ob, p->gpl, *p->align_flag, vec); | ED_gp_get_drawing_reference(p->scene, ob, p->gpl, *p->align_flag, vec); | ||||
| } | } | ||||
| /* Stroke Editing ---------------------------- */ | /* Stroke Editing ---------------------------- */ | ||||
| /* check if the current mouse position is suitable for adding a new point */ | /* check if the current mouse position is suitable for adding a new point */ | ||||
| static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) | static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2]) | ||||
| { | { | ||||
| Brush *brush = p->brush; | Brush *brush = p->brush; | ||||
| int dx = abs(mval[0] - pmval[0]); | int dx = (int)fabsf(mval[0] - pmval[0]); | ||||
| int dy = abs(mval[1] - pmval[1]); | int dy = (int)fabsf(mval[1] - pmval[1]); | ||||
| brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP; | brush->gpencil_settings->flag &= ~GP_BRUSH_STABILIZE_MOUSE_TEMP; | ||||
| /* if buffer is empty, just let this go through (i.e. so that dots will work) */ | /* if buffer is empty, just let this go through (i.e. so that dots will work) */ | ||||
| if (p->gpd->runtime.sbuffer_size == 0) { | if (p->gpd->runtime.sbuffer_size == 0) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| /* if lazy mouse, check minimum distance */ | /* if lazy mouse, check minimum distance */ | ||||
| else if (GPENCIL_LAZY_MODE(brush, p->shift)) { | else if (GPENCIL_LAZY_MODE(brush, p->shift)) { | ||||
| brush->gpencil_settings->flag |= GP_BRUSH_STABILIZE_MOUSE_TEMP; | brush->gpencil_settings->flag |= GP_BRUSH_STABILIZE_MOUSE_TEMP; | ||||
| if ((dx * dx + dy * dy) > (brush->smooth_stroke_radius * brush->smooth_stroke_radius)) { | if ((dx * dx + dy * dy) > (brush->smooth_stroke_radius * brush->smooth_stroke_radius)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| else { | else { | ||||
| /* If the mouse is moving within the radius of the last move, | /* If the mouse is moving within the radius of the last move, | ||||
| * don't update the mouse position. This allows sharp turns. */ | * don't update the mouse position. This allows sharp turns. */ | ||||
| copy_v2_v2_int(p->mval, p->mvalo); | copy_v2_v2(p->mval, p->mvalo); | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| /* check if mouse moved at least certain distance on both axes (best case) | /* check if mouse moved at least certain distance on both axes (best case) | ||||
| * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand | * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand | ||||
| */ | */ | ||||
| else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) | else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) | ||||
| return true; | return true; | ||||
| Show All 32 Lines | static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps) | ||||
| /* get drawing origin */ | /* get drawing origin */ | ||||
| gp_get_3d_reference(p, origin); | gp_get_3d_reference(p, origin); | ||||
| ED_gp_project_stroke_to_plane(obact, rv3d, gps, origin, p->lock_axis - 1); | ED_gp_project_stroke_to_plane(obact, rv3d, gps, origin, p->lock_axis - 1); | ||||
| } | } | ||||
| /* convert screen-coordinates to buffer-coordinates */ | /* convert screen-coordinates to buffer-coordinates */ | ||||
| /* XXX this method needs a total overhaul! */ | /* XXX this method needs a total overhaul! */ | ||||
| static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) | static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[3], float *depth) | ||||
| { | { | ||||
| bGPdata *gpd = p->gpd; | bGPdata *gpd = p->gpd; | ||||
| /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ | /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ | ||||
| if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) { | if (gpd->runtime.sbuffer_sflag & GP_STROKE_3DSPACE) { | ||||
| /* add small offset to keep stroke over the surface */ | /* add small offset to keep stroke over the surface */ | ||||
| if ((depth) && (gpd->zdepth_offset > 0.0f)) { | if ((depth) && (gpd->zdepth_offset > 0.0f)) { | ||||
| *depth *= (1.0f - gpd->zdepth_offset); | *depth *= (1.0f - gpd->zdepth_offset); | ||||
| } | } | ||||
| if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval, out, 0, depth))) { | int mval_i[2]; | ||||
| round_v2i_v2fl(mval_i, mval); | |||||
| if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval_i, out, 0, depth))) { | |||||
| /* projecting onto 3D-Geometry | /* projecting onto 3D-Geometry | ||||
| * - nothing more needs to be done here, since view_autodist_simple() has already done it | * - nothing more needs to be done here, since view_autodist_simple() has already done it | ||||
| */ | */ | ||||
| /* verify valid zdepth, if it's wrong, the default darwing mode is used | /* verify valid zdepth, if it's wrong, the default darwing mode is used | ||||
| * and the function doesn't return now */ | * and the function doesn't return now */ | ||||
| if ((depth == NULL) || (*depth <= 1.0f)) { | if ((depth == NULL) || (*depth <= 1.0f)) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| float mval_prj[2]; | float mval_prj[2]; | ||||
| float rvec[3], dvec[3]; | float rvec[3], dvec[3]; | ||||
| float mval_f[2]; | float mval_f[2]; | ||||
| copy_v2fl_v2i(mval_f, mval); | |||||
| float zfac; | float zfac; | ||||
| /* Current method just converts each point in screen-coordinates to | /* Current method just converts each point in screen-coordinates to | ||||
| * 3D-coordinates using the 3D-cursor as reference. In general, this | * 3D-coordinates using the 3D-cursor as reference. In general, this | ||||
| * works OK, but it could of course be improved. | * works OK, but it could of course be improved. | ||||
| * | * | ||||
| * TODO: | * TODO: | ||||
| * - investigate using nearest point(s) on a previous stroke as | * - investigate using nearest point(s) on a previous stroke as | ||||
| * reference point instead or as offset, for easier stroke matching | * reference point instead or as offset, for easier stroke matching | ||||
| */ | */ | ||||
| gp_get_3d_reference(p, rvec); | gp_get_3d_reference(p, rvec); | ||||
| zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL); | zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL); | ||||
| if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { | if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { | ||||
| sub_v2_v2v2(mval_f, mval_prj, mval_f); | sub_v2_v2v2(mval_f, mval_prj, mval); | ||||
| ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac); | ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac); | ||||
| sub_v3_v3v3(out, rvec, dvec); | sub_v3_v3v3(out, rvec, dvec); | ||||
| } | } | ||||
| else { | else { | ||||
| zero_v3(out); | zero_v3(out); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* apply jitter to stroke */ | /* apply jitter to stroke */ | ||||
| static void gp_brush_jitter( | static void gp_brush_jitter( | ||||
| bGPdata *gpd, Brush *brush, tGPspoint *pt, const int mval[2], | bGPdata *gpd, Brush *brush, tGPspoint *pt, const float mval[2], | ||||
| const float pressure, int r_mval[2], RNG *rng) | const float pressure, float r_mval[2], RNG *rng) | ||||
| { | { | ||||
| float tmp_pressure = pressure; | float tmp_pressure = pressure; | ||||
| if (brush->gpencil_settings->draw_jitter > 0.0f) { | if (brush->gpencil_settings->draw_jitter > 0.0f) { | ||||
| float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, pressure); | float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_jitter, 0, pressure); | ||||
| tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity; | tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity; | ||||
| } | } | ||||
| const float exfactor = (brush->gpencil_settings->draw_jitter + 2.0f) * (brush->gpencil_settings->draw_jitter + 2.0f); /* exponential value */ | const float exfactor = (brush->gpencil_settings->draw_jitter + 2.0f) * (brush->gpencil_settings->draw_jitter + 2.0f); /* exponential value */ | ||||
| const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure; | const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure; | ||||
| /* Jitter is applied perpendicular to the mouse movement vector (2D space) */ | /* Jitter is applied perpendicular to the mouse movement vector (2D space) */ | ||||
| float mvec[2], svec[2]; | float mvec[2], svec[2]; | ||||
| /* mouse movement in ints -> floats */ | /* mouse movement in ints -> floats */ | ||||
| if (gpd->runtime.sbuffer_size > 1) { | if (gpd->runtime.sbuffer_size > 1) { | ||||
| mvec[0] = (float)(mval[0] - (pt - 1)->x); | mvec[0] = (mval[0] - (pt - 1)->x); | ||||
| mvec[1] = (float)(mval[1] - (pt - 1)->y); | mvec[1] = (mval[1] - (pt - 1)->y); | ||||
| normalize_v2(mvec); | normalize_v2(mvec); | ||||
| } | } | ||||
| else { | else { | ||||
| mvec[0] = 0.0f; | mvec[0] = 0.0f; | ||||
| mvec[1] = 0.0f; | mvec[1] = 0.0f; | ||||
| } | } | ||||
| /* rotate mvec by 90 degrees... */ | /* rotate mvec by 90 degrees... */ | ||||
| svec[0] = -mvec[1]; | svec[0] = -mvec[1]; | ||||
| svec[1] = mvec[0]; | svec[1] = mvec[0]; | ||||
| /* scale the displacement by the random, and apply */ | /* scale the displacement by the random, and apply */ | ||||
| if (BLI_rng_get_float(rng) > 0.5f) { | if (BLI_rng_get_float(rng) > 0.5f) { | ||||
| mul_v2_fl(svec, -fac); | mul_v2_fl(svec, -fac); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v2_fl(svec, fac); | mul_v2_fl(svec, fac); | ||||
| } | } | ||||
| r_mval[0] = mval[0] + svec[0]; | r_mval[0] = mval[0] + svec[0]; | ||||
| r_mval[1] = mval[1] + svec[1]; | r_mval[1] = mval[1] + svec[1]; | ||||
| } | } | ||||
| /* apply pressure change depending of the angle of the stroke to simulate a pen with shape */ | /* apply pressure change depending of the angle of the stroke to simulate a pen with shape */ | ||||
| static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const int mval[2]) | static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const float mval[2]) | ||||
| { | { | ||||
| float mvec[2]; | float mvec[2]; | ||||
| float sen = brush->gpencil_settings->draw_angle_factor; /* sensitivity */; | float sen = brush->gpencil_settings->draw_angle_factor; /* sensitivity */; | ||||
| float fac; | float fac; | ||||
| float mpressure; | float mpressure; | ||||
| float angle = brush->gpencil_settings->draw_angle; /* default angle of brush in radians */; | float angle = brush->gpencil_settings->draw_angle; /* default angle of brush in radians */; | ||||
| float v0[2] = { cos(angle), sin(angle) }; /* angle vector of the brush with full thickness */ | float v0[2] = { cos(angle), sin(angle) }; /* angle vector of the brush with full thickness */ | ||||
| /* Apply to first point (only if there are 2 points because before no data to do it ) */ | /* Apply to first point (only if there are 2 points because before no data to do it ) */ | ||||
| if (gpd->runtime.sbuffer_size == 1) { | if (gpd->runtime.sbuffer_size == 1) { | ||||
| mvec[0] = (float)(mval[0] - (pt - 1)->x); | mvec[0] = (mval[0] - (pt - 1)->x); | ||||
| mvec[1] = (float)(mval[1] - (pt - 1)->y); | mvec[1] = (mval[1] - (pt - 1)->y); | ||||
| normalize_v2(mvec); | normalize_v2(mvec); | ||||
| /* uses > 1.0f to get a smooth transition in first point */ | /* uses > 1.0f to get a smooth transition in first point */ | ||||
| fac = 1.4f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */ | fac = 1.4f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */ | ||||
| (pt - 1)->pressure = (pt - 1)->pressure - (sen * fac); | (pt - 1)->pressure = (pt - 1)->pressure - (sen * fac); | ||||
| CLAMP((pt - 1)->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f); | CLAMP((pt - 1)->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f); | ||||
| } | } | ||||
| /* apply from second point */ | /* apply from second point */ | ||||
| if (gpd->runtime.sbuffer_size >= 1) { | if (gpd->runtime.sbuffer_size >= 1) { | ||||
| mvec[0] = (float)(mval[0] - (pt - 1)->x); | mvec[0] = (mval[0] - (pt - 1)->x); | ||||
| mvec[1] = (float)(mval[1] - (pt - 1)->y); | mvec[1] = (mval[1] - (pt - 1)->y); | ||||
| normalize_v2(mvec); | normalize_v2(mvec); | ||||
| fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */ | fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */ | ||||
| /* interpolate with previous point for smoother transitions */ | /* interpolate with previous point for smoother transitions */ | ||||
| mpressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f); | mpressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f); | ||||
| pt->pressure = mpressure; | pt->pressure = mpressure; | ||||
| CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f); | CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f); | ||||
| Show All 32 Lines | static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) | ||||
| tGPspoint *ptd = &points[idx - 1]; | tGPspoint *ptd = &points[idx - 1]; | ||||
| float sco[2] = { 0.0f }; | float sco[2] = { 0.0f }; | ||||
| float a[2], b[2], c[2], d[2]; | float a[2], b[2], c[2], d[2]; | ||||
| const float average_fac = 1.0f / steps; | const float average_fac = 1.0f / steps; | ||||
| /* Compute smoothed coordinate by taking the ones nearby */ | /* Compute smoothed coordinate by taking the ones nearby */ | ||||
| if (pta) { | if (pta) { | ||||
| copy_v2fl_v2i(a, &pta->x); | copy_v2_v2(a, &pta->x); | ||||
| madd_v2_v2fl(sco, a, average_fac); | madd_v2_v2fl(sco, a, average_fac); | ||||
| } | } | ||||
| if (ptb) { | if (ptb) { | ||||
| copy_v2fl_v2i(b, &ptb->x); | copy_v2_v2(b, &ptb->x); | ||||
| madd_v2_v2fl(sco, b, average_fac); | madd_v2_v2fl(sco, b, average_fac); | ||||
| } | } | ||||
| if (ptc) { | if (ptc) { | ||||
| copy_v2fl_v2i(c, &ptc->x); | copy_v2_v2(c, &ptc->x); | ||||
| madd_v2_v2fl(sco, c, average_fac); | madd_v2_v2fl(sco, c, average_fac); | ||||
| } | } | ||||
| if (ptd) { | if (ptd) { | ||||
| copy_v2fl_v2i(d, &ptd->x); | copy_v2_v2(d, &ptd->x); | ||||
| madd_v2_v2fl(sco, d, average_fac); | madd_v2_v2fl(sco, d, average_fac); | ||||
| } | } | ||||
| /* Based on influence factor, blend between original and optimal smoothed coordinate */ | /* Based on influence factor, blend between original and optimal smoothed coordinate */ | ||||
| interp_v2_v2v2(c, c, sco, inf); | interp_v2_v2v2(c, c, sco, inf); | ||||
| round_v2i_v2fl(&ptc->x, c); | copy_v2_v2(&ptc->x, c); | ||||
| } | } | ||||
| /* add current stroke-point to buffer (returns whether point was successfully added) */ | /* add current stroke-point to buffer (returns whether point was successfully added) */ | ||||
| static short gp_stroke_addpoint( | static short gp_stroke_addpoint( | ||||
| tGPsdata *p, const int mval[2], float pressure, double curtime) | tGPsdata *p, const float mval[2], float pressure, double curtime) | ||||
| { | { | ||||
| bGPdata *gpd = p->gpd; | bGPdata *gpd = p->gpd; | ||||
| Brush *brush = p->brush; | Brush *brush = p->brush; | ||||
| tGPspoint *pt; | tGPspoint *pt; | ||||
| ToolSettings *ts = p->scene->toolsettings; | ToolSettings *ts = p->scene->toolsettings; | ||||
| Object *obact = (Object *)p->ownerPtr.data; | Object *obact = (Object *)p->ownerPtr.data; | ||||
| Depsgraph *depsgraph = p->depsgraph; | Depsgraph *depsgraph = p->depsgraph; | ||||
| RegionView3D *rv3d = p->ar->regiondata; | RegionView3D *rv3d = p->ar->regiondata; | ||||
| View3D *v3d = p->sa->spacedata.first; | View3D *v3d = p->sa->spacedata.first; | ||||
| MaterialGPencilStyle *gp_style = p->material->gp_style; | MaterialGPencilStyle *gp_style = p->material->gp_style; | ||||
| const int def_nr = obact->actdef - 1; | const int def_nr = obact->actdef - 1; | ||||
| const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr); | const bool have_weight = (bool)BLI_findlink(&obact->defbase, def_nr); | ||||
| /* check painting mode */ | /* check painting mode */ | ||||
| if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { | if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { | ||||
| /* straight lines only - i.e. only store start and end point in buffer */ | /* straight lines only - i.e. only store start and end point in buffer */ | ||||
| if (gpd->runtime.sbuffer_size == 0) { | if (gpd->runtime.sbuffer_size == 0) { | ||||
| /* first point in buffer (start point) */ | /* first point in buffer (start point) */ | ||||
| pt = (tGPspoint *)(gpd->runtime.sbuffer); | pt = (tGPspoint *)(gpd->runtime.sbuffer); | ||||
| /* store settings */ | /* store settings */ | ||||
| copy_v2_v2_int(&pt->x, mval); | copy_v2_v2(&pt->x, mval); | ||||
| pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | ||||
| pt->strength = 1.0f; | pt->strength = 1.0f; | ||||
| pt->time = (float)(curtime - p->inittime); | pt->time = (float)(curtime - p->inittime); | ||||
| /* increment buffer size */ | /* increment buffer size */ | ||||
| gpd->runtime.sbuffer_size++; | gpd->runtime.sbuffer_size++; | ||||
| } | } | ||||
| else { | else { | ||||
| /* just reset the endpoint to the latest value | /* just reset the endpoint to the latest value | ||||
| * - assume that pointers for this are always valid... | * - assume that pointers for this are always valid... | ||||
| */ | */ | ||||
| pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1); | pt = ((tGPspoint *)(gpd->runtime.sbuffer) + 1); | ||||
| /* store settings */ | /* store settings */ | ||||
| copy_v2_v2_int(&pt->x, mval); | copy_v2_v2(&pt->x, mval); | ||||
| pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | ||||
| pt->strength = 1.0f; | pt->strength = 1.0f; | ||||
| pt->time = (float)(curtime - p->inittime); | pt->time = (float)(curtime - p->inittime); | ||||
| /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ | /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ | ||||
| gpd->runtime.sbuffer_size = 2; | gpd->runtime.sbuffer_size = 2; | ||||
| } | } | ||||
| Show All 17 Lines | else if (p->paintmode == GP_PAINTMODE_DRAW) { /* normal drawing */ | ||||
| else { | else { | ||||
| pt->pressure = 1.0f; | pt->pressure = 1.0f; | ||||
| } | } | ||||
| /* Apply jitter to position */ | /* Apply jitter to position */ | ||||
| if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && | if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && | ||||
| (brush->gpencil_settings->draw_jitter > 0.0f)) | (brush->gpencil_settings->draw_jitter > 0.0f)) | ||||
| { | { | ||||
| int r_mval[2]; | float r_mval[2]; | ||||
| const float jitpress = (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) ? pressure : 1.0f; | const float jitpress = (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) ? pressure : 1.0f; | ||||
| gp_brush_jitter(gpd, brush, pt, mval, jitpress, r_mval, p->rng); | gp_brush_jitter(gpd, brush, pt, mval, jitpress, r_mval, p->rng); | ||||
| copy_v2_v2_int(&pt->x, r_mval); | copy_v2_v2(&pt->x, r_mval); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v2_v2_int(&pt->x, mval); | copy_v2_v2(&pt->x, mval); | ||||
| } | } | ||||
| /* apply randomness to pressure */ | /* apply randomness to pressure */ | ||||
| if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && | if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && | ||||
| (brush->gpencil_settings->draw_random_press > 0.0f)) | (brush->gpencil_settings->draw_random_press > 0.0f)) | ||||
| { | { | ||||
| float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_sensitivity, 0, pressure); | float curvef = curvemapping_evaluateF(brush->gpencil_settings->curve_sensitivity, 0, pressure); | ||||
| float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity; | float tmp_pressure = curvef * brush->gpencil_settings->draw_sensitivity; | ||||
| if (BLI_rng_get_float(p->rng) > 0.5f) { | if (BLI_rng_get_float(p->rng) > 0.5f) { | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { | ||||
| /* enable special flag for drawing engine */ | /* enable special flag for drawing engine */ | ||||
| gpd->flag |= GP_DATA_STROKE_POLYGON; | gpd->flag |= GP_DATA_STROKE_POLYGON; | ||||
| bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); | bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); | ||||
| /* get pointer to destination point */ | /* get pointer to destination point */ | ||||
| pt = (tGPspoint *)(gpd->runtime.sbuffer); | pt = (tGPspoint *)(gpd->runtime.sbuffer); | ||||
| /* store settings */ | /* store settings */ | ||||
| copy_v2_v2_int(&pt->x, mval); | copy_v2_v2(&pt->x, mval); | ||||
| pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ | ||||
| pt->strength = 1.0f; | pt->strength = 1.0f; | ||||
| pt->time = (float)(curtime - p->inittime); | pt->time = (float)(curtime - p->inittime); | ||||
| /* if there's stroke for this poly line session add (or replace last) point | /* if there's stroke for this poly line session add (or replace last) point | ||||
| * to stroke. This allows to draw lines more interactively (see new segment | * to stroke. This allows to draw lines more interactively (see new segment | ||||
| * during mouse slide, e.g.) | * during mouse slide, e.g.) | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| float *depth_arr = NULL; | float *depth_arr = NULL; | ||||
| /* get an array of depths, far depths are blended */ | /* get an array of depths, far depths are blended */ | ||||
| if (gpencil_project_check(p)) { | if (gpencil_project_check(p)) { | ||||
| int mval[2], mval_prev[2] = { 0 }; | int mval_prev[2] = { 0 }; | ||||
| int interp_depth = 0; | int interp_depth = 0; | ||||
| int found_depth = 0; | int found_depth = 0; | ||||
| depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points"); | depth_arr = MEM_mallocN(sizeof(float) * gpd->runtime.sbuffer_size, "depth_points"); | ||||
| for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) { | for (i = 0, ptc = gpd->runtime.sbuffer; i < gpd->runtime.sbuffer_size; i++, ptc++, pt++) { | ||||
| copy_v2_v2_int(mval, &ptc->x); | |||||
| if ((ED_view3d_autodist_depth(p->ar, mval, depth_margin, depth_arr + i) == 0) && | int mval_i[2]; | ||||
| (i && (ED_view3d_autodist_depth_seg(p->ar, mval, mval_prev, depth_margin + 1, depth_arr + i) == 0))) | round_v2i_v2fl(mval_i, &ptc->x); | ||||
| if ((ED_view3d_autodist_depth(p->ar, mval_i, depth_margin, depth_arr + i) == 0) && | |||||
| (i && (ED_view3d_autodist_depth_seg(p->ar, mval_i, mval_prev, depth_margin + 1, depth_arr + i) == 0))) | |||||
| { | { | ||||
| interp_depth = true; | interp_depth = true; | ||||
| } | } | ||||
| else { | else { | ||||
| found_depth = true; | found_depth = true; | ||||
| } | } | ||||
| copy_v2_v2_int(mval_prev, mval); | copy_v2_v2_int(mval_prev, mval_i); | ||||
| } | } | ||||
| if (found_depth == false) { | if (found_depth == false) { | ||||
| /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ | /* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */ | ||||
| for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) | for (i = gpd->runtime.sbuffer_size - 1; i >= 0; i--) | ||||
| depth_arr[i] = 0.9999f; | depth_arr[i] = 0.9999f; | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, const int x, const int y) | ||||
| Object *obact = (Object *)p->ownerPtr.data; | Object *obact = (Object *)p->ownerPtr.data; | ||||
| if ((p->sa->spacetype == SPACE_VIEW3D) && | if ((p->sa->spacetype == SPACE_VIEW3D) && | ||||
| (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) | (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH)) | ||||
| { | { | ||||
| RegionView3D *rv3d = p->ar->regiondata; | RegionView3D *rv3d = p->ar->regiondata; | ||||
| bGPDlayer *gpl = p->gpl; | bGPDlayer *gpl = p->gpl; | ||||
| const int mval[2] = {x, y}; | const int mval_i[2] = {x, y}; | ||||
| float mval_3d[3]; | float mval_3d[3]; | ||||
| float fpt[3]; | float fpt[3]; | ||||
| float diff_mat[4][4]; | float diff_mat[4][4]; | ||||
| /* calculate difference matrix if parent object */ | /* calculate difference matrix if parent object */ | ||||
| ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat); | ED_gpencil_parent_location(p->depsgraph, obact, p->gpd, gpl, diff_mat); | ||||
| if (ED_view3d_autodist_simple(p->ar, mval, mval_3d, 0, NULL)) { | if (ED_view3d_autodist_simple(p->ar, mval_i, mval_3d, 0, NULL)) { | ||||
| const float depth_mval = view3d_point_depth(rv3d, mval_3d); | const float depth_mval = view3d_point_depth(rv3d, mval_3d); | ||||
| mul_v3_m4v3(fpt, diff_mat, &pt->x); | mul_v3_m4v3(fpt, diff_mat, &pt->x); | ||||
| const float depth_pt = view3d_point_depth(rv3d, fpt); | const float depth_pt = view3d_point_depth(rv3d, fpt); | ||||
| if (depth_pt > depth_mval) { | if (depth_pt > depth_mval) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* apply a falloff effect to brush strength, based on distance */ | /* apply a falloff effect to brush strength, based on distance */ | ||||
| static float gp_stroke_eraser_calc_influence(tGPsdata *p, const int mval[2], const int radius, const int co[2]) | static float gp_stroke_eraser_calc_influence(tGPsdata *p, const float mval[2], const int radius, const int co[2]) | ||||
| { | { | ||||
| Brush *brush = p->brush; | Brush *brush = p->brush; | ||||
| /* Linear Falloff... */ | /* Linear Falloff... */ | ||||
| float distance = (float)len_v2v2_int(mval, co); | int mval_i[2]; | ||||
| round_v2i_v2fl(mval_i, mval); | |||||
| float distance = (float)len_v2v2_int(mval_i, co); | |||||
| float fac; | float fac; | ||||
| CLAMP(distance, 0.0f, (float)radius); | CLAMP(distance, 0.0f, (float)radius); | ||||
| fac = 1.0f - (distance / (float)radius); | fac = 1.0f - (distance / (float)radius); | ||||
| /* apply strength factor */ | /* apply strength factor */ | ||||
| fac *= brush->gpencil_settings->draw_strength; | fac *= brush->gpencil_settings->draw_strength; | ||||
| ▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | for (i = 1; i < gps->totpoints - 1; i++, pt++) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* eraser tool - evaluation per stroke */ | /* eraser tool - evaluation per stroke */ | ||||
| /* TODO: this could really do with some optimization (KD-Tree/BVH?) */ | /* TODO: this could really do with some optimization (KD-Tree/BVH?) */ | ||||
| static void gp_stroke_eraser_dostroke(tGPsdata *p, | static void gp_stroke_eraser_dostroke(tGPsdata *p, | ||||
| bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, | bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, | ||||
| const int mval[2], const int mvalo[2], | const float mval[2], const float mvalo[2], | ||||
| const int radius, const rcti *rect) | const int radius, const rcti *rect) | ||||
| { | { | ||||
| Depsgraph *depsgraph = p->depsgraph; | Depsgraph *depsgraph = p->depsgraph; | ||||
| Object *obact = (Object *)p->ownerPtr.data; | Object *obact = (Object *)p->ownerPtr.data; | ||||
| Brush *eraser = p->eraser; | Brush *eraser = p->eraser; | ||||
| bGPDspoint *pt0, *pt1, *pt2; | bGPDspoint *pt0, *pt1, *pt2; | ||||
| int pc0[2] = {0}; | int pc0[2] = {0}; | ||||
| int pc1[2] = {0}; | int pc1[2] = {0}; | ||||
| Show All 12 Lines | else if (gps->totpoints == 1) { | ||||
| /* only process if it hasn't been masked out... */ | /* only process if it hasn't been masked out... */ | ||||
| if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) { | if (!(p->flags & GP_PAINTFLAG_SELECTMASK) || (gps->points->flag & GP_SPOINT_SELECT)) { | ||||
| bGPDspoint pt_temp; | bGPDspoint pt_temp; | ||||
| gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); | gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); | ||||
| gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]); | gp_point_to_xy(&p->gsc, gps, &pt_temp, &pc1[0], &pc1[1]); | ||||
| /* do boundbox check first */ | /* do boundbox check first */ | ||||
| if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { | if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { | ||||
| /* only check if point is inside */ | /* only check if point is inside */ | ||||
| if (len_v2v2_int(mval, pc1) <= radius) { | int mval_i[2]; | ||||
| round_v2i_v2fl(mval_i, mval); | |||||
antoniov: Colud you calc mval_i outside of the loop? | |||||
| if (len_v2v2_int(mval_i, pc1) <= radius) { | |||||
| /* free stroke */ | /* free stroke */ | ||||
| gp_free_stroke(p->gpd, gpf, gps); | gp_free_stroke(p->gpd, gpf, gps); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else if ((p->flags & GP_PAINTFLAG_STROKE_ERASER) || (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_STROKE)) { | else if ((p->flags & GP_PAINTFLAG_STROKE_ERASER) || (eraser->gpencil_settings->eraser_mode == GP_BRUSH_ERASER_STROKE)) { | ||||
| for (i = 0; (i + 1) < gps->totpoints; i++) { | for (i = 0; (i + 1) < gps->totpoints; i++) { | ||||
| /* only process if it hasn't been masked out... */ | /* only process if it hasn't been masked out... */ | ||||
| if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT)) | if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT)) | ||||
| continue; | continue; | ||||
| /* get points to work with */ | /* get points to work with */ | ||||
| pt1 = gps->points + i; | pt1 = gps->points + i; | ||||
| bGPDspoint npt; | bGPDspoint npt; | ||||
| gp_point_to_parent_space(pt1, diff_mat, &npt); | gp_point_to_parent_space(pt1, diff_mat, &npt); | ||||
| gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); | gp_point_to_xy(&p->gsc, gps, &npt, &pc1[0], &pc1[1]); | ||||
| /* do boundbox check first */ | /* do boundbox check first */ | ||||
| if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { | if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { | ||||
| /* only check if point is inside */ | /* only check if point is inside */ | ||||
| if (len_v2v2_int(mval, pc1) <= radius) { | int mval_i[2]; | ||||
| round_v2i_v2fl(mval_i, mval); | |||||
| if (len_v2v2_int(mval_i, pc1) <= radius) { | |||||
Done Inline ActionsSame as above (calc outside loop) antoniov: Same as above (calc outside loop) | |||||
| /* free stroke */ | /* free stroke */ | ||||
| gp_free_stroke(p->gpd, gpf, gps); | gp_free_stroke(p->gpd, gpf, gps); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | for (gps = gpf->strokes.first; gps; gps = gpn) { | ||||
| /* check if the color is editable */ | /* check if the color is editable */ | ||||
| if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) { | if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Not all strokes in the datablock may be valid in the current editor/context | /* Not all strokes in the datablock may be valid in the current editor/context | ||||
| * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) | * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) | ||||
| */ | */ | ||||
| if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) { | if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) { | ||||
| gp_stroke_eraser_dostroke(p, gpl, gpf, gps, p->mval, p->mvalo, calc_radius, &rect); | gp_stroke_eraser_dostroke(p, gpl, gpf, gps, (float *)p->mval, (float *)p->mvalo, calc_radius, &rect); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ******************************************* */ | /* ******************************************* */ | ||||
| /* Sketching Operator */ | /* Sketching Operator */ | ||||
| ▲ Show 20 Lines • Show All 831 Lines • ▼ Show 20 Lines | static void gpencil_draw_apply(bContext *C, wmOperator *op, tGPsdata *p, Depsgraph *depsgraph) | ||||
| } | } | ||||
| /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ | /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ | ||||
| else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { | else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { | ||||
| /* if lazy mouse, interpolate the last and current mouse positions */ | /* if lazy mouse, interpolate the last and current mouse positions */ | ||||
| if (GPENCIL_LAZY_MODE(p->brush, p->shift)) { | if (GPENCIL_LAZY_MODE(p->brush, p->shift)) { | ||||
| float now_mouse[2]; | float now_mouse[2]; | ||||
| float last_mouse[2]; | float last_mouse[2]; | ||||
| copy_v2fl_v2i(now_mouse, p->mval); | copy_v2_v2(now_mouse, p->mval); | ||||
| copy_v2fl_v2i(last_mouse, p->mvalo); | copy_v2_v2(last_mouse, p->mvalo); | ||||
| interp_v2_v2v2(now_mouse, now_mouse, last_mouse, p->brush->smooth_stroke_factor); | interp_v2_v2v2(now_mouse, now_mouse, last_mouse, p->brush->smooth_stroke_factor); | ||||
| round_v2i_v2fl(p->mval, now_mouse); | copy_v2_v2(p->mval, now_mouse); | ||||
| } | } | ||||
| /* try to add point */ | /* try to add point */ | ||||
| short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); | short ok = gp_stroke_addpoint(p, (float *)p->mval, p->pressure, p->curtime); | ||||
| /* handle errors while adding point */ | /* handle errors while adding point */ | ||||
| if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { | if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { | ||||
| /* finish off old stroke */ | /* finish off old stroke */ | ||||
| gp_paint_strokeend(p); | gp_paint_strokeend(p); | ||||
| /* And start a new one!!! Else, projection errors! */ | /* And start a new one!!! Else, projection errors! */ | ||||
| gp_paint_initstroke(p, p->paintmode, depsgraph); | gp_paint_initstroke(p, p->paintmode, depsgraph); | ||||
| /* start a new stroke, starting from previous point */ | /* start a new stroke, starting from previous point */ | ||||
| /* XXX Must manually reset inittime... */ | /* XXX Must manually reset inittime... */ | ||||
| /* XXX We only need to reuse previous point if overflow! */ | /* XXX We only need to reuse previous point if overflow! */ | ||||
| if (ok == GP_STROKEADD_OVERFLOW) { | if (ok == GP_STROKEADD_OVERFLOW) { | ||||
| p->inittime = p->ocurtime; | p->inittime = p->ocurtime; | ||||
| gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); | gp_stroke_addpoint(p, (float *)p->mvalo, p->opressure, p->ocurtime); | ||||
| } | } | ||||
| else { | else { | ||||
| p->inittime = p->curtime; | p->inittime = p->curtime; | ||||
| } | } | ||||
| gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); | gp_stroke_addpoint(p, (float *)p->mval, p->pressure, p->curtime); | ||||
| } | } | ||||
| else if (ok == GP_STROKEADD_INVALID) { | else if (ok == GP_STROKEADD_INVALID) { | ||||
| /* the painting operation cannot continue... */ | /* the painting operation cannot continue... */ | ||||
| BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke"); | BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke"); | ||||
| p->status = GP_STATUS_ERROR; | p->status = GP_STATUS_ERROR; | ||||
| if (G.debug & G_DEBUG) | if (G.debug & G_DEBUG) | ||||
| printf("Error: Grease-Pencil Paint - Add Point Invalid\n"); | printf("Error: Grease-Pencil Paint - Add Point Invalid\n"); | ||||
| Show All 17 Lines | else if ((p->brush->gpencil_settings->flag & GP_BRUSH_STABILIZE_MOUSE_TEMP) && | ||||
| pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; | pt = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_size - 1; | ||||
| if (p->paintmode != GP_PAINTMODE_ERASER) { | if (p->paintmode != GP_PAINTMODE_ERASER) { | ||||
| ED_gpencil_toggle_brush_cursor(C, true, &pt->x); | ED_gpencil_toggle_brush_cursor(C, true, &pt->x); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* handle draw event */ | /* handle draw event */ | ||||
| static void gpencil_draw_apply_event(bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, int x, int y) | static void gpencil_draw_apply_event(bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) | ||||
| { | { | ||||
| tGPsdata *p = op->customdata; | tGPsdata *p = op->customdata; | ||||
| PointerRNA itemptr; | PointerRNA itemptr; | ||||
| float mousef[2]; | float mousef[2]; | ||||
| int tablet = 0; | int tablet = 0; | ||||
| /* convert from window-space to area-space mouse coordinates | /* convert from window-space to area-space mouse coordinates | ||||
| * add any x,y override position for fake events | * add any x,y override position for fake events | ||||
| * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... | * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... | ||||
| */ | */ | ||||
| p->mval[0] = event->mval[0] + 1 - x; | p->mval[0] = event->mval[0] + 1.0f - x; | ||||
| p->mval[1] = event->mval[1] + 1 - y; | p->mval[1] = event->mval[1] + 1.0f - y; | ||||
| p->shift = event->shift; | p->shift = event->shift; | ||||
| /* verify key status for straight lines */ | /* verify key status for straight lines */ | ||||
| if ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false)) { | if ((event->alt > 0) && (RNA_boolean_get(op->ptr, "disable_straight") == false)) { | ||||
| if (p->straight[0] == 0) { | if (p->straight[0] == 0) { | ||||
| int dx = abs(p->mval[0] - p->mvalo[0]); | int dx = abs(p->mval[0] - p->mvalo[0]); | ||||
| int dy = abs(p->mval[1] - p->mvalo[1]); | int dy = abs(p->mval[1] - p->mvalo[1]); | ||||
| if ((dx > 0) || (dy > 0)) { | if ((dx > 0) || (dy > 0)) { | ||||
| ▲ Show 20 Lines • Show All 380 Lines • ▼ Show 20 Lines | static void gpencil_add_missing_events(bContext *C, wmOperator *op, const wmEvent *event, tGPsdata *p) | ||||
| else if (samples < 7) { | else if (samples < 7) { | ||||
| dot_factor = 0.3f; | dot_factor = 0.3f; | ||||
| } | } | ||||
| else if (samples < 10) { | else if (samples < 10) { | ||||
| dot_factor = 0.4f; | dot_factor = 0.4f; | ||||
| } | } | ||||
| float factor = ((thickness * dot_factor) / scale) * samples; | float factor = ((thickness * dot_factor) / scale) * samples; | ||||
| copy_v2fl_v2i(a, p->mvalo); | copy_v2_v2(a, p->mvalo); | ||||
| b[0] = event->mval[0] + 1; | b[0] = event->mval[0] + 1; | ||||
| b[1] = event->mval[1] + 1; | b[1] = event->mval[1] + 1; | ||||
| /* get distance in pixels */ | /* get distance in pixels */ | ||||
| float dist = len_v2v2(a, b); | float dist = len_v2v2(a, b); | ||||
| /* for very small distances, add a half way point */ | /* for very small distances, add a half way point */ | ||||
| if (dist <= 2.0f) { | if (dist <= 2.0f) { | ||||
| ▲ Show 20 Lines • Show All 392 Lines • Show Last 20 Lines | |||||
Colud you calc mval_i outside of the loop?