Cleanup: rename gizmo access functions
[blender.git] / source / blender / editors / gizmo_library / gizmo_library_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2015 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): none yet.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file gizmo_library_utils.c
27  *  \ingroup wm
28  *
29  * \name Gizmo Library Utilities
30  *
31  * \brief This file contains functions for common behaviors of gizmos.
32  */
33
34 #include "BLI_math.h"
35 #include "BLI_listbase.h"
36
37 #include "DNA_view3d_types.h"
38 #include "DNA_screen_types.h"
39
40 #include "BKE_context.h"
41
42 #include "RNA_access.h"
43
44 #include "WM_api.h"
45 #include "WM_types.h"
46
47 #include "ED_view3d.h"
48
49 /* own includes */
50 #include "gizmo_library_intern.h"
51
52 /* factor for precision tweaking */
53 #define GIZMO_PRECISION_FAC 0.05f
54
55
56 BLI_INLINE float gizmo_offset_from_value_constr(
57         const float range_fac, const float min, const float range, const float value,
58         const bool inverted)
59 {
60         return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
61 }
62
63 BLI_INLINE float gizmo_value_from_offset_constr(
64         const float range_fac, const float min, const float range, const float value,
65         const bool inverted)
66 {
67         return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
68 }
69
70 float gizmo_offset_from_value(
71         GizmoCommonData *data, const float value, const bool constrained, const bool inverted)
72 {
73         if (constrained)
74                 return gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
75
76         return value;
77 }
78
79 float gizmo_value_from_offset(
80         GizmoCommonData *data, GizmoInteraction *inter, const float offset,
81         const bool constrained, const bool inverted, const bool use_precision)
82 {
83         const float max = data->min + data->range;
84
85         if (use_precision) {
86                 /* add delta offset of this step to total precision_offset */
87                 inter->precision_offset += offset - inter->prev_offset;
88         }
89         inter->prev_offset = offset;
90
91         float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - GIZMO_PRECISION_FAC);
92         float value;
93
94         if (constrained) {
95                 value = gizmo_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted);
96         }
97         else {
98                 value = ofs_new;
99         }
100
101         /* clamp to custom range */
102         if (data->flag & GIZMO_CUSTOM_RANGE_SET) {
103                 CLAMP(value, data->min, max);
104         }
105
106         return value;
107 }
108
109 void gizmo_property_data_update(
110         wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop,
111         const bool constrained, const bool inverted)
112 {
113         if (gz_prop->custom_func.value_get_fn != NULL) {
114                 /* pass  */
115         }
116         else if (gz_prop->prop != NULL) {
117                 /* pass  */
118         }
119         else {
120                 data->offset = 0.0f;
121                 return;
122         }
123
124         float value = WM_gizmo_target_property_float_get(gz, gz_prop);
125
126         if (constrained) {
127                 if ((data->flag & GIZMO_CUSTOM_RANGE_SET) == 0) {
128                         float range[2];
129                         if (WM_gizmo_target_property_range_get(gz, gz_prop, range)) {
130                                 data->range = range[1] - range[0];
131                                 data->min = range[0];
132                         }
133                         else {
134                                 BLI_assert(0);
135                         }
136                 }
137                 data->offset = gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted);
138         }
139         else {
140                 data->offset = value;
141         }
142 }
143
144 void gizmo_property_value_reset(
145         bContext *C, const wmGizmo *gz, GizmoInteraction *inter,
146         wmGizmoProperty *gz_prop)
147 {
148         WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init_value);
149 }
150
151 /* -------------------------------------------------------------------- */
152
153 void gizmo_color_get(
154         const wmGizmo *gz, const bool highlight,
155         float r_col[4])
156 {
157         if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) {
158                 copy_v4_v4(r_col, gz->color_hi);
159         }
160         else {
161                 copy_v4_v4(r_col, gz->color);
162         }
163 }
164
165 /* -------------------------------------------------------------------- */
166
167 /**
168  * Takes mouse coordinates and returns them in relation to the gizmo.
169  * Both 2D & 3D supported, use so we can use 2D gizmos in the 3D view.
170  */
171 bool gizmo_window_project_2d(
172         bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset,
173         float r_co[2])
174 {
175         float mat[4][4];
176         {
177                 float mat_identity[4][4];
178                 struct WM_GizmoMatrixParams params = {NULL};
179                 if (use_offset == false) {
180                         unit_m4(mat_identity);
181                         params.matrix_offset = mat_identity;
182                 }
183                 WM_gizmo_calc_matrix_final_params(gz, &params, mat);
184         }
185
186         /* rotate mouse in relation to the center and relocate it */
187         if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
188                 /* For 3d views, transform 2D mouse pos onto plane. */
189                 View3D *v3d = CTX_wm_view3d(C);
190                 ARegion *ar = CTX_wm_region(C);
191
192                 float plane[4];
193
194                 plane_from_point_normal_v3(plane, mat[3], mat[2]);
195
196                 float ray_origin[3], ray_direction[3];
197
198                 if (ED_view3d_win_to_ray(CTX_data_depsgraph(C), ar, v3d, mval, ray_origin, ray_direction, false)) {
199                         float lambda;
200                         if (isect_ray_plane_v3(ray_origin, ray_direction, plane, &lambda, true)) {
201                                 float co[3];
202                                 madd_v3_v3v3fl(co, ray_origin, ray_direction, lambda);
203                                 float imat[4][4];
204                                 invert_m4_m4(imat, mat);
205                                 mul_m4_v3(imat, co);
206                                 r_co[0] = co[(axis + 1) % 3];
207                                 r_co[1] = co[(axis + 2) % 3];
208                                 return true;
209                         }
210                 }
211                 return false;
212         }
213         else {
214                 float co[3] = {mval[0], mval[1], 0.0f};
215                 float imat[4][4];
216                 invert_m4_m4(imat, mat);
217                 mul_mat3_m4_v3(imat, co);
218                 copy_v2_v2(r_co, co);
219                 return true;
220         }
221 }
222
223 bool gizmo_window_project_3d(
224         bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset,
225         float r_co[3])
226 {
227         float mat[4][4];
228         {
229                 float mat_identity[4][4];
230                 struct WM_GizmoMatrixParams params = {NULL};
231                 if (use_offset == false) {
232                         unit_m4(mat_identity);
233                         params.matrix_offset = mat_identity;
234                 }
235                 WM_gizmo_calc_matrix_final_params(gz, &params, mat);
236         }
237
238         if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
239                 View3D *v3d = CTX_wm_view3d(C);
240                 ARegion *ar = CTX_wm_region(C);
241                 /* Note: we might want a custom reference point passed in,
242                  * instead of the gizmo center. */
243                 ED_view3d_win_to_3d(v3d, ar, mat[3], mval, r_co);
244                 invert_m4(mat);
245                 mul_m4_v3(mat, r_co);
246                 return true;
247         }
248         else {
249                 float co[3] = {mval[0], mval[1], 0.0f};
250                 float imat[4][4];
251                 invert_m4_m4(imat, mat);
252                 mul_m4_v3(imat, co);
253                 copy_v2_v2(r_co, co);
254                 return true;
255         }
256 }