42895a7530bb4fa7601e401a4f29badf14c0f0a8
[blender.git] / source / blender / editors / space_view3d / view3d_header.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) 2004-2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_view3d/view3d_header.c
28  *  \ingroup spview3d
29  */
30
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "DNA_scene_types.h"
36 #include "DNA_object_types.h"
37
38 #include "BLI_utildefines.h"
39
40 #include "BLT_translation.h"
41
42 #include "BKE_context.h"
43 #include "BKE_depsgraph.h"
44 #include "BKE_main.h"
45 #include "BKE_screen.h"
46 #include "BKE_editmesh.h"
47
48 #include "RNA_access.h"
49 #include "RNA_define.h"
50 #include "RNA_enum_types.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "ED_mesh.h"
56 #include "ED_util.h"
57 #include "ED_screen.h"
58
59 #include "UI_interface.h"
60 #include "UI_resources.h"
61
62 #include "view3d_intern.h"
63
64 static void do_view3d_header_buttons(bContext *C, void *arg, int event);
65
66 #define B_SEL_VERT  110
67 #define B_SEL_EDGE  111
68 #define B_SEL_FACE  112
69
70 /* XXX quickly ported across */
71 static void handle_view3d_lock(bContext *C)
72 {
73         Main *bmain = CTX_data_main(C);
74         Scene *scene = CTX_data_scene(C);
75         ScrArea *sa = CTX_wm_area(C);
76         View3D *v3d = CTX_wm_view3d(C);
77         
78         if (v3d != NULL && sa != NULL) {
79                 if (v3d->localvd == NULL && v3d->scenelock && sa->spacetype == SPACE_VIEW3D) {
80                         /* copy to scene */
81                         scene->lay = v3d->lay;
82                         scene->layact = v3d->layact;
83                         scene->camera = v3d->camera;
84
85                         /* not through notifier, listener don't have context
86                          * and non-open screens or spaces need to be updated too */
87                         BKE_screen_view3d_main_sync(&bmain->screen, scene);
88                         
89                         /* notifiers for scene update */
90                         WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
91                 }
92         }
93 }
94
95 /**
96  * layer code is on three levels actually:
97  * - here for operator
98  * - uiTemplateLayers in interface/ code for buttons
99  * - ED_view3d_scene_layer_set for RNA
100  */
101 static void view3d_layers_editmode_ensure(Scene *scene, View3D *v3d)
102 {
103         /* sanity check - when in editmode disallow switching the editmode layer off since its confusing
104          * an alternative would be to always draw the editmode object. */
105         if (scene->obedit && (scene->obedit->lay & v3d->lay) == 0) {
106                 int bit;
107                 for (bit = 0; bit < 32; bit++) {
108                         if (scene->obedit->lay & (1u << bit)) {
109                                 v3d->lay |= (1u << bit);
110                                 break;
111                         }
112                 }
113         }
114 }
115
116 static int view3d_layers_exec(bContext *C, wmOperator *op)
117 {
118         Scene *scene = CTX_data_scene(C);
119         ScrArea *sa = CTX_wm_area(C);
120         View3D *v3d = sa->spacedata.first;
121         int nr = RNA_int_get(op->ptr, "nr");
122         const bool toggle = RNA_boolean_get(op->ptr, "toggle");
123         
124         if (nr < 0)
125                 return OPERATOR_CANCELLED;
126
127         if (nr == 0) {
128                 /* all layers */
129                 if (!v3d->lay_prev)
130                         v3d->lay_prev = 1;
131
132                 if (toggle && v3d->lay == ((1 << 20) - 1)) {
133                         /* return to active layer only */
134                         v3d->lay = v3d->lay_prev;
135
136                         view3d_layers_editmode_ensure(scene, v3d);
137                 }
138                 else {
139                         v3d->lay_prev = v3d->lay;
140                         v3d->lay |= (1 << 20) - 1;
141                 }
142         }
143         else {
144                 int bit;
145                 nr--;
146
147                 if (RNA_boolean_get(op->ptr, "extend")) {
148                         if (toggle && v3d->lay & (1 << nr) && (v3d->lay & ~(1 << nr)))
149                                 v3d->lay &= ~(1 << nr);
150                         else
151                                 v3d->lay |= (1 << nr);
152                 }
153                 else {
154                         v3d->lay = (1 << nr);
155                 }
156
157                 view3d_layers_editmode_ensure(scene, v3d);
158
159                 /* set active layer, ensure to always have one */
160                 if (v3d->lay & (1 << nr))
161                         v3d->layact = 1 << nr;
162                 else if ((v3d->lay & v3d->layact) == 0) {
163                         for (bit = 0; bit < 32; bit++) {
164                                 if (v3d->lay & (1u << bit)) {
165                                         v3d->layact = (1u << bit);
166                                         break;
167                                 }
168                         }
169                 }
170         }
171         
172         if (v3d->scenelock) handle_view3d_lock(C);
173         
174         DAG_on_visible_update(CTX_data_main(C), false);
175
176         ED_area_tag_redraw(sa);
177         
178         return OPERATOR_FINISHED;
179 }
180
181 /* applies shift and alt, lazy coding or ok? :) */
182 /* the local per-keymap-entry keymap will solve it */
183 static int view3d_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
184 {
185         if (event->ctrl || event->oskey)
186                 return OPERATOR_PASS_THROUGH;
187         
188         if (event->shift)
189                 RNA_boolean_set(op->ptr, "extend", true);
190         else
191                 RNA_boolean_set(op->ptr, "extend", false);
192         
193         if (event->alt) {
194                 const int nr = RNA_int_get(op->ptr, "nr") + 10;
195                 RNA_int_set(op->ptr, "nr", nr);
196         }
197         view3d_layers_exec(C, op);
198         
199         return OPERATOR_FINISHED;
200 }
201
202 static int view3d_layers_poll(bContext *C)
203 {
204         return (ED_operator_view3d_active(C) && CTX_wm_view3d(C)->localvd == NULL);
205 }
206
207 void VIEW3D_OT_layers(wmOperatorType *ot)
208 {
209         /* identifiers */
210         ot->name = "Layers";
211         ot->description = "Toggle layer(s) visibility";
212         ot->idname = "VIEW3D_OT_layers";
213         
214         /* api callbacks */
215         ot->invoke = view3d_layers_invoke;
216         ot->exec = view3d_layers_exec;
217         ot->poll = view3d_layers_poll;
218         
219         /* flags */
220         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
221         
222         RNA_def_int(ot->srna, "nr", 1, 0, 20, "Number", "The layer number to set, zero for all layers", 0, 20);
223         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Add this layer to the current view layers");
224         RNA_def_boolean(ot->srna, "toggle", 1, "Toggle", "Toggle the layer");
225 }
226
227 static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event)
228 {
229         wmWindow *win = CTX_wm_window(C);
230         const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift;
231
232         /* watch it: if sa->win does not exist, check that when calling direct drawing routines */
233
234         switch (event) {
235                 case B_SEL_VERT:
236                         if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) {
237                                 ED_undo_push(C, "Selectmode Set: Vertex");
238                         }
239                         break;
240                 case B_SEL_EDGE:
241                         if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) {
242                                 ED_undo_push(C, "Selectmode Set: Edge");
243                         }
244                         break;
245                 case B_SEL_FACE:
246                         if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) {
247                                 ED_undo_push(C, "Selectmode Set: Face");
248                         }
249                         break;
250                 default:
251                         break;
252         }
253 }
254
255 void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C)
256 {
257         Object *obedit = CTX_data_edit_object(C);
258         uiBlock *block = uiLayoutGetBlock(layout);
259
260         UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
261
262         if (obedit && (obedit->type == OB_MESH)) {
263                 BMEditMesh *em = BKE_editmesh_from_object(obedit);
264                 uiLayout *row;
265
266                 row = uiLayoutRow(layout, true);
267                 block = uiLayoutGetBlock(row);
268                 uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL,
269                                  0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
270                                  TIP_("Vertex select - Shift-Click for multiple modes, Ctrl-Click contracts selection"));
271                 uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL,
272                                  0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
273                                  TIP_("Edge select - Shift-Click for multiple modes, Ctrl-Click expands/contracts selection"));
274                 uiDefIconButBitS(block, UI_BTYPE_TOGGLE, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL,
275                                  0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0,
276                                  TIP_("Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"));
277         }
278 }
279
280 void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
281 {
282         bScreen *screen = CTX_wm_screen(C);
283         ScrArea *sa = CTX_wm_area(C);
284         View3D *v3d = sa->spacedata.first;
285         Scene *scene = CTX_data_scene(C);
286         ToolSettings *ts = CTX_data_tool_settings(C);
287         PointerRNA v3dptr, toolsptr, sceneptr;
288         Object *ob = OBACT;
289         Object *obedit = CTX_data_edit_object(C);
290         uiBlock *block;
291         uiLayout *row;
292         bool is_paint = false;
293         int modeselect;
294         
295         RNA_pointer_create(&screen->id, &RNA_SpaceView3D, v3d, &v3dptr);
296         RNA_pointer_create(&scene->id, &RNA_ToolSettings, ts, &toolsptr);
297         RNA_pointer_create(&scene->id, &RNA_Scene, scene, &sceneptr);
298
299         block = uiLayoutGetBlock(layout);
300         UI_block_func_handle_set(block, do_view3d_header_buttons, NULL);
301
302         /* other buttons: */
303         UI_block_emboss_set(block, UI_EMBOSS);
304         
305         /* mode */
306         if (ob) {
307                 modeselect = ob->mode;
308                 is_paint = ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT);
309         }
310         else {
311                 modeselect = OB_MODE_OBJECT;
312         }
313
314         row = uiLayoutRow(layout, false);
315         {
316                 EnumPropertyItem *item = object_mode_items;
317                 const char *name = "";
318                 int icon = ICON_OBJECT_DATAMODE;
319
320                 while (item->identifier) {
321                         if (item->value == modeselect && item->identifier[0]) {
322                                 name = IFACE_(item->name);
323                                 icon = item->icon;
324                                 break;
325                         }
326                         item++;
327                 }
328
329                 uiItemMenuEnumO(row, C, "OBJECT_OT_mode_set", "mode", name, icon);
330         }
331
332         /* Draw type */
333         uiItemR(layout, &v3dptr, "viewport_shade", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
334
335         if (obedit == NULL && is_paint) {
336                 if (ob->mode & OB_MODE_ALL_PAINT) {
337                         /* Only for Weight Paint. makes no sense in other paint modes. */
338                         row = uiLayoutRow(layout, true);
339                         uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
340                 }
341
342                 /* Manipulators aren't used in paint modes */
343                 if (!ELEM(ob->mode, OB_MODE_SCULPT, OB_MODE_PARTICLE_EDIT)) {
344                         /* masks aren't used for sculpt and particle painting */
345                         PointerRNA meshptr;
346
347                         RNA_pointer_create(ob->data, &RNA_Mesh, ob->data, &meshptr);
348                         if (ob->mode & (OB_MODE_TEXTURE_PAINT | OB_MODE_VERTEX_PAINT)) {
349                                 uiItemR(layout, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
350                         }
351                         else {
352                                 row = uiLayoutRow(layout, true);
353                                 uiItemR(row, &meshptr, "use_paint_mask", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
354                                 uiItemR(row, &meshptr, "use_paint_mask_vertex", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
355                         }
356                 }
357         }
358         else {
359                 row = uiLayoutRow(layout, true);
360                 uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
361
362                 /* pose/object only however we want to allow in weight paint mode too
363                  * so don't be totally strict and just check not-editmode for now 
364                  * XXX We never get here when we are in Weight Paint mode
365                  */
366                 if (obedit == NULL) {
367                         uiItemR(row, &v3dptr, "use_pivot_point_align", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
368                 }
369
370                 /* Transform widget / manipulators */
371                 row = uiLayoutRow(layout, true);
372                 uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
373                 if (v3d->twflag & V3D_USE_MANIPULATOR) {
374                         uiItemR(row, &v3dptr, "transform_manipulators", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
375                 }
376                 uiItemR(row, &v3dptr, "transform_orientation", 0, "", ICON_NONE);
377         }
378
379         if (obedit == NULL && v3d->localvd == NULL) {
380                 unsigned int ob_lay = ob ? ob->lay : 0;
381
382                 /* Layers */
383                 uiTemplateLayers(layout, v3d->scenelock ? &sceneptr : &v3dptr, "layers", &v3dptr, "layers_used", ob_lay);
384
385                 /* Scene lock */
386                 uiItemR(layout, &v3dptr, "lock_camera_and_layers", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
387         }
388         
389         uiTemplateEditModeSelection(layout, C);
390 }