dfe06ec4e665c4f2d988a672f5f7ebabe49452dc
[blender.git] / source / blender / editors / space_view3d / view3d_manipulator_lamp.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/editors/space_view3d/view3d_manipulator_lamp.c
22  *  \ingroup spview3d
23  */
24
25
26 #include "BLI_blenlib.h"
27 #include "BLI_math.h"
28 #include "BLI_utildefines.h"
29
30 #include "BKE_context.h"
31 #include "BKE_object.h"
32
33 #include "DNA_object_types.h"
34 #include "DNA_lamp_types.h"
35
36 #include "ED_screen.h"
37 #include "ED_manipulator_library.h"
38
39 #include "UI_resources.h"
40
41 #include "MEM_guardedalloc.h"
42
43 #include "RNA_access.h"
44
45 #include "WM_api.h"
46 #include "WM_types.h"
47
48 #include "view3d_intern.h"  /* own include */
49
50 /* -------------------------------------------------------------------- */
51
52 /** \name Spot Lamp Manipulators
53  * \{ */
54
55 static bool WIDGETGROUP_lamp_spot_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
56 {
57         Object *ob = CTX_data_active_object(C);
58
59         if (ob && ob->type == OB_LAMP) {
60                 Lamp *la = ob->data;
61                 return (la->type == LA_SPOT);
62         }
63         return false;
64 }
65
66 static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
67 {
68         wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
69
70         wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
71         wmManipulator *mpr = wwrapper->manipulator;
72         RNA_enum_set(mpr->ptr, "draw_options",  ED_MANIPULATOR_ARROW_STYLE_INVERTED);
73
74         mgroup->customdata = wwrapper;
75
76         ED_manipulator_arrow3d_set_range_fac(mpr, 4.0f);
77
78         UI_GetThemeColor3fv(TH_MANIPULATOR_SECONDARY, mpr->color);
79 }
80
81 static void WIDGETGROUP_lamp_spot_refresh(const bContext *C, wmManipulatorGroup *mgroup)
82 {
83         wmManipulatorWrapper *wwrapper = mgroup->customdata;
84         wmManipulator *mpr = wwrapper->manipulator;
85         Object *ob = CTX_data_active_object(C);
86         Lamp *la = ob->data;
87         float dir[3];
88
89         negate_v3_v3(dir, ob->obmat[2]);
90
91         WM_manipulator_set_matrix_rotation_from_z_axis(mpr, dir);
92         WM_manipulator_set_matrix_location(mpr, ob->obmat[3]);
93
94         /* need to set property here for undo. TODO would prefer to do this in _init */
95         PointerRNA lamp_ptr;
96         const char *propname = "spot_size";
97         RNA_pointer_create(&la->id, &RNA_Lamp, la, &lamp_ptr);
98         WM_manipulator_target_property_def_rna(mpr, "offset", &lamp_ptr, propname, -1);
99 }
100
101 void VIEW3D_WGT_lamp_spot(wmManipulatorGroupType *wgt)
102 {
103         wgt->name = "Spot Lamp Widgets";
104         wgt->idname = "VIEW3D_WGT_lamp_spot";
105
106         wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
107                       WM_MANIPULATORGROUPTYPE_3D |
108                       WM_MANIPULATORGROUPTYPE_DEPTH_3D);
109
110         wgt->poll = WIDGETGROUP_lamp_spot_poll;
111         wgt->setup = WIDGETGROUP_lamp_spot_setup;
112         wgt->refresh = WIDGETGROUP_lamp_spot_refresh;
113 }
114
115 /** \} */
116
117 /* -------------------------------------------------------------------- */
118
119 /** \name Area Lamp Manipulators
120  * \{ */
121
122 /* translate callbacks */
123 static void manipulator_area_lamp_prop_size_get(
124         const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
125         void *value_p)
126 {
127         float *value = value_p;
128         BLI_assert(mpr_prop->type->array_length == 2);
129         Lamp *la = mpr_prop->custom_func.user_data;
130
131         value[0] = la->area_size;
132         value[1] = (la->area_shape == LA_AREA_RECT) ? la->area_sizey : la->area_size;
133 }
134
135 static void manipulator_area_lamp_prop_size_set(
136         const wmManipulator *UNUSED(mpr), wmManipulatorProperty *mpr_prop,
137         const void *value_p)
138 {
139         const float *value = value_p;
140
141         BLI_assert(mpr_prop->type->array_length == 2);
142         Lamp *la = mpr_prop->custom_func.user_data;
143         if (la->area_shape == LA_AREA_RECT) {
144                 la->area_size = value[0];
145                 la->area_sizey = value[1];
146         }
147         else {
148                 la->area_size = value[0];
149         }
150 }
151
152 static void manipulator_area_lamp_prop_size_range(
153         const wmManipulator *UNUSED(mpr), wmManipulatorProperty *UNUSED(mpr_prop),
154         void *value_p)
155 {
156         float *value = value_p;
157         value[0] = 0.0f;
158         value[1] =  FLT_MAX;
159 }
160
161 static bool WIDGETGROUP_lamp_area_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
162 {
163         Object *ob = CTX_data_active_object(C);
164
165         if (ob && ob->type == OB_LAMP) {
166                 Lamp *la = ob->data;
167                 return (la->type == LA_AREA);
168         }
169         return false;
170 }
171
172 static void WIDGETGROUP_lamp_area_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
173 {
174         wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
175         wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_cage_2d", mgroup, NULL);
176         wmManipulator *mpr = wwrapper->manipulator;
177         RNA_enum_set(mpr->ptr, "transform",
178                      ED_MANIPULATOR_RECT_TRANSFORM_FLAG_SCALE);
179
180         mgroup->customdata = wwrapper;
181
182         WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_HOVER, true);
183
184         UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
185         UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
186 }
187
188 static void WIDGETGROUP_lamp_area_refresh(const bContext *C, wmManipulatorGroup *mgroup)
189 {
190         wmManipulatorWrapper *wwrapper = mgroup->customdata;
191         Object *ob = CTX_data_active_object(C);
192         Lamp *la = ob->data;
193         wmManipulator *mpr = wwrapper->manipulator;
194
195         copy_m4_m4(mpr->matrix_basis, ob->obmat);
196
197         RNA_enum_set(mpr->ptr, "transform",
198                      ED_MANIPULATOR_RECT_TRANSFORM_FLAG_SCALE |
199                      ((la->area_shape == LA_AREA_SQUARE) ? ED_MANIPULATOR_RECT_TRANSFORM_FLAG_SCALE_UNIFORM : 0));
200
201         /* need to set property here for undo. TODO would prefer to do this in _init */
202         WM_manipulator_target_property_def_func(
203                 mpr, "scale",
204                 &(const struct wmManipulatorPropertyFnParams) {
205                     .value_get_fn = manipulator_area_lamp_prop_size_get,
206                     .value_set_fn = manipulator_area_lamp_prop_size_set,
207                     .range_get_fn = manipulator_area_lamp_prop_size_range,
208                     .user_data = la,
209                 });
210 }
211
212 void VIEW3D_WGT_lamp_area(wmManipulatorGroupType *wgt)
213 {
214         wgt->name = "Area Lamp Widgets";
215         wgt->idname = "VIEW3D_WGT_lamp_area";
216
217         wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
218                       WM_MANIPULATORGROUPTYPE_3D |
219                       WM_MANIPULATORGROUPTYPE_DEPTH_3D);
220
221         wgt->poll = WIDGETGROUP_lamp_area_poll;
222         wgt->setup = WIDGETGROUP_lamp_area_setup;
223         wgt->refresh = WIDGETGROUP_lamp_area_refresh;
224 }
225
226 /** \} */
227
228
229 /* -------------------------------------------------------------------- */
230
231 /** \name Lamp Target Manipulator
232  * \{ */
233
234 static bool WIDGETGROUP_lamp_target_poll(const bContext *C, wmManipulatorGroupType *UNUSED(wgt))
235 {
236         Object *ob = CTX_data_active_object(C);
237
238         if (ob != NULL) {
239                 if (ob->type == OB_LAMP) {
240                         Lamp *la = ob->data;
241                         return (ELEM(la->type, LA_SUN, LA_SPOT, LA_HEMI, LA_AREA));
242                 }
243 #if 0
244                 else if (ob->type == OB_CAMERA) {
245                         return true;
246                 }
247 #endif
248         }
249         return false;
250 }
251
252 static void WIDGETGROUP_lamp_target_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
253 {
254         wmManipulatorWrapper *wwrapper = MEM_mallocN(sizeof(wmManipulatorWrapper), __func__);
255         wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_grab_3d", mgroup, NULL);
256         wmManipulator *mpr = wwrapper->manipulator;
257
258         mgroup->customdata = wwrapper;
259
260         UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
261         UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
262
263         mpr->scale_basis = 0.05f;
264
265         wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_transform_axis_target", true);
266         WM_manipulator_set_operator(mpr, ot, NULL);
267 }
268
269 static void WIDGETGROUP_lamp_target_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
270 {
271         wmManipulatorWrapper *wwrapper = mgroup->customdata;
272         Object *ob = CTX_data_active_object(C);
273         wmManipulator *mpr = wwrapper->manipulator;
274
275         copy_m4_m4(mpr->matrix_basis, ob->obmat);
276         unit_m4(mpr->matrix_offset);
277         mpr->matrix_offset[3][2] = -2.4f / mpr->scale_basis;
278         WM_manipulator_set_flag(mpr, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
279 }
280
281 void VIEW3D_WGT_lamp_target(wmManipulatorGroupType *wgt)
282 {
283         wgt->name = "Target Lamp Widgets";
284         wgt->idname = "VIEW3D_WGT_lamp_target";
285
286         wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
287                       WM_MANIPULATORGROUPTYPE_3D);
288
289         wgt->poll = WIDGETGROUP_lamp_target_poll;
290         wgt->setup = WIDGETGROUP_lamp_target_setup;
291         wgt->draw_prepare = WIDGETGROUP_lamp_target_draw_prepare;
292 }
293
294 /** \} */