Callbacks: exec invoke & modal now use a typed enum wmOperatorStatus. This helps avoid mistakes returning incompatible booleans or other values which don't make sense for operators to return. It also makes it more obvious functions in the WM API are intended to be used to calculate return values for operator callbacks. Operator enums have been moved into DNA_windowmanager_enums.h so this can be used in other headers without loading other includes indirectly. No functional changes expected. Ref !136227
278 lines
8.2 KiB
C++
278 lines
8.2 KiB
C++
/* SPDX-FileCopyrightText: 2001-2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup edobj
|
|
*/
|
|
|
|
#include "object_intern.hh"
|
|
|
|
#include "BKE_context.hh"
|
|
#include "BKE_light_linking.h"
|
|
|
|
#include "ED_object.hh"
|
|
#include "ED_screen.hh"
|
|
|
|
#include "WM_api.hh"
|
|
#include "WM_types.hh"
|
|
|
|
#include "UI_resources.hh"
|
|
|
|
#include "DNA_collection_types.h"
|
|
|
|
#include "RNA_access.hh"
|
|
#include "RNA_define.hh"
|
|
#include "RNA_prototypes.hh"
|
|
|
|
namespace blender::ed::object {
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Create New Light Linking Receiver/Blocker Collection Operators
|
|
* \{ */
|
|
|
|
template<LightLinkingType link_type>
|
|
static wmOperatorStatus light_linking_collection_new_exec(bContext *C, wmOperator * /*op*/)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
Object *object = context_active_object(C);
|
|
|
|
BKE_light_linking_collection_new(bmain, object, link_type);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_receiver_collection_new(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "New Light Linking Collection";
|
|
ot->description = "Create new light linking collection used by the active emitter";
|
|
ot->idname = "OBJECT_OT_light_linking_receiver_collection_new";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_collection_new_exec<LIGHT_LINKING_RECEIVER>;
|
|
ot->poll = ED_operator_object_active_editable;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_blocker_collection_new(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "New Light Linking Collection";
|
|
ot->description = "Create new light linking collection used by the active emitter";
|
|
ot->idname = "OBJECT_OT_light_linking_blocker_collection_new";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_collection_new_exec<LIGHT_LINKING_BLOCKER>;
|
|
ot->poll = ED_operator_object_active_editable;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select Light Linking Receivers/Blockers Operator
|
|
* \{ */
|
|
|
|
template<LightLinkingType link_type>
|
|
static wmOperatorStatus light_linking_select_exec(bContext *C, wmOperator * /*op*/)
|
|
{
|
|
Scene *scene = CTX_data_scene(C);
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
Object *emitter = context_active_object(C);
|
|
|
|
BKE_light_linking_select_receivers_of_emitter(scene, view_layer, emitter, link_type);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_receivers_select(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Light Linking Receivers";
|
|
ot->description = "Select all objects which receive light from this emitter";
|
|
ot->idname = "OBJECT_OT_light_linking_receivers_select";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_select_exec<LIGHT_LINKING_RECEIVER>;
|
|
ot->poll = ED_operator_object_active;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_blockers_select(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Light Linking Blockers";
|
|
ot->description = "Select all objects which block light from this emitter";
|
|
ot->idname = "OBJECT_OT_light_linking_blockers_select";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_select_exec<LIGHT_LINKING_BLOCKER>;
|
|
ot->poll = ED_operator_object_active;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Link Receivers/Blockers to Emitter Operator
|
|
* \{ */
|
|
|
|
template<LightLinkingType link_type>
|
|
static wmOperatorStatus light_linking_link_exec(bContext *C, wmOperator *op)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
Scene *scene = CTX_data_scene(C);
|
|
Object *emitter = context_active_object(C);
|
|
|
|
const eCollectionLightLinkingState link_state = eCollectionLightLinkingState(
|
|
RNA_enum_get(op->ptr, "link_state"));
|
|
|
|
CTX_DATA_BEGIN (C, Object *, receiver, selected_objects) {
|
|
if (receiver == emitter) {
|
|
continue;
|
|
}
|
|
|
|
BKE_light_linking_link_receiver_to_emitter(bmain, emitter, receiver, link_type, link_state);
|
|
}
|
|
CTX_DATA_END;
|
|
|
|
/* It is possible that the receiver collection is also used by the view layer.
|
|
* For this case send a notifier so that the UI is updated for the changes in the collection
|
|
* content. */
|
|
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_receivers_link(wmOperatorType *ot)
|
|
{
|
|
static const EnumPropertyItem link_state_items[] = {
|
|
{COLLECTION_LIGHT_LINKING_STATE_INCLUDE,
|
|
"INCLUDE",
|
|
ICON_NONE,
|
|
"Include",
|
|
"Include selected receivers to receive light from the active emitter"},
|
|
{COLLECTION_LIGHT_LINKING_STATE_EXCLUDE,
|
|
"EXCLUDE",
|
|
ICON_NONE,
|
|
"Exclude",
|
|
"Exclude selected receivers from receiving light from the active emitter"},
|
|
{0, nullptr, 0, nullptr, nullptr},
|
|
};
|
|
|
|
/* identifiers */
|
|
ot->name = "Link Receivers to Emitter";
|
|
ot->description = "Light link selected receivers to the active emitter object";
|
|
ot->idname = "OBJECT_OT_light_linking_receivers_link";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_link_exec<LIGHT_LINKING_RECEIVER>;
|
|
ot->poll = ED_operator_object_active_editable;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
"link_state",
|
|
link_state_items,
|
|
COLLECTION_LIGHT_LINKING_STATE_INCLUDE,
|
|
"Link State",
|
|
"State of the light linking");
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_blockers_link(wmOperatorType *ot)
|
|
{
|
|
static const EnumPropertyItem link_state_items[] = {
|
|
{COLLECTION_LIGHT_LINKING_STATE_INCLUDE,
|
|
"INCLUDE",
|
|
ICON_NONE,
|
|
"Include",
|
|
"Include selected blockers to cast shadows from the active emitter"},
|
|
{COLLECTION_LIGHT_LINKING_STATE_EXCLUDE,
|
|
"EXCLUDE",
|
|
ICON_NONE,
|
|
"Exclude",
|
|
"Exclude selected blockers from casting shadows from the active emitter"},
|
|
{0, nullptr, 0, nullptr, nullptr},
|
|
};
|
|
|
|
/* identifiers */
|
|
ot->name = "Link Blockers to Emitter";
|
|
ot->description = "Light link selected blockers to the active emitter object";
|
|
ot->idname = "OBJECT_OT_light_linking_blockers_link";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_link_exec<LIGHT_LINKING_BLOCKER>;
|
|
ot->poll = ED_operator_object_active_editable;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
"link_state",
|
|
link_state_items,
|
|
COLLECTION_LIGHT_LINKING_STATE_INCLUDE,
|
|
"Link State",
|
|
"State of the shadow linking");
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Unlink from the Light Linking Collection Operator
|
|
* \{ */
|
|
|
|
static wmOperatorStatus light_linking_unlink_from_collection_exec(bContext *C, wmOperator *op)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
|
|
ID *id = static_cast<ID *>(CTX_data_pointer_get_type(C, "id", &RNA_ID).data);
|
|
Collection *collection = static_cast<Collection *>(
|
|
CTX_data_pointer_get_type(C, "collection", &RNA_Collection).data);
|
|
|
|
if (!id || !collection) {
|
|
return OPERATOR_PASS_THROUGH;
|
|
}
|
|
|
|
if (!BKE_light_linking_unlink_id_from_collection(bmain, collection, id, op->reports)) {
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
|
|
/* Copy notifiers from the Outliner's "Unlink" operation for objects and collections. */
|
|
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, nullptr);
|
|
WM_event_add_notifier(C, NC_ID | NA_EDITED, nullptr);
|
|
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, nullptr);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void OBJECT_OT_light_linking_unlink_from_collection(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Remove From Light Linking Collection";
|
|
ot->description = "Remove this object or collection from the light linking collection";
|
|
ot->idname = "OBJECT_OT_light_linking_unlink_from_collection";
|
|
|
|
/* api callbacks */
|
|
ot->exec = light_linking_unlink_from_collection_exec;
|
|
ot->poll = ED_operator_object_active_editable;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
} // namespace blender::ed::object
|