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:
Diffstat (limited to 'source/blender/src/gpencil.c')
-rw-r--r--source/blender/src/gpencil.c172
1 files changed, 156 insertions, 16 deletions
diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c
index 0148ace20d4..6bbaecc2956 100644
--- a/source/blender/src/gpencil.c
+++ b/source/blender/src/gpencil.c
@@ -46,6 +46,7 @@
#include "BLI_blenlib.h"
#include "DNA_listBase.h"
+#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
@@ -59,11 +60,13 @@
#include "BKE_global.h"
#include "BKE_utildefines.h"
#include "BKE_blender.h"
+#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BIF_butspace.h"
+#include "BIF_editarmature.h"
#include "BIF_editview.h"
#include "BIF_graphics.h"
#include "BIF_interface.h"
@@ -719,8 +722,10 @@ static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float
}
}
+/* --- */
+
/* convert stroke to 3d path */
-static void gp_layer_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
{
bGPDspoint *pt;
Nurb *nu;
@@ -756,7 +761,7 @@ static void gp_layer_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
}
/* convert stroke to 3d bezier */
-static void gp_layer_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
+static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu)
{
bGPDspoint *pt;
Nurb *nu;
@@ -828,18 +833,105 @@ static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode)
for (gps= gpf->strokes.first; gps; gps= gps->next) {
switch (mode) {
case 1:
- gp_layer_to_path(gpl, gps, cu);
+ gp_stroke_to_path(gpl, gps, cu);
break;
case 2:
- gp_layer_to_bezier(gpl, gps, cu);
+ gp_stroke_to_bezier(gpl, gps, cu);
break;
}
}
}
+/* --- */
+
+/* convert a stroke to a bone chain */
+static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones)
+{
+ EditBone *ebo, *prev=NULL;
+ bGPDspoint *pt, *ptn;
+ int i;
+
+ /* add each segment separately */
+ for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) {
+ float p3da[3], p3db[3];
+
+ /* get coordinates to add at */
+ gp_strokepoint_convertcoords(gps, pt, p3da);
+ gp_strokepoint_convertcoords(gps, ptn, p3db);
+
+ /* allocate new bone */
+ ebo= MEM_callocN(sizeof(EditBone), "eBone");
+
+ VecCopyf(ebo->head, p3da);
+ VecCopyf(ebo->tail, p3db);
+
+ /* add new bone - note: sync with editarmature.c::add_editbone() */
+ BLI_strncpy(ebo->name, "Stroke", 32);
+ unique_editbone_name(bones, ebo->name);
+
+ BLI_addtail(bones, ebo);
+
+ ebo->flag |= BONE_CONNECTED;
+ ebo->weight= 1.0F;
+ ebo->dist= 0.25F;
+ ebo->xwidth= 0.1;
+ ebo->zwidth= 0.1;
+ ebo->ease1= 1.0;
+ ebo->ease2= 1.0;
+ ebo->rad_head= pt->pressure * gpl->thickness * 0.1;
+ ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1;
+ ebo->segments= 1;
+ ebo->layer= arm->layer;
+
+ /* set parenting */
+ // TODO: also adjust roll....
+ ebo->parent= prev;
+ }
+}
+
+/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */
+static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode)
+{
+ bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
+ bGPDstroke *gps;
+ Object *ob;
+ bArmature *arm;
+ ListBase bones = {0,0};
+
+ /* 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;
+
+ /* initialise the armature */
+ arm= add_armature(gpl->info);
+
+ /* init the armature object (remove rotation and assign armature data to it) */
+ add_object_draw(OB_ARMATURE);
+ ob= OBACT;
+ ob->loc[0]= ob->loc[1]= ob->loc[2]= 0;
+ ob->rot[0]= ob->rot[1]= ob->rot[2]= 0;
+ ob->data= arm;
+
+ /* convert segments to bones, strokes to bone chains */
+ for (gps= gpf->strokes.first; gps; gps= gps->next) {
+ gp_stroke_to_bonechain(gpl, gps, arm, &bones);
+ }
+
+ /* flush editbones to armature */
+ editbones_to_armature(&bones, ob);
+ if (bones.first) BLI_freelistN(&bones);
+}
+
+/* --- */
+
/* convert grease-pencil strokes to another representation
* mode: 1 - Active layer to path
* 2 - Active layer to bezier
+ * 3 - Active layer to armature
*/
void gpencil_convert_operation (short mode)
{
@@ -862,6 +954,12 @@ void gpencil_convert_operation (short mode)
gp_layer_to_curve(gpd, gpl, mode);
}
break;
+ case 3: /* active layer only (to armature) */
+ {
+ bGPDlayer *gpl= gpencil_layer_getactive(gpd);
+ gp_layer_to_armature(gpd, gpl, mode);
+ }
+ break;
}
/* redraw and undo-push */
@@ -879,7 +977,7 @@ void gpencil_convert_menu (void)
/* only show menu if it will be relevant */
if (gpd == NULL) return;
- mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2");
+ mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3");
if (mode <= 0) return;
gpencil_convert_operation(mode);
@@ -1210,9 +1308,18 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
bGPDspoint *pt;
tGPspoint *ptc;
int i, totelem;
+
+ /* macro to test if only converting endpoints */
+ #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY))
- /* get total number of points to allocate space for */
- totelem = gpd->sbuffer_size;
+ /* get total number of points to allocate space for:
+ * - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints
+ * - otherwise, do whole stroke
+ */
+ if (GP_BUFFER2STROKE_ENDPOINTS)
+ totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size;
+ else
+ totelem = gpd->sbuffer_size;
/* exit with error if no valid points from this stroke */
if (totelem == 0) {
@@ -1233,18 +1340,50 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
gps->flag= gpd->sbuffer_sflag;
/* copy points from the buffer to the stroke */
- for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
- /* convert screen-coordinates to appropriate coordinates (and store them) */
- gp_stroke_convertcoords(p, &ptc->x, &pt->x);
-
- /* copy pressure */
- pt->pressure= ptc->pressure;
-
- pt++;
+ if (GP_BUFFER2STROKE_ENDPOINTS) {
+ /* 'Draw Mode' + Ctrl-Modifier - only endpoints */
+ {
+ /* first point */
+ ptc= gpd->sbuffer;
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+
+ pt++;
+ }
+
+ if (totelem == 2) {
+ /* last point if applicable */
+ ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1);
+
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+ }
+ }
+ else {
+ /* convert all points (normal behaviour) */
+ for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) {
+ /* convert screen-coordinates to appropriate coordinates (and store them) */
+ gp_stroke_convertcoords(p, &ptc->x, &pt->x);
+
+ /* copy pressure */
+ pt->pressure= ptc->pressure;
+
+ pt++;
+ }
}
/* add stroke to frame */
BLI_addtail(&p->gpf->strokes, gps);
+
+ /* undefine macro to test if only converting endpoints */
+ #undef GP_BUFFER2STROKE_ENDPOINTS
}
/* --- 'Eraser' for 'Paint' Tool ------ */
@@ -1677,7 +1816,8 @@ short gpencil_do_paint (ScrArea *sa, short mbut)
/* currently, we will only 'paint' if:
* 1. draw-mode on gpd is set (for accessibility reasons)
- * (single 'dots' are only available via this method)
+ * a) single dots are only available by this method if a single click is made
+ * b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!)
* 2. if shift-modifier is held + lmb -> 'quick paint'
*
* OR