Grease Pencil: WIP Code Reordering + Context Stuff

* Shuffled some code around, and renamed some functions used for getting context info
- Split UI-buttons into a separate file from stroke-drawing code
- Removed some obsolete code (i.e. old paint code that used to be in _edit, but which has been moved to _paint). 

* Made drawing in 3D-View default to using the active object as the owner of the Grease Pencil data. For now, the drawing code will therefore only show the GP data for the active object only. More work to come on this.

* Fixed freeing code for Objects/Scenes with GP data.
This commit is contained in:
Joshua Leung 2009-08-28 12:41:45 +00:00
parent d7656684e2
commit c15db042cc
12 changed files with 478 additions and 2021 deletions

@ -284,6 +284,7 @@ void free_object(Object *ob)
if(ob->adt) BKE_free_animdata((ID *)ob);
if(ob->poselib) ob->poselib->id.us--;
if(ob->dup_group) ob->dup_group->id.us--;
if(ob->gpd) ob->gpd->id.us--;
if(ob->defbase.first)
BLI_freelistN(&ob->defbase);
if(ob->pose)

@ -245,6 +245,11 @@ void free_scene(Scene *sce)
base= base->next;
}
/* do not free objects! */
if(sce->gpd) {
sce->gpd->id.us--;
sce->gpd= NULL;
}
BLI_freelistN(&sce->base);
seq_free_editing(sce);

@ -3449,6 +3449,8 @@ static void lib_link_object(FileData *fd, Main *main)
}
for(a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
ob->gpd= newlibadr_us(fd, ob->id.lib, ob->gpd);
ob->id.flag -= LIB_NEEDLINK;
/* if id.us==0 a new base will be created later on */
@ -10418,6 +10420,8 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, ob->poselib);
expand_constraints(fd, mainvar, &ob->constraints);
expand_doit(fd, mainvar, ob->gpd);
// XXX depreceated - old animation system (for version patching only)
expand_doit(fd, mainvar, ob->ipo);
expand_doit(fd, mainvar, ob->action);

