Object Mode: move logic to 'object_modes.c'
[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
33 #include "BLI_utildefines.h"
34
35 #include "BKE_context.h"
36 #include "BKE_report.h"
37
38 #include "WM_api.h"
39 #include "WM_types.h"
40
41 #include "ED_object.h"
42
43 static const char *object_mode_op_string(eObjectMode mode)
44 {
45         if (mode & OB_MODE_EDIT)
46                 return "OBJECT_OT_editmode_toggle";
47         if (mode == OB_MODE_SCULPT)
48                 return "SCULPT_OT_sculptmode_toggle";
49         if (mode == OB_MODE_VERTEX_PAINT)
50                 return "PAINT_OT_vertex_paint_toggle";
51         if (mode == OB_MODE_WEIGHT_PAINT)
52                 return "PAINT_OT_weight_paint_toggle";
53         if (mode == OB_MODE_TEXTURE_PAINT)
54                 return "PAINT_OT_texture_paint_toggle";
55         if (mode == OB_MODE_PARTICLE_EDIT)
56                 return "PARTICLE_OT_particle_edit_toggle";
57         if (mode == OB_MODE_POSE)
58                 return "OBJECT_OT_posemode_toggle";
59         if (mode == OB_MODE_GPENCIL)
60                 return "GPENCIL_OT_editmode_toggle";
61         return NULL;
62 }
63
64 /**
65  * Checks the mode to be set is compatible with the object
66  * should be made into a generic function
67  */
68 bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
69 {
70         if (ob) {
71                 if (mode == OB_MODE_OBJECT)
72                         return true;
73                 else if (mode == OB_MODE_GPENCIL)
74                         return true; /* XXX: assume this is the case for now... */
75
76                 switch (ob->type) {
77                         case OB_MESH:
78                                 if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
79                                             OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT))
80                                 {
81                                         return true;
82                                 }
83                                 break;
84                         case OB_CURVE:
85                         case OB_SURF:
86                         case OB_FONT:
87                         case OB_MBALL:
88                                 if (mode & (OB_MODE_EDIT))
89                                         return true;
90                                 break;
91                         case OB_LATTICE:
92                                 if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT))
93                                         return true;
94                                 break;
95                         case OB_ARMATURE:
96                                 if (mode & (OB_MODE_EDIT | OB_MODE_POSE))
97                                         return true;
98                                 break;
99                 }
100         }
101
102         return false;
103 }
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, Object *ob, eObjectMode mode, ReportList *reports)
112 {
113         bool ok;
114         if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
115                 const char *opstring = object_mode_op_string(ob->mode);
116                 WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
117                 ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
118                 if (!ok) {
119                         wmOperatorType *ot = WM_operatortype_find(opstring, false);
120                         BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
121                 }
122         }
123         else {
124                 ok = true;
125         }
126
127         return ok;
128 }
129
130 void ED_object_mode_toggle(bContext *C, eObjectMode mode)
131 {
132         if (mode != OB_MODE_OBJECT) {
133                 const char *opstring = object_mode_op_string(mode);
134                 if (opstring) {
135                         WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
136                 }
137         }
138 }