Blender V4.3
grease_pencil_layers.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 "BLI_math_matrix.h"
10#include "BLI_math_matrix.hh"
11#include "BLI_string.h"
12
13#include "BKE_context.hh"
14#include "BKE_grease_pencil.hh"
15#include "BKE_object.hh"
16#include "BKE_report.hh"
17
18#include "BLT_translation.hh"
19
20#include "DEG_depsgraph.hh"
21
22#include "ED_grease_pencil.hh"
23
24#include "RNA_access.hh"
25#include "RNA_define.hh"
26
27#include "UI_interface.hh"
28
29#include "DNA_scene_types.h"
30
31#include "WM_api.hh"
32#include "WM_message.hh"
33
35
37 Object *parent,
38 StringRefNull bone,
39 const bool keep_transform)
40{
41 if (keep_transform) {
42 /* TODO apply current transform to geometry. */
43 }
44
45 layer.parent = parent;
46 layer.parsubstr = BLI_strdup_null(bone.c_str());
47 /* Calculate inverse parent matrix. */
48 if (parent) {
49 copy_m4_m4(layer.parentinv, parent->world_to_object().ptr());
50 }
51 else {
52 unit_m4(layer.parentinv);
53 }
54
55 return true;
56}
57
58void grease_pencil_layer_parent_clear(bke::greasepencil::Layer &layer, const bool keep_transform)
59{
60 if (layer.parent == nullptr) {
61 return;
62 }
63 if (keep_transform) {
64 /* TODO apply current transform to geometry. */
65 }
66
67 layer.parent = nullptr;
68 MEM_SAFE_FREE(layer.parsubstr);
69
70 copy_m4_m4(layer.parentinv, float4x4::identity().ptr());
71}
72
74{
75 using namespace blender::bke::greasepencil;
76
77 if (layer != nullptr) {
78 layer->set_selected(true);
79 }
80
81 if (grease_pencil.get_active_layer() != layer) {
82 grease_pencil.set_active_layer(layer);
84 }
85}
86
88{
89 using namespace blender::bke::greasepencil;
90 Scene *scene = CTX_data_scene(C);
92
93 int new_layer_name_length;
94 char *new_layer_name = RNA_string_get_alloc(
95 op->ptr, "new_layer_name", nullptr, 0, &new_layer_name_length);
96 BLI_SCOPED_DEFER([&] { MEM_SAFE_FREE(new_layer_name); });
97 Layer &new_layer = grease_pencil.add_layer(new_layer_name);
99 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
100
101 if (grease_pencil.has_active_layer()) {
102 grease_pencil.move_node_after(new_layer.as_node(),
103 grease_pencil.get_active_layer()->as_node());
104 }
105 else if (grease_pencil.has_active_group()) {
106 grease_pencil.move_node_into(new_layer.as_node(), *grease_pencil.get_active_group());
108 &grease_pencil.id,
109 &grease_pencil,
110 GreasePencilv3LayerGroup,
111 active);
112 }
113
114 grease_pencil.set_active_layer(&new_layer);
116 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
117
118 grease_pencil.insert_frame(new_layer, scene->r.cfra);
119
120 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
121 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
122
123 return OPERATOR_FINISHED;
124}
125
127{
129 op,
130 event,
131 IFACE_("Add New Grease Pencil Layer"),
133}
134
136{
137 /* identifiers */
138 ot->name = "Add New Layer";
139 ot->idname = "GREASE_PENCIL_OT_layer_add";
140 ot->description = "Add a new Grease Pencil layer in the active object";
141
142 /* callbacks */
146
148
150 ot->srna, "new_layer_name", "Layer", INT16_MAX, "Name", "Name of the new layer");
152 ot->prop = prop;
153}
154
156{
157 using namespace blender::bke::greasepencil;
159
160 if (!grease_pencil.has_active_layer()) {
161 return OPERATOR_CANCELLED;
162 }
163
164 grease_pencil.remove_layer(*grease_pencil.get_active_layer());
165
167 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
169 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
170
171 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
172 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
173
174 return OPERATOR_FINISHED;
175}
176
178{
179 /* identifiers */
180 ot->name = "Remove Layer";
181 ot->idname = "GREASE_PENCIL_OT_layer_remove";
182 ot->description = "Remove the active Grease Pencil layer";
183
184 /* callbacks */
187
189}
190
192 {LAYER_REORDER_ABOVE, "ABOVE", 0, "Above", ""},
193 {LAYER_REORDER_BELOW, "BELOW", 0, "Below", ""},
194 {0, nullptr, 0, nullptr, nullptr},
195};
196
198{
199 using namespace blender::bke::greasepencil;
200 Object *object = CTX_data_active_object(C);
201 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
202
203 if (!grease_pencil.has_active_layer()) {
204 return OPERATOR_CANCELLED;
205 }
206
207 int target_layer_name_length;
208 char *target_layer_name = RNA_string_get_alloc(
209 op->ptr, "target_layer_name", nullptr, 0, &target_layer_name_length);
210 const int reorder_location = RNA_enum_get(op->ptr, "location");
211
212 TreeNode *target_node = grease_pencil.find_node_by_name(target_layer_name);
213 if (!target_node || !target_node->is_layer()) {
214 MEM_SAFE_FREE(target_layer_name);
215 return OPERATOR_CANCELLED;
216 }
217
218 Layer &active_layer = *grease_pencil.get_active_layer();
219 switch (reorder_location) {
220 case LAYER_REORDER_ABOVE: {
221 /* NOTE: The layers are stored from bottom to top, so inserting above (visually), means
222 * inserting the link after the target. */
223 grease_pencil.move_node_after(active_layer.as_node(), *target_node);
224 break;
225 }
226 case LAYER_REORDER_BELOW: {
227 /* NOTE: The layers are stored from bottom to top, so inserting below (visually), means
228 * inserting the link before the target. */
229 grease_pencil.move_node_before(active_layer.as_node(), *target_node);
230 break;
231 }
232 default:
234 }
235
236 MEM_SAFE_FREE(target_layer_name);
237
238 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
239 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
240
242 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
244 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layer_groups);
245
246 return OPERATOR_FINISHED;
247}
248
250{
251 /* identifiers */
252 ot->name = "Reorder Layer";
253 ot->idname = "GREASE_PENCIL_OT_layer_reorder";
254 ot->description = "Reorder the active Grease Pencil layer";
255
256 /* callbacks */
259
261
263 "target_layer_name",
264 "Layer",
265 INT16_MAX,
266 "Target Name",
267 "Name of the target layer");
269
271 ot->srna, "location", prop_layer_reorder_location, LAYER_REORDER_ABOVE, "Location", "");
272}
273
274enum class LayerMoveDirection : int8_t { Up = -1, Down = 1 };
275
277 {int(LayerMoveDirection::Up), "UP", 0, "Up", ""},
278 {int(LayerMoveDirection::Down), "DOWN", 0, "Down", ""},
279 {0, nullptr, 0, nullptr, nullptr},
280};
281
283{
284 using namespace blender::bke::greasepencil;
286 return false;
287 }
288
290 const TreeNode *active_node = grease_pencil.get_active_node();
291
292 if (active_node == nullptr) {
293 return false;
294 }
295
296 const LayerGroup *parent = active_node->parent_group();
297
298 if (parent == nullptr || parent->num_direct_nodes() < 2) {
299 return false;
300 }
301
302 return true;
303}
304
306{
307 using namespace blender::bke::greasepencil;
309
310 const LayerMoveDirection direction = LayerMoveDirection(RNA_enum_get(op->ptr, "direction"));
311
312 TreeNode &active_node = *grease_pencil.get_active_node();
313
314 if (direction == LayerMoveDirection::Up) {
315 grease_pencil.move_node_up(active_node);
316 }
317 else if (direction == LayerMoveDirection::Down) {
318 grease_pencil.move_node_down(active_node);
319 }
320
321 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
322 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
323
325 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
326
327 return OPERATOR_FINISHED;
328}
329
331{
332 /* identifiers */
333 ot->name = "Reorder Layer";
334 ot->idname = "GREASE_PENCIL_OT_layer_move";
335 ot->description = "Move the active Grease Pencil layer or Group";
336
337 /* callbacks */
340
342
343 ot->prop = RNA_def_enum(ot->srna, "direction", enum_layer_move_direction, 0, "Direction", "");
344}
345
347{
348 using namespace blender::bke::greasepencil;
349 Object *object = CTX_data_active_object(C);
350 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
351 int layer_index = RNA_int_get(op->ptr, "layer");
352
353 Layer &layer = grease_pencil.layer(layer_index);
354 if (grease_pencil.is_layer_active(&layer)) {
355 return OPERATOR_CANCELLED;
356 }
357
358 if (grease_pencil.has_active_group()) {
360 &grease_pencil.id,
361 &grease_pencil,
362 GreasePencilv3LayerGroup,
363 active);
364 }
365 grease_pencil.set_active_layer(&layer);
366
368 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
369
370 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
371
372 return OPERATOR_FINISHED;
373}
374
376{
377 /* identifiers */
378 ot->name = "Set Active Layer";
379 ot->idname = "GREASE_PENCIL_OT_layer_active";
380 ot->description = "Set the active Grease Pencil layer";
381
382 /* callbacks */
385
387
388 PropertyRNA *prop = RNA_def_int(
389 ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
391}
392
394{
395 using namespace blender::bke::greasepencil;
397
398 int new_layer_group_name_length;
399 char *new_layer_group_name = RNA_string_get_alloc(
400 op->ptr, "new_layer_group_name", nullptr, 0, &new_layer_group_name_length);
401
402 LayerGroup &new_group = grease_pencil.add_layer_group(new_layer_group_name);
404 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layer_groups);
405
406 if (grease_pencil.has_active_layer()) {
407 grease_pencil.move_node_after(new_group.as_node(),
408 grease_pencil.get_active_layer()->as_node());
410 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
411 }
412 else if (grease_pencil.has_active_group()) {
413 grease_pencil.move_node_into(new_group.as_node(), *grease_pencil.get_active_group());
415 &grease_pencil.id,
416 &grease_pencil,
417 GreasePencilv3LayerGroup,
418 active);
419 }
420
421 MEM_SAFE_FREE(new_layer_group_name);
422 grease_pencil.set_active_node(&new_group.as_node());
423
425 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3LayerGroup, active);
426
427 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
428 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
430
431 return OPERATOR_FINISHED;
432}
433
435{
436 /* identifiers */
437 ot->name = "Add New Layer Group";
438 ot->idname = "GREASE_PENCIL_OT_layer_group_add";
439 ot->description = "Add a new Grease Pencil layer group in the active object";
440
441 /* callbacks */
444
446
448 ot->srna, "new_layer_group_name", nullptr, INT16_MAX, "Name", "Name of the new layer group");
450 ot->prop = prop;
451}
452
454{
455 using namespace blender::bke::greasepencil;
456 Object *object = CTX_data_active_object(C);
457 const bool keep_children = RNA_boolean_get(op->ptr, "keep_children");
458 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
459
460 if (!grease_pencil.has_active_group()) {
461 return OPERATOR_CANCELLED;
462 }
463
464 grease_pencil.remove_group(*grease_pencil.get_active_group(), keep_children);
465
466 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
467 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
468
470 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3LayerGroup, active);
472 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layer_groups);
473
474 return OPERATOR_FINISHED;
475}
476
478{
479 /* identifiers */
480 ot->name = "Remove Layer Group";
481 ot->idname = "GREASE_PENCIL_OT_layer_group_remove";
482 ot->description = "Remove Grease Pencil layer group in the active object";
483
484 /* callbacks */
487
489
491 "keep_children",
492 false,
493 "Keep children nodes",
494 "Keep the children nodes of the group and only delete the group itself");
495}
496
498{
499 using namespace blender::bke::greasepencil;
501 const bool unselected = RNA_boolean_get(op->ptr, "unselected");
502
503 if (!grease_pencil.has_active_layer()) {
504 return OPERATOR_CANCELLED;
505 }
506
507 if (unselected) {
508 /* hide unselected */
509 for (Layer *layer : grease_pencil.layers_for_write()) {
510 const bool is_active = grease_pencil.is_layer_active(layer);
511 layer->set_visible(is_active);
512 }
513 }
514 else {
515 /* hide selected/active */
516 Layer &active_layer = *grease_pencil.get_active_layer();
517 active_layer.set_visible(false);
518 }
519
520 /* notifiers */
521 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
522 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
524
525 return OPERATOR_FINISHED;
526}
527
529{
530 /* identifiers */
531 ot->name = "Hide Layer(s)";
532 ot->idname = "GREASE_PENCIL_OT_layer_hide";
533 ot->description = "Hide selected/unselected Grease Pencil layers";
534
535 /* callbacks */
538
539 /* flags */
541
542 /* props */
544 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected layers");
546 ot->prop = prop;
547}
548
550{
551 using namespace blender::bke::greasepencil;
553
554 if (!grease_pencil.has_active_layer()) {
555 return OPERATOR_CANCELLED;
556 }
557
558 for (Layer *layer : grease_pencil.layers_for_write()) {
559 layer->set_visible(true);
560 }
561
562 /* notifiers */
563 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
564 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
566
567 return OPERATOR_FINISHED;
568}
569
571{
572 /* identifiers */
573 ot->name = "Show All Layers";
574 ot->idname = "GREASE_PENCIL_OT_layer_reveal";
575 ot->description = "Show all Grease Pencil layers";
576
577 /* callbacks */
580
581 /* flags */
583}
584
586{
587 using namespace blender::bke::greasepencil;
589 const int affect_visibility = RNA_boolean_get(op->ptr, "affect_visibility");
590 bool isolate = false;
591
592 for (const Layer *layer : grease_pencil.layers()) {
593 if (grease_pencil.is_layer_active(layer)) {
594 continue;
595 }
596 if ((affect_visibility && layer->is_visible()) || !layer->is_locked()) {
597 isolate = true;
598 break;
599 }
600 }
601
602 for (Layer *layer : grease_pencil.layers_for_write()) {
603 if (grease_pencil.is_layer_active(layer) || !isolate) {
604 layer->set_locked(false);
605 if (affect_visibility) {
606 layer->set_visible(true);
607 }
608 }
609 else {
610 layer->set_locked(true);
611 if (affect_visibility) {
612 layer->set_visible(false);
613 }
614 }
615 }
616
617 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
618 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
620
621 return OPERATOR_FINISHED;
622}
623
625{
626 /* identifiers */
627 ot->name = "Isolate Layers";
628 ot->idname = "GREASE_PENCIL_OT_layer_isolate";
629 ot->description = "Make only active layer visible/editable";
630
631 /* callbacks */
634
635 /* flags */
637
638 /* properties */
640 ot->srna, "affect_visibility", false, "Affect Visibility", "Also affect the visibility");
641}
642
644{
645 using namespace blender::bke::greasepencil;
647 const bool lock_value = RNA_boolean_get(op->ptr, "lock");
648
649 if (grease_pencil.layers().is_empty()) {
650 return OPERATOR_CANCELLED;
651 }
652
653 for (Layer *layer : grease_pencil.layers_for_write()) {
654 layer->set_locked(lock_value);
655 }
656
657 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
658 WM_event_add_notifier(C, NC_GEOM | ND_DATA, &grease_pencil);
660
661 return OPERATOR_FINISHED;
662}
663
665{
666 /* identifiers */
667 ot->name = "Lock All Layers";
668 ot->idname = "GREASE_PENCIL_OT_layer_lock_all";
669 ot->description =
670 "Lock all Grease Pencil layers to prevent them from being accidentally modified";
671
672 /* callbacks */
675
676 /* flags */
678
679 /* properties */
680 RNA_def_boolean(ot->srna, "lock", true, "Lock Value", "Lock/Unlock all layers");
681}
682
684{
685 using namespace blender::bke::greasepencil;
687 const bool empty_keyframes = RNA_boolean_get(op->ptr, "empty_keyframes");
688
689 if (!grease_pencil.has_active_layer()) {
690 BKE_reportf(op->reports, RPT_ERROR, "No active layer to duplicate");
691 return OPERATOR_CANCELLED;
692 }
693
694 /* Duplicate layer. */
695 Layer &active_layer = *grease_pencil.get_active_layer();
696 Layer &new_layer = grease_pencil.duplicate_layer(active_layer);
697
699 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
700
701 /* Clear source keyframes and recreate them with duplicated drawings. */
702 new_layer.frames_for_write().clear();
703 for (auto [frame_number, frame] : active_layer.frames().items()) {
704 const int duration = active_layer.get_frame_duration_at(frame_number);
705
706 Drawing *dst_drawing = grease_pencil.insert_frame(
707 new_layer, frame_number, duration, eBezTriple_KeyframeType(frame.type));
708 if (!empty_keyframes) {
709 BLI_assert(dst_drawing != nullptr);
710 /* TODO: This can fail (return `nullptr`) if the drawing is a drawing reference! */
711 const Drawing &src_drawing = *grease_pencil.get_drawing_at(active_layer, frame_number);
712 /* Duplicate the drawing. */
713 *dst_drawing = src_drawing;
714 }
715 }
716
717 grease_pencil.move_node_after(new_layer.as_node(), active_layer.as_node());
718 grease_pencil.set_active_layer(&new_layer);
719
720 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
722
724 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
725
726 return OPERATOR_FINISHED;
727}
728
730{
731 /* identifiers */
732 ot->name = "Duplicate Layer";
733 ot->idname = "GREASE_PENCIL_OT_layer_duplicate";
734 ot->description = "Make a copy of the active Grease Pencil layer";
735
736 /* callbacks */
739
740 /* flags */
742
743 /* properties */
744 RNA_def_boolean(ot->srna, "empty_keyframes", false, "Empty Keyframes", "Add Empty Keyframes");
745}
746
747enum class MergeMode : int8_t {
748 Down = 0,
749 Group = 1,
750 All = 2,
751};
752
754{
755 using namespace blender::bke::greasepencil;
756 Main *bmain = CTX_data_main(C);
757 Object *object = CTX_data_active_object(C);
758 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
759 const MergeMode mode = MergeMode(RNA_enum_get(op->ptr, "mode"));
760
761 Vector<Vector<int>> src_layer_indices_by_dst_layer;
762 std::string merged_layer_name;
763 if (mode == MergeMode::Down) {
764 if (!grease_pencil.has_active_layer()) {
765 BKE_report(op->reports, RPT_ERROR, "No active layer");
766 return OPERATOR_CANCELLED;
767 }
768 const Layer &active_layer = *grease_pencil.get_active_layer();
769 GreasePencilLayerTreeNode *prev_node = active_layer.as_node().prev;
770 if (prev_node == nullptr || !prev_node->wrap().is_layer()) {
771 /* No layer below the active one. */
772 return OPERATOR_CANCELLED;
773 }
774 const Layer &prev_layer = prev_node->wrap().as_layer();
775 /* Get the indices of the two layers to be merged. */
776 const int prev_layer_index = *grease_pencil.get_layer_index(prev_layer);
777 const int active_layer_index = *grease_pencil.get_layer_index(active_layer);
778
779 /* Map all the other layers to their own index. */
780 const Span<const Layer *> layers = grease_pencil.layers();
781 for (const int layer_i : layers.index_range()) {
782 if (layer_i == active_layer_index) {
783 /* Active layer is merged into previous, skip. */
784 }
785 else if (layer_i == prev_layer_index) {
786 /* Previous layer merges itself and the active layer. */
787 src_layer_indices_by_dst_layer.append({prev_layer_index, active_layer_index});
788 }
789 else {
790 /* Other layers remain unchanged. */
791 src_layer_indices_by_dst_layer.append({layer_i});
792 }
793 }
794
795 /* Store the name of the current active layer as the name of the merged layer. */
796 merged_layer_name = grease_pencil.layer(prev_layer_index).name();
797 }
798 else if (mode == MergeMode::Group) {
799 if (!grease_pencil.has_active_group()) {
800 BKE_report(op->reports, RPT_ERROR, "No active group");
801 return OPERATOR_CANCELLED;
802 }
803 LayerGroup &active_group = *grease_pencil.get_active_group();
804 /* Remove all sub groups of the active group since they won't be needed anymore, but keep the
805 * layers. */
806 Array<LayerGroup *> groups = active_group.groups_for_write();
807 for (LayerGroup *group : groups) {
808 grease_pencil.remove_group(*group, true);
809 }
810
811 const Span<const Layer *> layers = grease_pencil.layers();
813 for (const int layer_i : layers.index_range()) {
814 const Layer &layer = grease_pencil.layer(layer_i);
815 if (!layer.is_child_of(active_group)) {
816 src_layer_indices_by_dst_layer.append({layer_i});
817 }
818 else {
819 indices.append(layer_i);
820 }
821 }
822 src_layer_indices_by_dst_layer.append(indices);
823
824 /* Store the name of the group as the name of the merged layer. */
825 merged_layer_name = active_group.name();
826
827 /* Remove the active group. */
828 grease_pencil.remove_group(active_group, true);
830 &grease_pencil.id,
831 &grease_pencil,
832 GreasePencilv3LayerGroup,
833 active);
834
835 /* Rename the first node so that the merged layer will have the name of the group. */
836 grease_pencil.rename_node(
837 *bmain, grease_pencil.layer(indices[0]).as_node(), merged_layer_name);
838 }
839 else if (mode == MergeMode::All) {
840 /* Remove all groups, keep the layers. */
841 Array<LayerGroup *> groups = grease_pencil.layer_groups_for_write();
842 for (LayerGroup *group : groups) {
843 grease_pencil.remove_group(*group, true);
844 }
845
847 for (const int layer_i : grease_pencil.layers().index_range()) {
848 indices.append(layer_i);
849 }
850 src_layer_indices_by_dst_layer.append(indices);
851
852 merged_layer_name = N_("Layer");
853 grease_pencil.rename_node(
854 *bmain, grease_pencil.layer(indices[0]).as_node(), merged_layer_name);
855 }
856 else {
858 }
859
860 GreasePencil *merged_grease_pencil = BKE_grease_pencil_new_nomain();
861 BKE_grease_pencil_copy_parameters(grease_pencil, *merged_grease_pencil);
863 grease_pencil, src_layer_indices_by_dst_layer, *merged_grease_pencil);
864 BKE_grease_pencil_nomain_to_grease_pencil(merged_grease_pencil, &grease_pencil);
865
867 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3, layers);
868
869 /* Try to set the active (merged) layer. */
870 TreeNode *node = grease_pencil.find_node_by_name(merged_layer_name);
871 if (node && node->is_layer()) {
872 Layer &layer = node->as_layer();
873 grease_pencil.set_active_layer(&layer);
874
876 CTX_wm_message_bus(C), &grease_pencil.id, &grease_pencil, GreasePencilv3Layers, active);
877 }
878
879 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
881
882 return OPERATOR_FINISHED;
883}
884
886{
887 static const EnumPropertyItem merge_modes[] = {
889 "ACTIVE",
890 0,
891 "Active",
892 "Combine the active layer with the layer just below (if it exists)"},
894 "GROUP",
895 0,
896 "Group",
897 "Combine layers in the active group into a single layer"},
898 {int(MergeMode::All), "ALL", 0, "All", "Combine all layers into a single layer"},
899 {0, nullptr, 0, nullptr, nullptr},
900 };
901
902 ot->name = "Merge";
903 ot->idname = "GREASE_PENCIL_OT_layer_merge";
904 ot->description = "Combine layers based on the mode into one layer";
905
908
910
911 ot->prop = RNA_def_enum(ot->srna, "mode", merge_modes, int(MergeMode::Down), "Mode", "");
912}
913
915{
916 using namespace blender::bke::greasepencil;
918
919 if (!grease_pencil.has_active_layer()) {
920 return OPERATOR_CANCELLED;
921 }
922 Layer &active_layer = *grease_pencil.get_active_layer();
923
924 int mask_name_length;
925 char *mask_name = RNA_string_get_alloc(op->ptr, "name", nullptr, 0, &mask_name_length);
926 BLI_SCOPED_DEFER([&] { MEM_SAFE_FREE(mask_name); });
927
928 if (TreeNode *node = grease_pencil.find_node_by_name(mask_name)) {
929 if (grease_pencil.is_layer_active(&node->as_layer())) {
930 BKE_report(op->reports, RPT_ERROR, "Cannot add active layer as mask");
931 return OPERATOR_CANCELLED;
932 }
933
934 if (BLI_findstring(&active_layer.masks,
935 mask_name,
936 offsetof(GreasePencilLayerMask, layer_name)) != nullptr)
937 {
938 BKE_report(op->reports, RPT_ERROR, "Layer already added");
939 return OPERATOR_CANCELLED;
940 }
941
942 LayerMask *new_mask = MEM_new<LayerMask>(__func__, mask_name);
943 BLI_addtail(&active_layer.masks, reinterpret_cast<GreasePencilLayerMask *>(new_mask));
944 /* Make the newly added mask active. */
945 active_layer.active_mask_index = BLI_listbase_count(&active_layer.masks) - 1;
946 }
947 else {
948 BKE_report(op->reports, RPT_ERROR, "Unable to find layer to add");
949 return OPERATOR_CANCELLED;
950 }
951
952 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
953 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
954
955 return OPERATOR_FINISHED;
956}
957
959{
960 /* identifiers */
961 ot->name = "Add New Mask Layer";
962 ot->idname = "GREASE_PENCIL_OT_layer_mask_add";
963 ot->description = "Add new layer as masking";
964
966
967 /* callbacks */
970
971 /* properties */
972 RNA_def_string(ot->srna, "name", nullptr, 0, "Layer", "Name of the layer");
973}
974
976{
977 using namespace blender::bke::greasepencil;
979
980 if (!grease_pencil.has_active_layer()) {
981 return OPERATOR_CANCELLED;
982 }
983
984 Layer &active_layer = *grease_pencil.get_active_layer();
985 if (GreasePencilLayerMask *mask = reinterpret_cast<GreasePencilLayerMask *>(
986 BLI_findlink(&active_layer.masks, active_layer.active_mask_index)))
987 {
988 BLI_remlink(&active_layer.masks, mask);
989 MEM_delete(reinterpret_cast<LayerMask *>(mask));
990 active_layer.active_mask_index = std::max(active_layer.active_mask_index - 1, 0);
991 }
992 else {
993 return OPERATOR_CANCELLED;
994 }
995
996 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
997 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
998
999 return OPERATOR_FINISHED;
1000}
1001
1003{
1004 /* identifiers */
1005 ot->name = "Remove Mask Layer";
1006 ot->idname = "GREASE_PENCIL_OT_layer_mask_remove";
1007 ot->description = "Remove Layer Mask";
1008
1010
1011 /* callbacks */
1014}
1015
1017{
1018 using namespace blender::bke::greasepencil;
1020
1021 if (!grease_pencil.has_active_layer()) {
1022 return OPERATOR_CANCELLED;
1023 }
1024 Layer &active_layer = *grease_pencil.get_active_layer();
1025 const int direction = RNA_enum_get(op->ptr, "direction");
1026
1027 bool changed = false;
1028 if (GreasePencilLayerMask *mask = reinterpret_cast<GreasePencilLayerMask *>(
1029 BLI_findlink(&active_layer.masks, active_layer.active_mask_index)))
1030 {
1031 if (BLI_listbase_link_move(&active_layer.masks, mask, direction)) {
1032 active_layer.active_mask_index = std::max(active_layer.active_mask_index + direction, 0);
1033 changed = true;
1034 }
1035 }
1036 else {
1037 return OPERATOR_CANCELLED;
1038 }
1039
1040 if (changed) {
1041 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
1042 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
1043 }
1044
1045 return OPERATOR_FINISHED;
1046}
1047
1049{
1050 /* identifiers */
1051 ot->name = "Reorder Grease Pencil Layer Mask";
1052 ot->idname = "GREASE_PENCIL_OT_layer_mask_reorder";
1053 ot->description = "Reorder the active Grease Pencil mask layer up/down in the list";
1054
1055 /* api callbacks */
1058
1059 /* flags */
1061
1062 ot->prop = RNA_def_enum(ot->srna, "direction", enum_layer_move_direction, 0, "Direction", "");
1063}
1064
1066 {LAYERGROUP_COLOR_NONE, "NONE", ICON_X, "Set Default icon", ""},
1067 {LAYERGROUP_COLOR_01, "COLOR1", ICON_LAYERGROUP_COLOR_01, "Color tag 1", ""},
1068 {LAYERGROUP_COLOR_02, "COLOR2", ICON_LAYERGROUP_COLOR_02, "Color tag 2", ""},
1069 {LAYERGROUP_COLOR_03, "COLOR3", ICON_LAYERGROUP_COLOR_03, "Color tag 3", ""},
1070 {LAYERGROUP_COLOR_04, "COLOR4", ICON_LAYERGROUP_COLOR_04, "Color tag 4", ""},
1071 {LAYERGROUP_COLOR_05, "COLOR5", ICON_LAYERGROUP_COLOR_05, "Color tag 5", ""},
1072 {LAYERGROUP_COLOR_06, "COLOR6", ICON_LAYERGROUP_COLOR_06, "Color tag 6", ""},
1073 {LAYERGROUP_COLOR_07, "COLOR7", ICON_LAYERGROUP_COLOR_07, "Color tag 7", ""},
1074 {LAYERGROUP_COLOR_08, "COLOR8", ICON_LAYERGROUP_COLOR_08, "Color tag 8", ""},
1075 {0, nullptr, 0, nullptr, nullptr},
1076};
1077
1079{
1080 using namespace blender::bke::greasepencil;
1082
1083 const int color_tag = RNA_enum_get(op->ptr, "color_tag");
1084 LayerGroup *active_group = grease_pencil.get_active_group();
1085 active_group->color_tag = color_tag;
1086
1087 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
1088 WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, &grease_pencil);
1089
1090 return OPERATOR_FINISHED;
1091}
1092
1094{
1095 /* identifiers */
1096 ot->name = "Grease Pencil group color tag";
1097 ot->idname = "GREASE_PENCIL_OT_layer_group_color_tag";
1098 ot->description = "Change layer group icon";
1099
1102
1103 ot->flag = OPTYPE_UNDO;
1104
1105 ot->prop = RNA_def_enum(ot->srna, "color_tag", enum_layergroup_color_items, 0, "color tag", "");
1106}
1107
1109 All = 0,
1110 Active,
1111};
1112
1113static void duplicate_layer_and_frames(GreasePencil &dst_grease_pencil,
1114 const GreasePencil &src_grease_pencil,
1115 const blender::bke::greasepencil::Layer &src_layer,
1116 const DuplicateCopyMode copy_frame_mode,
1117 const int current_frame)
1118{
1119 using namespace blender::bke::greasepencil;
1120 Layer &dst_layer = dst_grease_pencil.duplicate_layer(src_layer);
1121
1122 dst_layer.frames_for_write().clear();
1123 for (const auto [frame_number, frame] : src_layer.frames().items()) {
1124 if ((copy_frame_mode == DuplicateCopyMode::Active) &&
1125 (&frame != src_layer.frame_at(current_frame)))
1126 {
1127 continue;
1128 }
1129 const int duration = src_layer.get_frame_duration_at(frame_number);
1130
1131 Drawing *dst_drawing = dst_grease_pencil.insert_frame(
1132 dst_layer, frame_number, duration, eBezTriple_KeyframeType(frame.type));
1133 if (dst_drawing != nullptr) {
1134 /* Duplicate drawing. */
1135 const Drawing &src_drawing = *src_grease_pencil.get_drawing_at(src_layer, frame_number);
1136 *dst_drawing = src_drawing;
1137 }
1138 }
1139}
1140
1142{
1143 using namespace blender::bke::greasepencil;
1144 Object *src_object = CTX_data_active_object(C);
1145 const Scene *scene = CTX_data_scene(C);
1146 const int current_frame = scene->r.cfra;
1147 const GreasePencil &src_grease_pencil = *static_cast<GreasePencil *>(src_object->data);
1148 const bool only_active = RNA_boolean_get(op->ptr, "only_active");
1149 const DuplicateCopyMode copy_frame_mode = DuplicateCopyMode(RNA_enum_get(op->ptr, "mode"));
1150
1151 CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
1152 if (ob == src_object || ob->type != OB_GREASE_PENCIL) {
1153 continue;
1154 }
1155 GreasePencil &dst_grease_pencil = *static_cast<GreasePencil *>(ob->data);
1156
1157 if (only_active) {
1158 const Layer &active_layer = *src_grease_pencil.get_active_layer();
1160 dst_grease_pencil, src_grease_pencil, active_layer, copy_frame_mode, current_frame);
1161 }
1162 else {
1163 for (const Layer *layer : src_grease_pencil.layers()) {
1165 dst_grease_pencil, src_grease_pencil, *layer, copy_frame_mode, current_frame);
1166 }
1167 }
1168
1169 DEG_id_tag_update(&dst_grease_pencil.id, ID_RECALC_GEOMETRY);
1171 }
1173
1174 return OPERATOR_FINISHED;
1175}
1176
1178{
1179 /* identifiers */
1180 ot->name = "Duplicate Layer to New Object";
1181 ot->idname = "GREASE_PENCIL_OT_layer_duplicate_object";
1182 ot->description = "Make a copy of the active Grease Pencil layer to selected object";
1183
1184 /* api callbacks */
1187
1188 /* flags */
1190
1192 "only_active",
1193 true,
1194 "Only Active",
1195 "Copy only active Layer, uncheck to append all layers");
1196
1197 static const EnumPropertyItem copy_mode[] = {
1198 {int(DuplicateCopyMode::All), "ALL", 0, "All Frames", ""},
1199 {int(DuplicateCopyMode::Active), "ACTIVE", 0, "Active Frame", ""},
1200 {0, nullptr, 0, nullptr, nullptr},
1201 };
1202
1203 ot->prop = RNA_def_enum(ot->srna, "mode", copy_mode, 0, "Mode", "");
1204}
1205
1206} // namespace blender::ed::greasepencil
1207
1209{
1210 using namespace blender::ed::greasepencil;
1211 WM_operatortype_append(GREASE_PENCIL_OT_layer_add);
1212 WM_operatortype_append(GREASE_PENCIL_OT_layer_remove);
1213 WM_operatortype_append(GREASE_PENCIL_OT_layer_reorder);
1214 WM_operatortype_append(GREASE_PENCIL_OT_layer_move);
1215 WM_operatortype_append(GREASE_PENCIL_OT_layer_active);
1216 WM_operatortype_append(GREASE_PENCIL_OT_layer_hide);
1217 WM_operatortype_append(GREASE_PENCIL_OT_layer_reveal);
1218 WM_operatortype_append(GREASE_PENCIL_OT_layer_isolate);
1219 WM_operatortype_append(GREASE_PENCIL_OT_layer_lock_all);
1220 WM_operatortype_append(GREASE_PENCIL_OT_layer_duplicate);
1221 WM_operatortype_append(GREASE_PENCIL_OT_layer_merge);
1222
1223 WM_operatortype_append(GREASE_PENCIL_OT_layer_group_add);
1224 WM_operatortype_append(GREASE_PENCIL_OT_layer_group_remove);
1225
1226 WM_operatortype_append(GREASE_PENCIL_OT_layer_mask_add);
1227 WM_operatortype_append(GREASE_PENCIL_OT_layer_mask_remove);
1228 WM_operatortype_append(GREASE_PENCIL_OT_layer_mask_reorder);
1229 WM_operatortype_append(GREASE_PENCIL_OT_layer_group_color_tag);
1230 WM_operatortype_append(GREASE_PENCIL_OT_layer_duplicate_object);
1231}
#define CTX_DATA_BEGIN(C, Type, instance, member)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
#define CTX_DATA_END
wmMsgBus * CTX_wm_message_bus(const bContext *C)
Low-level operations for grease pencil.
void BKE_grease_pencil_copy_parameters(const GreasePencil &src, GreasePencil &dst)
void BKE_grease_pencil_nomain_to_grease_pencil(GreasePencil *grease_pencil_src, GreasePencil *grease_pencil_dst)
GreasePencil * BKE_grease_pencil_new_nomain()
General operations, lookup, etc. for blender objects.
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
void void void bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL()
Definition listbase.cc:435
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void unit_m4(float m[4][4])
Definition rct.c:1127
void copy_m4_m4(float m1[4][4], const float m2[4][4])
#define BLI_SCOPED_DEFER(function_to_defer)
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
Definition string.c:45
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
eBezTriple_KeyframeType
@ LAYERGROUP_COLOR_01
@ LAYERGROUP_COLOR_NONE
@ LAYERGROUP_COLOR_06
@ LAYERGROUP_COLOR_04
@ LAYERGROUP_COLOR_05
@ LAYERGROUP_COLOR_03
@ LAYERGROUP_COLOR_08
@ LAYERGROUP_COLOR_07
@ LAYERGROUP_COLOR_02
@ OB_GREASE_PENCIL
@ LAYER_REORDER_BELOW
@ LAYER_REORDER_ABOVE
#define MEM_SAFE_FREE(v)
@ PROP_SKIP_SAVE
Definition RNA_types.hh:245
@ PROP_HIDDEN
Definition RNA_types.hh:239
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
#define NA_EDITED
Definition WM_types.hh:550
#define NC_GPENCIL
Definition WM_types.hh:366
#define NA_SELECTED
Definition WM_types.hh:555
void clear()
Definition BLI_map.hh:989
ItemIterator items() const
Definition BLI_map.hh:864
constexpr const char * c_str() const
void append(const T &value)
const Map< FramesMapKeyT, GreasePencilFrame > & frames() const
const GreasePencilFrame * frame_at(const int frame_number) const
int get_frame_duration_at(const int frame_number) const
Map< FramesMapKeyT, GreasePencilFrame > & frames_for_write()
const LayerGroup * parent_group() const
#define offsetof(t, d)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static ushort indices[]
void ED_operatortypes_grease_pencil_layers()
static int grease_pencil_layer_lock_all_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_lock_all(wmOperatorType *ot)
bool active_grease_pencil_poll(bContext *C)
static int grease_pencil_layer_group_color_tag_exec(bContext *C, wmOperator *op)
static int grease_pencil_layer_reveal_exec(bContext *C, wmOperator *)
static int grease_pencil_layer_isolate_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem enum_layer_move_direction[]
static int grease_pencil_layer_group_add_exec(bContext *C, wmOperator *op)
static int grease_pencil_merge_layer_exec(bContext *C, wmOperator *op)
GreasePencil * from_context(bContext &C)
static void GREASE_PENCIL_OT_layer_group_add(wmOperatorType *ot)
void grease_pencil_layer_parent_clear(bke::greasepencil::Layer &layer, const bool keep_transform)
static void GREASE_PENCIL_OT_layer_group_color_tag(wmOperatorType *ot)
static int grease_pencil_layer_hide_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_remove(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_isolate(wmOperatorType *ot)
static int grease_pencil_layer_group_remove_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_hide(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_merge(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_add(wmOperatorType *ot)
static int grease_pencil_layer_mask_remove_exec(bContext *C, wmOperator *)
static const EnumPropertyItem prop_layer_reorder_location[]
static void GREASE_PENCIL_OT_layer_mask_add(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_active(wmOperatorType *ot)
const EnumPropertyItem enum_layergroup_color_items[]
static int grease_pencil_layer_mask_reorder_exec(bContext *C, wmOperator *op)
static int grease_pencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
static int grease_pencil_layer_reorder_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_move(wmOperatorType *ot)
static int grease_pencil_layer_move_exec(bContext *C, wmOperator *op)
static int grease_pencil_layer_mask_add_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
static int grease_pencil_layer_remove_exec(bContext *C, wmOperator *)
static int grease_pencil_layer_active_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_group_remove(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_duplicate(wmOperatorType *ot)
bool grease_pencil_layer_parent_set(bke::greasepencil::Layer &layer, Object *parent, StringRefNull bone, const bool keep_transform)
static int grease_pencil_layer_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool grease_pencil_context_poll(bContext *C)
static int grease_pencil_layer_add_exec(bContext *C, wmOperator *op)
static void GREASE_PENCIL_OT_layer_mask_reorder(wmOperatorType *ot)
static int grease_pencil_layer_duplicate_exec(bContext *C, wmOperator *op)
void merge_layers(const GreasePencil &src_grease_pencil, const Span< Vector< int > > src_layer_indices_by_dst_layer, GreasePencil &dst_grease_pencil)
void select_layer_channel(GreasePencil &grease_pencil, bke::greasepencil::Layer *layer)
static void GREASE_PENCIL_OT_layer_reveal(wmOperatorType *ot)
bool active_grease_pencil_layer_poll(bContext *C)
static void GREASE_PENCIL_OT_layer_reorder(wmOperatorType *ot)
static void GREASE_PENCIL_OT_layer_mask_remove(wmOperatorType *ot)
static void duplicate_layer_and_frames(GreasePencil &dst_grease_pencil, const GreasePencil &src_grease_pencil, const blender::bke::greasepencil::Layer &src_layer, const DuplicateCopyMode copy_frame_mode, const int current_frame)
static bool grease_pencil_layer_move_poll(bContext *C)
int RNA_int_get(PointerRNA *ptr, const char *name)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
#define INT16_MAX
Definition stdint.h:135
signed char int8_t
Definition stdint.h:75
struct GreasePencilLayerTreeNode * prev
char parsubstr[64]
const c_style_mat & ptr() const
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct PointerRNA * ptr
#define N_(msgid)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_)
void WM_operatortype_append(void(*opfunc)(wmOperatorType *))
int WM_operator_props_popup_confirm_ex(bContext *C, wmOperator *op, const wmEvent *, std::optional< std::string > title, std::optional< std::string > confirm_text, const bool cancel_default)