Exemplo n.º 1
0
/* delete active frame - wrapper around API calls */
static int gp_actframe_delete_exec(bContext *C, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	bGPdata *gpd = gpencil_data_get_active(C);
	bGPDlayer *gpl = gpencil_layer_getactive(gpd);
	bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
	
	/* if there's no existing Grease-Pencil data there, add some */
	if (gpd == NULL) {
		BKE_report(op->reports, RPT_ERROR, "No grease pencil data");
		return OPERATOR_CANCELLED;
	}
	if (ELEM(NULL, gpl, gpf)) {
		BKE_report(op->reports, RPT_ERROR, "No active frame to delete");
		return OPERATOR_CANCELLED;
	}
	
	/* delete it... */
	gpencil_layer_delframe(gpl, gpf);
	
	/* notifiers */
	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
	
	return OPERATOR_FINISHED;
}
Exemplo n.º 2
0
static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
{
	Scene *scene = CTX_data_scene(C);
	bGPDlayer *gpl;
	bGPDframe *gpf;
	bGPDstroke *gps;
	RulerItem *ruler_item;
	const char *ruler_name = RULER_ID;
	bool changed = false;

	if (scene->gpd == NULL) {
		scene->gpd = gpencil_data_addnew("GPencil");
	}

	gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
	if (gpl == NULL) {
		gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false);
		gpl->thickness = 1;
		gpl->flag |= GP_LAYER_HIDE;
	}

	gpf = gpencil_layer_getframe(gpl, CFRA, true);
	free_gpencil_strokes(gpf);

	for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
		bGPDspoint *pt;
		int j;

		/* allocate memory for a new stroke */
		gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
		if (ruler_item->flag & RULERITEM_USE_ANGLE) {
			gps->totpoints = 3;
			pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
			for (j = 0; j < 3; j++) {
				copy_v3_v3(&pt->x, ruler_item->co[j]);
				pt->pressure = 1.0f;
				pt++;
			}
		}
		else {
			gps->totpoints = 2;
			pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
			for (j = 0; j < 3; j += 2) {
				copy_v3_v3(&pt->x, ruler_item->co[j]);
				pt->pressure = 1.0f;
				pt++;
			}
		}
		gps->flag = GP_STROKE_3DSPACE;
		BLI_addtail(&gpf->strokes, gps);
		changed = true;
	}

	return changed;
}
Exemplo n.º 3
0
/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode)
{
	Scene *scene = CTX_data_scene(C);
	bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
	bGPDstroke *gps;
	Object *ob;
	Curve *cu;

	/* camera framing */
	rctf subrect, *subrect_ptr = NULL;

	/* error checking */
	if (ELEM3(NULL, gpd, gpl, gpf))
		return;
		
	/* only convert if there are any strokes on this layer's frame to convert */
	if (gpf->strokes.first == NULL)
		return;

	/* initialize camera framing */
	if (gp_camera_view_subrect(C, &subrect)) {
		subrect_ptr = &subrect;
	}

	/* init the curve object (remove rotation and get curve data from it)
	 *	- must clear transforms set on object, as those skew our results
	 */
	ob = BKE_object_add(scene, OB_CURVE);
	zero_v3(ob->loc);
	zero_v3(ob->rot);
	cu = ob->data;
	cu->flag |= CU_3D;
	
	/* rename object and curve to layer name */
	rename_id((ID *)ob, gpl->info);
	rename_id((ID *)cu, gpl->info);
	
	/* add points to curve */
	for (gps = gpf->strokes.first; gps; gps = gps->next) {
		switch (mode) {
			case GP_STROKECONVERT_PATH: 
				gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr);
				break;
			case GP_STROKECONVERT_CURVE:
				gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr);
				break;
			default:
				BLI_assert(!"invalid mode");
				break;
		}
	}
}
static int gp_convert_poll(bContext *C)
{
	bGPdata *gpd = ED_gpencil_data_get_active(C);
	bGPDlayer *gpl = NULL;
	bGPDframe *gpf = NULL;
	ScrArea *sa = CTX_wm_area(C);
	Scene *scene = CTX_data_scene(C);
	
	/* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!),
	 * and if we are not in edit mode!
	 */
	return ((sa && sa->spacetype == SPACE_VIEW3D) &&
	        (gpl = gpencil_layer_getactive(gpd)) &&
	        (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) &&
	        (gpf->strokes.first) &&
	        (scene->obedit == NULL));
}
Exemplo n.º 5
0
/* delete the last stroke of the given frame */
void gpencil_frame_delete_laststroke(bGPDlayer *gpl, bGPDframe *gpf)
{
	bGPDstroke *gps = (gpf) ? gpf->strokes.last : NULL;
	int cfra = (gpf) ? gpf->framenum : 0; /* assume that the current frame was not locked */
	
	/* error checking */
	if (ELEM(NULL, gpf, gps))
		return;
	
	/* free the stroke and its data */
	MEM_freeN(gps->points);
	BLI_freelinkN(&gpf->strokes, gps);
	
	/* if frame has no strokes after this, delete it */
	if (BLI_listbase_is_empty(&gpf->strokes)) {
		gpencil_layer_delframe(gpl, gpf);
		gpencil_layer_getframe(gpl, cfra, 0);
	}
}
/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator.
 * op may be NULL.
 */