@ -885,7 +885,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter
for (sa= sc->areabase.first; sa; sa= sa->next) {
/* try to get gp data */
// XXX need to put back grease pencil api...
gpd= gpencil_data_getactive(sa);
gpd= gpencil_data_get_active(sa);
if (gpd == NULL) continue;
/* add gpd as channel too (if for drawing, and it has layers) */

@ -67,278 +67,11 @@
#include "ED_sequencer.h"
#include "ED_util.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "gpencil_intern.h"
/* ************************************************** */
/* GREASE PENCIL PANEL-UI DRAWING */
/* Every space which implements Grease-Pencil functionality should have a panel
* for the settings. All of the space-dependent parts should be coded in the panel
* code for that space, but the rest is all handled by generic panel here.
*/
/* ------- Callbacks ----------- */
/* These are just 'dummy wrappers' around gpencil api calls */
#if 0
// XXX
/* make layer active one after being clicked on */
void gp_ui_activelayer_cb (void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* rename layer and set active */
void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
{
bGPdata *gpd= (bGPdata *)gpd_arg;
bGPDlayer *gpl= (bGPDlayer *)gpl_arg;
BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128);
gpencil_layer_setactive(gpd, gpl);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* add a new layer */
void gp_ui_addlayer_cb (void *gpd, void *dummy)
{
gpencil_layer_addnew(gpd);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* delete active layer */
void gp_ui_dellayer_cb (void *gpd, void *dummy)
{
gpencil_layer_delactive(gpd);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* delete last stroke of active layer */
void gp_ui_delstroke_cb (void *gpd, void *gpl)
{
bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
if (gpf) {
if (gpf->framenum != CFRA) return;
gpencil_layer_setactive(gpd, gpl);
gpencil_frame_delete_laststroke(gpl, gpf);
scrarea_queue_winredraw(curarea);
}
}
/* delete active frame of active layer */
void gp_ui_delframe_cb (void *gpd, void *gpl)
{
bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
gpencil_layer_setactive(gpd, gpl);
gpencil_layer_delframe(gpl, gpf);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* convert the active layer to geometry */
void gp_ui_convertlayer_cb (void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
gpencil_convert_menu();
scrarea_queue_winredraw(curarea);
}
#endif
/* ------- Drawing Code ------- */
#if 0
/* XXX */
/* draw the controls for a given layer */
static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
{
uiBut *but;
short active= (gpl->flag & GP_LAYER_ACTIVE);
short width= 314;
short height;
int rb_col;
/* unless button has own callback, it adds this callback to button */
uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
/* draw header */
{
uiBlockSetEmboss(block, UI_EMBOSSN);
/* rounded header */
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
rb_col= (active)?-20:20;
uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
if (active) uiBlockSetCol(block, TH_AUTO);
/* lock toggle */
uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED, *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
}
/* when layer is locked or hidden, only draw header */
if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
height= 0;
/* visibility button (only if hidden but not locked!) */
if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
/* name */
if (gpl->flag & GP_LAYER_HIDE)
sprintf(name, "%s (Hidden)", gpl->info);
else
sprintf(name, "%s (Locked)", gpl->info);
uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
/* delete button (only if hidden but not locked!) */
if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
}
uiBlockSetEmboss(block, UI_EMBOSS);
}
else {
height= 97;
/* draw rest of header */
{
/* visibility button */
uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
uiBlockSetEmboss(block, UI_EMBOSS);
/* name */
but= uiDefButC(block, TEX, B_REDR, "Info:", *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
/* delete 'button' */
uiBlockSetEmboss(block, UI_EMBOSSN);
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
}
/* draw backdrop */
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, "");
if (active) uiBlockSetCol(block, TH_AUTO);
/* draw settings */
{
/* color */
uiBlockBeginAlign(block);
uiDefButF(block, COL, B_REDR, "", *xco, *yco-26, 150, 19, gpl->color, 0, 0, 0, 0, "Color to use for all strokes on this Grease Pencil Layer");
uiDefButF(block, NUMSLI, B_REDR, "Opacity: ", *xco,*yco-45,150,19, &gpl->color[3], 0.3f, 1.0f, 0, 0, "Visibility of stroke (0.3 to 1.0)");
uiBlockEndAlign(block);
/* stroke thickness */
uiDefButS(block, NUMSLI, B_REDR, "Thickness:", *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
/* debugging options */
if (G.f & G_DEBUG) {
uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
}
/* onion-skinning */
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
uiDefButS(block, NUMSLI, B_REDR, "GStep:", *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
uiBlockEndAlign(block);
/* options */
uiBlockBeginAlign(block);
if (curarea->spacetype == SPACE_VIEW3D) {
but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)");
uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl);
}
else {
but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
}
but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
uiBlockEndAlign(block);
}
}
/* adjust height for new to start */
(*yco) -= (height + 27);
}
#endif
/* Draw the contents for a grease-pencil panel. This assumes several things:
* - that panel has been created, is 318 x 204. max yco is 225
* - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
* which is basically the top left-hand corner
* It will return the amount of extra space to extend the panel by
*/
short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
{
#if 0
uiBut *but;
bGPDlayer *gpl;
short xco= 10, yco= 170;
/* draw gpd settings first */
{
/* add new layer buttons */
but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
/* show override lmb-clicks button + painting lock */
uiBlockBeginAlign(block);
if ((gpd->flag & GP_DATA_EDITPAINT)==0) {
uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
uiBlockSetCol(block, TH_BUT_SETTING);
uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)");
uiBlockSetCol(block, TH_AUTO);
}
else
uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
uiBlockEndAlign(block);
/* 'view align' button (naming depends on context) */
if (sa->spacetype == SPACE_VIEW3D)
uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
else
uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
}
/* draw for each layer */
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
gp_drawui_layer(block, gpd, gpl, &xco, &yco);
}
/* return new height if necessary */
return (yco < 0) ? (204 - yco) : 204;
#endif
return 0;
}
/* ************************************************** */
/* GREASE PENCIL DRAWING */
@ -432,8 +165,8 @@ static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sfl
co[1]= (points->y * winy) + offsy;
}
else {
co[0]= (points->x / 1000 * winx);
co[1]= (points->y / 1000 * winy);
co[0]= (points->x / 100 * winx);
co[1]= (points->y / 100 * winy);
}
/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok
@ -525,8 +258,8 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
glVertex2f(x, y);
}
else {
const float x= (pt->x / 1000 * winx);
const float y= (pt->y / 1000 * winy);
const float x= (pt->x / 100 * winx);
const float y= (pt->y / 100 * winy);
glVertex2f(x, y);
}
@ -565,10 +298,10 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
s1[1]= (pt2->y * winy) + offsy;
}
else {
s0[0]= (pt1->x / 1000 * winx);
s0[1]= (pt1->y / 1000 * winy);
s1[0]= (pt2->x / 1000 * winx);
s1[1]= (pt2->y / 1000 * winy);
s0[0]= (pt1->x / 100 * winx);
s0[1]= (pt1->y / 100 * winy);
s1[0]= (pt2->x / 100 * winx);
s1[1]= (pt2->y / 100 * winy);
}
/* calculate gradient and normal - 'angle'=(ny/nx) */
@ -713,8 +446,8 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness,
glVertex2f(x, y);
}
else {
const float x= (float)(pt->x / 1000 * winx);
const float y= (float)(pt->y / 1000 * winy);
const float x= (float)(pt->x / 100 * winx);
const float y= (float)(pt->y / 100 * winy);
glVertex2f(x, y);
}
@ -872,47 +605,7 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
/* show info for debugging the status of gpencil */
#if 0
if ( ((dflag & GP_DRAWDATA_NOSTATUS)==0) && (gpd->flag & GP_DATA_DISPINFO) ) {
char printable[256];
short xmax;
/* get text to display */
if (actlay) {
if (gpd->flag & GP_DATA_EDITPAINT)
UI_ThemeColor(TH_BONE_POSE); // should be blue-ish
else if (actlay->actframe == NULL)
UI_ThemeColor(TH_REDALERT);
else if (actlay->actframe->framenum == cfra)
UI_ThemeColor(TH_VERTEX_SELECT); // should be yellow
else
UI_ThemeColor(TH_TEXT_HI);
if (actlay->actframe) {
sprintf(printable, "GPencil: Layer ('%s'), Frame (%d)%s",
actlay->info, actlay->actframe->framenum,
((gpd->flag & GP_DATA_EDITPAINT)?" , Draw Mode On":"") );
}
else {
sprintf(printable, "GPencil: Layer ('%s'), Frame <None>%s",
actlay->info, ((gpd->flag & GP_DATA_EDITPAINT)?" , Draw Mode On":"") );
}
}
else {
UI_ThemeColor(TH_REDALERT);
sprintf(printable, "GPencil: Layer <None>");
}
xmax= GetButStringLength(printable);
/* only draw it if view is wide enough (assume padding of 20 is enough for now) */
if (winx > (xmax + 20)) {
BLF_draw_default(winx-xmax, winy-20, 0.0f, printable);
}
}
#endif
/* restore initial gl conditions */
glLineWidth(1.0);
glPointSize(1.0);
@ -921,6 +614,12 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy
/* ----- Grease Pencil Sketches Drawing API ------ */
// ............................
// XXX
// We need to review the calls below, since they may be/are not that suitable for
// the new ways that we intend to be drawing data...
// ............................
/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */
void draw_gpencil_2dimage (bContext *C, ImBuf *ibuf)
{
@ -933,7 +632,7 @@ void draw_gpencil_2dimage (bContext *C, ImBuf *ibuf)
/* check that we have grease-pencil stuff to draw */
if (ELEM(NULL, sa, ibuf)) return;
gpd= gpencil_data_getactive(C);
gpd= gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
/* calculate rect */
@ -1007,7 +706,7 @@ void draw_gpencil_2dview (bContext *C, short onlyv2d)
/* check that we have grease-pencil stuff to draw */
if (sa == NULL) return;
gpd= gpencil_data_getactive(C);
gpd= gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
/* draw it! */
@ -1026,7 +725,7 @@ void draw_gpencil_3dview (bContext *C, short only3d)
int dflag = 0;
/* check that we have grease-pencil stuff to draw */
gpd= gpencil_data_getactive(C);
gpd= gpencil_data_get_active(C); // XXX
if (gpd == NULL) return;
/* draw it! */
@ -1046,7 +745,7 @@ void draw_gpencil_oglrender (bContext *C)
/* assume gpencil data comes from v3d */
if (v3d == NULL) return;
gpd= gpencil_data_getactive(C);
gpd= gpencil_data_get_active(C);
if (gpd == NULL) return;
/* pass 1: draw 3d-strokes ------------ > */

@ -0,0 +1,334 @@
/**
* $Id: drawgpencil.c 22802 2009-08-26 12:01:15Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
* This is a new part of Blender
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "MEM_guardedalloc.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "DNA_gpencil_types.h"
#include "DNA_listBase.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_utildefines.h"
#include "PIL_time.h"
#include "WM_api.h"
#include "WM_types.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "ED_gpencil.h"
#include "ED_sequencer.h"
#include "ED_util.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "gpencil_intern.h"
/* ************************************************** */
/* GREASE PENCIL PANEL-UI DRAWING */
/* Every space which implements Grease-Pencil functionality should have a panel
* for the settings. All of the space-dependent parts should be coded in the panel
* code for that space, but the rest is all handled by generic panel here.
*/
/* ------- Callbacks ----------- */
/* These are just 'dummy wrappers' around gpencil api calls */
#if 0
// XXX
/* make layer active one after being clicked on */
void gp_ui_activelayer_cb (void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* rename layer and set active */
void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg)
{
bGPdata *gpd= (bGPdata *)gpd_arg;
bGPDlayer *gpl= (bGPDlayer *)gpl_arg;
BLI_uniquename(&gpd->layers, gpl, "GP_Layer", '.', offsetof(bGPDlayer, info[0]), 128);
gpencil_layer_setactive(gpd, gpl);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* add a new layer */
void gp_ui_addlayer_cb (void *gpd, void *dummy)
{
gpencil_layer_addnew(gpd);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* delete active layer */
void gp_ui_dellayer_cb (void *gpd, void *dummy)
{
gpencil_layer_delactive(gpd);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* delete last stroke of active layer */
void gp_ui_delstroke_cb (void *gpd, void *gpl)
{
bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
if (gpf) {
if (gpf->framenum != CFRA) return;
gpencil_layer_setactive(gpd, gpl);
gpencil_frame_delete_laststroke(gpl, gpf);
scrarea_queue_winredraw(curarea);
}
}
/* delete active frame of active layer */
void gp_ui_delframe_cb (void *gpd, void *gpl)
{
bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0);
gpencil_layer_setactive(gpd, gpl);
gpencil_layer_delframe(gpl, gpf);
scrarea_queue_winredraw(curarea);
allqueue(REDRAWACTION, 0);
}
/* convert the active layer to geometry */
void gp_ui_convertlayer_cb (void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
gpencil_convert_menu();
scrarea_queue_winredraw(curarea);
}
#endif
/* ------- Drawing Code ------- */
#if 0
/* XXX */
/* draw the controls for a given layer */
static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short *xco, short *yco)
{
uiBut *but;
short active= (gpl->flag & GP_LAYER_ACTIVE);
short width= 314;
short height;
int rb_col;
/* unless button has own callback, it adds this callback to button */
uiBlockSetFunc(block, gp_ui_activelayer_cb, gpd, gpl);
/* draw header */
{
uiBlockSetEmboss(block, UI_EMBOSSN);
/* rounded header */
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
rb_col= (active)?-20:20;
uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15.0, (float)(rb_col-20), "");
if (active) uiBlockSetCol(block, TH_AUTO);
/* lock toggle */
uiDefIconButBitI(block, ICONTOG, GP_LAYER_LOCKED, B_REDR, ICON_UNLOCKED, *xco-7, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Layer cannot be modified");
}
/* when layer is locked or hidden, only draw header */
if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) {
char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */
height= 0;
/* visibility button (only if hidden but not locked!) */
if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED))
uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
/* name */
if (gpl->flag & GP_LAYER_HIDE)
sprintf(name, "%s (Hidden)", gpl->info);
else
sprintf(name, "%s (Locked)", gpl->info);
uiDefBut(block, LABEL, 1, name, *xco+35, *yco, 240, 20, NULL, 0.0, 0.0, 0, 0, "Short description of what this layer is for (optional)");
/* delete button (only if hidden but not locked!) */
if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
}
uiBlockSetEmboss(block, UI_EMBOSS);
}
else {
height= 97;
/* draw rest of header */
{
/* visibility button */
uiDefIconButBitI(block, ICONTOG, GP_LAYER_HIDE, B_REDR, ICON_RESTRICT_VIEW_OFF, *xco+12, *yco-1, 20, 20, &gpl->flag, 0.0, 0.0, 0, 0, "Visibility of layer");
uiBlockSetEmboss(block, UI_EMBOSS);
/* name */
but= uiDefButC(block, TEX, B_REDR, "Info:", *xco+36, *yco, 240, 19, gpl->info, 0, 127, 0, 0, "Short description of what this layer is for (optional)");
uiButSetFunc(but, gp_ui_renamelayer_cb, gpd, gpl);
/* delete 'button' */
uiBlockSetEmboss(block, UI_EMBOSSN);
but= uiDefIconBut(block, BUT, B_REDR, ICON_X, *xco+(width-30), *yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Delete layer");
uiButSetFunc(but, gp_ui_dellayer_cb, gpd, NULL);
uiBlockSetEmboss(block, UI_EMBOSS);
}
/* draw backdrop */
if (active) uiBlockSetCol(block, TH_BUT_ACTION);
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-height, width, height-1, NULL, 5.0, 0.0, 12.0, (float)rb_col, "");
if (active) uiBlockSetCol(block, TH_AUTO);
/* draw settings */
{
/* color */
uiBlockBeginAlign(block);
uiDefButF(block, COL, B_REDR, "", *xco, *yco-26, 150, 19, gpl->color, 0, 0, 0, 0, "Color to use for all strokes on this Grease Pencil Layer");
uiDefButF(block, NUMSLI, B_REDR, "Opacity: ", *xco,*yco-45,150,19, &gpl->color[3], 0.3f, 1.0f, 0, 0, "Visibility of stroke (0.3 to 1.0)");
uiBlockEndAlign(block);
/* stroke thickness */
uiDefButS(block, NUMSLI, B_REDR, "Thickness:", *xco, *yco-75, 150, 20, &gpl->thickness, 1, 10, 0, 0, "Thickness of strokes (in pixels)");
/* debugging options */
if (G.f & G_DEBUG) {
uiDefButBitI(block, TOG, GP_LAYER_DRAWDEBUG, B_REDR, "Show Points", *xco, *yco-95, 150, 20, &gpl->flag, 0, 0, 0, 0, "Show points which form the strokes");
}
/* onion-skinning */
uiBlockBeginAlign(block);
uiDefButBitI(block, TOG, GP_LAYER_ONIONSKIN, B_REDR, "Onion-Skin", *xco+160, *yco-26, 140, 20, &gpl->flag, 0, 0, 0, 0, "Ghost frames on either side of frame");
uiDefButS(block, NUMSLI, B_REDR, "GStep:", *xco+160, *yco-46, 140, 20, &gpl->gstep, 0, 120, 0, 0, "Max number of frames on either side of active frame to show (0 = just 'first' available sketch on either side)");
uiBlockEndAlign(block);
/* options */
uiBlockBeginAlign(block);
if (curarea->spacetype == SPACE_VIEW3D) {
but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)");
uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl);
}
else {
but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)");
uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl);
}
but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)");
uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl);
uiBlockEndAlign(block);
}
}
/* adjust height for new to start */
(*yco) -= (height + 27);
}
#endif
/* Draw the contents for a grease-pencil panel. This assumes several things:
* - that panel has been created, is 318 x 204. max yco is 225
* - that a toggle for turning on/off gpencil drawing is 150 x 20, starting from (10,225)
* which is basically the top left-hand corner
* It will return the amount of extra space to extend the panel by
*/
short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa)
{
#if 0
uiBut *but;
bGPDlayer *gpl;
short xco= 10, yco= 170;
/* draw gpd settings first */
{
/* add new layer buttons */
but= uiDefBut(block, BUT, B_REDR, "Add New Layer", 10,205,150,20, 0, 0, 0, 0, 0, "Adds a new Grease Pencil Layer");
uiButSetFunc(but, gp_ui_addlayer_cb, gpd, NULL);
/* show override lmb-clicks button + painting lock */
uiBlockBeginAlign(block);
if ((gpd->flag & GP_DATA_EDITPAINT)==0) {
uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 130, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
uiBlockSetCol(block, TH_BUT_SETTING);
uiDefIconButBitI(block, ICONTOG, GP_DATA_LMBPLOCK, B_REDR, ICON_UNLOCKED, 300, 225, 20, 20, &gpd->flag, 0.0, 0.0, 0, 0, "Painting cannot occur with Shift-LMB (when making selections)");
uiBlockSetCol(block, TH_AUTO);
}
else
uiDefButBitI(block, TOG, GP_DATA_EDITPAINT, B_REDR, "Draw Mode", 170, 225, 150, 20, &gpd->flag, 0, 0, 0, 0, "Interpret click-drag as new strokes");
uiBlockEndAlign(block);
/* 'view align' button (naming depends on context) */
if (sa->spacetype == SPACE_VIEW3D)
uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space");
else
uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas");
}
/* draw for each layer */
for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
gp_drawui_layer(block, gpd, gpl, &xco, &yco);
}
/* return new height if necessary */
return (yco < 0) ? (204 - yco) : 204;
#endif
return 0;
}
/* ************************************************** */

