7d33a82568fb0191aaf2f7747e0c37bb349e3004
[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         float vert_count;
88         unsigned int pos = VertexFormat_add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
89
90         if (style == MANIPULATOR_PRIMITIVE_STYLE_PLANE) {
91                 verts = verts_plane;
92                 vert_count = ARRAY_SIZE(verts_plane);
93         }
94
95         immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
96         wm_manipulator_vec_draw(col_inner, verts, vert_count, pos, PRIM_TRIANGLE_FAN);
97         wm_manipulator_vec_draw(col_outer, verts, vert_count, pos, PRIM_LINE_LOOP);
98         immUnbindProgram();
99 }
100
101 static void manipulator_primitive_draw_intern(
102         PrimitiveManipulator *prim, const bool UNUSED(select),
103         const bool highlight)
104 {
105         float col_inner[4], col_outer[4];
106         float rot[3][3];
107         float mat[4][4];
108
109         if (prim->flag & PRIM_UP_VECTOR_SET) {
110                 copy_v3_v3(rot[2], prim->direction);
111                 copy_v3_v3(rot[1], prim->up);
112                 cross_v3_v3v3(rot[0], prim->up, prim->direction);
113         }
114         else {
115                 const float up[3] = {0.0f, 0.0f, 1.0f};
116                 rotation_between_vecs_to_mat3(rot, up, prim->direction);
117         }
118
119         copy_m4_m3(mat, rot);
120         copy_v3_v3(mat[3], prim->manipulator.origin);
121         mul_mat3_m4_fl(mat, prim->manipulator.scale);
122
123         gpuPushMatrix();
124         gpuMultMatrix3D(mat);
125
126         manipulator_color_get(&prim->manipulator, highlight, col_outer);
127         copy_v4_v4(col_inner, col_outer);
128         col_inner[3] *= 0.5f;
129
130         glEnable(GL_BLEND);
131         gpuTranslate3fv(prim->manipulator.offset);
132         manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
133         glDisable(GL_BLEND);
134
135         gpuPopMatrix();
136
137         if (prim->manipulator.interaction_data) {
138                 ManipulatorInteraction *inter = prim->manipulator.interaction_data;
139
140                 copy_v4_fl(col_inner, 0.5f);
141                 copy_v3_fl(col_outer, 0.5f);
142                 col_outer[3] = 0.8f;
143
144                 copy_m4_m3(mat, rot);
145                 copy_v3_v3(mat[3], inter->init_origin);
146                 mul_mat3_m4_fl(mat, inter->init_scale);
147
148                 gpuPushMatrix();
149                 gpuMultMatrix3D(mat);
150
151                 glEnable(GL_BLEND);
152                 gpuTranslate3fv(prim->manipulator.offset);
153                 manipulator_primitive_draw_geom(col_inner, col_outer, prim->style);
154                 glDisable(GL_BLEND);
155
156                 gpuPopMatrix();
157         }
158 }
159
160 static void manipulator_primitive_render_3d_intersect(
161         const bContext *UNUSED(C), wmManipulator *manipulator,
162         int selectionbase)
163 {
164         GPU_select_load_id(selectionbase);
165         manipulator_primitive_draw_intern((PrimitiveManipulator *)manipulator, true, false);
166 }
167
168 static void manipulator_primitive_draw(const bContext *UNUSED(C), wmManipulator *manipulator)
169 {
170         manipulator_primitive_draw_intern(
171                     (PrimitiveManipulator *)manipulator, false,
172                     (manipulator->state & WM_MANIPULATOR_HIGHLIGHT));
173 }
174
175 static int manipulator_primitive_invoke(
176         bContext *UNUSED(C), const wmEvent *UNUSED(event), wmManipulator *manipulator)
177 {
178         ManipulatorInteraction *inter = MEM_callocN(sizeof(ManipulatorInteraction), __func__);
179
180         copy_v3_v3(inter->init_origin, manipulator->origin);
181         inter->init_scale = manipulator->scale;
182
183         manipulator->interaction_data = inter;
184
185         return OPERATOR_RUNNING_MODAL;
186 }
187
188
189 /* -------------------------------------------------------------------- */
190 /** \name Primitive Manipulator API
191  *
192  * \{ */
193
194 wmManipulator *MANIPULATOR_primitive_new(wmManipulatorGroup *mgroup, const char *name, const int style)
195 {
196         PrimitiveManipulator *prim = MEM_callocN(sizeof(PrimitiveManipulator), name);
197         const float dir_default[3] = {0.0f, 0.0f, 1.0f};
198
199         prim->manipulator.draw = manipulator_primitive_draw;
200         prim->manipulator.invoke = manipulator_primitive_invoke;
201         prim->manipulator.intersect = NULL;
202         prim->manipulator.render_3d_intersection = manipulator_primitive_render_3d_intersect;
203         prim->manipulator.flag |= WM_MANIPULATOR_DRAW_ACTIVE;
204         prim->style = style;
205
206         /* defaults */
207         copy_v3_v3(prim->direction, dir_default);
208
209         wm_manipulator_register(mgroup, &prim->manipulator, name);
210
211         return (wmManipulator *)prim;
212 }
213
214 /**
215  * Define direction the primitive will point towards
216  */
217 void MANIPULATOR_primitive_set_direction(wmManipulator *manipulator, const float direction[3])
218 {
219         PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
220
221         normalize_v3_v3(prim->direction, direction);
222 }
223
224 /**
225  * Define up-direction of the primitive manipulator
226  */
227 void MANIPULATOR_primitive_set_up_vector(wmManipulator *manipulator, const float direction[3])
228 {
229         PrimitiveManipulator *prim = (PrimitiveManipulator *)manipulator;
230
231         if (direction) {
232                 normalize_v3_v3(prim->up, direction);
233                 prim->flag |= PRIM_UP_VECTOR_SET;
234         }
235         else {
236                 prim->flag &= ~PRIM_UP_VECTOR_SET;
237         }
238 }
239
240 /** \} */ // Primitive Manipulator API
241
242
243 /* -------------------------------------------------------------------- */
244
245 void fix_linking_manipulator_primitive(void)
246 {
247         (void)0;
248 }