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:
authorJoseph Eagar <joeedh@gmail.com>2011-02-27 09:19:40 +0300
committerJoseph Eagar <joeedh@gmail.com>2011-02-27 09:19:40 +0300
commitf01261d040be27337db9f9996d648a279c89b7c4 (patch)
treec448230939b3c90d53ce8852dd00925d6052e3a4 /source/blender/editors/gpencil
parentdcaeda5c4e3a0687251b8511de4f2e8b85ef75c0 (diff)
parent2198cfdb2deec8b2e85e242c74a032f43d0b26ca (diff)
merge with/from trunk at r35190
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt18
-rw-r--r--source/blender/editors/gpencil/Makefile56
-rw-r--r--source/blender/editors/gpencil/SConscript4
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c16
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c68
-rw-r--r--source/blender/editors/gpencil/gpencil_buttons.c47
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c8
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h2
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c418
10 files changed, 385 insertions, 256 deletions
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 394418b5688..4269c590a14 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -19,11 +19,10 @@
#
# ***** END GPL LICENSE BLOCK *****
-FILE(GLOB SRC *.c)
-
-SET(INC
+set(INC
../include
../../blenkernel
+ ../../blenloader
../../blenlib
../../imbuf
../../makesdna
@@ -32,4 +31,15 @@ SET(INC
../../../../intern/guardedalloc
)
-BLENDERLIB(bf_editor_gpencil "${SRC}" "${INC}")
+set(SRC
+ drawgpencil.c
+ editaction_gpencil.c
+ gpencil_buttons.c
+ gpencil_edit.c
+ gpencil_ops.c
+ gpencil_paint.c
+
+ gpencil_intern.h
+)
+
+blender_add_lib(bf_editor_gpencil "${SRC}" "${INC}")
diff --git a/source/blender/editors/gpencil/Makefile b/source/blender/editors/gpencil/Makefile
deleted file mode 100644
index f3e781a0369..00000000000
--- a/source/blender/editors/gpencil/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2007 Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-#
-# Makes module object directory and bounces make to subdirectories.
-
-LIBNAME = ed_gpencil
-DIR = $(OCGDIR)/blender/$(LIBNAME)
-
-include nan_compile.mk
-
-CFLAGS += $(LEVEL_1_C_WARNINGS)
-
-CPPFLAGS += -I$(NAN_GLEW)/include
-CPPFLAGS += -I$(OPENGL_HEADERS)
-
-CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
-CPPFLAGS += -I$(NAN_ELBEEM)/include
-
-CPPFLAGS += -I../../windowmanager
-CPPFLAGS += -I../../blenkernel
-CPPFLAGS += -I../../blenloader
-CPPFLAGS += -I../../blenlib
-CPPFLAGS += -I../../makesdna
-CPPFLAGS += -I../../makesrna
-CPPFLAGS += -I../../imbuf
-CPPFLAGS += -I../../gpu
-CPPFLAGS += -I../../render/extern/include
-
-# own include
-
-CPPFLAGS += -I../include
diff --git a/source/blender/editors/gpencil/SConscript b/source/blender/editors/gpencil/SConscript
index baed179cbe9..e75e3f032c1 100644
--- a/source/blender/editors/gpencil/SConscript
+++ b/source/blender/editors/gpencil/SConscript
@@ -5,7 +5,11 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+<<<<<<< .working
incs += ' ../../gpu ../../bmesh'
+=======
+incs += ' ../../gpu ../../blenloader'
+>>>>>>> .merge-right.r35190
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
env.BlenderLib ( 'bf_editors_gpencil', sources, Split(incs), [], libtype=['core'], priority=[45] )
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 4b8c58a5308..7ef17542ea4 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -38,6 +38,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
@@ -48,7 +49,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_utildefines.h"
+
#include "WM_api.h"
@@ -199,7 +200,7 @@ static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sfl
}
/* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */
-static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy)
+static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thickness, short debug)
{
bGPDspoint *pt;
float oldpressure = 0.0f;
@@ -244,9 +245,12 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
-static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag,
+static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
short debug, int offsx, int offsy, int winx, int winy)
{
+ /* otherwise thickness is twice that of the 3D view */
+ float thickness= (float)thickness_s * 0.5f;
+
/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
* - 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
*/
@@ -498,7 +502,7 @@ static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int
if (gps->totpoints == 1)
gp_draw_stroke_point(gps->points, lthick, gps->flag, offsx, offsy, winx, winy);
else if (dflag & GP_DRAWDATA_ONLY3D)
- gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy);
+ gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, debug);
else if (gps->totpoints > 1)
gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy);
}
@@ -751,7 +755,7 @@ void draw_gpencil_view3d_ext (Scene *scene, View3D *v3d, ARegion *ar, short only
* deal with the camera border, otherwise map the coords to the camera border. */
if(rv3d->persp == RV3D_CAMOB && !(G.f & G_RENDER_OGL)) {
rctf rectf;
- view3d_calc_camera_border(scene, ar, rv3d, v3d, &rectf);
+ view3d_calc_camera_border(scene, ar, rv3d, v3d, &rectf, -1); /* negative shift */
BLI_copy_rcti_rctf(&rect, &rectf);
}
else {
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index d76e5fcf17c..6ea8b77cc71 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -31,20 +31,23 @@
#include <stddef.h>
#include <math.h>
-#include "BLI_math.h"
+#include "MEM_guardedalloc.h"
+
#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
-#include "gpencil_intern.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_scene_types.h"
-#if 0 // XXX disabled until grease pencil code stabilises again
+#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
-/* XXX */
-static void actdata_filter() {} // is now ANIM_animdata_filter()
-static void BIF_undo_push() {}
-static void error() {}
-static void *get_action_context() {return NULL;} // is now ANIM_animdata_get_context()
-/* XXX */
+#include "ED_anim_api.h"
+#include "ED_gpencil.h"
+#include "ED_keyframes_edit.h"
+#include "gpencil_intern.h"
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
@@ -126,6 +129,9 @@ short is_gplayer_frame_selected (bGPDlayer *gpl)
/* helper function - select gp-frame based on SELECT_* mode */
static void gpframe_select (bGPDframe *gpf, short select_mode)
{
+ if (gpf == NULL)
+ return;
+
switch (select_mode) {
case SELECT_ADD:
gpf->flag |= GP_FRAME_SELECT;
@@ -160,31 +166,19 @@ void set_gplayer_frame_selection (bGPDlayer *gpl, short mode)
/* error checking */
if (gpl == NULL)
return;
-
- /* convert mode to select_mode */
- switch (mode) {
- case 2:
- mode= SELECT_INVERT;
- break;
- case 1:
- mode= SELECT_ADD;
- break;
- case 0:
- mode= SELECT_SUBTRACT;
- break;
- default:
- return;
- }
/* now call the standard function */
- select_gpencil_frames (gpl, mode);
+ select_gpencil_frames(gpl, mode);
}
/* select the frame in this layer that occurs on this frame (there should only be one at most) */
void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode)
{
bGPDframe *gpf;
-
+
+ if (gpl == NULL)
+ return;
+
/* search through frames for a match */
for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
/* there should only be one frame with this frame-number */
@@ -200,6 +194,9 @@ void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short se
{
bGPDframe *gpf;
+ if (gpl == NULL)
+ return;
+
/* only select those frames which are in bounds */
for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
if (IN_RANGE(gpf->framenum, min, max))
@@ -207,6 +204,7 @@ void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short se
}
}
+#if 0 // XXX disabled until grease pencil code stabilises again
/* De-selects or inverts the selection of Layers for a grease-pencil block
* mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all
@@ -252,9 +250,12 @@ void deselect_gpencil_layers (void *data, short mode)
BLI_freelistN(&act_data);
}
+#endif // XXX disabled until Grease Pencil code stabilises again...
+
/* ***************************************** */
/* Frame Editing Tools */
+#if 0 // XXX disabled until grease pencil code stabilises again
/* Delete selected grease-pencil layers */
void delete_gpencil_layers (void)
{
@@ -291,6 +292,7 @@ void delete_gpencil_layers (void)
BIF_undo_push("Delete GPencil Layers");
}
+#endif // XXX disabled until Grease Pencil code stabilises again...
/* Delete selected frames */
void delete_gplayer_frames (bGPDlayer *gpl)
@@ -336,6 +338,7 @@ void duplicate_gplayer_frames (bGPDlayer *gpl)
}
}
+#if 0 // XXX disabled until grease pencil code stabilises again
/* -------------------------------------- */
/* Copy and Paste Tools */
/* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
@@ -668,15 +671,10 @@ static short mirror_gpf_marker (bGPDframe *gpf, Scene *scene)
}
else {
/* try to find a marker */
- for (marker= scene->markers.first; marker; marker=marker->next) {
- if (marker->flag & SELECT) {
- initialised = 1;
- break;
- }
+ marker= ED_markers_get_first_selected(&scene->markers);
+ if(marker) {
+ initialised= 1;
}
-
- if (initialised == 0)
- marker = NULL;
}
}
diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c
index 87a9c3cd52f..e6d22e3049f 100644
--- a/source/blender/editors/gpencil/gpencil_buttons.c
+++ b/source/blender/editors/gpencil/gpencil_buttons.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -66,7 +66,7 @@
/* These are just 'dummy wrappers' around gpencil api calls */
/* make layer active one after being clicked on */
-void gp_ui_activelayer_cb (bContext *C, void *gpd, void *gpl)
+static void gp_ui_activelayer_cb (bContext *C, void *gpd, void *gpl)
{
gpencil_layer_setactive(gpd, gpl);
@@ -74,7 +74,7 @@ void gp_ui_activelayer_cb (bContext *C, void *gpd, void *gpl)
}
/* delete 'active' layer */
-void gp_ui_dellayer_cb (bContext *C, void *gpd, void *gpl)
+static void gp_ui_dellayer_cb (bContext *C, void *gpd, void *gpl)
{
/* make sure the layer we want to remove is the active one */
gpencil_layer_setactive(gpd, gpl);
@@ -138,10 +138,10 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl)
sprintf(name, "%s (Hidden)", gpl->info);
else
sprintf(name, "%s (Locked)", gpl->info);
- uiItemL(subrow, name, 0);
+ uiItemL(subrow, name, ICON_NULL);
/* delete button (only if hidden but not locked!) */
- if ((gpl->flag & GP_LAYER_HIDE) & !(gpl->flag & GP_LAYER_LOCKED)) {
+ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) {
/* right-align ............................... */
subrow= uiLayoutRow(row, 1);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
@@ -165,7 +165,7 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl)
uiBlockSetEmboss(block, UI_EMBOSS);
/* name */
- uiItemR(subrow, &ptr, "info", 0, "", 0);
+ uiItemR(subrow, &ptr, "info", 0, "", ICON_NULL);
/* delete 'button' */
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -189,17 +189,17 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl)
/* color */
subcol= uiLayoutColumn(col, 1);
- uiItemR(subcol, &ptr, "color", 0, "", 0);
- uiItemR(subcol, &ptr, "alpha", UI_ITEM_R_SLIDER, NULL, 0);
+ uiItemR(subcol, &ptr, "color", 0, "", ICON_NULL);
+ uiItemR(subcol, &ptr, "alpha", UI_ITEM_R_SLIDER, NULL, ICON_NULL);
/* stroke thickness */
subcol= uiLayoutColumn(col, 1);
- uiItemR(subcol, &ptr, "line_width", UI_ITEM_R_SLIDER, NULL, 0);
+ uiItemR(subcol, &ptr, "line_width", UI_ITEM_R_SLIDER, NULL, ICON_NULL);
/* debugging options */
if (G.f & G_DEBUG) {
subcol= uiLayoutColumn(col, 1);
- uiItemR(subcol, &ptr, "show_points", 0, NULL, 0);
+ uiItemR(subcol, &ptr, "show_points", 0, NULL, ICON_NULL);
}
/* right column ................... */
@@ -207,13 +207,9 @@ static void gp_drawui_layer (uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl)
/* onion-skinning */
subcol= uiLayoutColumn(col, 1);
- uiItemR(subcol, &ptr, "use_onion_skinning", 0, "Onion Skinning", 0);
- uiItemR(subcol, &ptr, "ghost_range_max", 0, "Frames", 0); // XXX shorter name here? i.e. GStep
+ uiItemR(subcol, &ptr, "use_onion_skinning", 0, "Onion Skinning", ICON_NULL);
+ uiItemR(subcol, &ptr, "ghost_range_max", 0, "Frames", ICON_NULL); // XXX shorter name here? i.e. GStep
- /* additional options... */
- subcol= uiLayoutColumn(col, 1);
- uiItemO(subcol, "Delete Frame", 0, "GPENCIL_OT_active_frame_delete");
- uiItemO(subcol, "Convert...", 0, "GPENCIL_OT_convert");
}
}
@@ -242,8 +238,11 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
uiTemplateID(col, C, ctx_ptr, "grease_pencil", "GPENCIL_OT_data_add", NULL, "GPENCIL_OT_data_unlink");
/* add new layer button - can be used even when no data, since it can add a new block too */
- uiItemO(col, NULL, 0, "GPENCIL_OT_layer_add");
-
+ uiItemO(col, "New Layer", ICON_NULL, "GPENCIL_OT_layer_add");
+ row= uiLayoutRow(col, 1);
+ uiItemO(row, "Delete Frame", ICON_NULL, "GPENCIL_OT_active_frame_delete");
+ uiItemO(row, "Convert", ICON_NULL, "GPENCIL_OT_convert");
+
/* sanity checks... */
if (gpd == NULL)
return;
@@ -257,7 +256,7 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
/* draw gpd drawing settings first ------------------------------------- */
col= uiLayoutColumn(layout, 1);
/* label */
- uiItemL(col, "Drawing Settings:", 0);
+ uiItemL(col, "Drawing Settings:", ICON_NULL);
/* check whether advanced 3D-View drawing space options can be used */
if (CTX_wm_view3d(C)) {
@@ -269,16 +268,16 @@ static void draw_gpencil_panel (bContext *C, uiLayout *layout, bGPdata *gpd, Poi
/* drawing space options */
row= uiLayoutRow(col, 1);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, 0);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, 0);
+ uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "VIEW", NULL, ICON_NULL);
+ uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "CURSOR", NULL, ICON_NULL);
row= uiLayoutRow(col, 1);
uiLayoutSetActive(row, v3d_stroke_opts);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, 0);
- uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, 0);
+ uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "SURFACE", NULL, ICON_NULL);
+ uiItemEnumR_string(row, &gpd_ptr, "draw_mode", "STROKE", NULL, ICON_NULL);
row= uiLayoutRow(col, 0);
uiLayoutSetActive(row, v3d_stroke_opts==STROKE_OPTS_V3D_ON);
- uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, 0);
+ uiItemR(row, &gpd_ptr, "use_stroke_endpoints", 0, NULL, ICON_NULL);
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index e0d257ca3bf..b699d27dd89 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -37,6 +37,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -63,6 +64,7 @@
#include "UI_view2d.h"
+#include "ED_gpencil.h"
#include "ED_view3d.h"
#include "gpencil_intern.h"
@@ -542,9 +544,9 @@ static int gp_convert_poll (bContext *C)
{
bGPdata *gpd= gpencil_data_get_active(C);
ScrArea *sa= CTX_wm_area(C);
-
+
/* only if there's valid data, and the current view is 3D View */
- return ((sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd));
+ return ((sa && sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd));
}
static int gp_convert_layer_exec (bContext *C, wmOperator *op)
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 1bfe65eb36c..7ae68d194b3 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index b6b2675e6c8..55b2d2aa73d 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -38,6 +38,8 @@
#include "RNA_access.h"
+#include "ED_gpencil.h"
+
#include "gpencil_intern.h"
/* ****************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index f218ccd89f1..06e67128496 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -35,6 +35,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_utildefines.h"
#include "BKE_gpencil.h"
#include "BKE_context.h"
@@ -44,6 +45,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_windowmanager_types.h"
#include "UI_view2d.h"
@@ -65,6 +67,8 @@
/* Temporary 'Stroke' Operation data */
typedef struct tGPsdata {
Scene *scene; /* current scene from context */
+
+ wmWindow *win; /* window where painting originated */
ScrArea *sa; /* area where painting originated */
ARegion *ar; /* region where painting originated */
View2D *v2d; /* needed for GP_STROKE_2DSPACE */
@@ -141,15 +145,31 @@ static void gp_session_validatebuffer(tGPsdata *p);
/* check if context is suitable for drawing */
static int gpencil_draw_poll (bContext *C)
{
- /* check if current context can support GPencil data */
- return (gpencil_data_get_pointers(C, NULL) != NULL);
+ if (ED_operator_regionactive(C)) {
+ /* check if current context can support GPencil data */
+ if (gpencil_data_get_pointers(C, NULL) != NULL) {
+ /* check if Grease Pencil isn't already running */
+ if ((G.f & G_GREASEPENCIL) == 0)
+ return 1;
+ else
+ CTX_wm_operator_poll_msg_set(C, "Grease Pencil operator is already active");
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
+ }
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ }
+
+ return 0;
}
/* check if projecting strokes into 3d-geometry in the 3D-View */
static int gpencil_project_check (tGPsdata *p)
{
bGPdata *gpd= p->gpd;
- return ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && (p->gpd->flag & (GP_DATA_DEPTH_VIEW | GP_DATA_DEPTH_STROKE))) ? 1:0;
+ return ((gpd->sbuffer_sflag & GP_STROKE_3DSPACE) && (p->gpd->flag & (GP_DATA_DEPTH_VIEW | GP_DATA_DEPTH_STROKE)));
}
/* ******************************************* */
@@ -164,7 +184,7 @@ static void gp_get_3d_reference (tGPsdata *p, float *vec)
float *fp= give_cursor(p->scene, v3d);
/* the reference point used depends on the owner... */
-#if 0 // XXX: disabled for now, since we can't draw relative ot the owner yet
+#if 0 // XXX: disabled for now, since we can't draw relative to the owner yet
if (p->ownerPtr.type == &RNA_Object)
{
Object *ob= (Object *)p->ownerPtr.data;
@@ -194,13 +214,17 @@ static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2])
if (p->gpd->sbuffer_size == 0)
return 1;
- /* check if mouse moved at least certain distance on both axes (best case) */
+ /* check if mouse moved at least certain distance on both axes (best case)
+ * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand
+ */
else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX))
return 1;
- /* check if the distance since the last point is significant enough */
- // future optimisation: sqrt here may be too slow?
- else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX)
+ /* check if the distance since the last point is significant enough
+ * - prevents points being added too densely
+ * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though
+ */
+ else if ((dx*dx + dy*dy) > MIN_EUCLIDEAN_PX*MIN_EUCLIDEAN_PX)
return 1;
/* mouse 'didn't move' */
@@ -216,7 +240,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], flo
/* in 3d-space - pt->x/y/z are 3 side-by-side floats */
if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) {
- if(gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, 0, depth))) {
+ if (gpencil_project_check(p) && (view_autodist_simple(p->ar, mval, out, 0, depth))) {
/* projecting onto 3D-Geometry
* - nothing more needs to be done here, since view_autodist_simple() has already done it
*/
@@ -274,14 +298,14 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[], flo
/* 2d - relative to screen (viewport area) */
else {
- if(p->subrect == NULL) { /* normal 3D view */
- out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
- out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
- }
+ if (p->subrect == NULL) { /* normal 3D view */
+ out[0] = (float)(mval[0]) / (float)(p->ar->winx) * 100;
+ out[1] = (float)(mval[1]) / (float)(p->ar->winy) * 100;
+ }
else { /* camera view, use subrect */
out[0]= ((mval[0] - p->subrect->xmin) / ((p->subrect->xmax - p->subrect->xmin))) * 100;
out[1]= ((mval[1] - p->subrect->ymin) / ((p->subrect->ymax - p->subrect->ymin))) * 100;
-}
+ }
}
}
@@ -394,12 +418,12 @@ static void gp_stroke_simplify (tGPsdata *p)
short flag= gpd->sbuffer_sflag;
short i, j;
- /* only simplify if simlification is enabled, and we're not doing a straight line */
+ /* only simplify if simplification is enabled, and we're not doing a straight line */
if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT))
return;
/* don't simplify if less than 4 points in buffer */
- if ((num_points <= 2) || (old_points == NULL))
+ if ((num_points <= 4) || (old_points == NULL))
return;
/* clear buffer (but don't free mem yet) so that we can write to it
@@ -520,60 +544,69 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
}
else {
float *depth_arr= NULL;
-
+
/* get an array of depths, far depths are blended */
- if(gpencil_project_check(p)) {
- short mval[2];
+ if (gpencil_project_check(p)) {
+ short mval[2], mval_prev[2]= {0};
int interp_depth = 0;
int found_depth = 0;
-
+
depth_arr= MEM_mallocN(sizeof(float) * gpd->sbuffer_size, "depth_points");
for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size; i++, ptc++, pt++) {
mval[0]= ptc->x; mval[1]= ptc->y;
- if(view_autodist_depth(p->ar, mval, depth_margin, depth_arr+i) == 0)
+
+ if ((view_autodist_depth(p->ar, mval, depth_margin, depth_arr+i) == 0) &&
+ (i && (view_autodist_depth_segment(p->ar, mval, mval_prev, depth_margin + 1, depth_arr+i) == 0))
+ ) {
interp_depth= TRUE;
- else
+ }
+ else {
found_depth= TRUE;
- }
+ }
- if(found_depth==FALSE) {
+ VECCOPY2D(mval_prev, mval);
+ }
+
+ if (found_depth == FALSE) {
/* eeh... not much we can do.. :/, ignore depth in this case, use the 3D cursor */
for (i=gpd->sbuffer_size-1; i >= 0; i--)
depth_arr[i] = 0.9999f;
}
else {
- if(p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
+ if (p->gpd->flag & GP_DATA_DEPTH_STROKE_ENDPOINTS) {
/* remove all info between the valid endpoints */
int first_valid = 0;
int last_valid = 0;
-
- for (i=0; i < gpd->sbuffer_size; i++)
- if(depth_arr[i] != FLT_MAX)
+
+ for (i=0; i < gpd->sbuffer_size; i++) {
+ if (depth_arr[i] != FLT_MAX)
break;
+ }
first_valid= i;
-
- for (i=gpd->sbuffer_size-1; i >= 0; i--)
- if(depth_arr[i] != FLT_MAX)
+
+ for (i=gpd->sbuffer_size-1; i >= 0; i--) {
+ if (depth_arr[i] != FLT_MAX)
break;
+ }
last_valid= i;
-
+
/* invalidate non-endpoints, so only blend between first and last */
for (i=first_valid+1; i < last_valid; i++)
depth_arr[i]= FLT_MAX;
-
+
interp_depth= TRUE;
}
-
- if(interp_depth) {
+
+ if (interp_depth) {
interp_sparse_array(depth_arr, gpd->sbuffer_size, FLT_MAX);
}
}
}
-
-
+
+
pt= gps->points;
-
+
/* convert all points (normal behaviour) */
for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++, pt++) {
/* convert screen-coordinates to appropriate coordinates (and store them) */
@@ -582,8 +615,8 @@ static void gp_stroke_newfrombuffer (tGPsdata *p)
/* copy pressure */
pt->pressure= ptc->pressure;
}
-
- if(depth_arr)
+
+ if (depth_arr)
MEM_freeN(depth_arr);
}
@@ -662,7 +695,7 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i)
}
/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */
-static short gp_stroke_eraser_strokeinside (int mval[], int mvalo[], short rad, short x0, short y0, short x1, short y1)
+static short gp_stroke_eraser_strokeinside (int mval[], int UNUSED(mvalo[]), short rad, short x0, short y0, short x1, short y1)
{
/* simple within-radius check for now */
if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1))
@@ -713,10 +746,10 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, int mval[], int mvalo[], sho
}
#endif
else {
- if(p->subrect == NULL) { /* normal 3D view */
- x0= (int)(gps->points->x / 100 * p->ar->winx);
- y0= (int)(gps->points->y / 100 * p->ar->winy);
- }
+ if (p->subrect == NULL) { /* normal 3D view */
+ x0= (int)(gps->points->x / 100 * p->ar->winx);
+ y0= (int)(gps->points->y / 100 * p->ar->winy);
+ }
else { /* camera view, use subrect */
x0= (int)((gps->points->x / 100) * (p->subrect->xmax - p->subrect->xmin)) + p->subrect->xmin;
y0= (int)((gps->points->y / 100) * (p->subrect->ymax - p->subrect->ymin)) + p->subrect->ymin;
@@ -777,11 +810,11 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, int mval[], int mvalo[], sho
#endif
else {
if(p->subrect == NULL) { /* normal 3D view */
- x0= (int)(pt1->x / 100 * p->ar->winx);
- y0= (int)(pt1->y / 100 * p->ar->winy);
- x1= (int)(pt2->x / 100 * p->ar->winx);
- y1= (int)(pt2->y / 100 * p->ar->winy);
- }
+ x0= (int)(pt1->x / 100 * p->ar->winx);
+ y0= (int)(pt1->y / 100 * p->ar->winy);
+ x1= (int)(pt2->x / 100 * p->ar->winx);
+ y1= (int)(pt2->y / 100 * p->ar->winy);
+ }
else { /* camera view, use subrect */
x0= (int)((pt1->x / 100) * (p->subrect->xmax - p->subrect->xmin)) + p->subrect->xmin;
y0= (int)((pt1->y / 100) * (p->subrect->ymax - p->subrect->ymin)) + p->subrect->ymin;
@@ -865,8 +898,9 @@ static tGPsdata *gp_session_initpaint (bContext *C)
/* create new context data */
p= MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data");
- /* pass on current scene */
+ /* pass on current scene and window */
p->scene= CTX_data_scene(C);
+ p->win= CTX_wm_window(C);
switch (curarea->spacetype) {
/* supported views first */
@@ -887,10 +921,10 @@ static tGPsdata *gp_session_initpaint (bContext *C)
printf("Error: 3D-View active region doesn't have any region data, so cannot be drawable \n");
return p;
}
-
+
/* for camera view set the subrect */
if(rv3d->persp == RV3D_CAMOB) {
- view3d_calc_camera_border(p->scene, p->ar, NULL, v3d, &p->subrect_data);
+ view3d_calc_camera_border(p->scene, p->ar, NULL, v3d, &p->subrect_data, 1);
p->subrect= &p->subrect_data;
}
@@ -1003,9 +1037,6 @@ static tGPsdata *gp_session_initpaint (bContext *C)
/* set edit flags - so that buffer will get drawn */
G.f |= G_GREASEPENCIL;
- /* set initial run flag */
- p->flags |= GP_PAINTFLAG_FIRSTRUN;
-
/* clear out buffer (stored in gp-data), in case something contaminated it */
gp_session_validatebuffer(p);
@@ -1068,15 +1099,26 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode)
p->paintmode= paintmode;
if (p->paintmode == GP_PAINTMODE_ERASER)
p->gpd->sbuffer_sflag |= GP_STROKE_ERASER;
+
+ /* set 'initial run' flag, which is only used to denote when a new stroke is starting */
+ p->flags |= GP_PAINTFLAG_FIRSTRUN;
/* check if points will need to be made in view-aligned space */
if (p->gpd->flag & GP_DATA_VIEWALIGN) {
switch (p->sa->spacetype) {
case SPACE_VIEW3D:
{
+ View3D *v3d= p->sa->spacedata.first;
RegionView3D *rv3d= p->ar->regiondata;
float rvec[3];
+ /* for camera view set the subrect */
+ if (rv3d->persp == RV3D_CAMOB) {
+ view3d_calc_camera_border(p->scene, p->ar, NULL, v3d, &p->subrect_data, -1); /* negative shift */
+ p->subrect= &p->subrect_data;
+ }
+
+ /* get reference point for 3d space placement */
gp_get_3d_reference(p, rvec);
initgrabz(rv3d, rvec[0], rvec[1], rvec[2]);
@@ -1149,6 +1191,17 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode)
/* finish off a stroke (clears buffer, but doesn't finish the paint operation) */
static void gp_paint_strokeend (tGPsdata *p)
{
+ /* for surface sketching, need to set the right OpenGL context stuff so that
+ * the conversions will project the values correctly...
+ */
+ if (gpencil_project_check(p)) {
+ View3D *v3d= p->sa->spacedata.first;
+
+ /* need to restore the original projection settings before packing up */
+ view3d_region_operator_needs_opengl(p->win, p->ar);
+ view_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0);
+ }
+
/* check if doing eraser or not */
if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) {
/* smooth stroke before transferring? */
@@ -1224,14 +1277,6 @@ static void gpencil_draw_exit (bContext *C, wmOperator *op)
}
/* cleanup */
- if(gpencil_project_check(p)) {
- View3D *v3d= p->sa->spacedata.first;
-
- /* need to restore the original projection settings before packing up */
- view3d_operator_needs_opengl(C);
- view_autodist_init(p->scene, p->ar, v3d, (p->gpd->flag & GP_DATA_DEPTH_STROKE) ? 1:0);
- }
-
gp_paint_cleanup(p);
gp_session_cleanup(p);
@@ -1249,8 +1294,48 @@ static int gpencil_draw_cancel (bContext *C, wmOperator *op)
/* ------------------------------- */
+/* update UI indicators of status, including cursor and header prints */
+static void gpencil_draw_status_indicators (tGPsdata *p)
+{
+ /* header prints */
+ switch (p->status) {
+ case GP_STATUS_PAINTING:
+ /* only print this for paint-sessions, otherwise it gets annoying */
+ if (GPENCIL_SKETCH_SESSIONS_ON(p->scene))
+ ED_area_headerprint(p->sa, "Grease Pencil: Drawing/erasing stroke... Release to end stroke");
+ break;
+
+ case GP_STATUS_IDLING:
+ /* print status info */
+ switch (p->paintmode) {
+ case GP_PAINTMODE_ERASER:
+ ED_area_headerprint(p->sa, "Grease Pencil Erase Session: Hold and drag LMB or RMB to erase | ESC/Enter to end");
+ break;
+ case GP_PAINTMODE_DRAW_STRAIGHT:
+ ED_area_headerprint(p->sa, "Grease Pencil Line Session: Hold and drag LMB to draw | ESC/Enter to end");
+ break;
+ case GP_PAINTMODE_DRAW:
+ ED_area_headerprint(p->sa, "Grease Pencil Freehand Session: Hold and drag LMB to draw | ESC/Enter to end");
+ break;
+
+ default: /* unhandled future cases */
+ ED_area_headerprint(p->sa, "Grease Pencil Session: ESC/Enter to end");
+ break;
+ }
+ break;
+
+ case GP_STATUS_ERROR:
+ case GP_STATUS_DONE:
+ /* clear status string */
+ ED_area_headerprint(p->sa, NULL);
+ break;
+ }
+}
+
+/* ------------------------------- */
+
/* create a new stroke point at the point indicated by the painting context */
-static void gpencil_draw_apply (bContext *C, wmOperator *op, tGPsdata *p)
+static void gpencil_draw_apply (wmOperator *op, tGPsdata *p)
{
/* handle drawing/erasing -> test for erasing first */
if (p->paintmode == GP_PAINTMODE_ERASER) {
@@ -1294,7 +1379,7 @@ static void gpencil_draw_apply (bContext *C, wmOperator *op, tGPsdata *p)
}
/* handle draw event */
-static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *event)
+static void gpencil_draw_apply_event (wmOperator *op, wmEvent *event)
{
tGPsdata *p= op->customdata;
ARegion *ar= p->ar;
@@ -1313,12 +1398,22 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even
tablet= (wmtab->Active != EVT_TABLET_NONE);
p->pressure= wmtab->Pressure;
+
//if (wmtab->Active == EVT_TABLET_ERASER)
// TODO... this should get caught by the keymaps which call drawing in the first place
}
else
p->pressure= 1.0f;
+ /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
+ RNA_collection_add(op->ptr, "stroke", &itemptr);
+
+ mousef[0]= p->mval[0];
+ mousef[1]= p->mval[1];
+ RNA_float_set_array(&itemptr, "mouse", mousef);
+ RNA_float_set(&itemptr, "pressure", p->pressure);
+ RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN));
+
/* special exception for start of strokes (i.e. maybe for just a dot) */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
@@ -1334,16 +1429,8 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even
return;
}
- /* fill in stroke data (not actually used directly by gpencil_draw_apply) */
- RNA_collection_add(op->ptr, "stroke", &itemptr);
-
- mousef[0]= p->mval[0];
- mousef[1]= p->mval[1];
- RNA_float_set_array(&itemptr, "mouse", mousef);
- RNA_float_set(&itemptr, "pressure", p->pressure);
-
/* apply the current latest drawing point */
- gpencil_draw_apply(C, op, p);
+ gpencil_draw_apply(op, p);
/* force refresh */
ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
@@ -1384,6 +1471,17 @@ static int gpencil_draw_exec (bContext *C, wmOperator *op)
p->mval[1] = (short)mousef[1];
p->pressure= RNA_float_get(&itemptr, "pressure");
+ if (RNA_boolean_get(&itemptr, "is_start")) {
+ /* if first-run flag isn't set already (i.e. not true first stroke),
+ * then we must terminate the previous one first before continuing
+ */
+ 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);
+ }
+ }
+
/* if first run, set previous data too */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
@@ -1394,7 +1492,7 @@ static int gpencil_draw_exec (bContext *C, wmOperator *op)
}
/* apply this data as necessary now (as per usual) */
- gpencil_draw_apply(C, op, p);
+ gpencil_draw_apply(op, p);
}
RNA_END;
@@ -1435,6 +1533,8 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event)
// TODO: set any additional settings that we can take from the events?
// TODO? if tablet is erasing, force eraser to be on?
+ // TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway...
+
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
// TODO: this involves mucking around with radial control, so we leave this for now..
@@ -1456,7 +1556,7 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event)
p->status= GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- gpencil_draw_apply_event(C, op, event);
+ gpencil_draw_apply_event(op, event);
}
else {
/* toolbar invoked - don't start drawing yet... */
@@ -1472,67 +1572,136 @@ static int gpencil_draw_invoke (bContext *C, wmOperator *op, wmEvent *event)
static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event)
{
tGPsdata *p= op->customdata;
+ int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */
//printf("\tGP - handle modal event...\n");
- switch (event->type) {
- /* end of stroke -> ONLY when a mouse-button release occurs
- * otherwise, carry on to mouse-move...
- */
- case LEFTMOUSE:
- case RIGHTMOUSE:
- /* if painting, end stroke */
- if (p->status == GP_STATUS_PAINTING) {
- /* basically, this should be mouse-button up */
- //printf("\t\tGP - end of stroke \n");
- gpencil_draw_exit(C, op);
-
- /* one last flush before we're done */
- WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX need a nicer one that will work
+ /* exit painting mode (and/or end current stroke) */
+ if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) {
+ /* exit() ends the current stroke before cleaning up */
+ //printf("\t\tGP - end of paint op + end of stroke\n");
+ gpencil_draw_exit(C, op);
+ p->status= GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+
+ /* toggle painting mode upon mouse-button movement */
+ if (ELEM(event->type, LEFTMOUSE, RIGHTMOUSE)) {
+ /* if painting, end stroke */
+ if (p->status == GP_STATUS_PAINTING) {
+ /* basically, this should be mouse-button up = end stroke
+ * BUT what happens next depends on whether we 'painting sessions' is enabled
+ */
+ if (GPENCIL_SKETCH_SESSIONS_ON(p->scene)) {
+ /* end stroke only, and then wait to resume painting soon */
+ //printf("\t\tGP - end stroke only\n");
+ gp_paint_cleanup(p);
+ p->status= GP_STATUS_IDLING;
- return OPERATOR_FINISHED;
+ /* we've just entered idling state, so this event was processed (but no others yet) */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ //printf("\t\tGP - end of stroke + op\n");
+ gpencil_draw_exit(C, op);
+ p->status= GP_STATUS_DONE;
+ estate = OPERATOR_FINISHED;
+ }
+ }
+ else {
+ /* not painting, so start stroke (this should be mouse-button down) */
+
+ /* we must check that we're still within the area that we're set up to work from
+ * otherwise we could crash (see bug #20586)
+ */
+ if (CTX_wm_area(C) != p->sa) {
+ //printf("\t\t\tGP - wrong area execution abort! \n");
+ gpencil_draw_exit(C, op);
+ p->status= GP_STATUS_ERROR;
+ estate = OPERATOR_CANCELLED;
}
else {
- /* not painting, so start stroke (this should be mouse-button down) */
-
- /* we must check that we're still within the area that we're set up to work from
- * otherwise we could crash (see bug #20586)
- */
- if (CTX_wm_area(C) != p->sa) {
- //printf("\t\t\tGP - wrong area execution abort! \n");
- gpencil_draw_exit(C, op);
- return OPERATOR_CANCELLED;
- }
-
//printf("\t\tGP - start stroke \n");
p->status= GP_STATUS_PAINTING;
- /* no break now, since we should immediately start painting */
- }
-
- /* moving mouse - assumed that mouse button is down if in painting status */
- case MOUSEMOVE:
- case INBETWEEN_MOUSEMOVE:
- /* check if we're currently painting */
- if (p->status == GP_STATUS_PAINTING) {
- /* handle drawing event */
- //printf("\t\tGP - add point\n");
- gpencil_draw_apply_event(C, op, event);
- /* finish painting operation if anything went wrong just now */
+ /* we may need to set up paint env again if we're resuming */
+ // XXX: watch it with the paintmode! in future, it'd be nice to allow changing paint-mode when in sketching-sessions
+ // XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support
+ gp_paint_initstroke(p, p->paintmode);
+
if (p->status == GP_STATUS_ERROR) {
- //printf("\t\t\tGP - error done! \n");
gpencil_draw_exit(C, op);
- return OPERATOR_CANCELLED;
+ estate = OPERATOR_CANCELLED;
}
}
+ }
+ }
+
+ /* handle mode-specific events */
+ if (p->status == GP_STATUS_PAINTING) {
+ /* handle painting mouse-movements? */
+ 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);
+
+ /* finish painting operation if anything went wrong just now */
+ if (p->status == GP_STATUS_ERROR) {
+ //printf("\t\t\t\tGP - add error done! \n");
+ gpencil_draw_exit(C, op);
+ estate = OPERATOR_CANCELLED;
+ }
+ else {
+ /* event handled, so just tag as running modal */
+ //printf("\t\t\t\tGP - add point handled!\n");
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+ /* there shouldn't be any other events, but just in case there are, let's swallow them
+ * (i.e. to prevent problems with with undo)
+ */
+ else {
+ /* swallow event to save ourselves trouble */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+ else if (p->status == GP_STATUS_IDLING) {
+ /* standard undo/redo shouldn't be allowed to execute or else it causes crashes, so catch it here */
+ // FIXME: this is a hardcoded hotkey that can't be changed
+ // TODO: catch redo as well, but how?
+ if (event->type == ZKEY) {
+ /* oskey = cmd key on macs as they seem to use cmd-z for undo as well? */
+ if ((event->ctrl) || (event->oskey)) {
+ /* just delete last stroke, which will look like undo to the end user */
+ //printf("caught attempted undo event... deleting last stroke \n");
+ gpencil_frame_delete_laststroke(p->gpl, p->gpf);
+
+ /* event handled, so force refresh */
+ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */
+ estate = OPERATOR_RUNNING_MODAL;
+ }
+ }
+ }
+
+ /* update status indicators - cursor, header, etc. */
+ gpencil_draw_status_indicators(p);
+
+ /* process last operations before exiting */
+ switch (estate) {
+ case OPERATOR_FINISHED:
+ /* one last flush before we're done */
+ WM_event_add_notifier(C, NC_SCREEN|ND_GPENCIL|NA_EDITED, NULL); // XXX need a nicer one that will work
break;
-
- default:
- //printf("\t\tGP unknown event - %d \n", event->type);
+
+ case OPERATOR_RUNNING_MODAL|OPERATOR_PASS_THROUGH:
+ /* event doesn't need to be handled */
+ //printf("unhandled event -> %d (mmb? = %d | mmv? = %d)\n", event->type, event->type == MIDDLEMOUSE, event->type==MOUSEMOVE);
break;
}
- return OPERATOR_RUNNING_MODAL;
+ /* return status code */
+ return estate;
}
/* ------------------------------- */
@@ -1546,8 +1715,6 @@ static EnumPropertyItem prop_gpencil_drawmodes[] = {
void GPENCIL_OT_draw (wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name= "Grease Pencil Draw";
ot->idname= "GPENCIL_OT_draw";
@@ -1564,8 +1731,7 @@ void GPENCIL_OT_draw (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
/* settings for drawing */
- prop= RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements.");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements.");
RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", "");
}