Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / object / object_modes.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  * Contributor(s): Blender Foundation, 2002-2008 full recode
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/editors/object/object_modes.c
24  *  \ingroup edobj
25  *
26  * General utils to handle mode switching,
27  * actual mode switching logic is per-object type.
28  */
29
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_workspace_types.h"
33
34 #include "BLI_utildefines.h"
35
36 #include "BKE_context.h"
37 #include "BKE_report.h"
38
39 #include "WM_api.h"
40 #include "WM_types.h"
41
42 #include "ED_object.h"
43
44 static const char *object_mode_op_string(eObjectMode mode)
45 {
46         if (mode & OB_MODE_EDIT)
47                 return "OBJECT_OT_editmode_toggle";
48         if (mode == OB_MODE_SCULPT)
49                 return "SCULPT_OT_sculptmode_toggle";
50         if (mode == OB_MODE_VERTEX_PAINT)
51                 return "PAINT_OT_vertex_paint_toggle";
52         if (mode == OB_MODE_WEIGHT_PAINT)
53                 return "PAINT_OT_weight_paint_toggle";
54         if (mode == OB_MODE_TEXTURE_PAINT)
55                 return "PAINT_OT_texture_paint_toggle";
56         if (mode == OB_MODE_PARTICLE_EDIT)
57                 return "PARTICLE_OT_particle_edit_toggle";
58         if (mode == OB_MODE_POSE)
59                 return "OBJECT_OT_posemode_toggle";
60         if (mode == OB_MODE_GPENCIL)
61                 return "GPENCIL_OT_editmode_toggle";
62         return NULL;
63 }
64
65 /**
66  * Checks the mode to be set is compatible with the object
67  * should be made into a generic function
68  */
69 bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
70 {
71         if (ob) {
72                 if (mode == OB_MODE_OBJECT)
73                         return true;
74                 else if (mode == OB_MODE_GPENCIL)
75                         return true; /* XXX: assume this is the case for now... */
76
77                 switch (ob->type) {
78                         case OB_MESH:
79                                 if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
80                                             OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
81                                 {
82                                         return true;
83                                 }
84                                 break;
85                         case OB_CURVE:
86                         case OB_SURF:
87                         case OB_FONT:
88                         case OB_MBALL:
89                                 if (mode & (OB_MODE_EDIT))
90                                         return true;
91                                 break;
92                         case OB_LATTICE:
93                                 if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
94                                         return true;
95                                 break;
96                         case OB_ARMATURE:
97                                 if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
98                                         return true;
99                                 break;
100                 }
101         }
102
103         return false;
104 }
105
106 /**
107  * Sets the mode to a compatible state (use before entering the mode).
108  *
109  * This is so each mode's exec function can call
110  */
111 bool ED_object_mode_compat_set(bContext *C, WorkSpace *workspace, eObjectMode mode, ReportList *reports)
112 {
113         bool ok;
114         if (!ELEM(workspace->object_mode, mode, OB_MODE_OBJECT)) {
115                 const char *opstring = object_mode_op_string(workspace->object_mode);
116
117                 WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
118                 ok = ELEM(workspace->object_mode, mode, OB_MODE_OBJECT);
119                 if (!ok) {
120                         wmOperatorType *ot = WM_operatortype_find(opstring, false);
121                         BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
122                 }
123         }
124         else {
125                 ok = true;
126         }
127
128         return ok;
129 }
130
131 void ED_object_mode_toggle(bContext *C, eObjectMode mode)
132 {
133         if (mode != OB_MODE_OBJECT) {
134                 const char *opstring = object_mode_op_string(mode);
135
136                 if (opstring) {
137                         WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
138                 }
139         }
140 }