Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / gpencil / gpencil_paint.c
index af14050..c28d80a 100644 (file)
 #include "ED_view3d.h"
 #include "ED_clip.h"
 
-#include "BIF_gl.h"
 #include "BIF_glutil.h"
 
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "DEG_depsgraph.h"
+
 #include "gpencil_intern.h"
 
 /* ******************************************* */
@@ -112,6 +116,7 @@ typedef enum eGPencil_PaintFlags {
  */
 typedef struct tGPsdata {
        Scene *scene;       /* current scene from context */
+       struct Depsgraph *depsgraph;
 
        wmWindow *win;      /* window where painting originated */
        ScrArea *sa;        /* area where painting originated */
@@ -231,7 +236,7 @@ static bool gpencil_project_check(tGPsdata *p)
 static void gp_get_3d_reference(tGPsdata *p, float vec[3])
 {
        View3D *v3d = p->sa->spacedata.first;
-       const float *fp = ED_view3d_cursor3d_get(p->scene, v3d);
+       const float *fp = ED_view3d_cursor3d_get(p->scene, v3d)->location;
 
        /* the reference point used depends on the owner... */
 #if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */
@@ -480,7 +485,8 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
 }
 
 /* add current stroke-point to buffer (returns whether point was successfully added) */
-static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime)
+static short gp_stroke_addpoint(
+        tGPsdata *p, const int mval[2], float pressure, double curtime)
 {
        bGPdata *gpd = p->gpd;
        bGPDbrush *brush = p->brush;
@@ -638,7 +644,8 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
                                View3D *v3d = p->sa->spacedata.first;
 
                                view3d_region_operator_needs_opengl(p->win, p->ar);
-                               ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+                               ED_view3d_autodist_init(
+                                       p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
                        }
 
                        /* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -672,7 +679,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure,
 
 /* simplify a stroke (in buffer) before storing it
  *     - applies a reverse Chaikin filter
- *     - code adapted from etch-a-ton branch (editarmature_sketch.c)
+ *     - code adapted from etch-a-ton branch
  */
 static void gp_stroke_simplify(tGPsdata *p)
 {
@@ -1238,9 +1245,8 @@ static void gp_stroke_doeraser(tGPsdata *p)
        if (p->sa->spacetype == SPACE_VIEW3D) {
                if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) {
                        View3D *v3d = p->sa->spacedata.first;
-
                        view3d_region_operator_needs_opengl(p->win, p->ar);
-                       ED_view3d_autodist_init(p->scene, p->ar, v3d, 0);
+                       ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, 0);
                }
        }
 
@@ -1394,6 +1400,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
 
        /* pass on current scene and window */
        p->scene = CTX_data_scene(C);
+       p->depsgraph = CTX_data_depsgraph(C);
        p->win = CTX_wm_window(C);
 
        unit_m4(p->imat);
@@ -1548,6 +1555,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
        bGPDpalettecolor *palcolor = p->palettecolor;
        bGPdata *pdata = p->gpd;
        copy_v4_v4(pdata->scolor, palcolor->color);
+       copy_v4_v4(pdata->sfill, palcolor->fill);
        pdata->sflag = palcolor->flag;
        /* lock axis */
        p->lock_axis = ts->gp_sculpt.lock_axis;
@@ -1598,7 +1606,7 @@ static void gp_session_cleanup(tGPsdata *p)
 }
 
 /* init new stroke */
-static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
+static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
 {
        Scene *scene = p->scene;
        ToolSettings *ts = scene->toolsettings;
@@ -1727,7 +1735,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
 
                        /* for camera view set the subrect */
                        if (rv3d->persp == RV3D_CAMOB) {
-                               ED_view3d_calc_camera_border(p->scene, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
+                               ED_view3d_calc_camera_border(p->scene, depsgraph, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */
                                p->subrect = &p->subrect_data;
                        }
                }
@@ -1805,7 +1813,7 @@ static void gp_paint_strokeend(tGPsdata *p)
 
                /* need to restore the original projection settings before packing up */
                view3d_region_operator_needs_opengl(p->win, p->ar);
-               ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
+               ED_view3d_autodist_init(p->depsgraph, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0);
        }
 
        /* check if doing eraser or not */
@@ -1845,26 +1853,39 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
        tGPsdata *p = (tGPsdata *)p_ptr;
 
        if (p->paintmode == GP_PAINTMODE_ERASER) {
-               glPushMatrix();
-
-               glTranslatef((float)x, (float)y, 0.0f);
+               Gwn_VertFormat *format = immVertexFormat();
+               const uint shdr_pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 
                glEnable(GL_LINE_SMOOTH);
                glEnable(GL_BLEND);
+               glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+               immUniformColor4ub(255, 100, 100, 20);
+               imm_draw_circle_fill_2d(shdr_pos, x, y, p->radius, 40);
 
-               glColor4ub(255, 100, 100, 20);
-               glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40);
+               immUnbindProgram();
 
-               setlinestyle(6);
+               immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
 
-               glColor4ub(255, 100, 100, 200);
-               glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40);
+               float viewport_size[4];
+               glGetFloatv(GL_VIEWPORT, viewport_size);
+               immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+
+               immUniformColor4f(1.0f, 0.39f, 0.39f, 0.78f);
+               immUniform1i("num_colors", 0);  /* "simple" mode */
+               immUniform1f("dash_width", 12.0f);
+               immUniform1f("dash_factor", 0.5f);
+
+               imm_draw_circle_wire_2d(shdr_pos, x, y, p->radius,
+                                    /* XXX Dashed shader gives bad results with sets of small segments currently,
+                                     *     temp hack around the issue. :( */
+                                    max_ii(8, p->radius / 2));  /* was fixed 40 */
+
+               immUnbindProgram();
 
