Blender V4.5
overlay_grease_pencil.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "BLI_bounds.hh"
12#include "BLI_math_matrix.h"
13#include "BLI_math_matrix.hh"
14
15#include "BKE_curves.hh"
16#include "BKE_grease_pencil.hh"
17#include "BKE_material.hh"
18#include "BKE_object.hh"
19
20#include "DNA_material_types.h"
21
22#include "ED_grease_pencil.hh"
23
24#include "draw_cache.hh"
25#include "draw_manager_text.hh"
26
27#include "overlay_base.hh"
28
29namespace blender::draw::overlay {
30
36 private:
37 PassSimple edit_grease_pencil_ps_ = {"GPencil Edit"};
38 PassSimple::Sub *edit_points_ = nullptr;
39 PassSimple::Sub *edit_lines_ = nullptr;
40
41 PassSimple grid_ps_ = {"GPencil Grid"};
42
43 bool show_points_ = false;
44 bool show_lines_ = false;
45 bool show_grid_ = false;
46 bool show_weight_ = false;
47 bool show_material_name_ = false;
48
49 /* TODO(fclem): This is quite wasteful and expensive, prefer in shader Z modification like the
50 * retopology offset. */
51 View view_edit_cage_ = {"view_edit_cage"};
52 View::OffsetData offset_data_;
53
54 public:
55 void begin_sync(Resources &res, const State &state) final
56 {
57 enabled_ = state.is_space_v3d();
58
59 res.depth_planes.clear();
60 res.depth_planes_count = 0;
61
62 if (!enabled_) {
63 return;
64 }
65
66 offset_data_ = state.offset_data_get();
67
68 const View3D *v3d = state.v3d;
69 const ToolSettings *ts = state.scene->toolsettings;
70
71 show_material_name_ = (v3d->gp_flag & V3D_GP_SHOW_MATERIAL_NAME) && state.show_text;
72 const bool show_lines = (v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES);
73 const bool show_direction = (v3d->gp_flag & V3D_GP_SHOW_STROKE_DIRECTION);
74
75 show_points_ = show_lines_ = show_weight_ = false;
76
77 switch (state.object_mode) {
79 /* Draw mode. */
80 break;
82 /* Vertex paint mode. */
83 show_points_ = ts->gpencil_selectmode_vertex &
85 show_lines_ = show_lines && ts->gpencil_selectmode_vertex;
86 break;
87 case OB_MODE_EDIT:
88 /* Edit mode. */
89 show_points_ = ELEM(
91 show_lines_ = show_lines;
92 break;
94 /* Weight paint mode. */
95 show_points_ = true;
96 show_lines_ = show_lines;
97 show_weight_ = true;
98 break;
100 /* Sculpt mode. */
101 show_points_ = ts->gpencil_selectmode_sculpt &
103 show_lines_ = show_lines && ts->gpencil_selectmode_sculpt;
104 break;
105 default:
106 /* Not a Grease Pencil mode. */
107 break;
108 }
109
110 edit_points_ = nullptr;
111 edit_lines_ = nullptr;
112
113 {
114 auto &pass = edit_grease_pencil_ps_;
115 pass.init();
116 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
117 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
120 state.clipping_plane_count);
121
122 if (show_points_) {
123 auto &sub = pass.sub("Points");
124 sub.shader_set(res.shaders->curve_edit_points.get());
125 sub.bind_texture("weight_tx", &res.weight_ramp_tx);
126 sub.push_constant("use_weight", show_weight_);
127 sub.push_constant("use_grease_pencil", true);
128 sub.push_constant("do_stroke_endpoints", show_direction);
129 edit_points_ = ⊂
130 }
131
132 if (show_lines_) {
133 auto &sub = pass.sub("Lines");
134 sub.shader_set(res.shaders->curve_edit_line.get());
135 sub.bind_texture("weight_tx", &res.weight_ramp_tx);
136 sub.push_constant("use_weight", show_weight_);
137 sub.push_constant("use_grease_pencil", true);
138 edit_lines_ = ⊂
139 }
140 }
141
142 const bool is_depth_projection_mode = ts->gpencil_v3d_align &
144 show_grid_ = (v3d->gp_flag & V3D_GP_SHOW_GRID) && !is_depth_projection_mode;
145
146 {
147 const bool grid_xray = (v3d->gp_flag & V3D_GP_SHOW_GRID_XRAY);
148 DRWState depth_write_state = (grid_xray) ? DRW_STATE_DEPTH_ALWAYS :
150 auto &pass = grid_ps_;
151 pass.init();
152 pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA | depth_write_state,
153 state.clipping_plane_count);
154 if (show_grid_) {
155 const float4 col_grid(float3(state.overlay.gpencil_grid_color),
156 state.overlay.gpencil_grid_opacity);
157 pass.shader_set(res.shaders->grid_grease_pencil.get());
158 pass.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
159 pass.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
160 pass.push_constant("color", col_grid);
161 }
162 }
163 }
164
166 const ObjectRef &ob_ref,
167 Resources &res,
168 const State &state) final
169 {
170 if (!enabled_) {
171 return;
172 }
173
174 Object *ob = ob_ref.object;
175
176 if (show_points_) {
177 gpu::Batch *geom = show_weight_ ?
180 if (geom) {
181 edit_points_->draw(geom, manager.unique_handle(ob_ref));
182 }
183 }
184 if (show_lines_) {
185 gpu::Batch *geom = show_weight_ ? DRW_cache_grease_pencil_weight_lines_get(state.scene, ob) :
187 if (geom) {
188 edit_lines_->draw(geom, manager.unique_handle(ob_ref));
189 }
190 }
191
192 if (show_material_name_) {
193 draw_material_names(ob_ref, state, res);
194 }
195 }
196
198 const ObjectRef &ob_ref,
199 Resources &res,
200 const State &state)
201 {
202 /* Reuse same logic as edit mode. */
203 edit_object_sync(manager, ob_ref, res, state);
204 }
205
207 const ObjectRef &ob_ref,
208 Resources &res,
209 const State &state)
210 {
211 /* Reuse same logic as edit mode. */
212 edit_object_sync(manager, ob_ref, res, state);
213 }
214
215 void object_sync(Manager & /*manager*/,
216 const ObjectRef &ob_ref,
217 Resources & /*res*/,
218 const State &state) final
219 {
220 if (!enabled_) {
221 return;
222 }
223
224 if (ob_ref.object != state.object_active) {
225 /* Only display for the active object. */
226 return;
227 }
228
229 if (show_grid_) {
230 const int grid_lines = state.v3d->overlay.gpencil_grid_subdivisions;
231 const int line_count = grid_lines * 4 + 2;
232
233 const float3 grid_offset = float3(float2(state.v3d->overlay.gpencil_grid_offset), 0.0f);
234 const float3 grid_scale = float3(float2(state.v3d->overlay.gpencil_grid_scale), 0.0f);
235 const float4x4 transform_mat = math::from_loc_scale<float4x4>(grid_offset, grid_scale);
236
237 const float4x4 grid_mat = grid_matrix_get(*ob_ref.object, state.scene) * transform_mat;
238
239 grid_ps_.push_constant("axis_x", grid_mat.x_axis());
240 grid_ps_.push_constant("axis_y", grid_mat.y_axis());
241 grid_ps_.push_constant("origin", grid_mat.location());
242 grid_ps_.push_constant("half_line_count", line_count / 2);
243 grid_ps_.draw_procedural(GPU_PRIM_LINES, 1, line_count * 2);
244 }
245 }
246
247 static void compute_depth_planes(Manager &manager,
248 View &view,
249 Resources &res,
250 const State & /*state*/)
251 {
252 for (auto i : IndexRange(res.depth_planes_count)) {
254 const float4x4 &object_to_world =
255 manager.matrix_buf.current().get_or_resize(plane.handle.resource_index()).model;
256 plane.plane = GreasePencil::depth_plane_get(object_to_world, plane.bounds, view);
257 }
258 }
259
260 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
261 {
262 if (!enabled_) {
263 return;
264 }
265
266 GPU_framebuffer_bind(framebuffer);
267 manager.submit(grid_ps_, view);
268 }
269
270 void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
271 {
272 if (!enabled_) {
273 return;
274 }
275
276 view_edit_cage_.sync(view.viewmat(), offset_data_.winmat_polygon_offset(view.winmat(), 0.5f));
277
278 GPU_framebuffer_bind(framebuffer);
279 manager.submit(edit_grease_pencil_ps_, view_edit_cage_);
280 }
281
283 PassMain::Sub &pass,
284 const Scene *scene,
285 Object *ob,
286 ResourceHandle res_handle,
288 {
289 using namespace blender;
290 using namespace blender::ed::greasepencil;
292
293 const bool is_stroke_order_3d = (grease_pencil.flag & GREASE_PENCIL_STROKE_ORDER_3D) != 0;
294
295 if (is_stroke_order_3d) {
296 pass.push_constant("gp_depth_plane", float4(0.0f));
297 }
298 else {
299 int64_t index = res.depth_planes.append_and_get_index({});
300 res.depth_planes_count++;
301
302 GreasePencilDepthPlane &plane = res.depth_planes[index];
303 plane.bounds = BKE_object_boundbox_get(ob).value_or(blender::Bounds(float3(0)));
304 plane.handle = res_handle;
305
306 pass.push_constant("gp_depth_plane", &plane.plane);
307 }
308
309 int t_offset = 0;
310 const Vector<DrawingInfo> drawings = retrieve_visible_drawings(*scene, grease_pencil, true);
311 for (const DrawingInfo info : drawings) {
312
315
316 pass.push_constant("gp_stroke_order3d", is_stroke_order_3d);
317 pass.bind_texture("gp_pos_tx", position_tx);
318 pass.bind_texture("gp_col_tx", color_tx);
319
320 const bke::CurvesGeometry &curves = info.drawing.strokes();
321 const OffsetIndices<int> points_by_curve = curves.evaluated_points_by_curve();
322 const bke::AttributeAccessor attributes = curves.attributes();
323 const VArray<int> stroke_materials = *attributes.lookup_or_default<int>(
324 "material_index", bke::AttrDomain::Curve, 0);
325 const VArray<bool> cyclic = *attributes.lookup_or_default<bool>(
326 "cyclic", bke::AttrDomain::Curve, false);
327
328 IndexMaskMemory memory;
330 *ob, info.drawing, memory);
331
332 visible_strokes.foreach_index([&](const int stroke_i) {
333 const IndexRange points = points_by_curve[stroke_i];
334 const int material_index = stroke_materials[stroke_i];
335 MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, material_index + 1);
336
337 const bool hide_onion = info.onion_id != 0;
338 const bool hide_material = (gp_style->flag & GP_MATERIAL_HIDE) != 0;
339
340 const int num_stroke_triangles = (points.size() >= 3) ? (points.size() - 2) : 0;
341 const int num_stroke_vertices = (points.size() +
342 int(cyclic[stroke_i] && (points.size() >= 3)));
343
344 if (hide_material || hide_onion) {
345 t_offset += num_stroke_triangles;
346 t_offset += num_stroke_vertices * 2;
347 return;
348 }
349
350 blender::gpu::Batch *geom = draw::DRW_cache_grease_pencil_get(scene, ob);
351
352 const bool show_stroke = (gp_style->flag & GP_MATERIAL_STROKE_SHOW) != 0;
353 const bool show_fill = (points.size() >= 3) &&
354 (gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0;
355
356 if (show_fill) {
357 int v_first = t_offset * 3;
358 int v_count = num_stroke_triangles * 3;
359 pass.draw(geom, 1, v_count, v_first, res_handle, select_id.get());
360 }
361
362 t_offset += num_stroke_triangles;
363
364 if (show_stroke) {
365 int v_first = t_offset * 3;
366 int v_count = num_stroke_vertices * 2 * 3;
367 pass.draw(geom, 1, v_count, v_first, res_handle, select_id.get());
368 }
369 t_offset += num_stroke_vertices * 2;
370 });
371 }
372 }
373
374 private:
375 /* Returns the normal plane in NDC space. */
376 static float4 depth_plane_get(const float4x4 &object_to_world,
378 const View &view)
379 {
380 using namespace blender::math;
381
382 /* Find the normal most likely to represent the grease pencil object. */
383 /* TODO: This does not work quite well if you use
384 * strokes not aligned with the object axes. Maybe we could try to
385 * compute the minimum axis of all strokes. But this would be more
386 * computationally heavy and should go into the GPData evaluation. */
387 float3 center = bounds.center();
388 float3 size = bounds.size();
389 /* Avoid division by 0.0 later. */
390 size += 1e-8f;
391
392 /* Convert Bbox unit space to object space. */
393 float4x4 bbox_to_object = from_loc_scale<float4x4>(center, size * 0.5f);
394 float4x4 bbox_to_world = object_to_world * bbox_to_object;
395
396 float3 bbox_center = bbox_to_world.location();
397 float3 view_vector = (view.is_persp()) ? (view.location() - bbox_center) : view.forward();
398
399 float3x3 world_to_bbox = invert(float3x3(bbox_to_world));
400
401 /* Normalize the vector in BBox space. */
402 float3 local_plane_direction = normalize(transform_direction(world_to_bbox, view_vector));
403 /* `bbox_to_world_normal` is a "normal" matrix. It transforms BBox space normals to world. */
404 float3x3 bbox_to_world_normal = transpose(world_to_bbox);
405 float3 plane_direction = normalize(
406 transform_direction(bbox_to_world_normal, local_plane_direction));
407
408 return float4(plane_direction, -dot(plane_direction, bbox_center));
409 }
410
411 float4x4 grid_matrix_get(const Object &object, const Scene *scene)
412 {
413 const ToolSettings *ts = scene->toolsettings;
414
415 const ::GreasePencil &grease_pencil = DRW_object_get_data_for_drawing<::GreasePencil>(object);
416 const blender::bke::greasepencil::Layer *active_layer = grease_pencil.get_active_layer();
417
418 float4x4 mat = object.object_to_world();
419 if (active_layer && ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR) {
420 mat = active_layer->to_world_space(object);
421 }
422 const View3DCursor *cursor = &scene->cursor;
423
424 /* Set the grid in the selected axis */
425 switch (ts->gp_sculpt.lock_axis) {
426 case GP_LOCKAXIS_X:
427 std::swap(mat[0], mat[2]);
428 break;
429 case GP_LOCKAXIS_Y:
430 std::swap(mat[1], mat[2]);
431 break;
432 case GP_LOCKAXIS_Z:
433 /* Default. */
434 break;
435 case GP_LOCKAXIS_CURSOR: {
436 mat = float4x4(cursor->matrix<float3x3>());
437 break;
438 }
439 case GP_LOCKAXIS_VIEW:
440 /* view aligned */
441 /* TODO(fclem): Global access. */
443 break;
444 }
445
446 mat *= 2.0f;
447
449 mat.location() = cursor->location;
450 }
451 else if (active_layer) {
452 mat.location() = active_layer->to_world_space(object).location();
453 }
454 else {
455 mat.location() = object.object_to_world().location();
456 }
457 return mat;
458 }
459
460 void draw_material_names(const ObjectRef &ob_ref, const State &state, Resources &res)
461 {
462 Object &object = *ob_ref.object;
463
464 uchar4 color;
465 UI_GetThemeColor4ubv(res.object_wire_theme_id(ob_ref, state), color);
466
468
470 *state.scene, grease_pencil, false);
471 if (drawings.is_empty()) {
472 return;
473 }
474
475 for (const ed::greasepencil::DrawingInfo &info : drawings) {
476 const bke::greasepencil::Drawing &drawing = info.drawing;
477
478 const bke::CurvesGeometry strokes = drawing.strokes();
479 const OffsetIndices<int> points_by_curve = strokes.points_by_curve();
480 const bke::AttrDomain domain = show_points_ ? bke::AttrDomain::Point :
482 const VArray<bool> selections = *strokes.attributes().lookup_or_default<bool>(
483 ".selection", domain, true);
484 const VArray<int> materials = *strokes.attributes().lookup_or_default<int>(
485 "material_index", bke::AttrDomain::Curve, 0);
486 const Span<float3> positions = strokes.positions();
487
488 auto show_stroke_name = [&](const int stroke_i) {
489 if (show_points_) {
490 for (const int point_i : points_by_curve[stroke_i]) {
491 if (selections[point_i]) {
492 return true;
493 }
494 }
495 return false;
496 }
497 return selections[stroke_i];
498 };
499
500 for (const int stroke_i : strokes.curves_range()) {
501 if (!show_stroke_name(stroke_i)) {
502 continue;
503 }
504 const int point_i = points_by_curve[stroke_i].first();
505 const float3 fpt = math::transform_point(object.object_to_world(), positions[point_i]);
506 if (Material *ma = BKE_object_material_get_eval(&object, materials[stroke_i] + 1)) {
508 fpt,
509 ma->id.name + 2,
510 strlen(ma->id.name + 2),
511 10,
512 0,
514 color);
515 }
516 }
517 }
518 }
519};
520
521} // namespace blender::draw::overlay
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for materials.
MaterialGPencilStyle * BKE_gpencil_material_settings(Object *ob, short act)
Material * BKE_object_material_get_eval(Object *ob, short act)
General operations, lookup, etc. for blender objects.
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
#define ELEM(...)
float[3] Vector
struct GreasePencil GreasePencil
@ GREASE_PENCIL_STROKE_ORDER_3D
struct Material Material
@ GP_MATERIAL_HIDE
@ GP_MATERIAL_STROKE_SHOW
@ GP_MATERIAL_FILL_SHOW
@ OB_MODE_VERTEX_GREASE_PENCIL
@ OB_MODE_EDIT
@ OB_MODE_PAINT_GREASE_PENCIL
@ OB_MODE_SCULPT_GREASE_PENCIL
@ OB_MODE_WEIGHT_GREASE_PENCIL
struct Object Object
@ 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
static AppView * view
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
@ GPU_PRIM_LINES
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool is_empty() const
constexpr int64_t size() const
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
AttributeAccessor attributes() const
const bke::CurvesGeometry & strokes() const
float4x4 to_world_space(const Object &object) const
SwapChain< ObjectMatricesBuf, 2 > matrix_buf
static View & default_get()
Definition draw_view.cc:317
const float4x4 & viewinv(int view_id=0) const
Definition draw_view.hh:142
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
void draw(gpu::Batch *batch, uint instance_len=-1, uint vertex_len=-1, uint vertex_first=-1, ResourceHandleRange handle={0}, uint custom_id=0)
Definition draw_pass.hh:884
void push_constant(const char *name, const float &data)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:490
void sculpt_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void draw_color_only(Framebuffer &framebuffer, Manager &manager, View &view) final
void begin_sync(Resources &res, const State &state) final
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &, const State &state) final
void edit_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state) final
void paint_object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res, const State &state)
static void compute_depth_planes(Manager &manager, View &view, Resources &res, const State &)
static void draw_grease_pencil(Resources &res, PassMain::Sub &pass, const Scene *scene, Object *ob, ResourceHandle res_handle, select::ID select_id=select::SelectMap::select_invalid_id())
void foreach_index(Fn &&fn) const
Mesh & DRW_object_get_data_for_drawing(const Object &object)
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
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
VecBase< float, D > normalize(VecOp< float, D >) RET
MatBase< R, C > transpose(MatBase< C, R >) RET
static ulong state[N]
gpu::Batch * DRW_cache_grease_pencil_get(const Scene *scene, Object *ob)
detail::Pass< command::DrawCommandBuf > PassSimple
gpu::VertBuf * DRW_cache_grease_pencil_position_buffer_get(const Scene *scene, Object *ob)
gpu::Batch * DRW_cache_grease_pencil_edit_lines_get(const Scene *scene, Object *ob)
gpu::Batch * DRW_cache_grease_pencil_weight_lines_get(const Scene *scene, Object *ob)
gpu::Batch * DRW_cache_grease_pencil_edit_points_get(const Scene *scene, Object *ob)
gpu::Batch * DRW_cache_grease_pencil_weight_points_get(const Scene *scene, Object *ob)
gpu::VertBuf * DRW_cache_grease_pencil_color_buffer_get(const Scene *scene, Object *ob)
Vector< DrawingInfo > retrieve_visible_drawings(const Scene &scene, const GreasePencil &grease_pencil, const bool do_onion_skinning)
IndexMask retrieve_visible_strokes(Object &object, const bke::greasepencil::Drawing &drawing, IndexMaskMemory &memory)
MatT from_loc_scale(const typename MatT::loc_type &location, const VecBase< typename MatT::base_type, ScaleDim > &scale)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
struct ToolSettings * toolsettings
View3DCursor cursor
char gpencil_selectmode_vertex
char gpencil_selectmode_sculpt
struct GP_Sculpt_Settings gp_sculpt
detail::SubPassVector< GreasePencilDepthPlane, 16 > depth_planes
i
Definition text_draw.cc:230