Example #1
0
/* note: also check undo_history_exec() in bottom if you change notifiers */
static int ed_undo_step(bContext *C, int step, const char *undoname)
{
	wmWindowManager *wm = CTX_wm_manager(C);
	wmWindow *win = CTX_wm_window(C);
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	ScrArea *sa = CTX_wm_area(C);

	/* undo during jobs are running can easily lead to freeing data using by jobs,
	 * or they can just lead to freezing job in some other cases */
	if (WM_jobs_test(wm, scene, WM_JOB_TYPE_ANY)) {
		return OPERATOR_CANCELLED;
	}

	/* grease pencil can be can be used in plenty of spaces, so check it first */
	if (ED_gpencil_session_active()) {
		return ED_undo_gpencil_step(C, step, undoname);
	}

	if (sa && (sa->spacetype == SPACE_IMAGE)) {
		SpaceImage *sima = (SpaceImage *)sa->spacedata.first;
		
		if ((obact && (obact->mode & OB_MODE_TEXTURE_PAINT)) || (sima->mode == SI_MODE_PAINT)) {
			if (!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) {
				if (U.uiflag & USER_GLOBALUNDO) {
					ED_viewport_render_kill_jobs(C, true);
					BKE_undo_name(C, undoname);
				}
			}
			
			WM_event_add_notifier(C, NC_WINDOW, NULL);
			return OPERATOR_FINISHED;
		}
	}

	if (sa && (sa->spacetype == SPACE_TEXT)) {
		ED_text_undo_step(C, step);
	}
	else if (obedit) {
		if (OB_TYPE_SUPPORT_EDITMODE(obedit->type)) {
			if (undoname)
				undo_editmode_name(C, undoname);
			else
				undo_editmode_step(C, step);
			
			WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
		}
	}
	else {
		/* Note: we used to do a fall-through here where if the
		 * mode-specific undo system had no more steps to undo (or
		 * redo), the global undo would run.
		 *
		 * That was inconsistent with editmode, and also makes for
		 * unecessarily tricky interaction with the other undo
		 * systems. */
		if (obact && obact->mode & OB_MODE_TEXTURE_PAINT) {
			ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname);
		}
		else if (obact && obact->mode & OB_MODE_SCULPT) {
			ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname);
		}
		else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
			if (step == 1)
				PE_undo(scene);
			else
				PE_redo(scene);
		}
		else if (U.uiflag & USER_GLOBALUNDO) {
			// note python defines not valid here anymore.
			//#ifdef WITH_PYTHON
			// XXX		BPY_scripts_clear_pyobjects();
			//#endif
			
			/* for global undo/redo we should just clear the editmode stack */
			/* for example, texface stores image pointers */
			undo_editmode_clear();
			
			ED_viewport_render_kill_jobs(C, true);

			if (undoname)
				BKE_undo_name(C, undoname);
			else
				BKE_undo_step(C, step);

			scene = CTX_data_scene(C);
				
			WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
		}
	}
	
	WM_event_add_notifier(C, NC_WINDOW, NULL);

	if (win) {
		win->addmousemove = true;
	}
	
	return OPERATOR_FINISHED;
}
Example #2
0
/* loop over gpencil data layers, drawing them */
static void gp_draw_data_layers(bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
	bGPDlayer *gpl;
	
	for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
		bGPDframe *gpf;
		
		bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false;
		short lthick = gpl->thickness;
		
		/* don't draw layer if hidden */
		if (gpl->flag & GP_LAYER_HIDE)
			continue;
		
		/* get frame to draw */
		gpf = gpencil_layer_getframe(gpl, cfra, 0);
		if (gpf == NULL)
			continue;
		
		/* set basic stroke thickness */
		glLineWidth(lthick);
		
		/* Add layer drawing settings to the set of "draw flags"
		 * NOTE: If the setting doesn't apply, it *must* be cleared,
		 *       as dflag's carry over from the previous layer
		 */
#define GP_DRAWFLAG_APPLY(condition, draw_flag_value)     { \
			if (condition) dflag |= (draw_flag_value);      \
			else           dflag &= ~(draw_flag_value);     \
		} (void)0
		
		/* xray... */
		GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY);
		
		/* volumetric strokes... */
		GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC);
		
		/* fill strokes... */
		// XXX: this is not a very good limit
		GP_DRAWFLAG_APPLY((gpl->fill[3] > GPENCIL_ALPHA_OPACITY_THRESH), GP_DRAWDATA_FILL);
