Blender V5.0
select_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cfloat>
10#include <cmath>
11#include <cstring>
12
13#include "BLI_kdtree.h"
14
15#include "BLT_translation.hh"
16
18
19#include "RNA_access.hh"
20
21#include "WM_types.hh"
22
23#include "ED_select_utils.hh"
24
25int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside)
26{
27 switch (sel_op) {
28 case SEL_OP_ADD:
29 return (!is_select && (is_inside)) ? 1 : -1;
30 case SEL_OP_SUB:
31 return (is_select && is_inside) ? 0 : -1;
32 case SEL_OP_SET:
33 return is_inside ? 1 : 0;
34 case SEL_OP_AND:
35 return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
36 case SEL_OP_XOR:
37 return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
38 }
39 BLI_assert_msg(0, "invalid sel_op");
40 return -1;
41}
43 const bool is_select,
44 const bool is_inside)
45{
46 switch (sel_op) {
47 case SEL_OP_ADD:
48 return (!is_select && is_inside) ? 1 : -1;
49 case SEL_OP_SUB:
50 return (is_select && is_inside) ? 0 : -1;
51 case SEL_OP_SET:
52 /* Only difference w/ function above. */
53 return is_inside ? 1 : -1;
54 case SEL_OP_AND:
55 return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
56 case SEL_OP_XOR:
57 return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
58 }
59 BLI_assert_msg(0, "invalid sel_op");
60 return -1;
61}
62
63eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
64{
65 if (sel_op == SEL_OP_SET) {
66 if (is_first == false) {
67 return SEL_OP_ADD;
68 }
69 }
70 return sel_op;
71}
72
73bool ED_select_similar_compare_float(const float delta,
74 const float thresh,
75 const eSimilarCmp compare)
76{
77 BLI_assert(thresh >= 0.0f);
78 switch (compare) {
79 case SIM_CMP_EQ:
80 return (fabsf(delta) <= thresh);
81 case SIM_CMP_GT:
82 return ((delta + thresh) >= 0.0f);
83 case SIM_CMP_LT:
84 return ((delta - thresh) <= 0.0f);
85 default:
87 return false;
88 }
89}
90
92 const float length,
93 const float thresh,
94 const eSimilarCmp compare)
95{
96 BLI_assert(compare == SIM_CMP_EQ || length >= 0.0f); /* See precision note below. */
97
98 /* Length of the edge we want to compare against. */
99 float nearest_edge_length;
100
101 switch (compare) {
102 case SIM_CMP_EQ:
103 /* Compare to the edge closest to the current edge. */
104 nearest_edge_length = length;
105 break;
106 case SIM_CMP_GT:
107 /* Compare against the shortest edge. */
108 /* -FLT_MAX leads to some precision issues and the wrong edge being selected.
109 * For example, in a tree with 1, 2 and 3, which is stored squared as 1, 4, 9,
110 * it returns as the nearest length/node the "4" instead of "1". */
111 nearest_edge_length = -1.0f;
112 break;
113 case SIM_CMP_LT:
114 /* Compare against the longest edge. */
115 nearest_edge_length = FLT_MAX;
116 break;
117 default:
119 return false;
120 }
121
122 KDTreeNearest_1d nearest;
123 if (BLI_kdtree_1d_find_nearest(tree, &nearest_edge_length, &nearest) != -1) {
124 BLI_assert(compare == SIM_CMP_EQ || nearest.co[0] >= 0.0f); /* See precision note above. */
125 float delta = length - nearest.co[0];
126 return ED_select_similar_compare_float(delta, thresh, compare);
127 }
128
129 return false;
130}
131
133{
134 const bool extend = RNA_boolean_get(ptr, "extend");
135 const bool deselect = RNA_boolean_get(ptr, "deselect");
136 const bool toggle = RNA_boolean_get(ptr, "toggle");
137
138 if (extend) {
139 return SEL_OP_ADD;
140 }
141 if (deselect) {
142 return SEL_OP_SUB;
143 }
144 if (toggle) {
145 return SEL_OP_XOR;
146 }
147 return SEL_OP_SET;
148}
149
151{
154 params.deselect_all = RNA_boolean_get(ptr, "deselect_all");
155 params.select_passthrough = RNA_boolean_get(ptr, "select_passthrough");
156 return params;
157}
158
159/* -------------------------------------------------------------------- */
162
164{
165 PropertyRNA *prop = RNA_struct_find_property(ptr, "enumerate");
166 const bool enumerate = (prop && RNA_property_boolean_get(ptr, prop));
167
169 switch (params.sel_op) {
170 case SEL_OP_ADD:
171 if (enumerate) {
172 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Extend (List)");
173 }
174 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Extend");
175 case SEL_OP_SUB:
176 if (enumerate) {
177 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Deselect (List)");
178 }
180 case SEL_OP_XOR:
181 if (enumerate) {
182 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Toggle (List)");
183 }
184 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select Toggle");
185 case SEL_OP_AND:
188 case SEL_OP_SET:
189 break;
190 }
191
192 if (enumerate) {
193 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Select (List)");
194 }
195
197}
198
200{
201 /* Matches options in #WM_operator_properties_select_operation_simple */
202 const eSelectOp sel_op = eSelectOp(RNA_enum_get(ptr, "mode"));
203 switch (sel_op) {
204 case SEL_OP_ADD:
205 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select (Extend)");
206 case SEL_OP_SUB:
207 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select (Deselect)");
208 case SEL_OP_XOR:
210 case SEL_OP_AND:
213 case SEL_OP_SET:
214 break;
215 }
216 return CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Circle Select");
217}
218
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define ATTR_FALLTHROUGH
A KD-tree for nearest neighbor search.
#define CTX_IFACE_(context, msgid)
#define BLT_I18NCONTEXT_OPERATOR_DEFAULT
eSelectOp
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
@ SEL_OP_AND
@ SEL_OP_XOR
eSimilarCmp
@ SIM_CMP_LT
@ SIM_CMP_GT
@ SIM_CMP_EQ
KDTree_3d * tree
static bool is_inside(int x, int y, int cols, int rows)
Definition filesel.cc:764
float length(VecOp< float, D >) RET
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define fabsf
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
bool ED_select_similar_compare_float(const float delta, const float thresh, const eSimilarCmp compare)
bool ED_select_similar_compare_float_tree(const KDTree_1d *tree, const float length, const float thresh, const eSimilarCmp compare)
std::string ED_select_pick_get_name(wmOperatorType *, PointerRNA *ptr)
int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside)
eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
eSelectOp ED_select_op_from_operator(PointerRNA *ptr)
int ED_select_op_action_deselected(const eSelectOp sel_op, const bool is_select, const bool is_inside)
SelectPick_Params ED_select_pick_params_from_operator(PointerRNA *ptr)
std::string ED_select_circle_get_name(wmOperatorType *, PointerRNA *ptr)
#define FLT_MAX
Definition stdcycles.h:14
PointerRNA * ptr
Definition wm_files.cc:4238