Blender V4.3
overlay_grease_pencil.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "DRW_render.hh"
10
11#include "draw_manager_text.hh"
12
13#include "ED_grease_pencil.hh"
14
15#include "BKE_attribute.hh"
16#include "BKE_curves.hh"
17#include "BKE_grease_pencil.hh"
18
20
21#include "overlay_private.hh"
22
24
25static void is_selection_visible(bool &r_show_points, bool &r_show_lines)
26{
27 using namespace blender;
28
29 const DRWContextState *draw_ctx = DRW_context_state_get();
30 const ToolSettings *ts = draw_ctx->scene->toolsettings;
31 const bool in_sculpt_mode = (draw_ctx->object_mode & OB_MODE_SCULPT_GREASE_PENCIL) != 0;
32 const bool in_weight_mode = (draw_ctx->object_mode & OB_MODE_WEIGHT_GREASE_PENCIL) != 0;
33 const bool in_vertex_mode = (draw_ctx->object_mode & OB_MODE_VERTEX_GREASE_PENCIL) != 0;
34 const bool flag_show_lines = (draw_ctx->v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES) != 0;
35
36 if (in_weight_mode) {
37 /* Always display points in weight mode. */
38 r_show_points = true;
39 r_show_lines = flag_show_lines;
40 return;
41 }
42
43 if (in_sculpt_mode) {
44 /* Sculpt selection modes are flags and can be disabled individually. */
45 static constexpr int sculpt_point_modes = GP_SCULPT_MASK_SELECTMODE_POINT |
47 r_show_points = (ts->gpencil_selectmode_sculpt & sculpt_point_modes) != 0;
48 r_show_lines = flag_show_lines && (ts->gpencil_selectmode_sculpt != 0);
49 return;
50 }
51
52 if (in_vertex_mode) {
53 /* Vertex selection modes are flags and can be disabled individually. */
54 static constexpr int vertex_point_modes = GP_VERTEX_MASK_SELECTMODE_POINT |
56 r_show_points = (ts->gpencil_selectmode_vertex & vertex_point_modes) != 0;
57 r_show_lines = flag_show_lines && (ts->gpencil_selectmode_vertex != 0);
58 return;
59 }
60
61 /* Edit selection modes are exclusive. */
63 r_show_lines = flag_show_lines;
64}
65
67 const int mat_nr,
68 const blender::float3 position)
69{
70 Material *ma = BKE_object_material_get_eval(&object, mat_nr + 1);
71 const DRWContextState *draw_ctx = DRW_context_state_get();
72 ViewLayer *view_layer = draw_ctx->view_layer;
73
74 int theme_id = DRW_object_wire_theme_get(&object, view_layer, nullptr);
75 uchar color[4];
76 UI_GetThemeColor4ubv(theme_id, color);
77
78 const float3 fpt = blender::math::transform_point(object.object_to_world(), position);
79
82 fpt,
83 ma->id.name + 2,
84 strlen(ma->id.name + 2),
85 10,
86 0,
88 color);
89}
90
92{
93 using namespace blender;
94
95 const DRWContextState *draw_ctx = DRW_context_state_get();
96
97 bool show_points = false;
98 bool show_lines = false;
99 is_selection_visible(show_points, show_lines);
100
101 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
102
103 Vector<ed::greasepencil::DrawingInfo> drawings = ed::greasepencil::retrieve_visible_drawings(
104 *draw_ctx->scene, grease_pencil, false);
105 if (drawings.is_empty()) {
106 return;
107 }
108
109 for (const ed::greasepencil::DrawingInfo &info : drawings) {
110 const bke::greasepencil::Drawing &drawing = info.drawing;
111
112 const bke::CurvesGeometry strokes = drawing.strokes();
113 const OffsetIndices<int> points_by_curve = strokes.points_by_curve();
114 const bke::AttrDomain domain = show_points ? bke::AttrDomain::Point : bke::AttrDomain::Curve;
115 const VArray<bool> selections = *strokes.attributes().lookup_or_default<bool>(
116 ".selection", domain, true);
117 const VArray<int> materials = *strokes.attributes().lookup_or_default<int>(
118 "material_index", bke::AttrDomain::Curve, 0);
119 const Span<float3> positions = strokes.positions();
120
121 auto show_stroke_name = [&](const int stroke_i) {
122 if (show_points) {
123 for (const int point_i : points_by_curve[stroke_i]) {
124 if (selections[point_i]) {
125 return true;
126 }
127 }
128 return false;
129 }
130 return selections[stroke_i];
131 };
132
133 for (const int stroke_i : strokes.curves_range()) {
134 const int point_i = points_by_curve[stroke_i].first();
135 if (show_stroke_name(stroke_i)) {
136 overlay_grease_pencil_draw_stroke_color_name(*ob, materials[stroke_i], positions[point_i]);
137 }
138 }
139 }
140}
141
143{
144 using namespace blender;
145 OVERLAY_PassList *psl = vedata->psl;
146 OVERLAY_PrivateData *pd = vedata->stl->pd;
147 const DRWContextState *draw_ctx = DRW_context_state_get();
148 const bool use_weight = (draw_ctx->object_mode & OB_MODE_WEIGHT_GREASE_PENCIL) != 0;
149 View3D *v3d = draw_ctx->v3d;
150
151 GPUShader *sh;
152 DRWShadingGroup *grp;
153
157
158 bool show_points = false;
159 bool show_lines = false;
160 is_selection_visible(show_points, show_lines);
161
162 if (show_lines) {
165 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
166 DRW_shgroup_uniform_bool_copy(grp, "useWeight", use_weight);
167 DRW_shgroup_uniform_bool_copy(grp, "useGreasePencil", true);
169 }
170 else {
171 pd->edit_grease_pencil_wires_grp = nullptr;
172 }
173
174 if (show_points) {
177 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
178 DRW_shgroup_uniform_bool_copy(grp, "useWeight", use_weight);
179 DRW_shgroup_uniform_bool_copy(grp, "useGreasePencil", true);
181 const bool show_direction = (v3d->gp_flag & V3D_GP_SHOW_STROKE_DIRECTION) != 0;
182 DRW_shgroup_uniform_bool_copy(grp, "doStrokeEndpoints", show_direction);
183 }
184 else {
185 pd->edit_grease_pencil_points_grp = nullptr;
186 }
187}
188
190{
191 using namespace blender;
192 OVERLAY_PassList *psl = vedata->psl;
193 const DRWContextState *draw_ctx = DRW_context_state_get();
194 Scene *scene = draw_ctx->scene;
195 ToolSettings *ts = scene->toolsettings;
196 const View3D *v3d = draw_ctx->v3d;
197
198 GPUShader *sh;
199 DRWShadingGroup *grp;
200
201 /* Default: Display nothing. */
202 psl->grease_pencil_canvas_ps = nullptr;
203
204 Object *ob = draw_ctx->obact;
205 const bool show_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
206 const bool show_grid = (v3d->gp_flag & V3D_GP_SHOW_GRID) != 0 &&
207 ((ts->gpencil_v3d_align &
209 const bool grid_xray = (v3d->gp_flag & V3D_GP_SHOW_GRID_XRAY);
210
211 if (!ob || (ob->type != OB_GREASE_PENCIL) || !show_grid || !show_overlays) {
212 return;
213 }
214 const float3 base_color = float3(v3d->overlay.gpencil_grid_color);
215 const float4 col_grid = float4(base_color, v3d->overlay.gpencil_grid_opacity);
216
217 float4x4 mat = ob->object_to_world();
218
219 const GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
220 if (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR && grease_pencil.has_active_layer()) {
221 const bke::greasepencil::Layer &layer = *grease_pencil.get_active_layer();
222 mat = layer.to_world_space(*ob);
223 }
224 const View3DCursor *cursor = &scene->cursor;
225
226 /* Set the grid in the selected axis */
227 switch (ts->gp_sculpt.lock_axis) {
228 case GP_LOCKAXIS_X:
229 std::swap(mat[0], mat[2]);
230 break;
231 case GP_LOCKAXIS_Y:
232 std::swap(mat[1], mat[2]);
233 break;
234 case GP_LOCKAXIS_Z:
235 /* Default. */
236 break;
237 case GP_LOCKAXIS_CURSOR: {
238 mat = float4x4(cursor->matrix<float3x3>());
239 break;
240 }
241 case GP_LOCKAXIS_VIEW:
242 /* view aligned */
243 DRW_view_viewmat_get(nullptr, mat.ptr(), true);
244 break;
245 }
246
248 mat.location() = cursor->location;
249 }
250
251 /* Note: This is here to match the legacy size. */
252 mat.view<3, 3>() *= 2.0f;
253
254 /* Local transform of the grid from the overlay settings. */
255 const float3 offset = float3(
257 const float3 scale = float3(
259 const float4x4 local_transform = math::from_loc_scale<float4x4>(offset, scale);
260 mat = mat * local_transform;
261
262 const int gridlines = v3d->overlay.gpencil_grid_subdivisions;
263 const int line_count = gridlines * 4 + 2;
264
267
269
272 DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
273 DRW_shgroup_uniform_vec4_copy(grp, "color", col_grid);
274 DRW_shgroup_uniform_vec3_copy(grp, "xAxis", mat[0]);
275 DRW_shgroup_uniform_vec3_copy(grp, "yAxis", mat[1]);
276 DRW_shgroup_uniform_vec3_copy(grp, "origin", mat[3]);
277 DRW_shgroup_uniform_int_copy(grp, "halfLineCount", line_count / 2);
278 DRW_shgroup_call_procedural_lines(grp, nullptr, line_count);
279}
280
282{
283 using namespace blender::draw;
284 OVERLAY_PrivateData *pd = vedata->stl->pd;
285 const DRWContextState *draw_ctx = DRW_context_state_get();
286
288 if (lines_grp) {
289 blender::gpu::Batch *geom_lines = DRW_cache_grease_pencil_edit_lines_get(draw_ctx->scene, ob);
290 if (geom_lines) {
291 DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
292 }
293 }
294
296 if (points_grp) {
297 blender::gpu::Batch *geom_points = DRW_cache_grease_pencil_edit_points_get(draw_ctx->scene,
298 ob);
299 if (geom_points) {
300 DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
301 }
302 }
303
304 View3D *v3d = draw_ctx->v3d;
305 /* Don't show object extras in set's. */
306 if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
309 }
310 }
311}
312
314{
315 using namespace blender::draw;
316 OVERLAY_PrivateData *pd = vedata->stl->pd;
317 const DRWContextState *draw_ctx = DRW_context_state_get();
318
320 if (lines_grp) {
321 blender::gpu::Batch *geom_lines = DRW_cache_grease_pencil_edit_lines_get(draw_ctx->scene, ob);
322 if (geom_lines) {
323 DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
324 }
325 }
326
328 if (points_grp) {
329 blender::gpu::Batch *geom_points = DRW_cache_grease_pencil_edit_points_get(draw_ctx->scene,
330 ob);
331 if (geom_points) {
332 DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
333 }
334 }
335}
336
338{
339 using namespace blender::draw;
340 OVERLAY_PrivateData *pd = vedata->stl->pd;
341 const DRWContextState *draw_ctx = DRW_context_state_get();
342
344 if (lines_grp) {
345 blender::gpu::Batch *geom_lines = DRW_cache_grease_pencil_weight_lines_get(draw_ctx->scene,
346 ob);
347 if (geom_lines) {
348 DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
349 }
350 }
351
353 if (points_grp) {
354 blender::gpu::Batch *geom_points = DRW_cache_grease_pencil_weight_points_get(draw_ctx->scene,
355 ob);
356 if (geom_points) {
357 DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
358 }
359 }
360}
361
363{
364 using namespace blender::draw;
365 OVERLAY_PrivateData *pd = vedata->stl->pd;
366 const DRWContextState *draw_ctx = DRW_context_state_get();
367
369 if (lines_grp) {
370 blender::gpu::Batch *geom_lines = DRW_cache_grease_pencil_edit_lines_get(draw_ctx->scene, ob);
371 if (geom_lines) {
372 DRW_shgroup_call_no_cull(lines_grp, geom_lines, ob);
373 }
374 }
375
377 if (points_grp) {
378 blender::gpu::Batch *geom_points = DRW_cache_grease_pencil_edit_points_get(draw_ctx->scene,
379 ob);
380 if (geom_points) {
381 DRW_shgroup_call_no_cull(points_grp, geom_points, ob);
382 }
383 }
384}
385
387{
388 OVERLAY_PassList *psl = vedata->psl;
389
390 if (psl->grease_pencil_canvas_ps) {
392 }
393}
394
396{
397 OVERLAY_PassList *psl = vedata->psl;
398
399 if (psl->edit_grease_pencil_ps) {
401 }
402}
Low-level operations for curves.
Low-level operations for grease pencil.
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
unsigned char uchar
#define ELEM(...)
@ BASE_FROM_DUPLI
@ BASE_FROM_SET
@ OB_MODE_VERTEX_GREASE_PENCIL
@ OB_MODE_SCULPT_GREASE_PENCIL
@ OB_MODE_WEIGHT_GREASE_PENCIL
@ OB_GREASE_PENCIL
@ GP_LOCKAXIS_X
@ GP_LOCKAXIS_VIEW
@ GP_LOCKAXIS_Y
@ GP_LOCKAXIS_Z
@ GP_LOCKAXIS_CURSOR
@ GP_SELECTMODE_POINT
@ GP_SELECTMODE_SEGMENT
@ GP_SCULPT_MASK_SELECTMODE_POINT
@ GP_SCULPT_MASK_SELECTMODE_SEGMENT
@ GP_VERTEX_MASK_SELECTMODE_SEGMENT
@ GP_VERTEX_MASK_SELECTMODE_POINT
@ GP_PROJECT_DEPTH_VIEW
@ GP_PROJECT_CURSOR
@ GP_PROJECT_DEPTH_STROKE
@ V3D_GP_SHOW_MATERIAL_NAME
@ V3D_GP_SHOW_GRID_XRAY
@ V3D_GP_SHOW_STROKE_DIRECTION
@ V3D_GP_SHOW_EDIT_LINES
@ V3D_GP_SHOW_GRID
@ V3D_HIDE_OVERLAYS
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
#define DRW_PASS_CREATE(pass, state)
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
struct GPUShader GPUShader
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
OffsetIndices< int > points_by_curve() const
IndexRange curves_range() const
Span< float3 > positions() const
const bke::CurvesGeometry & strokes() const
int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color)
DRW_Global G_draw
bool DRW_state_show_text()
DRWTextStore * DRW_text_cache_ensure()
const DRWContextState * DRW_context_state_get()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_call_procedural_lines(DRWShadingGroup *shgroup, const Object *ob, uint line_count)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_draw_pass(DRWPass *pass)
void DRW_text_cache_add(DRWTextStore *dt, const float co[3], const char *str, const int str_len, short xoffs, short yoffs, short flag, const uchar col[4], const bool shadow, const bool align_center)
@ DRW_TEXT_CACHE_GLOBALSPACE
@ DRW_TEXT_CACHE_STRING_PTR
DRWState
Definition draw_state.hh:25
@ DRW_STATE_BLEND_ALPHA
Definition draw_state.hh:55
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_DEPTH_ALWAYS
Definition draw_state.hh:36
static ulong state[N]
MatT from_loc_scale(const typename MatT::loc_type &location, const VecBase< typename MatT::base_type, ScaleDim > &scale)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void OVERLAY_edit_grease_pencil_draw(OVERLAY_Data *vedata)
void OVERLAY_weight_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_vertex_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_edit_grease_pencil_cache_init(OVERLAY_Data *vedata)
static void overlay_grease_pencil_draw_stroke_color_name(Object &object, const int mat_nr, const blender::float3 position)
static void is_selection_visible(bool &r_show_points, bool &r_show_lines)
void OVERLAY_grease_pencil_cache_init(OVERLAY_Data *vedata)
void OVERLAY_edit_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_grease_pencil_draw(OVERLAY_Data *vedata)
void OVERLAY_sculpt_grease_pencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
static void OVERLAY_grease_pencil_material_names(Object *ob)
GPUShader * OVERLAY_shader_edit_particle_point()
GPUShader * OVERLAY_shader_edit_particle_strand()
GPUShader * OVERLAY_shader_gpencil_canvas()
ViewLayer * view_layer
eObjectMode object_mode
GPUTexture * weight_ramp
GPUUniformBuf * block_ubo
char name[66]
Definition DNA_ID.h:425
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
DRWPass * grease_pencil_canvas_ps
DRWPass * edit_grease_pencil_ps
DRWShadingGroup * edit_grease_pencil_wires_grp
DRWShadingGroup * edit_grease_pencil_points_grp
OVERLAY_PrivateData * pd
short base_flag
struct ToolSettings * toolsettings
char gpencil_selectmode_vertex
char gpencil_selectmode_sculpt
struct GP_Sculpt_Settings gp_sculpt
float gpencil_grid_color[3]
float gpencil_grid_scale[2]
float gpencil_grid_offset[2]
View3DOverlay overlay
const c_style_mat & ptr() const
const MatView< T, ViewNumCol, ViewNumRow, NumCol, NumRow, SrcStartCol, SrcStartRow, Alignment > view() const