File diff suppressed because it is too large Load Diff

@ -1,5 +1,28 @@
/* Grease Pencil - version 2
* By Joshua Leung
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008, Blender Foundation, Joshua Leung
* This is a new part of Blender
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h>
@ -38,8 +61,8 @@
#include "ED_view3d.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@ -48,65 +71,6 @@
/* ******************************************* */
/* Context Wrangling... */
/* Get the active Grease Pencil datablock */
// TODO: move this to a gpencil_utils.c?
bGPdata *gpencil_data_getactive (bContext *C)
{
Scene *scene= CTX_data_scene(C);
ScrArea *sa= CTX_wm_area(C);
/* if there's an active area, check if the particular editor may
* have defined any special Grease Pencil context for editing...
*/
if (sa) {
switch (sa->spacetype) {
case SPACE_VIEW3D: /* 3D-View */
{
Object *ob= CTX_data_active_object(C);
/* just in case... */
if (ob) {
/* depending on the mode of the object, we may be able to get some GP data
* from different elements - i.e. bones...
*/
if (ob->mode & OB_MODE_POSE) {
//bPoseChannel *pchan= CTX_data_active_pchan(C);
/* if posechannel has GP data, use that... */
//if (pchan && pchan->gpd)
// return pchan->gpd;
}
/* still here, so check if active Object has GP data */
//if (ob->gpd)
// return ob->gpd;
}
}
break;
case SPACE_NODE: /* Nodes Editor */
{
//SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
/* return the GP data for the active node block/node */
}
break;
case SPACE_SEQ: /* Sequencer */
{
//SpaceSeq *sseq= (SpaceSeq *)CTX_wm_space_data(C);
/* return the GP data for the active strips/image/etc. */
}
break;
}
}
/* just fall back on the scene's GP data */
return (scene) ? scene->gpd : NULL;
}
/* check if context is suitable for drawing */
static int gpencil_draw_poll (bContext *C)
{
@ -282,8 +246,8 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[])
/* 2d - relative to screen (viewport area) */
else {
out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 1000;
out[1] = (float)(mval[1]) / (float)(p->sa->winy) * 1000;
out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 100;
out[1] = (float)(mval[1]) / (float)(p->sa->winy) * 100;
}
}
@ -616,8 +580,8 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, int mval[], int mvalo[], sho
}
#endif
else {
x0= (int)(gps->points->x / 1000 * p->sa->winx);
y0= (int)(gps->points->y / 1000 * p->sa->winy);
x0= (int)(gps->points->x / 100 * p->sa->winx);
y0= (int)(gps->points->y / 100 * p->sa->winy);
}
/* do boundbox check first */
@ -673,10 +637,10 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, int mval[], int mvalo[], sho
}
#endif
else {
x0= (int)(pt1->x / 1000 * p->sa->winx);
y0= (int)(pt1->y / 1000 * p->sa->winy);
x1= (int)(pt2->x / 1000 * p->sa->winx);
y1= (int)(pt2->y / 1000 * p->sa->winy);
x0= (int)(pt1->x / 100 * p->sa->winx);
y0= (int)(pt1->y / 100 * p->sa->winy);
x1= (int)(pt2->x / 100 * p->sa->winx);
y1= (int)(pt2->y / 100 * p->sa->winy);
}
/* check that point segment of the boundbox of the eraser stroke */
@ -740,6 +704,7 @@ static void gp_session_validatebuffer (tGPsdata *p)
static tGPsdata *gp_session_initpaint (bContext *C)
{
tGPsdata *p = NULL;
bGPdata **gpd_ptr = NULL;
ScrArea *curarea= CTX_wm_area(C);
ARegion *ar= CTX_wm_region(C);
@ -852,11 +817,18 @@ static tGPsdata *gp_session_initpaint (bContext *C)
}
/* get gp-data */
p->gpd= gpencil_data_getactive(C);
if (p->gpd == NULL) {
/* add new GPencil block for the active scene for now... */
p->gpd= gpencil_data_addnew("GPencil");
p->scene->gpd= p->gpd;
gpd_ptr= gpencil_data_get_pointers(C, NULL);
if (gpd_ptr == NULL) {
p->status= GP_STATUS_ERROR;
if (G.f & G_DEBUG)
printf("Error: Current context doesn't allow for any Grease Pencil data \n");
return p;
}
else {
/* if no existing GPencil block exists, add one */
if (*gpd_ptr == NULL)
*gpd_ptr= gpencil_data_addnew("GPencil");
p->gpd= *gpd_ptr;
}
/* set edit flags - so that buffer will get drawn */

@ -38,49 +38,35 @@ struct SpaceSeq;
struct bGPdata;
struct bGPDlayer;
struct bGPDframe;
struct bGPdata;
struct PointerRNA;
struct uiLayout;
struct uiBlock;
struct ImBuf;
struct wmWindowManager;
/* ------------- Grease-Pencil Helpers -------------- */
/* ------------- Grease-Pencil Helpers ---------------- */
/* Temporary 'Stroke Point' data */
/* Temporary 'Stroke Point' data
*
* Used as part of the 'stroke cache' used during drawing of new strokes
*/
typedef struct tGPspoint {
short x, y; /* x and y coordinates of cursor (in relative to area) */
float pressure; /* pressure of tablet at this point */
} tGPspoint;
/* ----------- Grease Pencil New Tools ------------- */
/* ----------- Grease Pencil Tools/Context ------------- */
struct bGPdata *gpencil_data_getactive(struct bContext *C);
struct bGPdata **gpencil_data_get_pointers(struct bContext *C, struct PointerRNA *ptr);
struct bGPdata *gpencil_data_get_active(struct bContext *C);
/* ----------- Grease Pencil Operators ------------- */
/* ----------- Grease Pencil Operators ----------------- */
void gpencil_common_keymap(struct wmWindowManager *wm, ListBase *keymap);
void ED_operatortypes_gpencil(void);
/* ------------ Grease-Pencil Depreceated Stuff ------------------ */
//struct bGPdata *gpencil_data_getactive(struct ScrArea *sa);
short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd);
struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd);
/* ------------ Grease-Pencil Editing API ------------------ */
void gpencil_delete_actframe(struct bGPdata *gpd, int cfra);
void gpencil_delete_laststroke(struct bGPdata *gpd, int cfra);
void gpencil_delete_operation(int cfra, short mode);
void gpencil_delete_menu(void);
void gpencil_convert_operation(short mode);
void gpencil_convert_menu(void);
short gpencil_do_paint(struct bContext *C);
/* ------------ Grease-Pencil Drawing API ------------------ */
/* drawgpencil.c */

