Blender V5.0
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 "WM_api.hh"
35#include "WM_types.hh"
36
37#include "RNA_access.hh"
38#include "RNA_define.hh"
39#include "RNA_enum_types.hh"
40
41#include "ED_gpencil_legacy.hh"
42#include "ED_object.hh"
43#include "ED_view3d.hh"
44
45#include "DEG_depsgraph.hh"
47
48#include "gpencil_intern.hh"
49
50/* ************************************************ */
51/* Datablock Operators */
52
53/* ******************* Add New Data ************************ */
55{
56
57 /* the base line we have is that we have somewhere to add Grease Pencil data */
58 return ED_annotation_data_get_pointers(C, nullptr) != nullptr;
59}
60
61/* add new datablock - wrapper around API */
63{
64 PointerRNA gpd_owner = {};
65 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
66
67 if (gpd_ptr == nullptr) {
68 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
69 return OPERATOR_CANCELLED;
70 }
71
72 /* decrement user count and add new datablock */
73 /* TODO: if a datablock exists,
74 * we should make a copy of it instead of starting fresh (as in other areas) */
75 Main *bmain = CTX_data_main(C);
76
77 /* decrement user count of old GP datablock */
78 if (*gpd_ptr) {
79 bGPdata *gpd = (*gpd_ptr);
80 id_us_min(&gpd->id);
81 }
82
83 /* Add new datablock, with a single layer ready to use
84 * (so users don't have to perform an extra step). */
85 bGPdata *gpd = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
86 *gpd_ptr = gpd;
87
88 /* tag for annotations */
90
91 /* add new layer (i.e. a "note") */
92 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
93
94 /* notifiers */
96
97 return OPERATOR_FINISHED;
98}
99
101{
102 /* identifiers */
103 ot->name = "Annotation Add New";
104 ot->idname = "GPENCIL_OT_annotation_add";
105 ot->description = "Add new Annotation data-block";
107
108 /* callbacks */
111}
112
113/* ******************* Unlink Data ************************ */
114
115/* poll callback for adding data/layers - special */
117{
118 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
119
120 /* only unlink annotation datablocks */
121 if ((gpd_ptr != nullptr) && (*gpd_ptr != nullptr)) {
122 bGPdata *gpd = (*gpd_ptr);
123 if ((gpd->flag & GP_DATA_ANNOTATIONS) == 0) {
124 return false;
125 }
126 }
127 /* if we have access to some active data, make sure there's a datablock before enabling this */
128 return (gpd_ptr && *gpd_ptr);
129}
130
131/* unlink datablock - wrapper around API */
133{
134 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
135
136 if (gpd_ptr == nullptr) {
137 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
138 return OPERATOR_CANCELLED;
139 }
140 /* just unlink datablock now, decreasing its user count */
141 bGPdata *gpd = (*gpd_ptr);
142
143 id_us_min(&gpd->id);
144 *gpd_ptr = nullptr;
145
146 /* notifiers */
148
149 return OPERATOR_FINISHED;
150}
151
153{
154 /* identifiers */
155 ot->name = "Annotation Unlink";
156 ot->idname = "GPENCIL_OT_data_unlink";
157 ot->description = "Unlink active Annotation data-block";
159
160 /* callbacks */
163}
164
165/* ************************************************ */
166/* Layer Operators */
167
168/* ******************* Add New Layer ************************ */
169
170/* add new layer - wrapper around API */
172{
173 PointerRNA gpd_owner = {};
174 Main *bmain = CTX_data_main(C);
175 bGPdata *gpd = nullptr;
176
177 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, &gpd_owner);
178 /* if there's no existing Grease-Pencil data there, add some */
179 if (gpd_ptr == nullptr) {
180 BKE_report(op->reports, RPT_ERROR, "Nowhere for Grease Pencil data to go");
181 return OPERATOR_CANCELLED;
182 }
183 /* Annotations */
184 if (*gpd_ptr == nullptr) {
185 *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("Annotations"));
186 }
187
188 /* mark as annotation */
189 (*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
190 BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
191 gpd = *gpd_ptr;
192
193 /* notifiers */
194 if (gpd) {
196 }
199
200 return OPERATOR_FINISHED;
201}
202
204{
205 return ED_annotation_data_get_pointers(C, nullptr) != nullptr;
206}
207
209{
210 /* identifiers */
211 ot->name = "Add New Annotation Layer";
212 ot->idname = "GPENCIL_OT_layer_annotation_add";
213 ot->description = "Add new Annotation layer or note for the active data-block";
214
216
217 /* callbacks */
220}
221/* ******************* Remove Active Layer ************************* */
222
224{
227
228 /* sanity checks */
229 if (ELEM(nullptr, gpd, gpl)) {
230 return OPERATOR_CANCELLED;
231 }
232
233 if (gpl->flag & GP_LAYER_LOCKED) {
234 BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers");
235 return OPERATOR_CANCELLED;
236 }
237
238 /* make the layer before this the new active layer
239 * - use the one after if this is the first
240 * - if this is the only layer, this naturally becomes nullptr
241 */
242 if (gpl->prev) {
244 }
245 else {
247 }
248
249 if (gpl->flag & GP_LAYER_IS_RULER) {
251 }
252
253 /* delete the layer now... */
254 BKE_gpencil_layer_delete(gpd, gpl);
255
256 /* notifiers */
260
261 /* Free Grease Pencil data block when last annotation layer is removed, see: #112683. */
262 if (gpd->layers.first == nullptr) {
263 BKE_gpencil_free_data(gpd, true);
264
265 bGPdata **gpd_ptr = ED_annotation_data_get_pointers(C, nullptr);
266 *gpd_ptr = nullptr;
267
268 Main *bmain = CTX_data_main(C);
269 BKE_id_free_us(bmain, gpd);
270 }
271
272 return OPERATOR_FINISHED;
273}
274
276{
279
280 return (gpl != nullptr);
281}
282
284{
285 /* identifiers */
286 ot->name = "Remove Annotation Layer";
287 ot->idname = "GPENCIL_OT_layer_annotation_remove";
288 ot->description = "Remove active Annotation layer";
289
291
292 /* callbacks */
295}
296/* ******************* Move Layer Up/Down ************************** */
297
298enum {
301};
302
304{
307
308 const int direction = RNA_enum_get(op->ptr, "type") * -1;
309
310 /* sanity checks */
311 if (ELEM(nullptr, gpd, gpl)) {
312 return OPERATOR_CANCELLED;
313 }
314
315 BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */
316 if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) {
319 }
320
321 return OPERATOR_FINISHED;
322}
323
325{
326 static const EnumPropertyItem slot_move[] = {
327 {GP_LAYER_MOVE_UP, "UP", 0, "Up", ""},
328 {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""},
329 {0, nullptr, 0, nullptr, nullptr},
330 };
331
332 /* identifiers */
333 ot->name = "Move Annotation Layer";
334 ot->idname = "GPENCIL_OT_layer_annotation_move";
335 ot->description = "Move the active Annotation layer up/down in the list";
336
337 /* API callbacks. */
340
341 /* flags */
343
344 ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", "");
345}
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)
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:366
General operations, lookup, etc. for materials.
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#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:1054
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ 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:509
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NA_EDITED
Definition WM_types.hh:584
#define NC_GPENCIL
Definition WM_types.hh:399
#define NA_SELECTED
Definition WM_types.hh:589
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)
@ GP_LAYER_MOVE_DOWN
@ GP_LAYER_MOVE_UP
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)
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:4237