Cleanup: split eyedropper into separate files
[blender.git] / source / blender / editors / interface / interface_eyedropper_driver.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) 2009 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/interface/interface_eyedropper_driver.c
27  *  \ingroup edinterface
28  *
29  * Eyedropper (Animation Driver Targets).
30  *
31  * Defines:
32  * - #UI_OT_eyedropper_driver
33  */
34
35 #include "MEM_guardedalloc.h"
36
37 #include "DNA_anim_types.h"
38 #include "DNA_screen_types.h"
39 #include "DNA_object_types.h"
40
41 #include "BLI_math_vector.h"
42
43 #include "BKE_context.h"
44 #include "BKE_animsys.h"
45 #include "BKE_depsgraph.h"
46
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49
50 #include "UI_interface.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "ED_keyframing.h"
56
57 #include "interface_intern.h"
58 #include "interface_eyedropper_intern.h"
59
60 typedef struct DriverDropper {
61         /* Destination property (i.e. where we'll add a driver) */
62         PointerRNA ptr;
63         PropertyRNA *prop;
64         int index;
65
66         // TODO: new target?
67 } DriverDropper;
68
69 static bool driverdropper_init(bContext *C, wmOperator *op)
70 {
71         DriverDropper *ddr;
72         uiBut *but;
73
74         op->customdata = ddr = MEM_callocN(sizeof(DriverDropper), "DriverDropper");
75
76         but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &ddr->index);
77
78         if ((ddr->ptr.data == NULL) ||
79             (ddr->prop == NULL) ||
80             (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
81             (RNA_property_animateable(&ddr->ptr, ddr->prop) == false) ||
82             (but->flag & UI_BUT_DRIVEN))
83         {
84                 return false;
85         }
86
87         return true;
88 }
89
90 static void driverdropper_exit(bContext *C, wmOperator *op)
91 {
92         WM_cursor_modal_restore(CTX_wm_window(C));
93
94         if (op->customdata) {
95                 MEM_freeN(op->customdata);
96                 op->customdata = NULL;
97         }
98 }
99
100 static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *event)
101 {
102         DriverDropper *ddr = (DriverDropper *)op->customdata;
103         uiBut *but = eyedropper_get_property_button_under_mouse(C, event);
104
105         short mapping_type = RNA_enum_get(op->ptr, "mapping_type");
106         short flag = 0;
107
108         /* we can only add a driver if we know what RNA property it corresponds to */
109         if (but == NULL) {
110                 return;
111         }
112         else {
113                 /* Get paths for src... */
114                 PointerRNA *target_ptr = &but->rnapoin;
115                 PropertyRNA *target_prop = but->rnaprop;
116                 int target_index = but->rnaindex;
117
118                 char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop);
119
120                 /* ... and destination */
121                 char *dst_path    = BKE_animdata_driver_path_hack(C, &ddr->ptr, ddr->prop, NULL);
122
123                 /* Now create driver(s) */
124                 if (target_path && dst_path) {
125                         int success = ANIM_add_driver_with_target(op->reports,
126                                                                   ddr->ptr.id.data, dst_path, ddr->index,
127                                                                   target_ptr->id.data, target_path, target_index,
128                                                                   flag, DRIVER_TYPE_PYTHON, mapping_type);
129
130                         if (success) {
131                                 /* send updates */
132                                 UI_context_update_anim_flag(C);
133                                 DAG_relations_tag_update(CTX_data_main(C));
134                                 DAG_id_tag_update(ddr->ptr.id.data, OB_RECALC_OB | OB_RECALC_DATA);
135                                 WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);  // XXX
136                         }
137                 }
138
139                 /* cleanup */
140                 if (target_path)
141                         MEM_freeN(target_path);
142                 if (dst_path)
143                         MEM_freeN(dst_path);
144         }
145 }
146
147 static void driverdropper_cancel(bContext *C, wmOperator *op)
148 {
149         driverdropper_exit(C, op);
150 }
151
152 /* main modal status check */
153 static int driverdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
154 {
155         /* handle modal keymap */
156         if (event->type == EVT_MODAL_MAP) {
157                 switch (event->val) {
158                         case EYE_MODAL_CANCEL:
159                                 driverdropper_cancel(C, op);
160                                 return OPERATOR_CANCELLED;
161
162                         case EYE_MODAL_SAMPLE_CONFIRM:
163                                 driverdropper_sample(C, op, event);
164                                 driverdropper_exit(C, op);
165
166                                 return OPERATOR_FINISHED;
167                 }
168         }
169
170         return OPERATOR_RUNNING_MODAL;
171 }
172
173 /* Modal Operator init */
174 static int driverdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
175 {
176         /* init */
177         if (driverdropper_init(C, op)) {
178                 WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
179
180                 /* add temp handler */
181                 WM_event_add_modal_handler(C, op);
182
183                 return OPERATOR_RUNNING_MODAL;
184         }
185         else {
186                 driverdropper_exit(C, op);
187                 return OPERATOR_CANCELLED;
188         }
189 }
190
191 /* Repeat operator */
192 static int driverdropper_exec(bContext *C, wmOperator *op)
193 {
194         /* init */
195         if (driverdropper_init(C, op)) {
196                 /* cleanup */
197                 driverdropper_exit(C, op);
198
199                 return OPERATOR_FINISHED;
200         }
201         else {
202                 return OPERATOR_CANCELLED;
203         }
204 }
205
206 static int driverdropper_poll(bContext *C)
207 {
208         if (!CTX_wm_window(C)) return 0;
209         else return 1;
210 }
211
212 void UI_OT_eyedropper_driver(wmOperatorType *ot)
213 {
214         /* identifiers */
215         ot->name = "Eyedropper Driver";
216         ot->idname = "UI_OT_eyedropper_driver";
217         ot->description = "Pick a property to use as a driver target";
218
219         /* api callbacks */
220         ot->invoke = driverdropper_invoke;
221         ot->modal = driverdropper_modal;
222         ot->cancel = driverdropper_cancel;
223         ot->exec = driverdropper_exec;
224         ot->poll = driverdropper_poll;
225
226         /* flags */
227         ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL | OPTYPE_UNDO;
228
229         /* properties */
230         RNA_def_enum(ot->srna, "mapping_type", prop_driver_create_mapping_types, 0,
231                      "Mapping Type", "Method used to match target and driven properties");
232 }