Welcome to mirror list, hosted at ThFree Co, Russian Federation.

select_utils.c « util « editors « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 263ef06718fed7b2948d2a98b9d02bbc20212873 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup edutil
 */

#include <float.h>

#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"

#include "DNA_windowmanager_types.h"

#include "RNA_access.h"

#include "WM_types.h"

#include "ED_select_utils.h"

int ED_select_op_action(const eSelectOp sel_op, const bool is_select, const bool is_inside)
{
  switch (sel_op) {
    case SEL_OP_ADD:
      return (!is_select && (is_inside)) ? 1 : -1;
    case SEL_OP_SUB:
      return (is_select && is_inside) ? 0 : -1;
    case SEL_OP_SET:
      return is_inside ? 1 : 0;
    case SEL_OP_AND:
      return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
    case SEL_OP_XOR:
      return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
  }
  BLI_assert_msg(0, "invalid sel_op");
  return -1;
}
int ED_select_op_action_deselected(const eSelectOp sel_op,
                                   const bool is_select,
                                   const bool is_inside)
{
  switch (sel_op) {
    case SEL_OP_ADD:
      return (!is_select && is_inside) ? 1 : -1;
    case SEL_OP_SUB:
      return (is_select && is_inside) ? 0 : -1;
    case SEL_OP_SET:
      /* Only difference w/ function above. */
      return is_inside ? 1 : -1;
    case SEL_OP_AND:
      return (is_select && is_inside) ? -1 : (is_select ? 0 : -1);
    case SEL_OP_XOR:
      return (is_select && is_inside) ? 0 : ((!is_select && is_inside) ? 1 : -1);
  }
  BLI_assert_msg(0, "invalid sel_op");
  return -1;
}

eSelectOp ED_select_op_modal(const eSelectOp sel_op, const bool is_first)
{
  if (sel_op == SEL_OP_SET) {
    if (is_first == false) {
      return SEL_OP_ADD;
    }
  }
  return sel_op;
}

int ED_select_similar_compare_float(const float delta, const float thresh, const int compare)
{
  switch (compare) {
    case SIM_CMP_EQ:
      return (fabsf(delta) <= thresh);
    case SIM_CMP_GT:
      return ((delta + thresh) >= 0.0);
    case SIM_CMP_LT:
      return ((delta - thresh) <= 0.0);
    default:
      BLI_assert_unreachable();
      return 0;
  }
}

bool ED_select_similar_compare_float_tree(const KDTree_1d *tree,
                                          const float length,
                                          const float thresh,
                                          const int compare)
{
  /* Length of the edge we want to compare against. */
  float nearest_edge_length;

  switch (compare) {
    case SIM_CMP_EQ:
      /* Compare to the edge closest to the current edge. */
      nearest_edge_length = length;
      break;
    case SIM_CMP_GT:
      /* Compare against the shortest edge. */
      /* -FLT_MAX leads to some precision issues and the wrong edge being selected.
       * For example, in a tree with 1, 2 and 3, which is stored squared as 1, 4, 9,
       * it returns as the nearest length/node the "4" instead of "1". */
      nearest_edge_length = -1.0f;
      break;
    case SIM_CMP_LT:
      /* Compare against the longest edge. */
      nearest_edge_length = FLT_MAX;
      break;
    default:
      BLI_assert_unreachable();
      return false;
  }

  KDTreeNearest_1d nearest;
  if (BLI_kdtree_1d_find_nearest(tree, &nearest_edge_length, &nearest) != -1) {
    float delta = length - nearest.co[0];
    return ED_select_similar_compare_float(delta, thresh, compare);
  }

  return false;
}

eSelectOp ED_select_op_from_operator(PointerRNA *ptr)
{
  const bool extend = RNA_boolean_get(ptr, "extend");
  const bool deselect = RNA_boolean_get(ptr, "deselect");
  const bool toggle = RNA_boolean_get(ptr, "toggle");

  if (extend) {
    return SEL_OP_ADD;
  }
  if (deselect) {
    return SEL_OP_SUB;
  }
  if (toggle) {
    return SEL_OP_XOR;
  }
  return SEL_OP_SET;
}

void ED_select_pick_params_from_operator(PointerRNA *ptr, struct SelectPick_Params *params)
{
  memset(params, 0x0, sizeof(*params));
  params->sel_op = ED_select_op_from_operator(ptr);
  params->deselect_all = RNA_boolean_get(ptr, "deselect_all");
  params->select_passthrough = RNA_boolean_get(ptr, "select_passthrough");
}

/* -------------------------------------------------------------------- */
/** \name Operator Naming Callbacks
 * \{ */

const char *ED_select_pick_get_name(wmOperatorType *UNUSED(ot), PointerRNA *ptr)
{
  struct SelectPick_Params params = {0};
  ED_select_pick_params_from_operator(ptr, &params);
  switch (params.sel_op) {
    case SEL_OP_ADD:
      return "Select (Extend)";
    case SEL_OP_SUB:
      return "Select (Deselect)";
    case SEL_OP_XOR:
      return "Select (Toggle)";
    case SEL_OP_AND:
      BLI_assert_unreachable();
      ATTR_FALLTHROUGH;
    case SEL_OP_SET:
      break;
  }
  return "Select";
}

const char *ED_select_circle_get_name(wmOperatorType *UNUSED(ot), PointerRNA *ptr)
{
  /* Matches options in #WM_operator_properties_select_operation_simple */
  const eSelectOp sel_op = RNA_enum_get(ptr, "mode");
  switch (sel_op) {
    case SEL_OP_ADD:
      return "Circle Select (Extend)";
    case SEL_OP_SUB:
      return "Circle Select (Deselect)";
    case SEL_OP_XOR:
      ATTR_FALLTHROUGH;
    case SEL_OP_AND:
      BLI_assert_unreachable();
      ATTR_FALLTHROUGH;
    case SEL_OP_SET:
      break;
  }
  return "Circle Select";
}

/** \} */