#undef GP_DRAWFLAG_APPLY
		
		/* draw 'onionskins' (frame left + right) */
		if ((gpl->flag & GP_LAYER_ONIONSKIN) && !(dflag & GP_DRAWDATA_NO_ONIONS)) {
			/* Drawing method - only immediately surrounding (gstep = 0),
			 * or within a frame range on either side (gstep > 0)
			 */
			gp_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, lthick);
		}
		
		/* draw the strokes already in active frame */
		gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, gpl->color, gpl->fill);
		
		/* Draw verts of selected strokes
		 *  - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering
		 * 	- locked layers can't be edited, so there's no point showing these verts
		 *    as they will have no bearings on what gets edited
		 *  - only show when in editmode, since operators shouldn't work otherwise
		 *    (NOTE: doing it this way means that the toggling editmode shows visible change immediately)
		 */
		/* XXX: perhaps we don't want to show these when users are drawing... */
		if ((G.f & G_RENDER_OGL) == 0 &&
		    (gpl->flag & GP_LAYER_LOCKED) == 0 &&
		    (gpd->flag & GP_DATA_STROKE_EDITMODE))
		{
			gp_draw_strokes_edit(gpf, offsx, offsy, winx, winy, dflag,
			                     (gpl->color[3] < 0.95f) ? gpl->color : NULL);
		}
		
		/* Check if may need to draw the active stroke cache, only if this layer is the active layer
		 * that is being edited. (Stroke buffer is currently stored in gp-data)
		 */
		if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
		    (gpf->flag & GP_FRAME_PAINT))
		{
			/* Set color for drawing buffer stroke - since this may not be set yet */
			glColor4fv(gpl->color);
			
			/* Buffer stroke needs to be drawn with a different linestyle
			 * to help differentiate them from normal strokes.
			 * 
			 * It should also be noted that sbuffer contains temporary point types
			 * i.e. tGPspoints NOT bGPDspoints
			 */
			if (gpl->flag & GP_LAYER_VOLUMETRIC) {
				gp_draw_stroke_volumetric_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
			}
			else {
				gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
			}
		}
	}
}
Example #3
0
/* draw grease-pencil datablock */
static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
    bGPDlayer *gpl;

    /* reset line drawing style (in case previous user didn't reset) */
    setlinestyle(0);

    /* turn on smooth lines (i.e. anti-aliasing) */
    glEnable(GL_LINE_SMOOTH);

    /* turn on alpha-blending */
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    /* loop over layers, drawing them */
    for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
        bGPDframe *gpf;

        short debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? 1 : 0;
        short lthick= gpl->thickness;
        float color[4], tcolor[4];

        /* don't draw layer if hidden */
        if (gpl->flag & GP_LAYER_HIDE)
            continue;

        /* get frame to draw */
        gpf= gpencil_layer_getframe(gpl, cfra, 0);
        if (gpf == NULL)
            continue;

        /* set color, stroke thickness, and point size */
        glLineWidth(lthick);
        copy_v4_v4(color, gpl->color); // just for copying 4 array elements
        copy_v4_v4(tcolor, gpl->color); // additional copy of color (for ghosting)
        glColor4fv(color);
        glPointSize((float)(gpl->thickness + 2));

        /* apply xray layer setting */
        if (gpl->flag & GP_LAYER_NO_XRAY)	dflag |=  GP_DRAWDATA_NO_XRAY;
        else								dflag &= ~GP_DRAWDATA_NO_XRAY;

        /* draw 'onionskins' (frame left + right) */
        if (gpl->flag & GP_LAYER_ONIONSKIN) {
            /* drawing method - only immediately surrounding (gstep = 0), or within a frame range on either side (gstep > 0)*/
            if (gpl->gstep) {
                bGPDframe *gf;
                float fac;

                /* draw previous frames first */
                for (gf=gpf->prev; gf; gf=gf->prev) {
                    /* check if frame is drawable */
                    if ((gpf->framenum - gf->framenum) <= gpl->gstep) {
                        /* alpha decreases with distance from curframe index */
                        fac= 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1));
                        tcolor[3] = color[3] * fac * 0.66f;
                        gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
                    }
                    else
                        break;
                }

                /* now draw next frames */
                for (gf= gpf->next; gf; gf=gf->next) {
                    /* check if frame is drawable */
                    if ((gf->framenum - gpf->framenum) <= gpl->gstep) {
                        /* alpha decreases with distance from curframe index */
                        fac= 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep + 1));
                        tcolor[3] = color[3] * fac * 0.66f;
                        gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
                    }
                    else
                        break;
                }

                /* restore alpha */
                glColor4fv(color);
            }
            else {
                /* draw the strokes for the ghost frames (at half of the alpha set by user) */
                if (gpf->prev) {
                    tcolor[3] = (color[3] / 7);
                    gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
                }

                if (gpf->next) {
                    tcolor[3] = (color[3] / 4);
                    gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
                }

                /* restore alpha */
                glColor4fv(color);
            }
        }

        /* draw the strokes already in active frame */
        tcolor[3]= color[3];
        gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);

        /* Check if may need to draw the active stroke cache, only if this layer is the active layer
         * that is being edited. (Stroke buffer is currently stored in gp-data)
         */
        if (ED_gpencil_session_active() && (gpl->flag & GP_LAYER_ACTIVE) &&
                (gpf->flag & GP_FRAME_PAINT))
        {
            /* Buffer stroke needs to be drawn with a different linestyle to help differentiate them from normal strokes. */
            gp_draw_stroke_buffer(gpd->sbuffer, gpd->sbuffer_size, lthick, dflag, gpd->sbuffer_sflag);
        }
    }

    /* turn off alpha blending, then smooth lines */
    glDisable(GL_BLEND); // alpha blending
    glDisable(GL_LINE_SMOOTH); // smooth lines

    /* restore initial gl conditions */
    glLineWidth(1.0);
    glPointSize(1.0);
    glColor4f(0, 0, 0, 1);
}