forked from bartvdbraak/blender
GP: New Blend Layers functionality
Now it's possible define the blend mode between layers including the option to clamp the layer using underlying layers. Also a new Simplify option has been added to disable blend layers.
This commit is contained in:
parent
c0816cd03b
commit
99f7934e19
@ -135,13 +135,22 @@ class DATA_PT_gpencil_datapanel(Panel):
|
||||
col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index",
|
||||
rows=layer_rows, reverse=True)
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "blend_mode", text="Blend")
|
||||
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
srow.prop(gpl, "clamp_layer", text="",
|
||||
icon='MOD_MASK' if gpl.clamp_layer else 'ONIONSKIN_OFF')
|
||||
|
||||
col = row.column()
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.operator("gpencil.layer_add", icon='ADD', text="")
|
||||
sub.operator("gpencil.layer_remove", icon='REMOVE', text="")
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
|
||||
|
||||
@ -158,10 +167,6 @@ class DATA_PT_gpencil_datapanel(Panel):
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_ON', text="").affect_visibility = True
|
||||
|
||||
row = layout.row(align=True)
|
||||
if gpl:
|
||||
row.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class DATA_PT_gpencil_layer_optionpanel(LayerDataButtonsPanel, Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
@ -766,7 +766,6 @@ class AnnotationDataPanel:
|
||||
layout.prop(tool_settings, "annotation_thickness", text="Thickness")
|
||||
|
||||
if gpl:
|
||||
# layout.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
# Full-Row - Frame Locking (and Delete Frame)
|
||||
row = layout.row(align=True)
|
||||
row.active = not gpl.lock
|
||||
@ -873,6 +872,10 @@ class GPENCIL_UL_layer(UIList):
|
||||
row.prop(gpl, "info", text="", emboss=False)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(gpl, "clamp_layer", text="",
|
||||
icon='MOD_MASK' if gpl.clamp_layer else 'ONIONSKIN_OFF',
|
||||
emboss=False)
|
||||
|
||||
row.prop(gpl, "lock", text="", emboss=False)
|
||||
row.prop(gpl, "hide", text="", emboss=False)
|
||||
subrow = row.row(align=True)
|
||||
|
@ -650,6 +650,7 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
|
||||
rd = context.scene.render
|
||||
|
||||
@ -659,8 +660,8 @@ class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel):
|
||||
col.prop(rd, "simplify_gpencil_onplay", text="Playback Only")
|
||||
col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
|
||||
col.prop(rd, "simplify_gpencil_shader_fx", text="ShaderFX")
|
||||
col.prop(rd, "simplify_gpencil_blend", text="Layers Blending")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(rd, "simplify_gpencil_view_fill")
|
||||
sub = col.column()
|
||||
sub.active = rd.simplify_gpencil_view_fill
|
||||
|
@ -516,6 +516,16 @@ class TOPBAR_PT_gpencil_layers(Panel):
|
||||
col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index",
|
||||
rows=layer_rows, reverse=True)
|
||||
|
||||
gpl = context.active_gpencil_layer
|
||||
if gpl:
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "blend_mode", text="Blend")
|
||||
|
||||
srow = col.row(align=True)
|
||||
srow.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
srow.prop(gpl, "clamp_layer", text="",
|
||||
icon='MOD_MASK' if gpl.clamp_layer else 'ONIONSKIN_OFF')
|
||||
|
||||
col = row.column()
|
||||
|
||||
sub = col.column(align=True)
|
||||
@ -539,10 +549,6 @@ class TOPBAR_PT_gpencil_layers(Panel):
|
||||
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
|
||||
sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', text="").affect_visibility = True
|
||||
|
||||
row = layout.row(align=True)
|
||||
if gpl:
|
||||
row.prop(gpl, "opacity", text="Opacity", slider=True)
|
||||
|
||||
|
||||
class TOPBAR_MT_editor_menus(Menu):
|
||||
bl_idname = "TOPBAR_MT_editor_menus"
|
||||
|
@ -327,6 +327,7 @@ data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_geom.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_stroke_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_zdepth_mix_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_simple_mix_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_blend_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_vert.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_geom.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/gpencil_point_frag.glsl SRC)
|
||||
|
@ -83,8 +83,12 @@ tGPencilObjectCache *gpencil_object_cache_add(
|
||||
cache_elem->pixfactor = cache_elem->gpd->pixfactor;
|
||||
cache_elem->shader_fx = ob_orig->shader_fx;
|
||||
|
||||
cache_elem->init_grp = NULL;
|
||||
cache_elem->end_grp = NULL;
|
||||
/* shgrp array */
|
||||
cache_elem->tot_layers = 0;
|
||||
int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
|
||||
if (totgpl > 0) {
|
||||
cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
|
||||
}
|
||||
|
||||
/* calculate zdepth from point of view */
|
||||
float zdepth = 0.0;
|
||||
|
@ -244,13 +244,15 @@ static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, floa
|
||||
}
|
||||
|
||||
/* recalc the internal geometry caches for fill and uvs */
|
||||
static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
|
||||
static void DRW_gpencil_recalc_geometry_caches(
|
||||
Object *ob, bGPDlayer *gpl, MaterialGPencilStyle *gp_style, bGPDstroke *gps)
|
||||
{
|
||||
if (gps->flag & GP_STROKE_RECALC_CACHES) {
|
||||
/* Calculate triangles cache for filling area (must be done only after changes) */
|
||||
if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
|
||||
if ((gps->totpoints > 2) &&
|
||||
((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)))
|
||||
((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
|
||||
(gp_style->fill_style > 0) || (gpl->blend_mode != eGplBlendMode_Normal)))
|
||||
{
|
||||
DRW_gpencil_triangulate_stroke_fill(ob, gps);
|
||||
}
|
||||
@ -559,7 +561,9 @@ static void gpencil_add_fill_vertexdata(
|
||||
/* set color using material, tint color and opacity */
|
||||
interp_v3_v3v3(tfill, gps->runtime.tmp_fill_rgba, tintcolor, tintcolor[3]);
|
||||
tfill[3] = gps->runtime.tmp_fill_rgba[3] * opacity;
|
||||
if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) {
|
||||
if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
|
||||
(gp_style->fill_style > 0) ||
|
||||
(gpl->blend_mode != eGplBlendMode_Normal)) {
|
||||
if (cache->is_dirty) {
|
||||
const float *color;
|
||||
if (!onion) {
|
||||
@ -581,7 +585,8 @@ static void gpencil_add_fill_vertexdata(
|
||||
/* add to list of groups */
|
||||
if (old_len < cache->b_fill.vbo_len) {
|
||||
cache->grp_cache = gpencil_group_cache_add(
|
||||
cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Fill, onion,
|
||||
cache->grp_cache, gpl, gpf, gps,
|
||||
eGpencilBatchGroupType_Fill, onion,
|
||||
cache->b_fill.vbo_len,
|
||||
&cache->grp_size, &cache->grp_used);
|
||||
}
|
||||
@ -637,7 +642,8 @@ static void gpencil_add_stroke_vertexdata(
|
||||
/* add to list of groups */
|
||||
if (old_len < cache->b_stroke.vbo_len) {
|
||||
cache->grp_cache = gpencil_group_cache_add(
|
||||
cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Stroke, onion,
|
||||
cache->grp_cache, gpl, gpf, gps,
|
||||
eGpencilBatchGroupType_Stroke, onion,
|
||||
cache->b_stroke.vbo_len,
|
||||
&cache->grp_size, &cache->grp_used);
|
||||
}
|
||||
@ -687,7 +693,8 @@ static void gpencil_add_editpoints_vertexdata(
|
||||
|
||||
/* add to list of groups */
|
||||
cache->grp_cache = gpencil_group_cache_add(
|
||||
cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edlin, false,
|
||||
cache->grp_cache, gpl, gpf, gps,
|
||||
eGpencilBatchGroupType_Edlin, false,
|
||||
cache->b_edlin.vbo_len,
|
||||
&cache->grp_size, &cache->grp_used);
|
||||
}
|
||||
@ -699,7 +706,8 @@ static void gpencil_add_editpoints_vertexdata(
|
||||
|
||||
/* add to list of groups */
|
||||
cache->grp_cache = gpencil_group_cache_add(
|
||||
cache->grp_cache, gpl, gpf, gps, eGpencilBatchGroupType_Edit, false,
|
||||
cache->grp_cache, gpl, gpf, gps,
|
||||
eGpencilBatchGroupType_Edit, false,
|
||||
cache->b_edit.vbo_len,
|
||||
&cache->grp_size, &cache->grp_used);
|
||||
}
|
||||
@ -771,13 +779,14 @@ static void gpencil_draw_strokes(
|
||||
/* be sure recalc all cache in source stroke to avoid recalculation when frame change
|
||||
* and improve fps */
|
||||
if (src_gps) {
|
||||
DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps);
|
||||
DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, src_gps);
|
||||
}
|
||||
|
||||
/* if the fill has any value, it's considered a fill and is not drawn if simplify fill is enabled */
|
||||
if ((stl->storage->simplify_fill) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_REMOVE_FILL_LINE)) {
|
||||
if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
|
||||
(gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID))
|
||||
(gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
|
||||
(gpl->blend_mode != eGplBlendMode_Normal))
|
||||
{
|
||||
GP_SET_SRC_GPS(src_gps);
|
||||
continue;
|
||||
@ -798,9 +807,14 @@ static void gpencil_draw_strokes(
|
||||
}
|
||||
}
|
||||
|
||||
/* hide any blend layer */
|
||||
if ((!stl->storage->simplify_blend) ||
|
||||
(gpl->blend_mode == eGplBlendMode_Normal))
|
||||
{
|
||||
/* fill */
|
||||
if ((gp_style->flag & GP_STYLE_FILL_SHOW) &&
|
||||
(!stl->storage->simplify_fill))
|
||||
(!stl->storage->simplify_fill) &&
|
||||
((gps->flag & GP_STROKE_NOFILL) == 0))
|
||||
{
|
||||
gpencil_add_fill_vertexdata(
|
||||
cache, ob, gpl, derived_gpf, gps,
|
||||
@ -808,13 +822,15 @@ static void gpencil_draw_strokes(
|
||||
}
|
||||
/* stroke */
|
||||
if ((gp_style->flag & GP_STYLE_STROKE_SHOW) &&
|
||||
(gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH))
|
||||
((gp_style->stroke_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
|
||||
(gpl->blend_mode == eGplBlendMode_Normal)))
|
||||
{
|
||||
gpencil_add_stroke_vertexdata(
|
||||
cache, ob, gpl, derived_gpf, gps,
|
||||
opacity, tintcolor, false, custonion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* edit points (only in edit mode and not play animation not render) */
|
||||
if ((draw_ctx->obact == ob) && (src_gps) &&
|
||||
@ -1253,12 +1269,21 @@ static void DRW_gpencil_create_batches(GpencilBatchCache *cache)
|
||||
/* create all shading groups */
|
||||
static void DRW_gpencil_shgroups_create(
|
||||
GPENCIL_e_data *e_data, void *vedata,
|
||||
Object *ob, bGPdata *gpd,
|
||||
Object *ob,
|
||||
GpencilBatchCache *cache, tGPencilObjectCache *cache_ob)
|
||||
{
|
||||
GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
|
||||
GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl;
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
|
||||
GpencilBatchGroup *elm = NULL;
|
||||
DRWShadingGroup *shgrp = NULL;
|
||||
tGPencilObjectCache_shgrp *array_elm = NULL;
|
||||
|
||||
bGPDlayer *gpl = NULL;
|
||||
bGPDlayer *gpl_prev = NULL;
|
||||
int idx = 0;
|
||||
bool tag_first = false;
|
||||
|
||||
int start_stroke = 0;
|
||||
int start_point = 0;
|
||||
@ -1266,12 +1291,28 @@ static void DRW_gpencil_shgroups_create(
|
||||
int start_edit = 0;
|
||||
int start_edlin = 0;
|
||||
|
||||
cache_ob->init_grp = NULL;
|
||||
cache_ob->end_grp = NULL;
|
||||
|
||||
for (int i = 0; i < cache->grp_used; i++) {
|
||||
GpencilBatchGroup *elm = &cache->grp_cache[i];
|
||||
bGPDlayer *gpl = elm->gpl;
|
||||
elm = &cache->grp_cache[i];
|
||||
array_elm = &cache_ob->shgrp_array[idx];
|
||||
|
||||
/* save last group when change */
|
||||
if (gpl_prev == NULL) {
|
||||
gpl_prev = elm->gpl;
|
||||
tag_first = true;
|
||||
}
|
||||
else {
|
||||
if (elm->gpl != gpl_prev)
|
||||
{
|
||||
/* first layer is always blend Normal */
|
||||
array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
|
||||
array_elm->end_shgrp = shgrp;
|
||||
gpl_prev = elm->gpl;
|
||||
tag_first = true;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
gpl = elm->gpl;
|
||||
bGPDframe *gpf = elm->gpf;
|
||||
bGPDstroke *gps = elm->gps;
|
||||
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
|
||||
@ -1365,14 +1406,22 @@ static void DRW_gpencil_shgroups_create(
|
||||
}
|
||||
}
|
||||
/* save first group */
|
||||
if ((shgrp != NULL) && (cache_ob->init_grp == NULL)) {
|
||||
cache_ob->init_grp = shgrp;
|
||||
if ((shgrp != NULL) && (tag_first)) {
|
||||
array_elm = &cache_ob->shgrp_array[idx];
|
||||
array_elm->mode = idx == 0 ? eGplBlendMode_Normal: gpl->blend_mode;
|
||||
array_elm->clamp_layer = gpl->flag & GP_LAYER_USE_MASK;
|
||||
array_elm->blend_opacity = gpl->opacity;
|
||||
array_elm->init_shgrp = shgrp;
|
||||
cache_ob->tot_layers++;
|
||||
|
||||
tag_first = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* save last group */
|
||||
if (shgrp != NULL) {
|
||||
cache_ob->end_grp = shgrp;
|
||||
array_elm->mode = idx == 0 ? eGplBlendMode_Normal : gpl->blend_mode;
|
||||
array_elm->end_shgrp = shgrp;
|
||||
}
|
||||
}
|
||||
/* populate a datablock for multiedit (no onions, no modifiers) */
|
||||
@ -1425,7 +1474,7 @@ void DRW_gpencil_populate_multiedit(
|
||||
|
||||
/* create batchs and shading groups */
|
||||
DRW_gpencil_create_batches(cache);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
|
||||
|
||||
cache->is_dirty = false;
|
||||
}
|
||||
@ -1465,7 +1514,7 @@ void DRW_gpencil_populate_datablock(
|
||||
|
||||
/* if object is duplicate, only create shading groups */
|
||||
if (cache_ob->is_dup_ob) {
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1481,8 +1530,9 @@ void DRW_gpencil_populate_datablock(
|
||||
/* draw normal strokes */
|
||||
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
|
||||
/* don't draw layer if hidden */
|
||||
if (gpl->flag & GP_LAYER_HIDE)
|
||||
if (gpl->flag & GP_LAYER_HIDE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter view layer to gp layers in the same view layer (for compo) */
|
||||
if ((stl->storage->is_render) && (gpl->viewlayername[0] != '\0')) {
|
||||
@ -1560,7 +1610,7 @@ void DRW_gpencil_populate_datablock(
|
||||
|
||||
/* create batchs and shading groups */
|
||||
DRW_gpencil_create_batches(cache);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
|
||||
|
||||
cache->is_dirty = false;
|
||||
}
|
||||
@ -1574,9 +1624,8 @@ void DRW_gpencil_populate_particles(GPENCIL_e_data *e_data, void *vedata)
|
||||
tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
|
||||
Object *ob = cache_ob->ob;
|
||||
if (cache_ob->is_dup_ob) {
|
||||
bGPdata *gpd = (bGPdata *)ob->data;
|
||||
GpencilBatchCache *cache = ob->runtime.gpencil_cache;
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, gpd, cache, cache_ob);
|
||||
DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ extern char datatoc_gpencil_paper_frag_glsl[];
|
||||
extern char datatoc_gpencil_edit_point_vert_glsl[];
|
||||
extern char datatoc_gpencil_edit_point_geom_glsl[];
|
||||
extern char datatoc_gpencil_edit_point_frag_glsl[];
|
||||
extern char datatoc_gpencil_blend_frag_glsl[];
|
||||
|
||||
/* *********** STATIC *********** */
|
||||
static GPENCIL_e_data e_data = {NULL}; /* Engine data */
|
||||
@ -221,6 +222,11 @@ static void GPENCIL_create_shaders(void)
|
||||
e_data.gpencil_simple_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_simple_mix_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
/* blend */
|
||||
if (!e_data.gpencil_blend_fullscreen_sh) {
|
||||
e_data.gpencil_blend_fullscreen_sh = DRW_shader_create_fullscreen(datatoc_gpencil_blend_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
/* shaders for use when drawing */
|
||||
if (!e_data.gpencil_background_sh) {
|
||||
e_data.gpencil_background_sh = DRW_shader_create_fullscreen(datatoc_gpencil_background_frag_glsl, NULL);
|
||||
@ -266,6 +272,7 @@ static void GPENCIL_engine_free(void)
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_edit_point_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_fullscreen_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_simple_fullscreen_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_blend_fullscreen_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_background_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.gpencil_paper_sh);
|
||||
|
||||
@ -371,6 +378,7 @@ void GPENCIL_cache_init(void *vedata)
|
||||
stl->storage->simplify_fill = GP_SIMPLIFY_FILL(scene, stl->storage->is_playing);
|
||||
stl->storage->simplify_modif = GP_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
|
||||
stl->storage->simplify_fx = GP_SIMPLIFY_FX(scene, stl->storage->is_playing);
|
||||
stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
|
||||
|
||||
/* save pixsize */
|
||||
stl->storage->pixsize = DRW_viewport_pixelsize_get();
|
||||
@ -485,6 +493,20 @@ void GPENCIL_cache_init(void *vedata)
|
||||
stl->g_data->shgrps_grid = DRW_shgroup_create(e_data.gpencil_line_sh, psl->grid_pass);
|
||||
}
|
||||
|
||||
/* blend layers pass */
|
||||
psl->blend_pass = DRW_pass_create(
|
||||
"GPencil Blend Layers Pass",
|
||||
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||
DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh, psl->blend_pass);
|
||||
DRW_shgroup_call_add(blend_shgrp, quad, NULL);
|
||||
DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a);
|
||||
DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a);
|
||||
DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx);
|
||||
DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendDepth", &e_data.temp_depth_tx_fx);
|
||||
DRW_shgroup_uniform_int(blend_shgrp, "mode", &stl->storage->blend_mode, 1);
|
||||
DRW_shgroup_uniform_int(blend_shgrp, "clamp_layer", &stl->storage->clamp_layer, 1);
|
||||
DRW_shgroup_uniform_float(blend_shgrp, "blend_opacity", &stl->storage->blend_opacity, 1);
|
||||
|
||||
/* create effects passes */
|
||||
if (!stl->storage->simplify_fx) {
|
||||
GPENCIL_create_fx_passes(psl);
|
||||
@ -639,12 +661,40 @@ static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl)
|
||||
tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i];
|
||||
bGPdata *gpd = cache_ob->gpd;
|
||||
gpd->flag &= ~GP_DATA_CACHE_IS_DIRTY;
|
||||
|
||||
/* free shgrp array */
|
||||
cache_ob->tot_layers = 0;
|
||||
MEM_SAFE_FREE(cache_ob->shgrp_array);
|
||||
}
|
||||
|
||||
/* free the cache itself */
|
||||
MEM_SAFE_FREE(stl->g_data->gp_object_cache);
|
||||
}
|
||||
|
||||
static void gpencil_draw_pass_range(
|
||||
GPENCIL_FramebufferList *fbl, GPENCIL_StorageList *stl,
|
||||
GPENCIL_PassList *psl, GPENCIL_TextureList *txl,
|
||||
GPUFrameBuffer *fb,
|
||||
DRWShadingGroup *init_shgrp, DRWShadingGroup *end_shgrp, bool multi)
|
||||
{
|
||||
if (init_shgrp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* previews don't use AA */
|
||||
if ((!stl->storage->is_mat_preview) && (multi)) {
|
||||
MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
|
||||
}
|
||||
|
||||
DRW_draw_pass_subset(
|
||||
psl->stroke_pass, init_shgrp, end_shgrp);
|
||||
|
||||
if ((!stl->storage->is_mat_preview) && (multi)) {
|
||||
MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fb, txl);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* draw scene */
|
||||
void GPENCIL_draw_scene(void *ved)
|
||||
{
|
||||
@ -657,6 +707,10 @@ void GPENCIL_draw_scene(void *ved)
|
||||
GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl;
|
||||
|
||||
tGPencilObjectCache *cache_ob;
|
||||
tGPencilObjectCache_shgrp *array_elm = NULL;
|
||||
DRWShadingGroup *init_shgrp = NULL;
|
||||
DRWShadingGroup *end_shgrp = NULL;
|
||||
|
||||
const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
@ -712,7 +766,7 @@ void GPENCIL_draw_scene(void *ved)
|
||||
for (int i = 0; i < stl->g_data->gp_cache_used; i++) {
|
||||
cache_ob = &stl->g_data->gp_object_cache[i];
|
||||
bGPdata *gpd = cache_ob->gpd;
|
||||
|
||||
init_shgrp = NULL;
|
||||
/* Render stroke in separated framebuffer */
|
||||
GPU_framebuffer_bind(fbl->temp_fb_a);
|
||||
GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
|
||||
@ -720,19 +774,67 @@ void GPENCIL_draw_scene(void *ved)
|
||||
/* Stroke Pass:
|
||||
* draw only a subset that usually starts with a fill and ends with stroke
|
||||
*/
|
||||
if (cache_ob->init_grp) {
|
||||
/* previews don't use AA */
|
||||
if (!stl->storage->is_mat_preview) {
|
||||
MULTISAMPLE_GP_SYNC_ENABLE(stl->storage->multisamples, fbl);
|
||||
bool use_blend = false;
|
||||
if (cache_ob->tot_layers > 0) {
|
||||
for (int e = 0; e < cache_ob->tot_layers; e++) {
|
||||
bool is_last = e == cache_ob->tot_layers - 1 ? true : false;
|
||||
array_elm = &cache_ob->shgrp_array[e];
|
||||
|
||||
if (((array_elm->mode == eGplBlendMode_Normal) &&
|
||||
(!use_blend) && (!array_elm->clamp_layer)) ||
|
||||
( e == 0))
|
||||
{
|
||||
if (init_shgrp == NULL) {
|
||||
init_shgrp = array_elm->init_shgrp;
|
||||
}
|
||||
end_shgrp = array_elm->end_shgrp;
|
||||
}
|
||||
else {
|
||||
use_blend = true;
|
||||
/* draw pending groups */
|
||||
gpencil_draw_pass_range(
|
||||
fbl, stl, psl, txl, fbl->temp_fb_a,
|
||||
init_shgrp, end_shgrp, is_last);
|
||||
|
||||
/* draw current group in separated texture */
|
||||
init_shgrp = array_elm->init_shgrp;
|
||||
end_shgrp = array_elm->end_shgrp;
|
||||
|
||||
GPU_framebuffer_bind(fbl->temp_fb_fx);
|
||||
GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f);
|
||||
gpencil_draw_pass_range(
|
||||
fbl, stl, psl, txl, fbl->temp_fb_fx,
|
||||
init_shgrp, end_shgrp,
|
||||
is_last);
|
||||
|
||||
/* Blend A texture and FX texture */
|
||||
GPU_framebuffer_bind(fbl->temp_fb_b);
|
||||
GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f);
|
||||
stl->storage->blend_mode = array_elm->mode;
|
||||
stl->storage->clamp_layer = (int)array_elm->clamp_layer;
|
||||
stl->storage->blend_opacity = array_elm->blend_opacity;
|
||||
DRW_draw_pass(psl->blend_pass);
|
||||
|
||||
/* Copy B texture to A texture to follow loop */
|
||||
e_data.input_depth_tx = e_data.temp_depth_tx_b;
|
||||
e_data.input_color_tx = e_data.temp_color_tx_b;
|
||||
|
||||
GPU_framebuffer_bind(fbl->temp_fb_a);
|
||||
GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f);
|
||||
DRW_draw_pass(psl->mix_pass_noblend);
|
||||
|
||||
/* prepare next group */
|
||||
init_shgrp = NULL;
|
||||
}
|
||||
|
||||
DRW_draw_pass_subset(
|
||||
psl->stroke_pass, cache_ob->init_grp, cache_ob->end_grp);
|
||||
}
|
||||
/* last group */
|
||||
gpencil_draw_pass_range(
|
||||
fbl, stl, psl, txl, fbl->temp_fb_a,
|
||||
init_shgrp, end_shgrp,
|
||||
true);
|
||||
}
|
||||
|
||||
if (!stl->storage->is_mat_preview) {
|
||||
MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, fbl->temp_fb_a, txl);
|
||||
}
|
||||
}
|
||||
/* Current buffer drawing */
|
||||
if ((!is_render) && (cache_ob->is_dup_ob == false)) {
|
||||
DRW_draw_pass(psl->drawing_pass);
|
||||
|
@ -54,17 +54,23 @@ struct RenderLayer;
|
||||
#define GP_SIMPLIFY_FILL(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
|
||||
#define GP_SIMPLIFY_MODIF(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
|
||||
#define GP_SIMPLIFY_FX(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
|
||||
#define GP_SIMPLIFY_BLEND(scene, playing) ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
|
||||
|
||||
#define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
|
||||
|
||||
/* *********** OBJECTS CACHE *********** */
|
||||
typedef struct tGPencilObjectCache_shgrp {
|
||||
int mode;
|
||||
bool clamp_layer;
|
||||
float blend_opacity;
|
||||
DRWShadingGroup *init_shgrp;
|
||||
DRWShadingGroup *end_shgrp;
|
||||
} tGPencilObjectCache_shgrp;
|
||||
|
||||
/* used to save gpencil object data for drawing */
|
||||
typedef struct tGPencilObjectCache {
|
||||
struct Object *ob;
|
||||
struct bGPdata *gpd;
|
||||
DRWShadingGroup *init_grp;
|
||||
DRWShadingGroup *end_grp;
|
||||
int idx; /*original index, can change after sort */
|
||||
|
||||
/* effects */
|
||||
@ -90,6 +96,11 @@ typedef struct tGPencilObjectCache {
|
||||
/* GPU data size */
|
||||
int tot_vertex;
|
||||
int tot_triangles;
|
||||
|
||||
/* Save shader groups by layer */
|
||||
int tot_layers;
|
||||
tGPencilObjectCache_shgrp *shgrp_array;
|
||||
|
||||
} tGPencilObjectCache;
|
||||
|
||||
/* *********** LISTS *********** */
|
||||
@ -127,10 +138,15 @@ typedef struct GPENCIL_Storage {
|
||||
int tonemapping;
|
||||
short multisamples;
|
||||
|
||||
int blend_mode;
|
||||
int clamp_layer;
|
||||
float blend_opacity;
|
||||
|
||||
/* simplify settings*/
|
||||
bool simplify_fill;
|
||||
bool simplify_modif;
|
||||
bool simplify_fx;
|
||||
bool simplify_blend;
|
||||
|
||||
/* Render Matrices and data */
|
||||
float persmat[4][4], persinv[4][4];
|
||||
@ -158,6 +174,7 @@ typedef struct GPENCIL_PassList {
|
||||
struct DRWPass *background_pass;
|
||||
struct DRWPass *paper_pass;
|
||||
struct DRWPass *grid_pass;
|
||||
struct DRWPass *blend_pass;
|
||||
|
||||
/* effects */
|
||||
struct DRWPass *fx_shader_pass;
|
||||
@ -232,6 +249,7 @@ typedef struct GPENCIL_e_data {
|
||||
struct GPUShader *gpencil_drawing_fill_sh;
|
||||
struct GPUShader *gpencil_fullscreen_sh;
|
||||
struct GPUShader *gpencil_simple_fullscreen_sh;
|
||||
struct GPUShader *gpencil_blend_fullscreen_sh;
|
||||
struct GPUShader *gpencil_background_sh;
|
||||
struct GPUShader *gpencil_paper_sh;
|
||||
|
||||
|
@ -0,0 +1,130 @@
|
||||
in vec4 uvcoordsvar;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D strokeColor;
|
||||
uniform sampler2D strokeDepth;
|
||||
uniform sampler2D blendColor;
|
||||
uniform sampler2D blendDepth;
|
||||
uniform int mode;
|
||||
uniform int clamp_layer;
|
||||
uniform float blend_opacity;
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
|
||||
#define MODE_NORMAL 0
|
||||
#define MODE_OVERLAY 1
|
||||
#define MODE_ADD 2
|
||||
#define MODE_SUB 3
|
||||
#define MODE_MULTIPLY 4
|
||||
#define MODE_DIVIDE 5
|
||||
|
||||
float overlay_color(float a, float b)
|
||||
{
|
||||
float rtn;
|
||||
if (a < 0.5) {
|
||||
rtn = 2.0 * a * b;
|
||||
}
|
||||
else {
|
||||
rtn = 1.0 - 2.0 * (1.0 - a) * (1.0 - b);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
vec4 get_blend_color(int mode, vec4 src_color, vec4 blend_color)
|
||||
{
|
||||
vec4 mix_color = blend_color;
|
||||
vec4 outcolor;
|
||||
|
||||
if (mix_color.a == 0) {
|
||||
outcolor = src_color;
|
||||
}
|
||||
else if (mode == MODE_OVERLAY) {
|
||||
mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
|
||||
outcolor.r = overlay_color(src_color.r, mix_color.r);
|
||||
outcolor.g = overlay_color(src_color.g, mix_color.g);
|
||||
outcolor.b = overlay_color(src_color.b, mix_color.b);
|
||||
outcolor.a = src_color.a;
|
||||
}
|
||||
else if (mode == MODE_ADD){
|
||||
mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
|
||||
outcolor = src_color + mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
}
|
||||
else if (mode == MODE_SUB){
|
||||
outcolor = src_color - mix_color;
|
||||
outcolor.a = clamp(src_color.a - (mix_color.a * blend_opacity), 0.0, 1.0);
|
||||
}
|
||||
else if (mode == MODE_MULTIPLY) {
|
||||
mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
|
||||
outcolor = src_color * mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
}
|
||||
else if (mode == MODE_DIVIDE) {
|
||||
mix_color.rgb = mix_color.rgb * mix_color.a * blend_opacity;
|
||||
outcolor = src_color / mix_color;
|
||||
outcolor.a = src_color.a;
|
||||
}
|
||||
else {
|
||||
outcolor = mix_color * blend_opacity;;
|
||||
outcolor.a = src_color.a;
|
||||
}
|
||||
|
||||
return outcolor;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 outcolor;
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
vec4 stroke_color = texelFetch(strokeColor, uv, 0).rgba;
|
||||
float stroke_depth = texelFetch(strokeDepth, uv, 0).r;
|
||||
|
||||
vec4 mix_color = texelFetch(blendColor, uv, 0).rgba;
|
||||
float mix_depth = texelFetch(blendDepth, uv, 0).r;
|
||||
|
||||
/* premult alpha factor to remove double blend effects */
|
||||
if (stroke_color.a > 0) {
|
||||
stroke_color = vec4(vec3(stroke_color.rgb / stroke_color.a), stroke_color.a);
|
||||
}
|
||||
if (mix_color.a > 0) {
|
||||
mix_color = vec4(vec3(mix_color.rgb / mix_color.a), mix_color.a);
|
||||
}
|
||||
|
||||
/* Normal mode */
|
||||
if (mode == MODE_NORMAL) {
|
||||
if (stroke_color.a > 0) {
|
||||
if (mix_color.a > 0) {
|
||||
FragColor = vec4(mix(stroke_color.rgb, mix_color.rgb, mix_color.a), stroke_color.a);
|
||||
gl_FragDepth = mix_depth;
|
||||
}
|
||||
else {
|
||||
FragColor = stroke_color;
|
||||
gl_FragDepth = stroke_depth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (clamp_layer == ON) {
|
||||
discard;
|
||||
}
|
||||
else {
|
||||
FragColor = mix_color;
|
||||
gl_FragDepth = mix_depth;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* if not using mask, return mix color */
|
||||
if ((stroke_color.a == 0) && (clamp_layer == OFF)) {
|
||||
FragColor = mix_color;
|
||||
gl_FragDepth = mix_depth;
|
||||
return;
|
||||
}
|
||||
|
||||
/* apply blend mode */
|
||||
FragColor = get_blend_color(mode, stroke_color, mix_color);
|
||||
gl_FragDepth = stroke_depth;
|
||||
}
|
@ -269,6 +269,9 @@ typedef struct bGPDlayer {
|
||||
float opacity; /* Opacity of the layer */
|
||||
char viewlayername[64]; /* Name of the layer used to filter render output */
|
||||
|
||||
int blend_mode; /* blend modes */
|
||||
char pad_[4];
|
||||
|
||||
bGPDlayer_Runtime runtime;
|
||||
} bGPDlayer;
|
||||
|
||||
@ -292,6 +295,8 @@ typedef enum eGPDlayer_Flag {
|
||||
GP_LAYER_VOLUMETRIC = (1 << 10),
|
||||
/* Unlock color */
|
||||
GP_LAYER_UNLOCK_COLOR = (1 << 12),
|
||||
/* Mask Layer */
|
||||
GP_LAYER_USE_MASK = (1 << 13),
|
||||
} eGPDlayer_Flag;
|
||||
|
||||
/* bGPDlayer->onion_flag */
|
||||
@ -300,6 +305,16 @@ typedef enum eGPDlayer_OnionFlag {
|
||||
GP_LAYER_ONIONSKIN = (1 << 0),
|
||||
} eGPDlayer_OnionFlag;
|
||||
|
||||
/* layer blend_mode */
|
||||
typedef enum eGPLayerBlendModes {
|
||||
eGplBlendMode_Normal = 0,
|
||||
eGplBlendMode_Overlay = 1,
|
||||
eGplBlendMode_Add = 2,
|
||||
eGplBlendMode_Subtract = 3,
|
||||
eGplBlendMode_Multiply = 4,
|
||||
eGplBlendMode_Divide = 5,
|
||||
} eGPLayerBlendModes;
|
||||
|
||||
/* ***************************************** */
|
||||
/* GP Datablock */
|
||||
|
||||
|
@ -2144,7 +2144,9 @@ typedef enum eGPencil_SimplifyFlags {
|
||||
/* Remove fill external line */
|
||||
SIMPLIFY_GPENCIL_REMOVE_FILL_LINE = (1 << 4),
|
||||
/* Simplify Shader FX */
|
||||
SIMPLIFY_GPENCIL_FX = (1 << 5)
|
||||
SIMPLIFY_GPENCIL_FX = (1 << 5),
|
||||
/* Simplify layer blending */
|
||||
SIMPLIFY_GPENCIL_BLEND = (1 << 6),
|
||||
} eGPencil_SimplifyFlags;
|
||||
|
||||
/* ToolSettings.gpencil_*_align - Stroke Placement mode flags */
|
||||
|
@ -78,6 +78,15 @@ const EnumPropertyItem rna_enum_gplayer_move_type_items[] = {
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
static const EnumPropertyItem rna_enum_layer_blend_modes_items[] = {
|
||||
{eGplBlendMode_Normal, "NORMAL", 0, "Normal", "" },
|
||||
{eGplBlendMode_Overlay, "OVERLAY", 0, "Overlay", "" },
|
||||
{eGplBlendMode_Add, "ADD", 0, "Add", "" },
|
||||
{eGplBlendMode_Subtract, "SUBTRACT", 0, "Subtract", "" },
|
||||
{eGplBlendMode_Multiply, "MULTIPLY", 0, "Multiply", "" },
|
||||
{eGplBlendMode_Divide, "DIVIDE", 0, "Divide", "" },
|
||||
{0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
@ -1159,6 +1168,13 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "ViewLayer",
|
||||
"Only include Layer in this View Layer render output (leave blank to include always)");
|
||||
|
||||
/* blend mode */
|
||||
prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "blend_mode");
|
||||
RNA_def_property_enum_items(prop, rna_enum_layer_blend_modes_items);
|
||||
RNA_def_property_ui_text(prop, "Blend Mode", "Blend mode");
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
|
||||
|
||||
/* Flags */
|
||||
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE);
|
||||
@ -1184,6 +1200,12 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Lock Material", "Disable Material editing");
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "clamp_layer", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_MASK);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Clamp Layer",
|
||||
"Clamp any pixel outside underlying layers drawing");
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL);
|
||||
|
||||
/* exposed as layers.active */
|
||||
#if 0
|
||||
|
@ -5344,6 +5344,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Simplify Shaders", "Do not apply shader fx");
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
|
||||
|
||||
prop = RNA_def_property(srna, "simplify_gpencil_blend", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_BLEND);
|
||||
RNA_def_property_ui_text(prop, "Layers Blending", "Do not display blend layers");
|
||||
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
|
||||
|
||||
/* persistent data */
|
||||
prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA);
|
||||
|
Loading…
Reference in New Issue
Block a user