fix use of uninitialized variable
[blender.git] / source / blender / windowmanager / manipulators / intern / manipulator_library / primitive_manipulator.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/windowmanager/manipulators/intern/manipulator_library/primitive_manipulator.c
22  *  \ingroup wm
23  *
24  * \name Primitive Manipulator
25  *
26  * 3D Manipulator
27  *
28  * \brief Manipulator with primitive drawing type (plane, cube, etc.).
29  * Currently only plane primitive supported without own handling, use with operator only.
30  */
31
32 #include "BIF_gl.h"
33
34 #include "BKE_context.h"
35
36 #include "BLI_math.h"
37
38 #include "DNA_view3d_types.h"
39 #include "DNA_manipulator_types.h"
40
41 #include "GPU_immediate.h"
42 #include "GPU_matrix.h"
43 #include "GPU_select.h"
44
45 #include "MEM_guardedalloc.h"
46
47 #include "WM_api.h"
48 #include "WM_types.h"
49
50 /* own includes */
51 #include "WM_manipulator_types.h"
52 #include "WM_manipulator_library.h"
53 #include "wm_manipulator_wmapi.h"
54 #include "wm_manipulator_intern.h"
55 #include "manipulator_library_intern.h"
56
57
58 /* PrimitiveManipulator->flag */
59 enum {
60         PRIM_UP_VECTOR_SET = (1 << 0),
61 };
62
63 typedef struct PrimitiveManipulator {
64         wmManipulator manipulator;
65
66         float direction[3];
67         float up[3];
68         int style;
69         int flag;
70 } PrimitiveManipulator;
71
72
73 static float verts_plane[4][3] = {
74         {-1, -1, 0},
75         { 1, -1, 0},
76         { 1,  1, 0},
77         {-1,  1, 0},
78 };
79
80
81 /* -------------------------------------------------------------------- */
82
83 static void manipulator_primitive_draw_geom(
84         const float col_inner[4], const float col_outer[4], const int style)
85 {
86         float (*verts)[3];
87         unsigned int vert_count = 0;
88
89         if (style == MANIPULATOR_PRIMITIVE_STYLE_PLANE) {
90                 verts = verts_plane;
91                 vert_count = ARRAY_SIZE(verts_plane);
92         }
93
94         if (vert_count > 0) {
95                 unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
96                 immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
97                 wm_manipulator_vec_draw(col_inner, verts, vert_count, pos, PRIM_TRIANGLE_FAN);
98                 wm_manipulator_vec_draw(col_outer, verts, vert_count, pos, PRIM_LINE_LOOP);
99                 immUnbindProgram();
100         }
101 }
102
103 static void manipulator_primitive_draw_intern(
104         PrimitiveManipulator *prim, const bool UNUSED(select),
105         const bool highlight)
106 {
107         float col_inner[4], col_outer[4];
108         float rot[3][3];
109         float mat[4][4];
110
111         if (prim->flag & PRIM_UP_VECTOR_SET) {
112                 copy_v3_v3(rot[2], prim->direction);
113                 copy_v3_v3(rot[1], prim->up);
114                 cross_v3_v3v3(rot[0], prim->up, prim->direction);
115         }
116         else {
117                 const float up[3] = {0.0f, 0.0f, 1.0f};
118                 rotation_between_vecs_to_mat3(rot, up, prim->direction);
119         }
120
121         copy_m4_m3(mat, rot);
122         copy_v3_v3(mat[3], prim->manipulator.origin);
123         mul_mat3_m4_fl(mat, prim->manipulator.scale);
124
125         gpuPushMatrix();
126         gpuMultMatrix3D(mat);
127
128         manipulator_color_get(&prim->manipulator, highlight, col_outer);
129         copy_v4_v4(col_inner, col_outer);
130         col_inner[3] *= 0.5f;
131
132         glEnable(GL_BLEND);
133         gpuTranslate3fv(prim->manipulator.offset);
134         manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
135         glDisable(GL_BLEND);
136
137         gpuPopMatrix();
138
139         if (prim->manipulator.interaction_data) {
140                 ManipulatorInteraction *inter = prim->manipulator.interaction_data;
141
142                 copy_v4_fl(col_inner, 0.5f);
143                 copy_v3_fl(col_outer, 0.5f);
144                 col_outer[3] = 0.8f;
145
146                 copy_m4_m3(mat, rot);
147                 copy_v3_v3(mat[3], inter->init_origin);
148                 mul_mat3_m4_fl(mat, inter->init_scale);
149
150                 gpuPushMatrix();
151                 gpuMultMatrix3D(mat);
152
153                 glEnable(GL_BLEND);
154                 gpuTranslate3fv(prim->manipulator.offset);
155                 manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
156                 glDisable(GL_BLEND);
157
158                 gpuPopMatrix();
159         }
160 }
161
162 static void manipulator_primitive_render_3d_intersect(
163         const bContext *UNUSED(C), wmManipulator *manipulator,
164         int selectionbase)
165 {
166         GPU_select_load_id(selectionbase);
167         manipulator_primitive_draw_intern((PrimitiveManipulator *)manipulator, true, false);
168 }
169
170 static void manipulator_primitive_draw(const bContext *UNUSED(C), wmManipulator *manipulator)
171 {
172         manipulator_primitive_draw_intern(
173                     (PrimitiveManipulator *)manipulator, false,
174                     (manipulator->state & WM_MANIPULATOR_HIGHLIGHT));
175 }
176
177 static int manipulator_primitive_invoke(
178         bContext *UNUSED(C), const wmEvent *UNUSED(event), wmManipulator *manipulator)
179 {
180         ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
181
182         copy_v3_v3(inter->init_origin, manipulator->origin);
183         inter->init_scale = manipulator->scale;
184
185         manipulator->interaction_data = inter;
186
187         return OPERATOR_RUNNING_MODAL;
188 }
189
190
191 /* -------------------------------------------------------------------- */
192 /** \name Primitive Manipulator API
193  *
194  * \{ */
195
196 wmManipulator *MANIPULATOR_primitive_new(wmManipulatorGroup *mgroup, const char *name, const int style)
197 {
198         PrimitiveManipulator *prim = MEM_callocN(sizeof(PrimitiveManipulator), name);
199         const float dir_default[3] = {0.0f, 0.0f, 1.0f};
200
201         prim->manipulator.draw = manipulator_primitive_draw;
202         prim->manipulator.invoke = manipulator_primitive_invoke;
203         prim->manipulator.intersect = NULL;
204         prim->manipulator.render_3d_intersection = manipulator_primitive_render_3d_intersect;
205         prim->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
206         prim->style = style;
207
208         /* defaults */
209         copy_v3_v3(prim->direction, dir_default);
210
211         wm_manipulator_register(mgroup, &prim->manipulator, name);
212
213         return (wmManipulator *)prim;
214 }
215
216 /**
217  * Define direction the primitive will point towards
218  */
219 void MANIPULATOR_primitive_set_direction(wmManipulator *manipulator, const float direction[3])
220 {
221         PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
222
223         normalize_v3_v3(prim->direction, direction);
224 }
225
226 /**
227  * Define up-direction of the primitive manipulator
228  */
229 void MANIPULATOR_primitive_set_up_vector(wmManipulator *manipulator, const float direction[3])
230 {
231         PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
232
233         if (direction) {
234                 normalize_v3_v3(prim->up, direction);
235                 prim->flag |= PRIM_UP_VECTOR_SET;
236         }
237         else {
238                 prim->flag &= ~PRIM_UP_VECTOR_SET;
239         }
240 }
241
242 /** \} */ // Primitive Manipulator API
243
244
245 /* -------------------------------------------------------------------- */
246
247 void fix_linking_manipulator_primitive(void)
248 {
249         (void)0;
250 }