Blender V4.5
gpencil_data.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstdlib>
12#include <cstring>
13
14#include "BLI_listbase.h"
15#include "BLI_utildefines.h"
16
17#include "BLT_translation.hh"
18
20#include "DNA_screen_types.h"
21
22#include "BKE_anim_data.hh"
23#include "BKE_animsys.h"
24#include "BKE_brush.hh"
25#include "BKE_context.hh"
26#include "BKE_fcurve_driver.h"
27#include "BKE_gpencil_legacy.h"
28#include "BKE_lib_id.hh"
29#include "BKE_main.hh"
30#include "BKE_material.hh"
31#include "BKE_paint.hh"
32#include "BKE_report.hh"
33
34#include "UI_interface.hh"
35
36#include "WM_api.hh"
37#include "WM_types.hh"
38
39#include "RNA_access.hh"
40#include "RNA_define.hh"
41#include "RNA_enum_types.hh"
42
43#include "ED_gpencil_legacy.hh"
44#include "ED_object.hh"
45#include "ED_view3d.hh"
46
47#include "DEG_depsgraph.hh"
49
50#include "gpencil_intern.hh"
51
52/* ************************************************ */
53/* Datablock Operators */
54
55/* ******************* Add New Data ************************ */
57{
58
59 /* the base line we have is that we have somewhere to add Grease Pencil data */
60 return ED_annotation_data_get_pointers(C, nullptr) != nullptr;
61}
62
63/* add new datablock - wrapper around API */
65{
66 PointerRNA gpd_owner = {};
67 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
68
69 if (gpd_ptr == nullptr) {
70 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
71 return OPERATOR_CANCELLED;
72 }
73
74 /* decrement user count and add new datablock */
75 /* TODO: if a datablock exists,
76 * we should make a copy of it instead of starting fresh (as in other areas) */
77 Main *bmain = CTX_data_main(C);
78
79 /* decrement user count of old GP datablock */
80 if (*gpd_ptr) {
81 bGPdata *gpd = (*gpd_ptr);
82 id_us_min(&gpd->id);
83 }
84
85 /* Add new datablock, with a single layer ready to use
86 * (so users don't have to perform an extra step). */
87 bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
88 *gpd_ptr = gpd;
89
90 /* tag for annotations */
92
93 /* add new layer (i.e. a "note") */
94 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
95
96 /* notifiers */
98
99 return OPERATOR_FINISHED;
100}
101
103{
104 /* identifiers */
105 ot->name = "Annotation Add New";
106 ot->idname = "GPENCIL_OT_annotation_add";
107 ot->description = "Add new Annotation data-block";
109
110 /* callbacks */
113}
114
115/* ******************* Unlink Data ************************ */
116
117/* poll callback for adding data/layers - special */
119{
120 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
121
122 /* only unlink annotation datablocks */
123 if ((gpd_ptr != nullptr) && (*gpd_ptr != nullptr)) {
124 bGPdata *gpd = (*gpd_ptr);
125 if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
126 return false;
127 }
128 }
129 /* if we have access to some active data, make sure there's a datablock before enabling this */
130 return (gpd_ptr && *gpd_ptr);
131}
132
133/* unlink datablock - wrapper around API */
135{
136 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
137
138 if (gpd_ptr == nullptr) {
139 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
140 return OPERATOR_CANCELLED;
141 }
142 /* just unlink datablock now, decreasing its user count */
143 bGPdata *gpd = (*gpd_ptr);
144
145 id_us_min(&gpd->id);
146 *gpd_ptr = nullptr;
147
148 /* notifiers */
150
151 return OPERATOR_FINISHED;
152}
153
155{
156 /* identifiers */
157 ot->name = "Annotation Unlink";
158 ot->idname = "GPENCIL_OT_data_unlink";
159 ot->description = "Unlink active Annotation data-block";
161
162 /* callbacks */
165}
166
167/* ************************************************ */
168/* Layer Operators */
169
170/* ******************* Add New Layer ************************ */
171
172/* add new layer - wrapper around API */
174{
175 PointerRNA gpd_owner = {};
176 Main *bmain = CTX_data_main(C);
177 bGPdata *gpd = nullptr;
178
179 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
180 /* if there's no existing Grease-Pencil data there, add some */
181 if (gpd_ptr == nullptr) {
182 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
183 return OPERATOR_CANCELLED;
184 }
185 /* Annotations */
186 if (*gpd_ptr == nullptr) {
187 *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
188 }
189
190 /* mark as annotation */
191 (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
192 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
193 gpd = *gpd_ptr;
194
195 /* notifiers */
196 if (gpd) {
198 }
201
202 return OPERATOR_FINISHED;
203}
204
206{
207 return ED_annotation_data_get_pointers(C, nullptr) != nullptr;
208}
209
211{
212 /* identifiers */
213 ot->name = "Add New Annotation Layer";
214 ot->idname = "GPENCIL_OT_layer_annotation_add";
215 ot->description = "Add new Annotation layer or note for the active data-block";
216
218
219 /* callbacks */
222}
223/* ******************* Remove Active Layer ************************* */
224
226{
229
230 /* sanity checks */
231 if (ELEM(nullptr, gpd, gpl)) {
232 return OPERATOR_CANCELLED;
233 }
234
235 if (gpl->flag & GP_LAYER_LOCKED) {
236 BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
237 return OPERATOR_CANCELLED;
238 }
239
240 /* make the layer before this the new active layer
241 * - use the one after if this is the first
242 * - if this is the only layer, this naturally becomes nullptr
243 */
244 if (gpl->prev) {
246 }
247 else {
249 }
250
251 if (gpl->flag & GP_LAYER_IS_RULER) {
253 }
254
255 /* delete the layer now... */
256 BKE_gpencil_layer_delete(gpd, gpl);
257
258 /* Reorder masking. */
260
261 /* notifiers */
265
266 /* Free Grease Pencil data block when last annotation layer is removed, see: #112683. */
267 if (gpd->layers.first == nullptr) {
268 BKE_gpencil_free_data(gpd, true);
269
270 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
271 *gpd_ptr = nullptr;
272
273 Main *bmain = CTX_data_main(C);
274 BKE_id_free_us(bmain, gpd);
275 }
276
277 return OPERATOR_FINISHED;
278}
279
281{
284
285 return (gpl != nullptr);
286}
287
289{
290 /* identifiers */
291 ot->name = "Remove Annotation Layer";
292 ot->idname = "GPENCIL_OT_layer_annotation_remove";
293 ot->description = "Remove active Annotation layer";
294
296
297 /* callbacks */
300}
301/* ******************* Move Layer Up/Down ************************** */
302
303enum {
306};
307
309{
312
313 const int direction = RNA_enum_get(op->ptr, "type") * -1;
314
315 /* sanity checks */
316 if (ELEM(nullptr, gpd, gpl)) {
317 return OPERATOR_CANCELLED;
318 }
319
320 BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
321 if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
322 /* Reorder masking. */
324
327 }
328
329 return OPERATOR_FINISHED;
330}
331
333{
334 static const EnumPropertyItem slot_move[] = {
335 {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
336 {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
337 {0, nullptr, 0, nullptr, nullptr},
338 };
339
340 /* identifiers */
341 ot->name = "Move Annotation Layer";
342 ot->idname = "GPENCIL_OT_layer_annotation_move";
343 ot->description = "Move the active Annotation layer up/down in the list";
344
345 /* API callbacks. */
348
349 /* flags */
351
352 ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
353}
Main * CTX_data_main(const bContext *C)
void BKE_gpencil_layer_active_set(struct bGPdata *gpd, struct bGPDlayer *active)
void BKE_gpencil_free_data(struct bGPdata *gpd, bool free_all)
struct bGPDlayer * BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive, bool add_to_header)
void BKE_gpencil_layer_mask_sort_all(struct bGPdata *gpd)
struct bGPDlayer * BKE_gpencil_layer_active_get(struct bGPdata *gpd)
struct bGPdata * BKE_gpencil_data_addnew(struct Main *bmain, const char name[])
void BKE_gpencil_layer_delete(struct bGPdata *gpd, struct bGPDlayer *gpl)
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void id_us_min(ID *id)
Definition lib_id.cc:361
General operations, lookup, etc. for materials.
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BLI_assert(a)
Definition BLI_assert.h:46
void void void bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL()
Definition listbase.cc:436
#define ELEM(...)
#define DATA_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:962
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_view3d_gizmo_ruler_remove_by_gpencil_layer(struct bContext *C, bGPDlayer *gpl)
#define C
Definition RandGen.cpp:29
#define ND_DATA
Definition WM_types.hh:506
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NA_EDITED
Definition WM_types.hh:581
#define NC_GPENCIL
Definition WM_types.hh:396
#define NA_SELECTED
Definition WM_types.hh:586
static bool gpencil_active_layer_annotation_poll(bContext *C)
static wmOperatorStatus gpencil_layer_move_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot)
void GPENCIL_OT_layer_annotation_remove(wmOperatorType *ot)
static bool gpencil_data_unlink_poll(bContext *C)
static wmOperatorStatus gpencil_layer_add_exec(bContext *C, wmOperator *op)
static wmOperatorStatus gpencil_data_add_exec(bContext *C, wmOperator *op)
static bool gpencil_data_add_poll(bContext *C)
static wmOperatorStatus gpencil_layer_remove_exec(bContext *C, wmOperator *op)
static bool gpencil_add_annotation_poll(bContext *C)
void GPENCIL_OT_annotation_add(wmOperatorType *ot)
@ GP_LAYER_MOVE_DOWN
@ GP_LAYER_MOVE_UP
void GPENCIL_OT_data_unlink(wmOperatorType *ot)
void GPENCIL_OT_layer_annotation_add(wmOperatorType *ot)
static wmOperatorStatus gpencil_data_unlink_exec(bContext *C, wmOperator *op)
bGPdata * ED_annotation_data_get_active(const bContext *C)
bGPdata ** ED_annotation_data_get_pointers(const bContext *C, PointerRNA *r_ptr)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void * first
struct bGPDlayer * next
struct bGPDlayer * prev
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4225