Blender  V3.3
object_collection.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_utildefines.h"
12 
13 #include "DNA_collection_types.h"
14 #include "DNA_object_types.h"
15 #include "DNA_scene_types.h"
16 
17 #include "BKE_collection.h"
18 #include "BKE_context.h"
19 #include "BKE_lib_id.h"
20 #include "BKE_main.h"
21 #include "BKE_object.h"
22 #include "BKE_report.h"
23 
24 #include "DEG_depsgraph.h"
25 #include "DEG_depsgraph_build.h"
26 
27 #include "ED_object.h"
28 #include "ED_screen.h"
29 
30 #include "WM_api.h"
31 #include "WM_types.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_define.h"
35 #include "RNA_enum_types.h"
36 #include "RNA_prototypes.h"
37 
38 #include "UI_interface_icons.h"
39 
40 #include "object_intern.h"
41 
42 /********************* 3d view operators ***********************/
43 
44 /* can be called with C == NULL */
47  PropertyRNA *UNUSED(prop),
48  bool *r_free)
49 {
50  Main *bmain = CTX_data_main(C);
52  Object *ob;
53  EnumPropertyItem *item = NULL, item_tmp = {0};
54  int totitem = 0;
55 
56  if (C == NULL) {
57  return DummyRNA_NULL_items;
58  }
59 
60  ob = ED_object_context(C);
61 
62  /* check that the object exists */
63  if (ob) {
64  Collection *collection;
65  int i = 0, count = 0;
66 
67  /* if 2 or more collections, add option to add to all collections */
68  collection = NULL;
69  while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
70  count++;
71  }
72 
73  if (count >= 2) {
74  item_tmp.identifier = item_tmp.name = "All Collections";
75  item_tmp.value = INT_MAX; /* this will give NULL on lookup */
76  RNA_enum_item_add(&item, &totitem, &item_tmp);
77  RNA_enum_item_add_separator(&item, &totitem);
78  }
79 
80  /* add collections */
81  collection = NULL;
82  while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
83  item_tmp.identifier = item_tmp.name = collection->id.name + 2;
84  item_tmp.icon = UI_icon_color_from_collection(collection);
85  item_tmp.value = i;
86  RNA_enum_item_add(&item, &totitem, &item_tmp);
87  i++;
88  }
89  }
90 
91  RNA_enum_item_end(&item, &totitem);
92  *r_free = true;
93 
94  return item;
95 }
96 
97 /* get the collection back from the enum index, quite awkward and UI specific */
99  Scene *scene,
100  Object *ob,
101  const int collection_object_index)
102 {
103  Collection *collection = NULL;
104  int i = 0;
105  while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
106  if (i == collection_object_index) {
107  break;
108  }
109  i++;
110  }
111 
112  return collection;
113 }
114 
116 {
117  Object *ob = ED_object_context(C);
118  Main *bmain = CTX_data_main(C);
120  int single_collection_index = RNA_enum_get(op->ptr, "collection");
121  Collection *single_collection = collection_object_active_find_index(
122  bmain, scene, ob, single_collection_index);
123  bool is_cycle = false;
124  bool updated = false;
125 
126  if (ob == NULL) {
127  return OPERATOR_CANCELLED;
128  }
129 
130  /* now add all selected objects to the collection(s) */
131  FOREACH_COLLECTION_BEGIN (bmain, scene, Collection *, collection) {
132  if (single_collection && collection != single_collection) {
133  continue;
134  }
135  if (!BKE_collection_has_object(collection, ob)) {
136  continue;
137  }
138 
139  CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
140  if (BKE_collection_has_object(collection, base->object)) {
141  continue;
142  }
143 
144  if (!BKE_collection_object_cyclic_check(bmain, base->object, collection)) {
145  BKE_collection_object_add(bmain, collection, base->object);
146  DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
147  updated = true;
148  }
149  else {
150  is_cycle = true;
151  }
152  }
153  CTX_DATA_END;
154  }
156 
157  if (is_cycle) {
158  BKE_report(op->reports, RPT_WARNING, "Skipped some collections because of cycle detected");
159  }
160 
161  if (!updated) {
162  return OPERATOR_CANCELLED;
163  }
164 
167 
168  return OPERATOR_FINISHED;
169 }
170 
172 {
173  PropertyRNA *prop;
174 
175  /* identifiers */
176  ot->name = "Add Selected to Active Collection";
177  ot->description = "Add the object to an object collection that contains the active object";
178  ot->idname = "COLLECTION_OT_objects_add_active";
179 
180  /* api callbacks */
184 
185  /* flags */
187 
188  /* properties */
189  prop = RNA_def_enum(ot->srna,
190  "collection",
192  0,
193  "Collection",
194  "The collection to add other selected objects to");
197  ot->prop = prop;
198 }
199 
201 {
202  Main *bmain = CTX_data_main(C);
204  ViewLayer *view_layer = CTX_data_view_layer(C);
205  Object *ob = OBACT(view_layer);
206  int single_collection_index = RNA_enum_get(op->ptr, "collection");
207  Collection *single_collection = collection_object_active_find_index(
208  bmain, scene, ob, single_collection_index);
209  bool ok = false;
210 
211  if (ob == NULL) {
212  return OPERATOR_CANCELLED;
213  }
214 
215  /* Linking to same collection requires its own loop so we can avoid
216  * looking up the active objects collections each time. */
217  FOREACH_COLLECTION_BEGIN (bmain, scene, Collection *, collection) {
218  if (single_collection && collection != single_collection) {
219  continue;
220  }
221 
222  if (BKE_collection_has_object(collection, ob)) {
223  /* Remove collections from selected objects */
224  CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
225  BKE_collection_object_remove(bmain, collection, base->object, false);
226  DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
227  ok = 1;
228  }
229  CTX_DATA_END;
230  }
231  }
233 
234  if (!ok) {
235  BKE_report(op->reports, RPT_ERROR, "Active object contains no collections");
236  }
237 
240 
241  return OPERATOR_FINISHED;
242 }
243 
245 {
246  PropertyRNA *prop;
247 
248  /* identifiers */
249  ot->name = "Remove Selected from Active Collection";
250  ot->description = "Remove the object from an object collection that contains the active object";
251  ot->idname = "COLLECTION_OT_objects_remove_active";
252 
253  /* api callbacks */
257 
258  /* flags */
260 
261  /* properties */
262  prop = RNA_def_enum(ot->srna,
263  "collection",
265  0,
266  "Collection",
267  "The collection to remove other selected objects from");
270  ot->prop = prop;
271 }
272 
274 {
275  Main *bmain = CTX_data_main(C);
277 
278  CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
279  BKE_object_groups_clear(bmain, scene, base->object);
280  }
281  CTX_DATA_END;
282 
285 
286  return OPERATOR_FINISHED;
287 }
288 
290 {
291  /* identifiers */
292  ot->name = "Remove from All Collections";
293  ot->description = "Remove selected objects from all collections";
294  ot->idname = "COLLECTION_OT_objects_remove_all";
295 
296  /* api callbacks */
299 
300  /* flags */
302 }
303 
305 {
306  Object *ob = ED_object_context(C);
307  Main *bmain = CTX_data_main(C);
309  int single_collection_index = RNA_enum_get(op->ptr, "collection");
310  Collection *single_collection = collection_object_active_find_index(
311  bmain, scene, ob, single_collection_index);
312  bool updated = false;
313 
314  if (ob == NULL) {
315  return OPERATOR_CANCELLED;
316  }
317 
318  FOREACH_COLLECTION_BEGIN (bmain, scene, Collection *, collection) {
319  if (single_collection && collection != single_collection) {
320  continue;
321  }
322  if (!BKE_collection_has_object(collection, ob)) {
323  continue;
324  }
325 
326  /* now remove all selected objects from the collection */
327  CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) {
328  BKE_collection_object_remove(bmain, collection, base->object, false);
329  DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
330  updated = true;
331  }
332  CTX_DATA_END;
333  }
335 
336  if (!updated) {
337  return OPERATOR_CANCELLED;
338  }
339 
342 
343  return OPERATOR_FINISHED;
344 }
345 
347 {
348  PropertyRNA *prop;
349 
350  /* identifiers */
351  ot->name = "Remove from Collection";
352  ot->description = "Remove selected objects from a collection";
353  ot->idname = "COLLECTION_OT_objects_remove";
354 
355  /* api callbacks */
359 
360  /* flags */
362 
363  /* properties */
364  prop = RNA_def_enum(ot->srna,
365  "collection",
367  0,
368  "Collection",
369  "The collection to remove this object from");
372  ot->prop = prop;
373 }
374 
376 {
377  Main *bmain = CTX_data_main(C);
378  char name[MAX_ID_NAME - 2]; /* id name */
379 
380  RNA_string_get(op->ptr, "name", name);
381 
382  Collection *collection = BKE_collection_add(bmain, NULL, name);
383  id_fake_user_set(&collection->id);
384 
385  CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
386  BKE_collection_object_add(bmain, collection, base->object);
388  }
389  CTX_DATA_END;
390 
393 
394  return OPERATOR_FINISHED;
395 }
396 
398 {
399  /* identifiers */
400  ot->name = "Create New Collection";
401  ot->description = "Create an object collection from selected objects";
402  ot->idname = "COLLECTION_OT_create";
403 
404  /* api callbacks */
407 
408  /* flags */
410 
412  ot->srna, "name", "Collection", MAX_ID_NAME - 2, "Name", "Name of the new collection");
413 }
414 
415 /****************** properties window operators *********************/
416 
418 {
419  Object *ob = ED_object_context(C);
420  Main *bmain = CTX_data_main(C);
421 
422  if (ob == NULL) {
423  return OPERATOR_CANCELLED;
424  }
425 
426  Collection *collection = BKE_collection_add(bmain, NULL, "Collection");
427  id_fake_user_set(&collection->id);
428  BKE_collection_object_add(bmain, collection, ob);
429 
432 
434 
435  return OPERATOR_FINISHED;
436 }
437 
439 {
440  /* identifiers */
441  ot->name = "Add to Collection";
442  ot->idname = "OBJECT_OT_collection_add";
443  ot->description = "Add an object to a new collection";
444 
445  /* api callbacks */
448 
449  /* flags */
451 }
452 
454 {
455  Main *bmain = CTX_data_main(C);
456  Object *ob = ED_object_context(C);
457  Collection *collection = BLI_findlink(&bmain->collections, RNA_enum_get(op->ptr, "collection"));
458 
459  if (ELEM(NULL, ob, collection)) {
460  return OPERATOR_CANCELLED;
461  }
462 
463  /* Early return check, if the object is already in collection
464  * we could skip all the dependency check and just consider
465  * operator is finished.
466  */
467  if (BKE_collection_has_object(collection, ob)) {
468  return OPERATOR_FINISHED;
469  }
470 
471  /* Currently this should not be allowed (might be supported in the future though...). */
472  if (ID_IS_OVERRIDE_LIBRARY(&collection->id)) {
473  BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is overridden");
474  return OPERATOR_CANCELLED;
475  }
476  /* Linked collections are already checked for by using RNA_collection_local_itemf
477  * but operator can be called without invoke */
478  if (ID_IS_LINKED(&collection->id)) {
479  BKE_report(op->reports, RPT_ERROR, "Could not add the collection because it is linked");
480  return OPERATOR_CANCELLED;
481  }
482 
483  /* Adding object to collection which is used as dupli-collection for self is bad idea.
484  *
485  * It is also bad idea to add object to collection which is in collection which
486  * contains our current object.
487  */
488  if (BKE_collection_object_cyclic_check(bmain, ob, collection)) {
489  BKE_report(op->reports,
490  RPT_ERROR,
491  "Could not add the collection because of dependency cycle detected");
492  return OPERATOR_CANCELLED;
493  }
494 
495  BKE_collection_object_add(bmain, collection, ob);
496 
499 
501 
502  return OPERATOR_FINISHED;
503 }
504 
506 {
507  PropertyRNA *prop;
508 
509  /* identifiers */
510  ot->name = "Link to Collection";
511  ot->idname = "OBJECT_OT_collection_link";
512  ot->description = "Add an object to an existing collection";
513 
514  /* api callbacks */
518 
519  /* flags */
521 
522  /* properties */
523  prop = RNA_def_enum(ot->srna, "collection", DummyRNA_NULL_items, 0, "Collection", "");
526  ot->prop = prop;
527 }
528 
530 {
531  Main *bmain = CTX_data_main(C);
532  Object *ob = ED_object_context(C);
533  Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
534 
535  if (!ob || !collection) {
536  return OPERATOR_CANCELLED;
537  }
538  if (ID_IS_LINKED(collection) || ID_IS_OVERRIDE_LIBRARY(collection)) {
539  BKE_report(op->reports,
540  RPT_ERROR,
541  "Cannot remove an object from a linked or library override collection");
542  return OPERATOR_CANCELLED;
543  }
544 
545  BKE_collection_object_remove(bmain, collection, ob, false);
546 
549 
551 
552  return OPERATOR_FINISHED;
553 }
554 
556 {
557  /* identifiers */
558  ot->name = "Remove Collection";
559  ot->idname = "OBJECT_OT_collection_remove";
560  ot->description = "Remove the active object from this collection";
561 
562  /* api callbacks */
565 
566  /* flags */
568 }
569 
571 {
572  Main *bmain = CTX_data_main(C);
573  Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
574 
575  if (!collection) {
576  return OPERATOR_CANCELLED;
577  }
578  if (ID_IS_OVERRIDE_LIBRARY(collection) &&
579  collection->id.override_library->hierarchy_root != &collection->id) {
580  BKE_report(op->reports,
581  RPT_ERROR,
582  "Cannot unlink a library override collection which is not the root of its override "
583  "hierarchy");
584  return OPERATOR_CANCELLED;
585  }
586 
587  BKE_id_delete(bmain, collection);
588 
590 
592 
593  return OPERATOR_FINISHED;
594 }
595 
597 {
598  /* identifiers */
599  ot->name = "Unlink Collection";
600  ot->idname = "OBJECT_OT_collection_unlink";
601  ot->description = "Unlink the collection from all objects";
602 
603  /* api callbacks */
606 
607  /* flags */
609 }
610 
611 /* Select objects in the same collection as the active */
613 {
615  Collection *collection = CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data;
616 
617  if (!collection) {
618  return OPERATOR_CANCELLED;
619  }
620 
621  CTX_DATA_BEGIN (C, Base *, base, visible_bases) {
622  if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLE) != 0)) {
623  if (BKE_collection_has_object_recursive(collection, base->object)) {
625  }
626  }
627  }
628  CTX_DATA_END;
629 
632 
633  return OPERATOR_FINISHED;
634 }
635 
637 {
638  /* identifiers */
639  ot->name = "Select Objects in Collection";
640  ot->idname = "OBJECT_OT_collection_objects_select";
641  ot->description = "Select all objects in collection";
642 
643  /* api callbacks */
646 
647  /* flags */
649 }
struct Collection * BKE_collection_add(struct Main *bmain, struct Collection *parent, const char *name)
Definition: collection.c:425
struct Collection * BKE_collection_object_find(struct Main *bmain, struct Scene *scene, struct Collection *collection, struct Object *ob)
Definition: collection.c:950
#define FOREACH_COLLECTION_BEGIN(_bmain, _scene, Type, _instance)
bool BKE_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *ob)
Definition: collection.c:1125
bool BKE_collection_object_cyclic_check(struct Main *bmain, struct Object *object, struct Collection *collection)
Definition: collection.c:898
bool BKE_collection_has_object(struct Collection *collection, const struct Object *ob)
bool BKE_collection_has_object_recursive(struct Collection *collection, struct Object *ob)
Definition: collection.c:921
bool BKE_collection_object_remove(struct Main *bmain, struct Collection *collection, struct Object *object, bool free_us)
Definition: collection.c:1170
#define FOREACH_COLLECTION_END
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:473
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
void id_fake_user_set(struct ID *id)
Definition: lib_id.c:343
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL()
General operations, lookup, etc. for blender objects.
void BKE_object_groups_clear(struct Main *bmain, struct Scene *scene, struct Object *object)
Definition: object.cc:5245
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define UNUSED(x)
#define ELEM(...)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define MAX_ID_NAME
Definition: DNA_ID.h:337
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
Object groups, one object can be in many groups at once.
@ BASE_SELECTABLE
@ BASE_SELECTED
Object is a sort of wrapper for general info.
#define OBACT(_view_layer)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
struct Object * ED_object_context(const struct bContext *C)
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode)
Definition: object_select.c:76
@ BA_SELECT
Definition: ED_object.h:155
bool ED_operator_objectmode(struct bContext *C)
Definition: screen_ops.c:186
const EnumPropertyItem * RNA_collection_local_itemf(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free)
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:294
#define C
Definition: RandGen.cpp:25
int UI_icon_color_from_collection(const struct Collection *collection)
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DRAW
Definition: WM_types.h:410
#define ND_OB_SELECT
Definition: WM_types.h:390
#define NC_SCENE
Definition: WM_types.h:328
#define NC_GROUP
Definition: WM_types.h:333
#define NA_EDITED
Definition: WM_types.h:523
#define NC_OBJECT
Definition: WM_types.h:329
Scene scene
int count
static Collection * collection_object_active_find_index(Main *bmain, Scene *scene, Object *ob, const int collection_object_index)
void COLLECTION_OT_create(wmOperatorType *ot)
void COLLECTION_OT_objects_remove(wmOperatorType *ot)
static int collection_remove_exec(bContext *C, wmOperator *op)
void OBJECT_OT_collection_link(wmOperatorType *ot)
void COLLECTION_OT_objects_remove_all(wmOperatorType *ot)
void OBJECT_OT_collection_unlink(wmOperatorType *ot)
void OBJECT_OT_collection_objects_select(wmOperatorType *ot)
static int collection_unlink_exec(bContext *C, wmOperator *op)
static int objects_add_active_exec(bContext *C, wmOperator *op)
static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op))
void COLLECTION_OT_objects_remove_active(wmOperatorType *ot)
static const EnumPropertyItem * collection_object_active_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
static int collection_objects_remove_exec(bContext *C, wmOperator *op)
static int collection_link_exec(bContext *C, wmOperator *op)
static int collection_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_collection_add(wmOperatorType *ot)
static int collection_add_exec(bContext *C, wmOperator *UNUSED(op))
static int collection_create_exec(bContext *C, wmOperator *op)
void OBJECT_OT_collection_remove(wmOperatorType *ot)
void COLLECTION_OT_objects_add_active(wmOperatorType *ot)
static int objects_remove_active_exec(bContext *C, wmOperator *op)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_enum_item_add_separator(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4459
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
struct ID * hierarchy_root
Definition: DNA_ID.h:303
IDOverrideLibrary * override_library
Definition: DNA_ID.h:412
char name[66]
Definition: DNA_ID.h:378
Definition: BKE_main.h:121
ListBase collections
Definition: BKE_main.h:189
void * data
Definition: RNA_types.h:38
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))