Merge branch 'blender-v2.91-release'
[blender.git] / source / blender / editors / curve / editcurve_query.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edcurve
22  */
23
24 #include "DNA_object_types.h"
25 #include "DNA_scene_types.h"
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_math.h"
30
31 #include "BKE_curve.h"
32 #include "BKE_fcurve.h"
33 #include "BKE_layer.h"
34
35 #include "DEG_depsgraph.h"
36 #include "DEG_depsgraph_build.h"
37
38 #include "ED_curve.h"
39 #include "ED_view3d.h"
40
41 #include "curve_intern.h"
42
43 /* -------------------------------------------------------------------- */
44 /** \name Cursor Picking API
45  * \{ */
46
47 static void ED_curve_pick_vert__do_closest(void *userData,
48                                            Nurb *nu,
49                                            BPoint *bp,
50                                            BezTriple *bezt,
51                                            int beztindex,
52                                            bool handles_visible,
53                                            const float screen_co[2])
54 {
55   struct {
56     BPoint *bp;
57     BezTriple *bezt;
58     Nurb *nurb;
59     float dist;
60     int hpoint, select;
61     float mval_fl[2];
62     bool is_changed;
63   } *data = userData;
64
65   uint8_t flag;
66   float dist_test;
67
68   if (bp) {
69     flag = bp->f1;
70   }
71   else {
72     BLI_assert(handles_visible || beztindex == 1);
73
74     if (beztindex == 0) {
75       flag = bezt->f1;
76     }
77     else if (beztindex == 1) {
78       flag = bezt->f2;
79     }
80     else {
81       flag = bezt->f3;
82     }
83   }
84
85   dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
86   if ((flag & SELECT) == data->select) {
87     dist_test += 5.0f;
88   }
89   if (bezt && beztindex == 1) {
90     dist_test += 3.0f; /* middle points get a small disadvantage */
91   }
92
93   if (dist_test < data->dist) {
94     data->dist = dist_test;
95
96     data->bp = bp;
97     data->bezt = bezt;
98     data->nurb = nu;
99     data->hpoint = bezt ? beztindex : 0;
100     data->is_changed = true;
101   }
102
103   UNUSED_VARS_NDEBUG(handles_visible);
104 }
105
106 bool ED_curve_pick_vert(ViewContext *vc,
107                         short sel,
108                         Nurb **r_nurb,
109                         BezTriple **r_bezt,
110                         BPoint **r_bp,
111                         short *r_handle,
112                         Base **r_base)
113 {
114   /* (sel == 1): selected gets a disadvantage */
115   /* in nurb and bezt or bp the nearest is written */
116   /* return 0 1 2: handlepunt */
117   struct {
118     BPoint *bp;
119     BezTriple *bezt;
120     Nurb *nurb;
121     float dist;
122     int hpoint, select;
123     float mval_fl[2];
124     bool is_changed;
125   } data = {NULL};
126
127   data.dist = ED_view3d_select_dist_px();
128   data.hpoint = 0;
129   data.select = sel;
130   data.mval_fl[0] = vc->mval[0];
131   data.mval_fl[1] = vc->mval[1];
132
133   uint bases_len;
134   Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
135       vc->view_layer, vc->v3d, &bases_len);
136   for (uint base_index = 0; base_index < bases_len; base_index++) {
137     Base *base = bases[base_index];
138     data.is_changed = false;
139
140     ED_view3d_viewcontext_init_object(vc, base->object);
141     ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
142     nurbs_foreachScreenVert(vc, ED_curve_pick_vert__do_closest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
143
144     if (r_base && data.is_changed) {
145       *r_base = base;
146     }
147   }
148   MEM_freeN(bases);
149
150   *r_nurb = data.nurb;
151   *r_bezt = data.bezt;
152   *r_bp = data.bp;
153
154   if (r_handle) {
155     *r_handle = data.hpoint;
156   }
157
158   return (data.bezt || data.bp);
159 }
160
161 /** \} */
162
163 /* -------------------------------------------------------------------- */
164 /** \name Selection Queries
165  * \{ */
166
167 void ED_curve_nurb_vert_selected_find(
168     Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp)
169 {
170   /* in nu and (bezt or bp) selected are written if there's 1 sel.  */
171   /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */
172   ListBase *editnurb = &cu->editnurb->nurbs;
173   Nurb *nu1;
174   BezTriple *bezt1;
175   BPoint *bp1;
176   int a;
177
178   *r_nu = NULL;
179   *r_bezt = NULL;
180   *r_bp = NULL;
181
182   for (nu1 = editnurb->first; nu1; nu1 = nu1->next) {
183     if (nu1->type == CU_BEZIER) {
184       bezt1 = nu1->bezt;
185       a = nu1->pntsu;
186       while (a--) {
187         if (BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt1)) {
188           if (*r_nu != NULL && *r_nu != nu1) {
189             *r_nu = NULL;
190             *r_bp = NULL;
191             *r_bezt = NULL;
192             return;
193           }
194
195           if (*r_bezt || *r_bp) {
196             *r_bp = NULL;
197             *r_bezt = NULL;
198           }
199           else {
200             *r_bezt = bezt1;
201             *r_nu = nu1;
202           }
203         }
204         bezt1++;
205       }
206     }
207     else {
208       bp1 = nu1->bp;
209       a = nu1->pntsu * nu1->pntsv;
210       while (a--) {
211         if (bp1->f1 & SELECT) {
212           if (*r_nu != NULL && *r_nu != nu1) {
213             *r_bp = NULL;
214             *r_bezt = NULL;
215             *r_nu = NULL;
216             return;
217           }
218
219           if (*r_bezt || *r_bp) {
220             *r_bp = NULL;
221             *r_bezt = NULL;
222           }
223           else {
224             *r_bp = bp1;
225             *r_nu = nu1;
226           }
227         }
228         bp1++;
229       }
230     }
231   }
232 }
233
234 bool ED_curve_active_center(Curve *cu, float center[3])
235 {
236   Nurb *nu = NULL;
237   void *vert = NULL;
238
239   if (!BKE_curve_nurb_vert_active_get(cu, &nu, &vert)) {
240     return false;
241   }
242
243   if (nu->type == CU_BEZIER) {
244     BezTriple *bezt = (BezTriple *)vert;
245     copy_v3_v3(center, bezt->vec[1]);
246   }
247   else {
248     BPoint *bp = (BPoint *)vert;
249     copy_v3_v3(center, bp->vec);
250   }
251
252   return true;
253 }
254
255 /** \} */