diff options
author | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
commit | f01261d040be27337db9f9996d648a279c89b7c4 (patch) | |
tree | c448230939b3c90d53ce8852dd00925d6052e3a4 /source/blender/editors/gpencil | |
parent | dcaeda5c4e3a0687251b8511de4f2e8b85ef75c0 (diff) | |
parent | 2198cfdb2deec8b2e85e242c74a032f43d0b26ca (diff) |
merge with/from trunk at r35190
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r-- | source/blender/editors/gpencil/CMakeLists.txt | 18 | ||||
-rw-r--r-- | source/blender/editors/gpencil/Makefile | 56 | ||||
-rw-r--r-- | source/blender/editors/gpencil/SConscript | 4 | ||||
-rw-r--r-- | source/blender/editors/gpencil/drawgpencil.c | 16 | ||||
-rw-r--r-- | source/blender/editors/gpencil/editaction_gpencil.c | 68 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_buttons.c | 47 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_edit.c | 8 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_ops.c | 4 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 418 |
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", ""); } |