Curves: Unify poll functions, add message with no surface

The "snap to surface" operators now have "disabled" poll messages
when there is no surface object.

The implementation in most curves operators is also unified.
The goal is to avoid having to define and use the poll failure messages
in multiple places, to reduce the boilerplate that tends to be
necessary to add an operator, and to increase the likelihood that
operators are implemented with proper poll messages.

Differential Revision: https://developer.blender.org/D15528
This commit is contained in:
Hans Goudey 2022-07-25 11:59:33 -05:00
parent 739136caca
commit 00a3533429
3 changed files with 56 additions and 73 deletions

View File

@ -94,6 +94,47 @@ VectorSet<Curves *> get_unique_editable_curves(const bContext &C)
return unique_curves;
}
static bool curves_poll_impl(bContext *C, const bool check_editable, const bool check_surface)
{
Object *object = CTX_data_active_object(C);
if (object == nullptr || object->type != OB_CURVES) {
return false;
}
if (check_editable) {
if (!ED_operator_object_active_editable_ex(C, object)) {
return false;
}
}
if (check_surface) {
Curves &curves = *static_cast<Curves *>(object->data);
if (curves.surface == nullptr || curves.surface->type != OB_MESH) {
CTX_wm_operator_poll_msg_set(C, "Curves must have a mesh surface object set");
return false;
}
}
return true;
}
bool editable_curves_with_surface_poll(bContext *C)
{
return curves_poll_impl(C, true, true);
}
bool curves_with_surface_poll(bContext *C)
{
return curves_poll_impl(C, false, true);
}
bool editable_curves_poll(bContext *C)
{
return curves_poll_impl(C, false, false);
}
bool curves_poll(bContext *C)
{
return curves_poll_impl(C, false, false);
}
using bke::CurvesGeometry;
namespace convert_to_particle_system {
@ -337,16 +378,6 @@ static int curves_convert_to_particle_system_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static bool curves_convert_to_particle_system_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == nullptr || ob->type != OB_CURVES) {
return false;
}
Curves &curves = *static_cast<Curves *>(ob->data);
return curves.surface != nullptr;
}
} // namespace convert_to_particle_system
static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot)
@ -355,7 +386,7 @@ static void CURVES_OT_convert_to_particle_system(wmOperatorType *ot)
ot->idname = "CURVES_OT_convert_to_particle_system";
ot->description = "Add a new or update an existing hair particle system on the surface object";
ot->poll = convert_to_particle_system::curves_convert_to_particle_system_poll;
ot->poll = curves_with_surface_poll;
ot->exec = convert_to_particle_system::curves_convert_to_particle_system_exec;
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
@ -501,22 +532,6 @@ enum class AttachMode {
Deform,
};
static bool snap_curves_to_surface_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == nullptr || ob->type != OB_CURVES) {
return false;
}
if (!ED_operator_object_active_editable_ex(C, ob)) {
return false;
}
Curves &curves = *static_cast<Curves *>(ob->data);
if (curves.surface == nullptr) {
return false;
}
return true;
}
static void snap_curves_to_surface_exec_object(Object &curves_ob,
const Object &surface_ob,
const AttachMode attach_mode,
@ -694,7 +709,7 @@ static void CURVES_OT_snap_curves_to_surface(wmOperatorType *ot)
ot->idname = "CURVES_OT_snap_curves_to_surface";
ot->description = "Move curves so that the first point is exactly on the surface mesh";
ot->poll = snap_curves_to_surface_poll;
ot->poll = editable_curves_with_surface_poll;
ot->exec = snap_curves_to_surface_exec;
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
@ -723,21 +738,6 @@ static void CURVES_OT_snap_curves_to_surface(wmOperatorType *ot)
"How to find the point on the surface to attach to");
}
bool selection_operator_poll(bContext *C)
{
const Object *object = CTX_data_active_object(C);
if (object == nullptr) {
return false;
}
if (object->type != OB_CURVES) {
return false;
}
if (!BKE_id_is_editable(CTX_data_main(C), static_cast<const ID *>(object->data))) {
return false;
}
return true;
}
namespace set_selection_domain {
static int curves_set_selection_domain_exec(bContext *C, wmOperator *op)
@ -791,7 +791,7 @@ static void CURVES_OT_set_selection_domain(wmOperatorType *ot)
ot->description = "Change the mode used for selection masking in curves sculpt mode";
ot->exec = set_selection_domain::curves_set_selection_domain_exec;
ot->poll = selection_operator_poll;
ot->poll = editable_curves_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -827,7 +827,7 @@ static void CURVES_OT_disable_selection(wmOperatorType *ot)
ot->description = "Disable the drawing of influence of selection in sculpt mode";
ot->exec = disable_selection::curves_disable_selection_exec;
ot->poll = selection_operator_poll;
ot->poll = editable_curves_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
@ -933,7 +933,7 @@ static void SCULPT_CURVES_OT_select_all(wmOperatorType *ot)
ot->description = "(De)select all control points";
ot->exec = select_all::select_all_exec;
ot->poll = selection_operator_poll;
ot->poll = editable_curves_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;

View File

@ -26,10 +26,14 @@ void ED_operatortypes_curves(void);
namespace blender::ed::curves {
bke::CurvesGeometry primitive_random_sphere(int curves_size, int points_per_curve);
bool selection_operator_poll(bContext *C);
bool has_anything_selected(const Curves &curves_id);
VectorSet<Curves *> get_unique_editable_curves(const bContext &C);
void ensure_surface_deformation_node_exists(bContext &C, Object &curves_ob);
bool editable_curves_with_surface_poll(bContext *C);
bool curves_with_surface_poll(bContext *C);
bool editable_curves_poll(bContext *C);
bool curves_poll(bContext *C);
} // namespace blender::ed::curves
#endif

View File

@ -269,18 +269,6 @@ static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
/** \name * CURVES_OT_sculptmode_toggle
* \{ */
static bool curves_sculptmode_toggle_poll(bContext *C)
{
const Object *ob = CTX_data_active_object(C);
if (ob == nullptr) {
return false;
}
if (ob->type != OB_CURVES) {
return false;
}
return true;
}
static void curves_sculptmode_enter(bContext *C)
{
Scene *scene = CTX_data_scene(C);
@ -342,7 +330,7 @@ static void CURVES_OT_sculptmode_toggle(wmOperatorType *ot)
ot->description = "Enter/Exit sculpt mode for curves";
ot->exec = curves_sculptmode_toggle_exec;
ot->poll = curves_sculptmode_toggle_poll;
ot->poll = curves::curves_poll;
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
}
@ -485,7 +473,7 @@ static void SCULPT_CURVES_OT_select_random(wmOperatorType *ot)
ot->description = "Randomizes existing selection or create new random selection";
ot->exec = select_random::select_random_exec;
ot->poll = curves::selection_operator_poll;
ot->poll = curves::editable_curves_poll;
ot->ui = select_random::select_random_ui;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -529,7 +517,7 @@ static void SCULPT_CURVES_OT_select_random(wmOperatorType *ot)
namespace select_end {
static bool select_end_poll(bContext *C)
{
if (!curves::selection_operator_poll(C)) {
if (!curves::editable_curves_poll(C)) {
return false;
}
const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
@ -911,7 +899,7 @@ static void SCULPT_CURVES_OT_select_grow(wmOperatorType *ot)
ot->invoke = select_grow::select_grow_invoke;
ot->modal = select_grow::select_grow_modal;
ot->poll = curves::selection_operator_poll;
ot->poll = curves::editable_curves_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@ -932,16 +920,7 @@ namespace min_distance_edit {
static bool min_distance_edit_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
if (ob == nullptr) {
return false;
}
if (ob->type != OB_CURVES) {
return false;
}
Curves *curves_id = static_cast<Curves *>(ob->data);
if (curves_id->surface == nullptr || curves_id->surface->type != OB_MESH) {
CTX_wm_operator_poll_msg_set(C, "Curves must have a mesh surface object set");
if (!curves::curves_with_surface_poll(C)) {
return false;
}
Scene *scene = CTX_data_scene(C);