Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / gizmo_library / gizmo_library_utils.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) 2015 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edgizmolib
22  *
23  * \name Gizmo Library Utilities
24  *
25  * \brief This file contains functions for common behaviors of gizmos.
26  */
27
28 #include "BLI_math.h"
29
30 #include "DNA_view3d_types.h"
31 #include "DNA_screen_types.h"
32
33 #include "BKE_context.h"
34
35 #include "RNA_access.h"
36
37 #include "WM_api.h"
38 #include "WM_types.h"
39
40 #include "ED_view3d.h"
41
42 /* own includes */
43 #include "gizmo_library_intern.h"
44
45 /* factor for precision tweaking */
46 #define GIZMO_PRECISION_FAC 0.05f
47
48 BLI_INLINE float gizmo_offset_from_value_constr(const float range_fac,
49                                                 const float min,
50                                                 const float range,
51                                                 const float value,
52                                                 const bool inverted)
53 {
54   return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range));
55 }
56
57 BLI_INLINE float gizmo_value_from_offset_constr(const float range_fac,
58                                                 const float min,
59                                                 const float range,
60                                                 const float value,
61                                                 const bool inverted)
62 {
63   return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac);
64 }
65
66 float gizmo_offset_from_value(GizmoCommonData *data,
67                               const float value,
68                               const bool constrained,
69                               const bool inverted)
70 {
71   if (constrained) {
72     return gizmo_offset_from_value_constr(
73         data->range_fac, data->min, data->range, value, inverted);
74   }
75
76   return value;
77 }
78
79 float gizmo_value_from_offset(GizmoCommonData *data,
80                               GizmoInteraction *inter,
81                               const float offset,
82                               const bool constrained,
83                               const bool inverted,
84                               const bool use_precision)
85 {
86   const float max = data->min + data->range;
87
88   if (use_precision) {
89     /* add delta offset of this step to total precision_offset */
90     inter->precision_offset += offset - inter->prev_offset;
91   }
92   inter->prev_offset = offset;
93
94   float ofs_new = inter->init_offset + offset -
95                   inter->precision_offset * (1.0f - GIZMO_PRECISION_FAC);
96   float value;
97
98   if (constrained) {
99     value = gizmo_value_from_offset_constr(
100         data->range_fac, data->min, data->range, ofs_new, inverted);
101   }
102   else {
103     value = ofs_new;
104   }
105
106   /* clamp to custom range */
107   if (data->is_custom_range_set) {
108     CLAMP(value, data->min, max);
109   }
110
111   return value;
112 }
113
114 void gizmo_property_data_update(wmGizmo *gz,
115                                 GizmoCommonData *data,
116                                 wmGizmoProperty *gz_prop,
117                                 const bool constrained,
118                                 const bool inverted)
119 {
120   if (gz_prop->custom_func.value_get_fn != NULL) {
121     /* pass  */
122   }
123   else if (gz_prop->prop != NULL) {
124     /* pass  */
125   }
126   else {
127     data->offset = 0.0f;
128     return;
129   }
130
131   float value = WM_gizmo_target_property_float_get(gz, gz_prop);
132
133   if (constrained) {
134     if (data->is_custom_range_set == false) {
135       float range[2];
136       if (WM_gizmo_target_property_float_range_get(gz, gz_prop, range)) {
137         data->range = range[1] - range[0];
138         data->min = range[0];
139       }
140       else {
141         BLI_assert(0);
142       }
143     }
144     data->offset = gizmo_offset_from_value_constr(
145         data->range_fac, data->min, data->range, value, inverted);
146   }
147   else {
148     data->offset = value;
149   }
150 }
151
152 void gizmo_property_value_reset(bContext *C,
153                                 const wmGizmo *gz,
154                                 GizmoInteraction *inter,
155                                 wmGizmoProperty *gz_prop)
156 {
157   WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init_value);
158 }
159
160 /* -------------------------------------------------------------------- */
161
162 void gizmo_color_get(const wmGizmo *gz, const bool highlight, float r_col[4])
163 {
164   if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) {
165     copy_v4_v4(r_col, gz->color_hi);
166   }
167   else {
168     copy_v4_v4(r_col, gz->color);
169   }
170 }
171
172 /* -------------------------------------------------------------------- */
173
174 /**
175  * Takes mouse coordinates and returns them in relation to the gizmo.
176  * Both 2D & 3D supported, use so we can use 2D gizmos in the 3D view.
177  */
178 bool gizmo_window_project_2d(bContext *C,
179                              const struct wmGizmo *gz,
180                              const float mval[2],
181                              int axis,
182                              bool use_offset,
183                              float r_co[2])
184 {
185   float mat[4][4];
186   {
187     float mat_identity[4][4];
188     struct WM_GizmoMatrixParams params = {NULL};
189     if (use_offset == false) {
190       unit_m4(mat_identity);
191       params.matrix_offset = mat_identity;
192     }
193     WM_gizmo_calc_matrix_final_params(gz, &params, mat);
194   }
195
196   /* rotate mouse in relation to the center and relocate it */
197   if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) {
198     /* For 3d views, transform 2D mouse pos onto plane. */
199     ARegion *ar = CTX_wm_region(C);
200
201     float plane[4], co[3];
202     plane_from_point_normal_v3(plane, mat[3], mat[2]);
203     bool clip_ray = ((RegionView3D *)ar->regiondata)->is_persp;
204     if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, clip_ray, co)) {
205       float imat[4][4];
206       invert_m4_m4(imat, mat);
207       mul_m4_v3(imat, co);
208       r_co[0] = co[(axis + 1) % 3];
209       r_co[1] = co[(axis + 2) % 3];
210       return true;
211     }
212     return false;
213   }
214   else {
215     float co[3] = {mval[0], mval[1], 0.0f};
216     float imat[4][4];
217     invert_m4_m4(imat, mat);
218     mul_m4_v3(imat, co);
219     copy_v2_v2(r_co, co);
220     return true;
221   }
222 }
223
224 bool gizmo_window_project_3d(
225     bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, 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 }