diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_grease_pencil_common.py | 48 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_sequencer.py | 12 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 12 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil.c | 3 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 13 | ||||
-rw-r--r-- | source/blender/editors/gpencil/annotate_draw.c | 98 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_gpencil_types.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_gpencil.c | 38 |
8 files changed, 223 insertions, 9 deletions
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index b18254a9102..ff294e7d922 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -779,6 +779,54 @@ class AnnotationDataPanel: row.operator("gpencil.active_frame_delete", text="", icon='X') +class AnnotationOnionSkin: + bl_label = "Onion Skin" + bl_region_type = 'UI' + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + # Show this panel as long as someone that might own this exists + # AND the owner isn't an object (e.g. GP Object) + if context.gpencil_data_owner is None: + return False + elif type(context.gpencil_data_owner) is bpy.types.Object: + return False + else: + gpl = context.active_gpencil_layer + if gpl is None: + return False + + return True + + @staticmethod + def draw_header(self, context): + gpl = context.active_gpencil_layer + self.layout.prop(gpl, "use_annotation_onion_skinning", text="") + + @staticmethod + def draw(self, context): + layout = self.layout + layout.use_property_decorate = False + + gpl = context.active_gpencil_layer + col = layout.column() + split = col.split(factor=0.5) + split.active = gpl.use_annotation_onion_skinning + + # - Before Frames + sub = split.column(align=True) + row = sub.row(align=True) + row.prop(gpl, "annotation_onion_before_color", text="") + sub.prop(gpl, "annotation_onion_before_range", text="Before") + + # - After Frames + sub = split.column(align=True) + row = sub.row(align=True) + row.prop(gpl, "annotation_onion_after_color", text="") + sub.prop(gpl, "annotation_onion_after_range", text="After") + + class GreasePencilOnionPanel: @staticmethod def draw_settings(layout, gp): diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index eb72d5cabb6..199b1f98fa9 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -22,6 +22,7 @@ from bpy.types import Header, Menu, Panel from rna_prop_ui import PropertyPanel from .properties_grease_pencil_common import ( AnnotationDataPanel, + AnnotationOnionSkin, GreasePencilToolsPanel, ) from bpy.app.translations import pgettext_iface as iface_ @@ -1335,6 +1336,16 @@ class SEQUENCER_PT_grease_pencil(AnnotationDataPanel, SequencerButtonsPanel_Outp # But, it should only show up when there are images in the preview region +class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_Output, Panel): + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'UI' + bl_category = "Strip" + bl_parent_id = 'SEQUENCER_PT_grease_pencil' + + # NOTE: this is just a wrapper around the generic GP Panel + # But, it should only show up when there are images in the preview region + + class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel): bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'UI' @@ -1381,6 +1392,7 @@ classes = ( SEQUENCER_PT_view_safe_areas, SEQUENCER_PT_modifiers, SEQUENCER_PT_grease_pencil, + SEQUENCER_PT_annotation_onion, SEQUENCER_PT_grease_pencil_tools, SEQUENCER_PT_custom_props, ) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 8eac3cec976..5321c7d655e 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -20,7 +20,7 @@ import bpy from bpy.types import Header, Menu, Panel from .properties_paint_common import UnifiedPaintPanel -from .properties_grease_pencil_common import AnnotationDataPanel +from .properties_grease_pencil_common import AnnotationDataPanel, AnnotationOnionSkin from bpy.app.translations import contexts as i18n_contexts @@ -5171,6 +5171,15 @@ class VIEW3D_PT_grease_pencil(AnnotationDataPanel, Panel): # NOTE: this is just a wrapper around the generic GP Panel +class VIEW3D_PT_annotation_onion(AnnotationOnionSkin, Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'UI' + bl_category = "View" + bl_parent_id = 'VIEW3D_PT_grease_pencil' + + # NOTE: this is just a wrapper around the generic GP Panel + + class TOPBAR_PT_annotation_layers(Panel, AnnotationDataPanel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' @@ -5539,6 +5548,7 @@ classes = ( VIEW3D_PT_collections, VIEW3D_PT_object_type_visibility, VIEW3D_PT_grease_pencil, + VIEW3D_PT_annotation_onion, VIEW3D_PT_gpencil_multi_frame, VIEW3D_MT_gpencil_autoweights, VIEW3D_MT_gpencil_edit_specials, diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 98d255df080..e694c12e543 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -373,6 +373,9 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti /* set default thickness of new strokes for this layer */ gpl->thickness = 3; + /* Onion colors */ + ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f); + ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f); } else { /* thickness parameter represents "thickness change", not absolute thickness */ diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 1bec320b00a..5d1d4a9ad2f 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1116,7 +1116,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Init grease pencil pixel size factor */ - if (!DNA_struct_elem_find(fd->filesdna, "bGPDdata", "int", "pixfactor")) { + if (!DNA_struct_elem_find(fd->filesdna, "bGPdata", "int", "pixfactor")) { for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) { gpd->pixfactor = GP_DEFAULT_PIX_FACTOR; } @@ -2463,5 +2463,16 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) STRNCPY(scene->r.engine, RE_engine_id_BLENDER_WORKBENCH); } } + + /* init Annotations onion skin */ + if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "int", "gstep")) { + for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) { + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + ARRAY_SET_ITEMS(gpl->gcolor_prev, 0.302f, 0.851f, 0.302f); + ARRAY_SET_ITEMS(gpl->gcolor_next, 0.250f, 0.1f, 1.0f); + } + } + } + } } diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index c83015675a0..345a623a234 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -242,7 +242,7 @@ static void gp_draw_stroke_point( /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */ static void gp_draw_stroke_3d( - const bGPDspoint *points, int totpoints, short thickness, bool UNUSED(debug), + const bGPDspoint *points, int totpoints, short thickness, short UNUSED(sflag), const float ink[4], bool cyclic) { float curpressure = points[0].pressure; @@ -323,7 +323,7 @@ static void gp_draw_stroke_3d( /* draw a given stroke in 2d */ static void gp_draw_stroke_2d( const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag, - bool UNUSED(debug), int offsx, int offsy, int winx, int winy, const float ink[4]) + int offsx, int offsy, int winx, int winy, const float ink[4]) { /* otherwise thickness is twice that of the 3D view */ float thickness = (float)thickness_s * 0.5f; @@ -521,7 +521,7 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) /* draw a set of strokes */ static void gp_draw_strokes( bGPdata *UNUSED(gpd), bGPDlayer *UNUSED(gpl), const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, - int dflag, bool debug, short lthick, const float color[4]) + int dflag, short lthick, const float color[4]) { GPU_enable_program_point_size(); @@ -552,7 +552,7 @@ static void gp_draw_strokes( } else { gp_draw_stroke_3d( - gps->points, gps->totpoints, lthick, debug, gps->flag, + gps->points, gps->totpoints, lthick, gps->flag, color, gps->flag & GP_STROKE_CYCLIC); } @@ -570,7 +570,7 @@ static void gp_draw_strokes( } else { gp_draw_stroke_2d( - gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, + gps->points, gps->totpoints, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color); } } @@ -714,6 +714,86 @@ static void gp_draw_strokes_edit( } /* ----- General Drawing ------ */ +/* draw onion-skinning for a layer */ +static void gp_draw_onionskins( + bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, + int UNUSED(cfra), int dflag) +{ + const float alpha = 1.0f; + float color[4]; + + /* 1) Draw Previous Frames First */ + copy_v3_v3(color, gpl->gcolor_prev); + + if (gpl->gstep > 0) { + bGPDframe *gf; + float fac; + + /* draw previous frames first */ + for (gf = gpf->prev; gf; gf = gf->prev) { + /* check if frame is drawable */ + if ((gpf->framenum - gf->framenum) <= gpl->gstep) { + /* alpha decreases with distance from curframe index */ + fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1)); + color[3] = alpha * fac * 0.66f; + gp_draw_strokes( + gpd, gpl, gf, offsx, offsy, winx, winy, dflag, + gpl->thickness, color); + } + else + break; + } + } + else if (gpl->gstep == 0) { + /* draw the strokes for the ghost frames (at half of the alpha set by user) */ + if (gpf->prev) { + color[3] = (alpha / 7); + gp_draw_strokes( + gpd, gpl, gpf->prev, offsx, offsy, winx, winy, dflag, + gpl->thickness, color); + } + } + else { + /* don't draw - disabled */ + } + + + /* 2) Now draw next frames */ + copy_v3_v3(color, gpl->gcolor_next); + + if (gpl->gstep_next > 0) { + bGPDframe *gf; + float fac; + + /* now draw next frames */ + for (gf = gpf->next; gf; gf = gf->next) { + /* check if frame is drawable */ + if ((gf->framenum - gpf->framenum) <= gpl->gstep_next) { + /* alpha decreases with distance from curframe index */ + fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1)); + color[3] = alpha * fac * 0.66f; + gp_draw_strokes( + gpd, gpl, gf, offsx, offsy, winx, winy, dflag, + gpl->thickness, color); + } + else + break; + } + } + else if (gpl->gstep_next == 0) { + /* draw the strokes for the ghost frames (at half of the alpha set by user) */ + if (gpf->next) { + color[3] = (alpha / 4); + gp_draw_strokes( + gpd, gpl, gpf->next, offsx, offsy, winx, winy, dflag, + gpl->thickness, color); + } + } + else { + /* don't draw - disabled */ + } + +} /* loop over gpencil data layers, drawing them */ static void gp_draw_data_layers( @@ -723,7 +803,6 @@ static void gp_draw_data_layers( float ink[4]; for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG); short lthick = gpl->thickness; /* apply layer opacity */ @@ -750,8 +829,13 @@ static void gp_draw_data_layers( /* xray... */ SET_FLAG_FROM_TEST(dflag, gpl->flag & GP_LAYER_NO_XRAY, GP_DRAWDATA_NO_XRAY); + /* Draw 'onionskins' (frame left + right) */ + if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { + gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag); + } + /* draw the strokes already in active frame */ - gp_draw_strokes(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, debug, lthick, ink); + gp_draw_strokes(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, lthick, ink); /* Draw verts of selected strokes * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index cebdc4b29b9..43ce3649db3 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -272,6 +272,14 @@ typedef struct bGPDlayer { int blend_mode; /* blend modes */ char pad_[4]; + /* annotation onion skin */ + short gstep; /* Ghosts Before: max number of ghost frames to show between active frame and the one before it (0 = only the ghost itself) */ + short gstep_next; /* Ghosts After: max number of ghost frames to show after active frame and the following it (0 = only the ghost itself) */ + + float gcolor_prev[3]; /* color for ghosts before the active frame */ + float gcolor_next[3]; /* color for ghosts after the active frame */ + char pad_1[4]; + bGPDlayer_Runtime runtime; } bGPDlayer; diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index d6257aa0c1b..0006a8859bf 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -1076,6 +1076,8 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) PropertyRNA *prop; FunctionRNA *func; + static const float default_onion_color_b[] = { 0.302f, 0.851f, 0.302f }; + static const float default_onion_color_a[] = { 0.250f, 0.1f, 1.0f }; srna = RNA_def_struct(brna, "GPencilLayer", NULL); RNA_def_struct_sdna(srna, "bGPDlayer"); @@ -1157,6 +1159,42 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Onion Skinning", "Display onion skins before and after the current frame"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + prop = RNA_def_property(srna, "use_annotation_onion_skinning", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_LAYER_ONIONSKIN); + RNA_def_property_ui_text(prop, "Onion Skinning", + "Display annotation onion skins before and after the current frame"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + prop = RNA_def_property(srna, "annotation_onion_before_range", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "gstep"); + RNA_def_property_range(prop, -1, 120); + RNA_def_property_ui_text(prop, "Frames Before", + "Maximum number of frames to show before current frame"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + prop = RNA_def_property(srna, "annotation_onion_after_range", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "gstep_next"); + RNA_def_property_range(prop, -1, 120); + RNA_def_property_ui_text(prop, "Frames After", + "Maximum number of frames to show after current frame"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + prop = RNA_def_property(srna, "annotation_onion_before_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "gcolor_prev"); + RNA_def_property_array(prop, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_array_default(prop, default_onion_color_b); + RNA_def_property_ui_text(prop, "Before Color", "Base color for ghosts before the active frame"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + + prop = RNA_def_property(srna, "annotation_onion_after_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "gcolor_next"); + RNA_def_property_array(prop, 3); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_array_default(prop, default_onion_color_a); + RNA_def_property_ui_text(prop, "After Color", "Base color for ghosts after the active frame"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* pass index for compositing and modifiers */ prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "pass_index"); |