static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op)
{
	Scene *scene = CTX_data_scene(C);
	bGPDframe *gpf = NULL;
	bGPDstroke *gps = NULL;
	bGPDspoint *pt;
	double base_time, cur_time, prev_time = -1.0;
	int i;
	bool valid = true;
	
	if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first))
		return false;
	
	do {
		base_time = cur_time = gps->inittime;
		if (cur_time <= prev_time) {
			valid = false;
			break;
		}
		
		prev_time = cur_time;
		for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
			cur_time = base_time + (double)pt->time;
			/* First point of a stroke should have the same time as stroke's inittime,
			 * so it's the only case where equality is allowed!
			 */
			if ((i && cur_time <= prev_time) || (cur_time < prev_time)) {
				valid = false;
				break;
			}
			prev_time = cur_time;
		}
		
		if (!valid) {
			break;
		}
	} while ((gps = gps->next));
	
	if (op) {
		RNA_boolean_set(op->ptr, "use_timing_data", valid);
	}
	return valid;
}
Exemplo n.º 7
0
static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
{
	Scene *scene = CTX_data_scene(C);
	bool changed = false;

	if (scene->gpd) {
		bGPDlayer *gpl;
		const char *ruler_name = RULER_ID;
		gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
		if (gpl) {
			bGPDframe *gpf;
			gpf = gpencil_layer_getframe(gpl, CFRA, false);
			if (gpf) {
				bGPDstroke *gps;
				for (gps = gpf->strokes.first; gps; gps = gps->next) {
					bGPDspoint *pt = gps->points;
					int j;
					if (gps->totpoints == 3) {
						RulerItem *ruler_item = ruler_item_add(ruler_info);
						for (j = 0; j < 3; j++) {
							copy_v3_v3(ruler_item->co[j], &pt->x);
							pt++;
						}
						ruler_item->flag |= RULERITEM_USE_ANGLE;
						changed = true;
					}
					else if (gps->totpoints == 2) {
						RulerItem *ruler_item = ruler_item_add(ruler_info);
						for (j = 0; j < 3; j += 2) {
							copy_v3_v3(ruler_item->co[j], &pt->x);
							pt++;
						}
						changed = true;
					}
				}
			}
		}
	}

	return changed;
}
Exemplo n.º 8
0
/* Pastes keyframes from buffer, and reports success */
bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
{
	ListBase anim_data = {NULL, NULL};
	bAnimListElem *ale;
	int filter;
	
	Scene *scene = ac->scene;
	bool no_name = false;
	int offset = 0;
	
	/* check if buffer is empty */
	if (BLI_listbase_is_empty(&gp_anim_copybuf)) {
		BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste");
		return false;
	}
	
	/* check if single channel in buffer (disregard names if so)  */
	if (gp_anim_copybuf.first == gp_anim_copybuf.last) {
		no_name = true;
	}
	
	/* methods of offset (eKeyPasteOffset) */
	switch (offset_mode) {
		case KEYFRAME_PASTE_OFFSET_CFRA_START:
			offset = (CFRA - gp_anim_copy_firstframe);
			break;
		case KEYFRAME_PASTE_OFFSET_CFRA_END:
			offset = (CFRA - gp_anim_copy_lastframe);
			break;
		case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE:
			offset = (CFRA - gp_anim_copy_cfra);
			break;
		case KEYFRAME_PASTE_OFFSET_NONE:
			offset = 0;
			break;
	}

	
	/* filter data */
	// TODO: try doing it with selection, then without selection imits
	filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
	ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
	
	/* from selected channels */
	for (ale = anim_data.first; ale; ale = ale->next) {
		bGPDlayer *gpld = (bGPDlayer *)ale->data;
		bGPDlayer *gpls = NULL;
		bGPDframe *gpfs, *gpf;
		
		
		/* find suitable layer from buffer to use to paste from */
		for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) {
			/* check if layer name matches */
			if ((no_name) || STREQ(gpls->info, gpld->info)) {
				break;
			}
		}
		
		/* this situation might occur! */
		if (gpls == NULL)
			continue;
		
		/* add frames from buffer */
		for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) {
			/* temporarily apply offset to buffer-frame while copying */
			gpfs->framenum += offset;
			
			/* get frame to copy data into (if no frame returned, then just ignore) */
			gpf = gpencil_layer_getframe(gpld, gpfs->framenum, 1);
			if (gpf) {
				bGPDstroke *gps, *gpsn;
				
				/* This should be the right frame... as it may be a pre-existing frame,
				 * must make sure that only compatible stroke types get copied over
				 *	- We cannot just add a duplicate frame, as that would cause errors
				 *  - For now, we don't check if the types will be compatible since we
				 *    don't have enough info to do so. Instead, we simply just paste,
				 *    af it works, it will show up.
				 */
				for (gps = gpfs->strokes.first; gps; gps = gps->next) {
					/* make a copy of stroke, then of its points array */
					gpsn = MEM_dupallocN(gps);
					gpsn->points = MEM_dupallocN(gps->points);
					/* duplicate triangle information */
					gpsn->triangles = MEM_dupallocN(gps->triangles);
					/* append stroke to frame */
					BLI_addtail(&gpf->strokes, gpsn);				
				}
				
				/* if no strokes (i.e. new frame) added, free gpf */
				if (BLI_listbase_is_empty(&gpf->strokes))
					gpencil_layer_delframe(gpld, gpf);
			}
			
			/* unapply offset from buffer-frame */
			gpfs->framenum -= offset;
		}
	}
	
	/* clean up */
	ANIM_animdata_freelist(&anim_data);
	return true;
}
Exemplo n.º 9
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, *actlay=NULL;
	
	/* 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;
		
		/* if layer is active one, store pointer to it */
		if (gpl->flag & GP_LAYER_ACTIVE)
			actlay= gpl;
		
		/* get frame to draw */
		gpf= gpencil_layer_getframe(gpl, cfra, 0);
		if (gpf == NULL) 
			continue;
		
		/* set color, stroke thickness, and point size */
		glLineWidth(lthick);
		QUATCOPY(color, gpl->color); // just for copying 4 array elements
		QUATCOPY(tcolor, gpl->color); // additional copy of color (for ghosting)
		glColor4f(color[0], color[1], color[2], color[3]);
		glPointSize((float)(gpl->thickness + 2));
		
		/* 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= (float)(gpf->framenum - gf->framenum) / (float)gpl->gstep;
						tcolor[3] = color[3] - fac;
						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= (float)(gf->framenum - gpf->framenum) / (float)gpl->gstep;
						tcolor[3] = color[3] - fac;
						gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor);
					}
					else 
						break;
				}	
				
				/* restore alpha */
				glColor4f(color[0], color[1], color[2], color[3]);
			}
			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 */
				glColor4f(color[0], color[1], color[2], color[3]);
			}
		}
		
		/* 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 ((G.f & G_GREASEPENCIL) && (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);
}
/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, const int mode,
                              const bool norm_weights, const float rad_fac, const bool link_strokes, tGpTimingData *gtd)
{
	struct Main *bmain = CTX_data_main(C);
	View3D *v3d = CTX_wm_view3d(C);  /* may be NULL */
	Scene *scene = CTX_data_scene(C);
	bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0);
	bGPDstroke *gps, *prev_gps = NULL;
	Object *ob;
	Curve *cu;
	Nurb *nu = NULL;
	Base *base_orig = BASACT, *base_new = NULL;
	float minmax_weights[2] = {1.0f, 0.0f};
	
	/* camera framing */
	rctf subrect, *subrect_ptr = NULL;
	
	/* error checking */
	if (ELEM(NULL, gpd, gpl, gpf))
		return;
	
	/* only convert if there are any strokes on this layer's frame to convert */
	if (BLI_listbase_is_empty(&gpf->strokes))
		return;
	
	/* initialize camera framing */
	if (gp_camera_view_subrect(C, &subrect)) {
		subrect_ptr = &subrect;
	}
	
	/* init the curve object (remove rotation and get curve data from it)
	 *	- must clear transforms set on object, as those skew our results
	 */
	ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
	cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
	base_new = BKE_scene_base_add(scene, ob);
	
	cu->flag |= CU_3D;
	
	gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime;
	
	/* add points to curve */
	for (gps = gpf->strokes.first; gps; gps = gps->next) {
		const bool add_start_point = (link_strokes && !(prev_gps));
		const bool add_end_point = (link_strokes && !(gps->next));
		
		/* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */
		bool stitch = false;
		if (prev_gps) {
			bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1];
			bGPDspoint *pt2 = &gps->points[0];
			
			if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) {
				stitch = true;
			}
		}
		
		/* Decide whether we connect this stroke to previous one */
		if (!(stitch || link_strokes)) {
			nu = NULL;
		}
		
		switch (mode) {
			case GP_STROKECONVERT_PATH:
				gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
				                  add_start_point, add_end_point, gtd);
				break;
			case GP_STROKECONVERT_CURVE:
			case GP_STROKECONVERT_POLY:  /* convert after */
				gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch,
				                    add_start_point, add_end_point, gtd);
				break;
			default:
				BLI_assert(!"invalid mode");
				break;
		}
		prev_gps = gps;
	}
	
	/* If link_strokes, be sure first and last points have a zero weight/size! */
	if (link_strokes) {
		gp_stroke_finalize_curve_endpoints(cu);
	}
	
	/* Update curve's weights, if needed */
	if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) {
		gp_stroke_norm_curve_weights(cu, minmax_weights);
	}
	
	/* Create the path animation, if needed */
	gp_stroke_path_animation(C, reports, cu, gtd);
	
	if (mode == GP_STROKECONVERT_POLY) {
		for (nu = cu->nurb.first; nu; nu = nu->next) {
			BKE_nurb_type_convert(nu, CU_POLY, false);
		}
	}
	
	/* set the layer and select */
	base_new->lay  = ob->lay  = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
	base_new->flag = ob->flag = base_new->flag | SELECT;
}
Exemplo n.º 11
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);
			}
		}
	}
}
Exemplo n.º 12
0
void paste_gpdata (Scene *scene)
{
	ListBase act_data = {NULL, NULL};
	bActListElem *ale;
	int filter;
	void *data;
	short datatype;
	
	const int offset = (CFRA - gpcopy_firstframe);
	short no_name= 0;
	
	/* check if buffer is empty */
	if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
		error("No data in buffer to paste");
		return;
	}
	/* check if single channel in buffer (disregard names if so)  */
	if (gpcopybuf.first == gpcopybuf.last)
		no_name= 1;
	
	/* get data */
	data= get_action_context(&datatype);
	if (data == NULL) return;
	if (datatype != ACTCONT_GPENCIL) return;
	
	/* filter data */
	filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
	actdata_filter(&act_data, filter, data, datatype);
	
	/* from selected channels */
	for (ale= act_data.first; ale; ale= ale->next) {
		bGPDlayer *gpld= (bGPDlayer *)ale->data;
		bGPDlayer *gpls= NULL;
		bGPDframe *gpfs, *gpf;
		
		/* find suitable layer from buffer to use to paste from */
		for (gpls= gpcopybuf.first; gpls; gpls= gpls->next) {
			/* check if layer name matches */
			if ((no_name) || (strcmp(gpls->info, gpld->info)==0))
				break;
		}
		
		/* this situation might occur! */
		if (gpls == NULL)
			continue;
		
		/* add frames from buffer */
		for (gpfs= gpls->frames.first; gpfs; gpfs= gpfs->next) {
			/* temporarily apply offset to buffer-frame while copying */
			gpfs->framenum += offset;
			
			/* get frame to copy data into (if no frame returned, then just ignore) */
			gpf= gpencil_layer_getframe(gpld, gpfs->framenum, 1);
			if (gpf) {
				bGPDstroke *gps, *gpsn;
				ScrArea *sa;
				
				/* get area that gp-data comes from */
				//sa= gpencil_data_findowner((bGPdata *)ale->owner);	
				sa = NULL;
				
				/* this should be the right frame... as it may be a pre-existing frame, 
				 * must make sure that only compatible stroke types get copied over 
				 *	- we cannot just add a duplicate frame, as that would cause errors
				 *	- need to check for compatible types to minimise memory usage (copying 'junk' over)
				 */
				for (gps= gpfs->strokes.first; gps; gps= gps->next) {
					short stroke_ok;
					
					/* if there's an area, check that it supports this type of stroke */
					if (sa) {
						stroke_ok= 0;
						
						/* check if spacetype supports this type of stroke
						 *	- NOTE: must sync this with gp_paint_initstroke() in gpencil.c
						 */
						switch (sa->spacetype) {
							case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
								if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
									stroke_ok= 1;
								break;
								
							case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
							case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
								if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
									stroke_ok= 1;
								break;
								
							case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
								if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
									stroke_ok= 1;
								break;
						}
					}
					else
						stroke_ok= 1;
					
					/* if stroke is ok, we make a copy of this stroke and add to frame */
					if (stroke_ok) {
						/* make a copy of stroke, then of its points array */
						gpsn= MEM_dupallocN(gps);
						gpsn->points= MEM_dupallocN(gps->points);
						
						/* append stroke to frame */
						BLI_addtail(&gpf->strokes, gpsn);
					}
				}
				
				/* if no strokes (i.e. new frame) added, free gpf */
				if (gpf->strokes.first == NULL)
					gpencil_layer_delframe(gpld, gpf);
			}
			
			/* unapply offset from buffer-frame */
			gpfs->framenum -= offset;
		}
	}
	
	/* free temp memory */
	BLI_freelistN(&act_data);
	
	/* undo and redraw stuff */
	BIF_undo_push("Paste Grease Pencil Frames");
}