diff --git a/scripts/startup/bl_ui/properties_data_grease_pencil.py b/scripts/startup/bl_ui/properties_data_grease_pencil.py index 69d7078e989..39a21fdcaff 100644 --- a/scripts/startup/bl_ui/properties_data_grease_pencil.py +++ b/scripts/startup/bl_ui/properties_data_grease_pencil.py @@ -71,9 +71,25 @@ class DATA_PT_grease_pencil_layers(DataButtonsPanel, Panel): col.prop(layer, "opacity", text="Opacity", slider=True) +class DATA_PT_grease_pencil_display(DataButtonsPanel, Panel): + bl_label = "Viewport Display" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + ob = context.object + grease_pencil = context.grease_pencil + + layout.prop(grease_pencil, "edit_line_color", text="Edit Line Color") + + classes = ( DATA_PT_context_grease_pencil, DATA_PT_grease_pencil_layers, + DATA_PT_grease_pencil_display, GREASE_PENCIL_MT_grease_pencil_add_layer_extra, ) diff --git a/source/blender/blenkernel/intern/grease_pencil.cc b/source/blender/blenkernel/intern/grease_pencil.cc index 9eab1056352..f7d6fe1cb69 100644 --- a/source/blender/blenkernel/intern/grease_pencil.cc +++ b/source/blender/blenkernel/intern/grease_pencil.cc @@ -73,6 +73,8 @@ static void grease_pencil_init_data(ID *id) grease_pencil->root_group_ptr = MEM_new(__func__); grease_pencil->active_layer = nullptr; grease_pencil->flag |= GREASE_PENCIL_ANIM_CHANNEL_EXPANDED; + + ARRAY_SET_ITEMS(grease_pencil->line_color, 0.6f, 0.6f, 0.6f, 0.5f); } static void grease_pencil_copy_data(Main * /*bmain*/, @@ -123,6 +125,8 @@ static void grease_pencil_copy_data(Main * /*bmain*/, grease_pencil_dst->find_layer_by_name(grease_pencil_src->active_layer->wrap().name())); } + copy_v4_v4(grease_pencil_dst->line_color, grease_pencil_src->line_color); + /* Make sure the runtime pointer exists. */ grease_pencil_dst->runtime = MEM_new(__func__); } diff --git a/source/blender/draw/engines/overlay/overlay_edit_curves.cc b/source/blender/draw/engines/overlay/overlay_edit_curves.cc index 2e9f62644ee..f07eb4c56ee 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_curves.cc +++ b/source/blender/draw/engines/overlay/overlay_edit_curves.cc @@ -54,11 +54,16 @@ void OVERLAY_edit_curves_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } + float empty_color[4]; + zero_v4(empty_color); + DRW_PASS_CREATE(psl->edit_curves_lines_ps[i], (state | pd->clipping_state)); sh = OVERLAY_shader_edit_particle_strand(); grp = pd->edit_curves_lines_grp[i] = DRW_shgroup_create(sh, psl->edit_curves_lines_ps[i]); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "useWeight", false); + /* Set to zero so that `globalsBlock.color_wire` will be used. */ + DRW_shgroup_uniform_vec4_copy(grp, "replaceColor", empty_color); } } diff --git a/source/blender/draw/engines/overlay/overlay_grease_pencil.cc b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc index d7cb92098f2..4dc6672dea6 100644 --- a/source/blender/draw/engines/overlay/overlay_grease_pencil.cc +++ b/source/blender/draw/engines/overlay/overlay_grease_pencil.cc @@ -24,6 +24,10 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata) DRW_STATE_BLEND_ALPHA; DRW_PASS_CREATE(psl->edit_grease_pencil_ps, (state | pd->clipping_state)); + sh = OVERLAY_shader_edit_particle_strand(); + grp = pd->edit_grease_pencil_wires_grp = DRW_shgroup_create(sh, psl->edit_grease_pencil_ps); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + sh = OVERLAY_shader_edit_particle_point(); grp = pd->edit_grease_pencil_points_grp = DRW_shgroup_create(sh, psl->edit_grease_pencil_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); @@ -32,11 +36,22 @@ void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata) void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob) { OVERLAY_PrivateData *pd = vedata->stl->pd; + GreasePencil &grease_pencil = *static_cast(ob->data); + + DRWShadingGroup *lines_grp = pd->edit_grease_pencil_wires_grp; + if (lines_grp) { + DRWShadingGroup *grp = DRW_shgroup_create_sub(lines_grp); + DRW_shgroup_uniform_vec4_copy(grp, "replaceColor", grease_pencil.line_color); + + GPUBatch *geom_lines = DRW_cache_grease_pencil_edit_lines_get(ob, pd->cfra); + + DRW_shgroup_call_no_cull(grp, geom_lines, ob); + } DRWShadingGroup *points_grp = pd->edit_grease_pencil_points_grp; if (points_grp) { - GPUBatch *geom = DRW_cache_grease_pencil_edit_points_get(ob, pd->cfra); - DRW_shgroup_call_no_cull(points_grp, geom, ob); + GPUBatch *geom_points = DRW_cache_grease_pencil_edit_points_get(ob, pd->cfra); + DRW_shgroup_call_no_cull(points_grp, geom_points, ob); } } diff --git a/source/blender/draw/engines/overlay/overlay_particle.cc b/source/blender/draw/engines/overlay/overlay_particle.cc index d2698aadf77..139103d165e 100644 --- a/source/blender/draw/engines/overlay/overlay_particle.cc +++ b/source/blender/draw/engines/overlay/overlay_particle.cc @@ -37,11 +37,16 @@ void OVERLAY_edit_particle_cache_init(OVERLAY_Data *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; DRW_PASS_CREATE(psl->edit_particle_ps, state | pd->clipping_state); + float empty_color[4]; + zero_v4(empty_color); + sh = OVERLAY_shader_edit_particle_strand(); pd->edit_particle_strand_grp = grp = DRW_shgroup_create(sh, psl->edit_particle_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "useWeight", pd->edit_particle.use_weight); DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.weight_ramp); + /* Set to zero so that `globalsBlock.color_wire` will be used. */ + DRW_shgroup_uniform_vec4_copy(grp, "replaceColor", empty_color); sh = OVERLAY_shader_edit_particle_point(); pd->edit_particle_point_grp = grp = DRW_shgroup_create(sh, psl->edit_particle_ps); diff --git a/source/blender/draw/engines/overlay/overlay_private.hh b/source/blender/draw/engines/overlay/overlay_private.hh index 7cf71331dda..390c1addc7c 100644 --- a/source/blender/draw/engines/overlay/overlay_private.hh +++ b/source/blender/draw/engines/overlay/overlay_private.hh @@ -251,6 +251,7 @@ struct OVERLAY_PrivateData { DRWShadingGroup *edit_lattice_wires_grp; DRWShadingGroup *edit_gpencil_points_grp; DRWShadingGroup *edit_gpencil_wires_grp; + DRWShadingGroup *edit_grease_pencil_wires_grp; DRWShadingGroup *edit_grease_pencil_points_grp; DRWShadingGroup *edit_gpencil_curve_handle_grp; DRWShadingGroup *edit_gpencil_curve_points_grp; diff --git a/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh b/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh index 6079212f02a..984bc97a654 100644 --- a/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh +++ b/source/blender/draw/engines/overlay/shaders/infos/overlay_edit_mode_info.hh @@ -531,6 +531,7 @@ GPU_SHADER_CREATE_INFO(overlay_edit_particle_strand) .vertex_in(1, Type::FLOAT, "selection") .sampler(0, ImageType::FLOAT_1D, "weightTex") .push_constant(Type::BOOL, "useWeight") + .push_constant(Type::VEC4, "replaceColor") .vertex_out(overlay_edit_smooth_color_iface) .fragment_out(0, Type::VEC4, "fragColor") .vertex_source("overlay_edit_particle_strand_vert.glsl") diff --git a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl index e9ae111f0ea..dd1fa9c4485 100644 --- a/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/overlay_edit_particle_strand_vert.glsl @@ -7,11 +7,13 @@ #define no_active_weight 666.0 +#define base_color (replaceColor == 0.0 ? colorWire : replaceColor) + vec3 weight_to_rgb(float t) { if (t == no_active_weight) { /* No weight. */ - return colorWire.rgb; + return base_color.rgb; } if (t > 1.0 || t < 0.0) { /* Error color */ @@ -31,7 +33,7 @@ void main() finalColor = vec4(weight_to_rgb(selection), 1.0); } else { - finalColor = mix(colorWire, colorVertexSelect, selection); + finalColor = mix(base_color, colorVertexSelect, selection); } view_clipping_distances(world_pos); diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 821f8d12951..d6df94513d6 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -281,6 +281,7 @@ void DRW_cache_gpencil_sbuffer_clear(struct Object *ob); struct GPUBatch *DRW_cache_grease_pencil_get(struct Object *ob, int cfra); struct GPUBatch *DRW_cache_grease_pencil_edit_points_get(struct Object *ob, int cfra); +struct GPUBatch *DRW_cache_grease_pencil_edit_lines_get(struct Object *ob, int cfra); struct GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(struct Object *ob, int cfra); struct GPUVertBuf *DRW_cache_grease_pencil_color_buffer_get(struct Object *ob, int cfra); diff --git a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc index 3d7768f6a1c..8d7bc1ec621 100644 --- a/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc +++ b/source/blender/draw/intern/draw_cache_impl_grease_pencil.cc @@ -37,11 +37,14 @@ struct GreasePencilBatchCache { /** Batches */ GPUBatch *geom_batch; GPUBatch *edit_points; + GPUBatch *edit_lines; /* Crazy-space point positions for original points. */ GPUVertBuf *edit_points_pos; /* Selection of original points. */ GPUVertBuf *edit_points_selection; + /* Indices for lines segments. */ + GPUIndexBuf *edit_line_indices; /** Cache is dirty. */ bool is_dirty; @@ -139,8 +142,10 @@ static void grease_pencil_batch_cache_clear(GreasePencil &grease_pencil) GPU_INDEXBUF_DISCARD_SAFE(cache->ibo); GPU_BATCH_DISCARD_SAFE(cache->edit_points); + GPU_BATCH_DISCARD_SAFE(cache->edit_lines); GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_pos); GPU_VERTBUF_DISCARD_SAFE(cache->edit_points_selection); + GPU_INDEXBUF_DISCARD_SAFE(cache->edit_line_indices); cache->is_dirty = true; } @@ -212,6 +217,7 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr int total_points_num = 0; int total_verts_num = 0; int total_triangles_num = 0; + int total_line_ids_num = 0; int v_offset = 0; Vector> verts_start_offsets_per_visible_drawing; Vector> tris_start_offsets_per_visible_drawing; @@ -241,6 +247,19 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr t_offset += points.size() - 2; } + if (points.size() > 1) { + /* Add one id for the first point in the curve. */ + total_line_ids_num++; + /* Add ids for the segments. */ + total_line_ids_num += points.size() - 1; + /* Add one segment for the cycle line. */ + if (points.size() > 2 && is_cyclic) { + total_line_ids_num++; + } + /* Add one id for the jump to the next curve. */ + total_line_ids_num++; + } + verts_start_offsets[curve_i] = v_offset; v_offset += 1 + points.size() + (is_cyclic ? 1 : 0) + 1; } @@ -291,6 +310,7 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr GPU_vertbuf_data_alloc(cache->vbo_col, total_verts_num + 2); GPUIndexBufBuilder ibo; + GPUIndexBufBuilder elb; MutableSpan verts = { static_cast(GPU_vertbuf_get_data(cache->vbo)), GPU_vertbuf_get_vertex_len(cache->vbo)}; @@ -305,6 +325,10 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr GPU_vertbuf_get_vertex_len(cache->edit_points_selection)}; /* Create IBO. */ GPU_indexbuf_init(&ibo, GPU_PRIM_TRIS, total_triangles_num, 0xFFFFFFFFu); + GPU_indexbuf_init_ex(&elb, + GPU_PRIM_LINE_STRIP, + total_line_ids_num, + GPU_vertbuf_get_vertex_len(cache->edit_points_pos)); /* Fill buffers with data. */ int drawing_start_offset = 0; @@ -334,7 +358,6 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr MutableSpan selection_slice = edit_points_selection.slice(drawing_start_offset, curves.points_num()); selection_float.materialize(selection_slice); - drawing_start_offset += curves.points_num(); auto populate_point = [&](IndexRange verts_range, int curve_i, @@ -394,6 +417,18 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr } } + if (points.size() > 1) { + for (const int point : points) { + GPU_indexbuf_add_generic_vert(&elb, point + drawing_start_offset); + } + + if (points.size() > 2 && is_cyclic) { + GPU_indexbuf_add_generic_vert(&elb, points.first() + drawing_start_offset); + } + + GPU_indexbuf_add_primitive_restart(&elb); + } + /* Write all the point attributes to the vertex buffers. Create a quad for each point. */ for (const int i : IndexRange(points.size())) { const int idx = i + 1; @@ -423,6 +458,7 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr verts_slice.last().mat = -1; } }); + drawing_start_offset += curves.points_num(); } if (grease_pencil.runtime->has_stroke_buffer()) { @@ -488,6 +524,12 @@ static void grease_pencil_geom_batch_ensure(GreasePencil &grease_pencil, int cfr cache->edit_points = GPU_batch_create(GPU_PRIM_POINTS, cache->edit_points_pos, nullptr); GPU_batch_vertbuf_add(cache->edit_points, cache->edit_points_selection, false); + cache->edit_line_indices = GPU_indexbuf_build(&elb); + + cache->edit_lines = GPU_batch_create( + GPU_PRIM_LINE_STRIP, cache->edit_points_pos, cache->edit_line_indices); + GPU_batch_vertbuf_add(cache->edit_lines, cache->edit_points_selection, false); + cache->is_dirty = false; } @@ -551,6 +593,16 @@ GPUBatch *DRW_cache_grease_pencil_edit_points_get(Object *ob, int cfra) return cache->edit_points; } +GPUBatch *DRW_cache_grease_pencil_edit_lines_get(Object *ob, int cfra) +{ + using namespace blender::draw; + GreasePencil &grease_pencil = *static_cast(ob->data); + GreasePencilBatchCache *cache = grease_pencil_batch_cache_get(grease_pencil); + grease_pencil_geom_batch_ensure(grease_pencil, cfra); + + return cache->edit_lines; +} + GPUVertBuf *DRW_cache_grease_pencil_position_buffer_get(Object *ob, int cfra) { using namespace blender::draw; diff --git a/source/blender/makesdna/DNA_grease_pencil_types.h b/source/blender/makesdna/DNA_grease_pencil_types.h index b9403691f51..a81fad49025 100644 --- a/source/blender/makesdna/DNA_grease_pencil_types.h +++ b/source/blender/makesdna/DNA_grease_pencil_types.h @@ -401,6 +401,9 @@ typedef struct GreasePencil { int drawing_array_num; char _pad[4]; + /* Color for line (edit mode). */ + float line_color[4]; + /* Root group of the layer tree. */ GreasePencilLayerTreeGroup *root_group_ptr; diff --git a/source/blender/makesrna/intern/rna_grease_pencil.cc b/source/blender/makesrna/intern/rna_grease_pencil.cc index 2979e99b7a7..9d78b66fd41 100644 --- a/source/blender/makesrna/intern/rna_grease_pencil.cc +++ b/source/blender/makesrna/intern/rna_grease_pencil.cc @@ -292,6 +292,8 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; + static float default_line_color[4] = {0.6f, 0.6f, 0.6f, 0.5f}; + srna = RNA_def_struct(brna, "GreasePencilv3", "ID"); RNA_def_struct_sdna(srna, "GreasePencil"); RNA_def_struct_ui_text(srna, "Grease Pencil", "Grease Pencil data-block"); @@ -328,6 +330,15 @@ static void rna_def_grease_pencil_data(BlenderRNA *brna) nullptr, /* TODO */ nullptr); RNA_def_property_ui_text(prop, "Layer Groups", "Grease Pencil layer groups"); + + /* Line Color (Edit Mode) */ + prop = RNA_def_property(srna, "edit_line_color", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, nullptr, "line_color"); + RNA_def_property_array(prop, 4); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_array_default(prop, default_line_color); + RNA_def_property_ui_text(prop, "Edit Line Color", "Color for editing line"); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update"); } void RNA_def_grease_pencil(BlenderRNA *brna)