-               setlinestyle(0);
                glDisable(GL_BLEND);
                glDisable(GL_LINE_SMOOTH);
-
-               glPopMatrix();
        }
 }
 
@@ -1955,7 +1976,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event)
        }
 
        /* init painting data */
-       gp_paint_initstroke(p, paintmode);
+       gp_paint_initstroke(p, paintmode, CTX_data_depsgraph(C));
        if (p->status == GP_STATUS_ERROR) {
                gpencil_draw_exit(C, op);
                return 0;
@@ -2032,7 +2053,7 @@ static void gpencil_draw_status_indicators(tGPsdata *p)
 /* ------------------------------- */
 
 /* create a new stroke point at the point indicated by the painting context */
-static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
+static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph)
 {
        /* handle drawing/erasing -> test for erasing first */
        if (p->paintmode == GP_PAINTMODE_ERASER) {
@@ -2054,7 +2075,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
                        /* finish off old stroke */
                        gp_paint_strokeend(p);
                        /* And start a new one!!! Else, projection errors! */
-                       gp_paint_initstroke(p, p->paintmode);
+                       gp_paint_initstroke(p, p->paintmode, depsgraph);
 
                        /* start a new stroke, starting from previous point */
                        /* XXX Must manually reset inittime... */
@@ -2087,7 +2108,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p)
 }
 
 /* handle draw event */
-static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
+static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event, Depsgraph *depsgraph)
 {
        tGPsdata *p = op->customdata;
        PointerRNA itemptr;
@@ -2192,7 +2213,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
        RNA_float_set(&itemptr, "time", p->curtime - p->inittime);
 
        /* apply the current latest drawing point */
-       gpencil_draw_apply(op, p);
+       gpencil_draw_apply(op, p, depsgraph);
 
        /* force refresh */
        ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
@@ -2204,6 +2225,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event)
 static int gpencil_draw_exec(bContext *C, wmOperator *op)
 {
        tGPsdata *p = NULL;
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
 
        /* printf("GPencil - Starting Re-Drawing\n"); */
 
@@ -2241,7 +2263,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
                        if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) {
                                /* TODO: both of these ops can set error-status, but we probably don't need to worry */
                                gp_paint_strokeend(p);
-                               gp_paint_initstroke(p, p->paintmode);
+                               gp_paint_initstroke(p, p->paintmode, depsgraph);
                        }
                }
 
@@ -2256,7 +2278,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op)
                }
 
                /* apply this data as necessary now (as per usual) */
-               gpencil_draw_apply(op, p);
+               gpencil_draw_apply(op, p, depsgraph);
        }
        RNA_END;
 
@@ -2315,7 +2337,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
                p->status = GP_STATUS_PAINTING;
 
                /* handle the initial drawing - i.e. for just doing a simple dot */
-               gpencil_draw_apply_event(op, event);
+               gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
                op->flag |= OP_IS_MODAL_CURSOR_REGION;
        }
        else {
@@ -2356,7 +2378,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op)
         *      it'd be nice to allow changing paint-mode when in sketching-sessions */
 
        if (gp_session_initdata(C, p))
-               gp_paint_initstroke(p, p->paintmode);
+               gp_paint_initstroke(p, p->paintmode, CTX_data_depsgraph(C));
 
        if (p->status != GP_STATUS_ERROR) {
                p->status = GP_STATUS_PAINTING;
@@ -2647,7 +2669,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
                if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) {
                        /* handle drawing event */
                        /* printf("\t\tGP - add point\n"); */
-                       gpencil_draw_apply_event(op, event);
+                       gpencil_draw_apply_event(op, event, CTX_data_depsgraph(C));
 
                        /* finish painting operation if anything went wrong just now */
                        if (p->status == GP_STATUS_ERROR) {