@ -4736,7 +4736,7 @@ void special_aftertrans_update(TransInfo *t)
* - sync this with actdata_filter_gpencil() in editaction.c
*/
for (sa= sc->areabase.first; sa; sa= sa->next) {
bGPdata *gpd= gpencil_data_getactive(sa);
bGPdata *gpd= gpencil_data_get_active(sa);
if (gpd)
posttrans_gpd_clean(gpd);

@ -54,7 +54,10 @@ struct FluidsimSettings;
struct ParticleSystem;
struct DerivedMesh;
struct SculptSession;
struct bGPdata;
/* Vertex Groups - Name Info */
typedef struct bDeformGroup {
struct bDeformGroup *next, *prev;
char name[32];
@ -110,6 +113,8 @@ typedef struct Object {
struct bPose *pose;
void *data;
struct bGPdata *gpd; /* Grease Pencil data */
ListBase constraintChannels; // XXX depreceated... old animation system
ListBase effect;
ListBase disp;
@ -209,7 +214,7 @@ typedef struct Object {
short recalc; /* dependency flag */
float anisotropicFriction[3];
ListBase constraints;
ListBase constraints; /* object constraints */
ListBase nlastrips; // XXX depreceated... old animation system
ListBase hooks;
ListBase particlesystem; /* particle systems */

@ -1464,6 +1464,13 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "X-Ray", "Makes the object draw in front of others.");
RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL);
/* Grease Pencil */
prop= RNA_def_property(srna, "grease_pencil", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gpd");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
/* pose */
prop= RNA_def_property(srna, "pose_library", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "poselib");