Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / interface / interface_ops.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_ops.c
27  *  \ingroup edinterface
28  */
29
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_screen_types.h"
35 #include "DNA_text_types.h" /* for UI_OT_reports_to_text */
36 #include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
37
38 #include "BLI_blenlib.h"
39 #include "BLI_math_color.h"
40
41 #include "BLF_api.h"
42 #include "BLT_lang.h"
43
44 #include "BKE_context.h"
45 #include "BKE_idprop.h"
46 #include "BKE_layer.h"
47 #include "BKE_screen.h"
48 #include "BKE_global.h"
49 #include "BKE_library_override.h"
50 #include "BKE_node.h"
51 #include "BKE_text.h" /* for UI_OT_reports_to_text */
52 #include "BKE_report.h"
53
54 #include "DEG_depsgraph.h"
55
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58 #include "RNA_types.h"
59
60 #include "UI_interface.h"
61
62 #include "interface_intern.h"
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "ED_paint.h"
68
69 /* only for UI_OT_editsource */
70 #include "ED_screen.h"
71 #include "BKE_main.h"
72 #include "BLI_ghash.h"
73
74 /* Reset Default Theme ------------------------ */
75
76 static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
77 {
78         ui_theme_init_default();
79         ui_style_init_default();
80         WM_event_add_notifier(C, NC_WINDOW, NULL);
81         
82         return OPERATOR_FINISHED;
83 }
84
85 static void UI_OT_reset_default_theme(wmOperatorType *ot)
86 {
87         /* identifiers */
88         ot->name = "Reset to Default Theme";
89         ot->idname = "UI_OT_reset_default_theme";
90         ot->description = "Reset to the default theme colors";
91         
92         /* callbacks */
93         ot->exec = reset_default_theme_exec;
94         
95         /* flags */
96         ot->flag = OPTYPE_REGISTER;
97 }
98
99 /* Copy Data Path Operator ------------------------ */
100
101 static int copy_data_path_button_poll(bContext *C)
102 {
103         PointerRNA ptr;
104         PropertyRNA *prop;
105         char *path;
106         int index;
107
108         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
109
110         if (ptr.id.data && ptr.data && prop) {
111                 path = RNA_path_from_ID_to_property(&ptr, prop);
112                 
113                 if (path) {
114                         MEM_freeN(path);
115                         return 1;
116                 }
117         }
118
119         return 0;
120 }
121
122 static int copy_data_path_button_exec(bContext *C, wmOperator *op)
123 {
124         PointerRNA ptr;
125         PropertyRNA *prop;
126         char *path;
127         int index;
128
129         const bool full_path = RNA_boolean_get(op->ptr, "full_path");
130
131         /* try to create driver using property retrieved from UI */
132         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
133
134         if (ptr.id.data != NULL) {
135
136                 if (full_path) {
137
138                         if (prop) {
139                                 path = RNA_path_full_property_py_ex(&ptr, prop, index, true);
140                         }
141                         else {
142                                 path = RNA_path_full_struct_py(&ptr);
143                         }
144                 }
145                 else {
146                         path = RNA_path_from_ID_to_property(&ptr, prop);
147                 }
148
149                 if (path) {
150                         WM_clipboard_text_set(path, false);
151                         MEM_freeN(path);
152                         return OPERATOR_FINISHED;
153                 }
154         }
155
156         return OPERATOR_CANCELLED;
157 }
158
159 static void UI_OT_copy_data_path_button(wmOperatorType *ot)
160 {
161         PropertyRNA *prop;
162
163         /* identifiers */
164         ot->name = "Copy Data Path";
165         ot->idname = "UI_OT_copy_data_path_button";
166         ot->description = "Copy the RNA data path for this property to the clipboard";
167
168         /* callbacks */
169         ot->exec = copy_data_path_button_exec;
170         ot->poll = copy_data_path_button_poll;
171
172         /* flags */
173         ot->flag = OPTYPE_REGISTER;
174
175         /* properties */
176         prop = RNA_def_boolean(ot->srna, "full_path", false, "full_path", "Copy full data path");
177         RNA_def_property_flag(prop, PROP_SKIP_SAVE);
178 }
179
180 static int copy_python_command_button_poll(bContext *C)
181 {
182         uiBut *but = UI_context_active_but_get(C);
183
184         if (but && (but->optype != NULL)) {
185                 return 1;
186         }
187
188         return 0;
189 }
190
191 static int copy_python_command_button_exec(bContext *C, wmOperator *UNUSED(op))
192 {
193         uiBut *but = UI_context_active_but_get(C);
194
195         if (but && (but->optype != NULL)) {
196                 PointerRNA *opptr;
197                 char *str;
198                 opptr = UI_but_operator_ptr_get(but); /* allocated when needed, the button owns it */
199
200                 str = WM_operator_pystring_ex(C, NULL, false, true, but->optype, opptr);
201
202                 WM_clipboard_text_set(str, 0);
203
204                 MEM_freeN(str);
205
206                 return OPERATOR_FINISHED;
207         }
208
209         return OPERATOR_CANCELLED;
210 }
211
212 static void UI_OT_copy_python_command_button(wmOperatorType *ot)
213 {
214         /* identifiers */
215         ot->name = "Copy Python Command";
216         ot->idname = "UI_OT_copy_python_command_button";
217         ot->description = "Copy the Python command matching this button";
218
219         /* callbacks */
220         ot->exec = copy_python_command_button_exec;
221         ot->poll = copy_python_command_button_poll;
222
223         /* flags */
224         ot->flag = OPTYPE_REGISTER;
225 }
226
227 /* Reset to Default Values Button Operator ------------------------ */
228
229 static int operator_button_property_finish(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
230 {
231         ID *id = ptr->id.data;
232
233         /* perform updates required for this property */
234         RNA_property_update(C, ptr, prop);
235
236         /* as if we pressed the button */
237         UI_context_active_but_prop_handle(C);
238
239         /* Since we don't want to undo _all_ edits to settings, eg window
240          * edits on the screen or on operator settings.
241          * it might be better to move undo's inline - campbell */
242         if (id && ID_CHECK_UNDO(id)) {
243                 /* do nothing, go ahead with undo */
244                 return OPERATOR_FINISHED;
245         }
246         else {
247                 return OPERATOR_CANCELLED;
248         }
249 }
250
251 static int reset_default_button_poll(bContext *C)
252 {
253         PointerRNA ptr;
254         PropertyRNA *prop;
255         int index;
256
257         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
258         
259         return (ptr.data && prop && RNA_property_editable(&ptr, prop));
260 }
261
262 static int reset_default_button_exec(bContext *C, wmOperator *op)
263 {
264         PointerRNA ptr;
265         PropertyRNA *prop;
266         int index;
267         const bool all = RNA_boolean_get(op->ptr, "all");
268
269         /* try to reset the nominated setting to its default value */
270         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
271         
272         /* if there is a valid property that is editable... */
273         if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
274                 if (RNA_property_reset(&ptr, prop, (all) ? -1 : index))
275                         return operator_button_property_finish(C, &ptr, prop);
276         }
277
278         return OPERATOR_CANCELLED;
279 }
280
281 static void UI_OT_reset_default_button(wmOperatorType *ot)
282 {
283         /* identifiers */
284         ot->name = "Reset to Default Value";
285         ot->idname = "UI_OT_reset_default_button";
286         ot->description = "Reset this property's value to its default value";
287
288         /* callbacks */
289         ot->poll = reset_default_button_poll;
290         ot->exec = reset_default_button_exec;
291
292         /* flags */
293         ot->flag = OPTYPE_UNDO;
294         
295         /* properties */
296         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
297 }
298
299 /* Unset Property Button Operator ------------------------ */
300
301 static int unset_property_button_exec(bContext *C, wmOperator *UNUSED(op))
302 {
303         PointerRNA ptr;
304         PropertyRNA *prop;
305         int index;
306
307         /* try to unset the nominated property */
308         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
309
310         /* if there is a valid property that is editable... */
311         if (ptr.data && prop && RNA_property_editable(&ptr, prop) &&
312             /* RNA_property_is_idprop(prop) && */
313             RNA_property_is_set(&ptr, prop))
314         {
315                 RNA_property_unset(&ptr, prop);
316                 return operator_button_property_finish(C, &ptr, prop);
317         }
318
319         return OPERATOR_CANCELLED;
320 }
321
322 static void UI_OT_unset_property_button(wmOperatorType *ot)
323 {
324         /* identifiers */
325         ot->name = "Unset property";
326         ot->idname = "UI_OT_unset_property_button";
327         ot->description = "Clear the property and use default or generated value in operators";
328
329         /* callbacks */
330         ot->poll = ED_operator_regionactive;
331         ot->exec = unset_property_button_exec;
332
333         /* flags */
334         ot->flag = OPTYPE_UNDO;
335 }
336
337 /* Use/Unuse Property Button Operator ------------------------ */
338
339 static int use_property_button_exec(bContext *C, wmOperator *UNUSED(op))
340 {
341         PointerRNA ptr, scene_props_ptr;
342         PropertyRNA *prop;
343         IDProperty *props;
344
345         uiBut *but = UI_context_active_but_get(C);
346
347         prop = but->rnaprop;
348         ptr = but->rnapoin;
349         props = (IDProperty *)ptr.data;
350         /* XXX Using existing data struct to pass another RNAPointer */
351         scene_props_ptr = but->rnasearchpoin;
352
353         const char *identifier = RNA_property_identifier(prop);
354         if (IDP_GetPropertyFromGroup(props, identifier)) {
355                 return OPERATOR_CANCELLED;
356         }
357
358         int array_len = RNA_property_array_length(&scene_props_ptr, prop);
359         bool is_array = array_len != 0;
360
361         switch (RNA_property_type(prop)) {
362                 case PROP_FLOAT:
363                 {
364                         if (is_array) {
365                                 float values[RNA_MAX_ARRAY_LENGTH];
366                                 RNA_property_float_get_array(&scene_props_ptr, prop, values);
367                                 BKE_collection_engine_property_add_float_array(props, identifier, values, array_len);
368                         }
369                         else {
370                                 float value = RNA_property_float_get(&scene_props_ptr, prop);
371                                 BKE_collection_engine_property_add_float(props, identifier, value);
372                         }
373                         break;
374                 }
375                 case PROP_ENUM:
376                 {
377                         int value = RNA_enum_get(&scene_props_ptr, identifier);
378                         BKE_collection_engine_property_add_int(props, identifier, value);
379                         break;
380                 }
381                 case PROP_INT:
382                 {
383                         int value = RNA_int_get(&scene_props_ptr, identifier);
384                         BKE_collection_engine_property_add_int(props, identifier, value);
385                         break;
386                 }
387                 case PROP_BOOLEAN:
388                 {
389                         int value = RNA_boolean_get(&scene_props_ptr, identifier);
390                         BKE_collection_engine_property_add_bool(props, identifier, value);
391                         break;
392                 }
393                 case PROP_STRING:
394                 case PROP_POINTER:
395                 case PROP_COLLECTION:
396                 default:
397                         break;
398         }
399
400         /* TODO(sergey): Use proper flag for tagging here. */
401         DEG_id_tag_update((ID *)CTX_data_scene(C), 0);
402
403         return OPERATOR_FINISHED;
404 }
405
406 static void UI_OT_use_property_button(wmOperatorType *ot)
407 {
408         /* identifiers */
409         ot->name = "Use property";
410         ot->idname = "UI_OT_use_property_button";
411         ot->description = "Create a property";
412
413         /* callbacks */
414         ot->poll = ED_operator_regionactive;
415         ot->exec = use_property_button_exec;
416
417         /* flags */
418         ot->flag = OPTYPE_UNDO;
419 }
420
421 static int unuse_property_button_exec(bContext *C, wmOperator *UNUSED(op))
422 {
423         PointerRNA ptr;
424         PropertyRNA *prop;
425         int index;
426
427         /* try to unset the nominated property */
428         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
429         const char *identifier = RNA_property_identifier(prop);
430
431         IDProperty *props = (IDProperty *)ptr.data;
432         IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier);
433         IDP_FreeFromGroup(props, prop_to_remove);
434
435         /* TODO(sergey): Use proper flag for tagging here. */
436         DEG_id_tag_update((ID *)CTX_data_scene(C), 0);
437
438         return OPERATOR_FINISHED;
439 }
440
441 static void UI_OT_unuse_property_button(wmOperatorType *ot)
442 {
443         /* identifiers */
444         ot->name = "Unuse property";
445         ot->idname = "UI_OT_unuse_property_button";
446         ot->description = "Remove a property";
447
448         /* callbacks */
449         ot->poll = ED_operator_regionactive;
450         ot->exec = unuse_property_button_exec;
451
452         /* flags */
453         ot->flag = OPTYPE_UNDO;
454 }
455
456
457
458
459
460 /* Note that we use different values for UI/UX than 'real' override operations, user does not care
461  * whether it's added or removed for the differential operation e.g. */
462 enum {
463         UIOverride_Type_NOOP = 0,
464         UIOverride_Type_Replace = 1,
465         UIOverride_Type_Difference = 2,  /* Add/subtract */
466         UIOverride_Type_Factor = 3,  /* Multiply */
467         /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
468 };
469
470 static EnumPropertyItem override_type_items[] = {
471         {UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
472                               "'No-Operation', place holder preventing automatic override to ever affect the property"},
473         {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
474         {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
475         {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
476         {0, NULL, 0, NULL, NULL}
477 };
478
479
480 static int override_type_set_button_poll(bContext *C)
481 {
482         PointerRNA ptr;
483         PropertyRNA *prop;
484         int index;
485
486         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
487
488         const int override_status = RNA_property_override_status(&ptr, prop, index);
489
490         return (ptr.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE));
491 }
492
493 static int override_type_set_button_exec(bContext *C, wmOperator *op)
494 {
495         PointerRNA ptr;
496         PropertyRNA *prop;
497         int index;
498         bool created;
499         const bool all = RNA_boolean_get(op->ptr, "all");
500         const int op_type = RNA_enum_get(op->ptr, "type");
501
502         short operation;
503
504         switch (op_type) {
505                 case UIOverride_Type_NOOP:
506                         operation = IDOVERRIDESTATIC_OP_NOOP;
507                         break;
508                 case UIOverride_Type_Replace:
509                         operation = IDOVERRIDESTATIC_OP_REPLACE;
510                         break;
511                 case UIOverride_Type_Difference:
512                         operation = IDOVERRIDESTATIC_OP_ADD;  /* override code will automatically switch to subtract if needed. */
513                         break;
514                 case UIOverride_Type_Factor:
515                         operation = IDOVERRIDESTATIC_OP_MULTIPLY;
516                         break;
517                 default:
518                         operation = IDOVERRIDESTATIC_OP_REPLACE;
519                         BLI_assert(0);
520                         break;
521         }
522
523         /* try to reset the nominated setting to its default value */
524         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
525
526         BLI_assert(ptr.id.data != NULL);
527
528         if (all) {
529                 index = -1;
530         }
531
532         IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
533                                                 &ptr, prop, operation, index, true, NULL, &created);
534         if (!created) {
535                 opop->operation = operation;
536         }
537
538         return operator_button_property_finish(C, &ptr, prop);
539 }
540
541 static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
542 {
543         return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
544 }
545
546 static void UI_OT_override_type_set_button(wmOperatorType *ot)
547 {
548         /* identifiers */
549         ot->name = "Define Override Type";
550         ot->idname = "UI_OT_override_type_set_button";
551         ot->description = "Create an override operation, or set the type of an existing one";
552
553         /* callbacks */
554         ot->poll = override_type_set_button_poll;
555         ot->exec = override_type_set_button_exec;
556         ot->invoke = override_type_set_button_invoke;
557
558         /* flags */
559         ot->flag = OPTYPE_UNDO;
560
561         /* properties */
562         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
563         ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
564                                 "Type", "Type of override operation");
565         /* TODO: add itemf callback, not all aoptions are available for all data types... */
566 }
567
568
569 static int override_remove_button_poll(bContext *C)
570 {
571         PointerRNA ptr;
572         PropertyRNA *prop;
573         int index;
574
575         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
576
577         const int override_status = RNA_property_override_status(&ptr, prop, index);
578
579         return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
580 }
581
582 static int override_remove_button_exec(bContext *C, wmOperator *op)
583 {
584         PointerRNA ptr, id_refptr, src;
585         PropertyRNA *prop;
586         int index;
587         const bool all = RNA_boolean_get(op->ptr, "all");
588
589         /* try to reset the nominated setting to its default value */
590         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
591
592         ID *id = ptr.id.data;
593         IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
594         BLI_assert(oprop != NULL);
595         BLI_assert(id != NULL && id->override_static != NULL);
596
597         const bool is_template = (id->override_static->reference == NULL);
598
599         /* We need source (i.e. linked data) to restore values of deleted overrides...
600          * If this is an override template, we obviously do not need to restore anything. */
601         if (!is_template) {
602                 RNA_id_pointer_create(id->override_static->reference, &id_refptr);
603                 if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
604                         BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
605                 }
606         }
607
608         if (!all && index != -1) {
609                 bool is_strict_find;
610                 /* Remove override operation for given item, add singular operations for the other items as needed. */
611                 IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
612                                                         oprop, NULL, NULL, index, index, false, &is_strict_find);
613                 BLI_assert(opop != NULL);
614                 if (!is_strict_find) {
615                         /* No specific override operation, we have to get generic one,
616                          * and create item-specific override operations for all but given index, before removing generic one. */
617                         for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
618                                 if (idx != index) {
619                                         BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
620                                 }
621                         }
622                 }
623                 BKE_override_static_property_operation_delete(oprop, opop);
624                 if (!is_template) {
625                         RNA_property_copy(&ptr, &src, prop, index);
626                 }
627                 if (BLI_listbase_is_empty(&oprop->operations)) {
628                         BKE_override_static_property_delete(id->override_static, oprop);
629                 }
630         }
631         else {
632                 /* Just remove whole generic override operation of this property. */
633                 BKE_override_static_property_delete(id->override_static, oprop);
634                 if (!is_template) {
635                         RNA_property_copy(&ptr, &src, prop, -1);
636                 }
637         }
638
639         return operator_button_property_finish(C, &ptr, prop);
640 }
641
642 static void UI_OT_override_remove_button(wmOperatorType *ot)
643 {
644         /* identifiers */
645         ot->name = "Remove Override";
646         ot->idname = "UI_OT_override_remove_button";
647         ot->description = "Remove an override operation";
648
649         /* callbacks */
650         ot->poll = override_remove_button_poll;
651         ot->exec = override_remove_button_exec;
652
653         /* flags */
654         ot->flag = OPTYPE_UNDO;
655
656         /* properties */
657         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
658 }
659
660
661
662
663 /* Copy To Selected Operator ------------------------ */
664
665 bool UI_context_copy_to_selected_list(
666         bContext *C, PointerRNA *ptr, PropertyRNA *prop,
667         ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
668 {
669         *r_use_path_from_id = false;
670         *r_path = NULL;
671
672         if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
673                 *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
674         }
675         else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
676                 *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
677         }
678         else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
679                 ListBase lb;
680                 lb = CTX_data_collection_get(C, "selected_pose_bones");
681
682                 if (!BLI_listbase_is_empty(&lb)) {
683                         CollectionPointerLink *link;
684                         for (link = lb.first; link; link = link->next) {
685                                 bPoseChannel *pchan = link->ptr.data;
686                                 RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
687                         }
688                 }
689
690                 *r_lb = lb;
691         }
692         else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
693                 *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
694         }
695         else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) {
696                 *r_lb = CTX_data_collection_get(C, "selected_editable_fcurves");
697         }
698         else if (RNA_struct_is_a(ptr->type, &RNA_Node) ||
699                  RNA_struct_is_a(ptr->type, &RNA_NodeSocket))
700         {
701                 ListBase lb = {NULL, NULL};
702                 char *path = NULL;
703                 bNode *node = NULL;
704
705                 /* Get the node we're editing */
706                 if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
707                         bNodeTree *ntree = ptr->id.data;
708                         bNodeSocket *sock = ptr->data;
709                         if (nodeFindNode(ntree, sock, &node, NULL)) {
710                                 if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
711                                         /* we're good! */
712                                 }
713                                 else {
714                                         node = NULL;
715                                 }
716                         }
717                 }
718                 else {
719                         node = ptr->data;
720                 }
721
722                 /* Now filter by type */
723                 if (node) {
724                         CollectionPointerLink *link, *link_next;
725                         lb = CTX_data_collection_get(C, "selected_nodes");
726
727                         for (link = lb.first; link; link = link_next) {
728                                 bNode *node_data = link->ptr.data;
729                                 link_next = link->next;
730
731                                 if (node_data->type != node->type) {
732                                         BLI_remlink(&lb, link);
733                                         MEM_freeN(link);
734                                 }
735                         }
736                 }
737
738                 *r_lb = lb;
739                 *r_path = path;
740         }
741         else if (ptr->id.data) {
742                 ID *id = ptr->id.data;
743
744                 if (GS(id->name) == ID_OB) {
745                         *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
746                         *r_use_path_from_id = true;
747                         *r_path = RNA_path_from_ID_to_property(ptr, prop);
748                 }
749                 else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
750                         /* check we're using the active object */
751                         const short id_code = GS(id->name);
752                         ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
753                         char *path = RNA_path_from_ID_to_property(ptr, prop);
754
755                         /* de-duplicate obdata */
756                         if (!BLI_listbase_is_empty(&lb)) {
757                                 CollectionPointerLink *link, *link_next;
758
759                                 for (link = lb.first; link; link = link->next) {
760                                         Object *ob = link->ptr.id.data;
761                                         if (ob->data) {
762                                                 ID *id_data = ob->data;
763                                                 id_data->tag |= LIB_TAG_DOIT;
764                                         }
765                                 }
766
767                                 for (link = lb.first; link; link = link_next) {
768                                         Object *ob = link->ptr.id.data;
769                                         ID *id_data = ob->data;
770                                         link_next = link->next;
771
772                                         if ((id_data == NULL) ||
773                                             (id_data->tag & LIB_TAG_DOIT) == 0 ||
774                                             ID_IS_LINKED(id_data) ||
775                                             (GS(id_data->name) != id_code))
776                                         {
777                                                 BLI_remlink(&lb, link);
778                                                 MEM_freeN(link);
779                                         }
780                                         else {
781                                                 /* avoid prepending 'data' to the path */
782                                                 RNA_id_pointer_create(id_data, &link->ptr);
783                                         }
784
785                                         if (id_data) {
786                                                 id_data->tag &= ~LIB_TAG_DOIT;
787                                         }
788                                 }
789                         }
790
791                         *r_lb = lb;
792                         *r_path = path;
793                 }
794                 else if (GS(id->name) == ID_SCE) {
795                         /* Sequencer's ID is scene :/ */
796                         /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
797                         if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
798                                 *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
799                         }
800                 }
801                 return (*r_path != NULL);
802         }
803         else {
804                 return false;
805         }
806
807         return true;
808 }
809
810 /**
811  * called from both exec & poll
812  *
813  * \note: normally we wouldn't call a loop from within a poll function,
814  * However this is a special case, and for regular poll calls, getting
815  * the context from the button will fail early.
816  */
817 static bool copy_to_selected_button(bContext *C, bool all, bool poll)
818 {
819         PointerRNA ptr, lptr, idptr;
820         PropertyRNA *prop, *lprop;
821         bool success = false;
822         int index;
823
824         /* try to reset the nominated setting to its default value */
825         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
826
827         /* if there is a valid property that is editable... */
828         if (ptr.data && prop) {
829                 char *path = NULL;
830                 bool use_path_from_id;
831                 CollectionPointerLink *link;
832                 ListBase lb = {NULL};
833
834                 if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
835                     !BLI_listbase_is_empty(&lb))
836                 {
837                         for (link = lb.first; link; link = link->next) {
838                                 if (link->ptr.data != ptr.data) {
839                                         if (use_path_from_id) {
840                                                 /* Path relative to ID. */
841                                                 lprop = NULL;
842                                                 RNA_id_pointer_create(link->ptr.id.data, &idptr);
843                                                 RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
844                                         }
845                                         else if (path) {
846                                                 /* Path relative to elements from list. */
847                                                 lprop = NULL;
848                                                 RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
849                                         }
850                                         else {
851                                                 lptr = link->ptr;
852                                                 lprop = prop;
853                                         }
854
855                                         if (lptr.data == ptr.data) {
856                                                 /* lptr might not be the same as link->ptr! */
857                                                 continue;
858                                         }
859
860                                         if (lprop == prop) {
861                                                 if (RNA_property_editable(&lptr, lprop)) {
862                                                         if (poll) {
863                                                                 success = true;
864                                                                 break;
865                                                         }
866                                                         else {
867                                                                 if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
868                                                                         RNA_property_update(C, &lptr, prop);
869                                                                         success = true;
870                                                                 }
871                                                         }
872                                                 }
873                                         }
874                                 }
875                         }
876                 }
877                 MEM_SAFE_FREE(path);
878                 BLI_freelistN(&lb);
879         }
880
881         return success;
882 }
883
884 static int copy_to_selected_button_poll(bContext *C)
885 {
886         return copy_to_selected_button(C, false, true);
887 }
888
889 static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
890 {
891         bool success;
892
893         const bool all = RNA_boolean_get(op->ptr, "all");
894
895         success = copy_to_selected_button(C, all, false);
896
897         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
898 }
899
900 static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
901 {
902         /* identifiers */
903         ot->name = "Copy To Selected";
904         ot->idname = "UI_OT_copy_to_selected_button";
905         ot->description = "Copy property from this object to selected objects or bones";
906
907         /* callbacks */
908         ot->poll = copy_to_selected_button_poll;
909         ot->exec = copy_to_selected_button_exec;
910
911         /* flags */
912         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
913
914         /* properties */
915         RNA_def_boolean(ot->srna, "all", true, "All", "Copy to selected all elements of the array");
916 }
917
918 /* Reports to Textblock Operator ------------------------ */
919
920 /* FIXME: this is just a temporary operator so that we can see all the reports somewhere 
921  * when there are too many to display...
922  */
923
924 static int reports_to_text_poll(bContext *C)
925 {
926         return CTX_wm_reports(C) != NULL;
927 }
928
929 static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
930 {
931         ReportList *reports = CTX_wm_reports(C);
932         Main *bmain = CTX_data_main(C);
933         Text *txt;
934         char *str;
935         
936         /* create new text-block to write to */
937         txt = BKE_text_add(bmain, "Recent Reports");
938         
939         /* convert entire list to a display string, and add this to the text-block
940          *      - if commandline debug option enabled, show debug reports too
941          *      - otherwise, up to info (which is what users normally see)
942          */
943         str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
944
945         if (str) {
946                 TextUndoBuf *utxt = NULL; // FIXME
947                 BKE_text_write(txt, utxt, str);
948                 MEM_freeN(str);
949
950                 return OPERATOR_FINISHED;
951         }
952         else {
953                 return OPERATOR_CANCELLED;
954         }
955 }
956
957 static void UI_OT_reports_to_textblock(wmOperatorType *ot)
958 {
959         /* identifiers */
960         ot->name = "Reports to Text Block";
961         ot->idname = "UI_OT_reports_to_textblock";
962         ot->description = "Write the reports ";
963         
964         /* callbacks */
965         ot->poll = reports_to_text_poll;
966         ot->exec = reports_to_text_exec;
967 }
968
969 #ifdef WITH_PYTHON
970
971 /* ------------------------------------------------------------------------- */
972 /* EditSource Utility funcs and operator,
973  * note, this includes utility functions and button matching checks */
974
975 typedef struct uiEditSourceStore {
976         uiBut but_orig;
977         GHash *hash;
978 } uiEditSourceStore;
979
980 typedef struct uiEditSourceButStore {
981         char py_dbg_fn[FILE_MAX];
982         int py_dbg_ln;
983 } uiEditSourceButStore;
984
985 /* should only ever be set while the edit source operator is running */
986 static struct uiEditSourceStore *ui_editsource_info = NULL;
987
988 bool UI_editsource_enable_check(void)
989 {
990         return (ui_editsource_info != NULL);
991 }
992
993 static void ui_editsource_active_but_set(uiBut *but)
994 {
995         BLI_assert(ui_editsource_info == NULL);
996
997         ui_editsource_info = MEM_callocN(sizeof(uiEditSourceStore), __func__);
998         memcpy(&ui_editsource_info->but_orig, but, sizeof(uiBut));
999
1000         ui_editsource_info->hash = BLI_ghash_ptr_new(__func__);
1001 }
1002
1003 static void ui_editsource_active_but_clear(void)
1004 {
1005         BLI_ghash_free(ui_editsource_info->hash, NULL, MEM_freeN);
1006         MEM_freeN(ui_editsource_info);
1007         ui_editsource_info = NULL;
1008 }
1009
1010 static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
1011 {
1012 #if 0
1013         printf("matching buttons: '%s' == '%s'\n",
1014                but_a->drawstr, but_b->drawstr);
1015 #endif
1016
1017         /* this just needs to be a 'good-enough' comparison so we can know beyond
1018          * reasonable doubt that these buttons are the same between redraws.
1019          * if this fails it only means edit-source fails - campbell */
1020         if (BLI_rctf_compare(&but_a->rect, &but_b->rect, FLT_EPSILON) &&
1021             (but_a->type == but_b->type) &&
1022             (but_a->rnaprop == but_b->rnaprop) &&
1023             (but_a->optype == but_b->optype) &&
1024             (but_a->unit_type == but_b->unit_type) &&
1025             STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR))
1026         {
1027                 return true;
1028         }
1029         else {
1030                 return false;
1031         }
1032 }
1033
1034 void UI_editsource_active_but_test(uiBut *but)
1035 {
1036         extern void PyC_FileAndNum_Safe(const char **filename, int *lineno);
1037
1038         struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
1039
1040         const char *fn;
1041         int lineno = -1;
1042
1043 #if 0
1044         printf("comparing buttons: '%s' == '%s'\n",
1045                but->drawstr, ui_editsource_info->but_orig.drawstr);
1046 #endif
1047
1048         PyC_FileAndNum_Safe(&fn, &lineno);
1049
1050         if (lineno != -1) {
1051                 BLI_strncpy(but_store->py_dbg_fn, fn,
1052                             sizeof(but_store->py_dbg_fn));
1053                 but_store->py_dbg_ln = lineno;
1054         }
1055         else {
1056                 but_store->py_dbg_fn[0] = '\0';
1057                 but_store->py_dbg_ln = -1;
1058         }
1059
1060         BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
1061 }
1062
1063 static int editsource_text_edit(
1064         bContext *C, wmOperator *op,
1065         char filepath[FILE_MAX], int line)
1066 {
1067         struct Main *bmain = CTX_data_main(C);
1068         Text *text;
1069
1070         for (text = bmain->text.first; text; text = text->id.next) {
1071                 if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
1072                         break;
1073                 }
1074         }
1075
1076         if (text == NULL) {
1077                 text = BKE_text_load(bmain, filepath, bmain->name);
1078                 id_us_ensure_real(&text->id);
1079         }
1080
1081         if (text == NULL) {
1082                 BKE_reportf(op->reports, RPT_WARNING, "File '%s' cannot be opened", filepath);
1083                 return OPERATOR_CANCELLED;
1084         }
1085         else {
1086                 /* naughty!, find text area to set, not good behavior
1087                  * but since this is a dev tool lets allow it - campbell */
1088                 ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
1089                 if (sa) {
1090                         SpaceText *st = sa->spacedata.first;
1091                         st->text = text;
1092                 }
1093                 else {
1094                         BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2);
1095                 }
1096
1097                 txt_move_toline(text, line - 1, false);
1098                 WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
1099         }
1100
1101         return OPERATOR_FINISHED;
1102 }
1103
1104 static int editsource_exec(bContext *C, wmOperator *op)
1105 {
1106         uiBut *but = UI_context_active_but_get(C);
1107
1108         if (but) {
1109                 GHashIterator ghi;
1110                 struct uiEditSourceButStore *but_store = NULL;
1111
1112                 ARegion *ar = CTX_wm_region(C);
1113                 int ret;
1114
1115                 /* needed else the active button does not get tested */
1116                 UI_screen_free_active_but(C, CTX_wm_screen(C));
1117
1118                 // printf("%s: begin\n", __func__);
1119
1120                 /* take care not to return before calling ui_editsource_active_but_clear */
1121                 ui_editsource_active_but_set(but);
1122
1123                 /* redraw and get active button python info */
1124                 ED_region_do_draw(C, ar);
1125                 ar->do_draw = false;
1126
1127                 for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
1128                      BLI_ghashIterator_done(&ghi) == false;
1129                      BLI_ghashIterator_step(&ghi))
1130                 {
1131                         uiBut *but_key = BLI_ghashIterator_getKey(&ghi);
1132                         if (but_key && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but_key)) {
1133                                 but_store = BLI_ghashIterator_getValue(&ghi);
1134                                 break;
1135                         }
1136
1137                 }
1138
1139                 if (but_store) {
1140                         if (but_store->py_dbg_ln != -1) {
1141                                 ret = editsource_text_edit(C, op,
1142                                                            but_store->py_dbg_fn,
1143                                                            but_store->py_dbg_ln);
1144                         }
1145                         else {
1146                                 BKE_report(op->reports, RPT_ERROR, "Active button is not from a script, cannot edit source");
1147                                 ret = OPERATOR_CANCELLED;
1148                         }
1149                 }
1150                 else {
1151                         BKE_report(op->reports, RPT_ERROR, "Active button match cannot be found");
1152                         ret = OPERATOR_CANCELLED;
1153                 }
1154
1155
1156                 ui_editsource_active_but_clear();
1157
1158                 // printf("%s: end\n", __func__);
1159
1160                 return ret;
1161         }
1162         else {
1163                 BKE_report(op->reports, RPT_ERROR, "Active button not found");
1164                 return OPERATOR_CANCELLED;
1165         }
1166 }
1167
1168 static void UI_OT_editsource(wmOperatorType *ot)
1169 {
1170         /* identifiers */
1171         ot->name = "Edit Source";
1172         ot->idname = "UI_OT_editsource";
1173         ot->description = "Edit UI source code of the active button";
1174
1175         /* callbacks */
1176         ot->exec = editsource_exec;
1177 }
1178
1179 /* ------------------------------------------------------------------------- */
1180
1181 /**
1182  * EditTranslation utility funcs and operator,
1183  * \note: this includes utility functions and button matching checks.
1184  * this only works in conjunction with a py operator!
1185  */
1186 static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen)
1187 {
1188         char tstr[32]; /* Should be more than enough! */
1189
1190         /* First, full lang code. */
1191         BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng);
1192         BLI_join_dirfile(path, maxlen, root, uilng);
1193         BLI_path_append(path, maxlen, tstr);
1194         if (BLI_is_file(path))
1195                 return;
1196
1197         /* Now try without the second iso code part (_ES in es_ES). */
1198         {
1199                 const char *tc = NULL;
1200                 size_t szt = 0;
1201                 tstr[0] = '\0';
1202
1203                 tc = strchr(uilng, '_');
1204                 if (tc) {
1205                         szt = tc - uilng;
1206                         if (szt < sizeof(tstr)) /* Paranoid, should always be true! */
1207                                 BLI_strncpy(tstr, uilng, szt + 1); /* +1 for '\0' char! */
1208                 }
1209                 if (tstr[0]) {
1210                         /* Because of some codes like sr_SR@latin... */
1211                         tc = strchr(uilng, '@');
1212                         if (tc)
1213                                 BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt);
1214
1215                         BLI_join_dirfile(path, maxlen, root, tstr);
1216                         strcat(tstr, ".po");
1217                         BLI_path_append(path, maxlen, tstr);
1218                         if (BLI_is_file(path))
1219                                 return;
1220                 }
1221         }
1222
1223         /* Else no po file! */
1224         path[0] = '\0';
1225 }
1226
1227 static int edittranslation_exec(bContext *C, wmOperator *op)
1228 {
1229         uiBut *but = UI_context_active_but_get(C);
1230         int ret = OPERATOR_CANCELLED;
1231
1232         if (but) {
1233                 wmOperatorType *ot;
1234                 PointerRNA ptr;
1235                 char popath[FILE_MAX];
1236                 const char *root = U.i18ndir;
1237                 const char *uilng = BLT_lang_get();
1238
1239                 uiStringInfo but_label = {BUT_GET_LABEL, NULL};
1240                 uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
1241                 uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
1242                 uiStringInfo but_tip = {BUT_GET_TIP, NULL};
1243                 uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
1244                 uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
1245                 uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
1246                 uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
1247                 uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
1248                 uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
1249
1250                 if (!BLI_is_dir(root)) {
1251                         BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' 'Translation Branches "
1252                                                            "Directory' path to a valid directory");
1253                         return OPERATOR_CANCELLED;
1254                 }
1255                 ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
1256                 if (ot == NULL) {
1257                         BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate add-on "
1258                                                             "in the User Preferences", EDTSRC_I18N_OP_NAME);
1259                         return OPERATOR_CANCELLED;
1260                 }
1261                 /* Try to find a valid po file for current language... */
1262                 edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
1263 /*              printf("po path: %s\n", popath);*/
1264                 if (popath[0] == '\0') {
1265                         BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
1266                         return OPERATOR_CANCELLED;
1267                 }
1268
1269                 UI_but_string_info_get(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
1270                                 &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL);
1271
1272                 WM_operator_properties_create_ptr(&ptr, ot);
1273                 RNA_string_set(&ptr, "lang", uilng);
1274                 RNA_string_set(&ptr, "po_file", popath);
1275                 RNA_string_set(&ptr, "but_label", but_label.strinfo);
1276                 RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
1277                 RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
1278                 RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
1279                 RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
1280                 RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
1281                 RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
1282                 RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
1283                 RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
1284                 RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
1285                 ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
1286
1287                 /* Clean up */
1288                 if (but_label.strinfo)
1289                         MEM_freeN(but_label.strinfo);
1290                 if (rna_label.strinfo)
1291                         MEM_freeN(rna_label.strinfo);
1292                 if (enum_label.strinfo)
1293                         MEM_freeN(enum_label.strinfo);
1294                 if (but_tip.strinfo)
1295                         MEM_freeN(but_tip.strinfo);
1296                 if (rna_tip.strinfo)
1297                         MEM_freeN(rna_tip.strinfo);
1298                 if (enum_tip.strinfo)
1299                         MEM_freeN(enum_tip.strinfo);
1300                 if (rna_struct.strinfo)
1301                         MEM_freeN(rna_struct.strinfo);
1302                 if (rna_prop.strinfo)
1303                         MEM_freeN(rna_prop.strinfo);
1304                 if (rna_enum.strinfo)
1305                         MEM_freeN(rna_enum.strinfo);
1306                 if (rna_ctxt.strinfo)
1307                         MEM_freeN(rna_ctxt.strinfo);
1308
1309                 return ret;
1310         }
1311         else {
1312                 BKE_report(op->reports, RPT_ERROR, "Active button not found");
1313                 return OPERATOR_CANCELLED;
1314         }
1315 }
1316
1317 static void UI_OT_edittranslation_init(wmOperatorType *ot)
1318 {
1319         /* identifiers */
1320         ot->name = "Edit Translation";
1321         ot->idname = "UI_OT_edittranslation_init";
1322         ot->description = "Edit i18n in current language for the active button";
1323
1324         /* callbacks */
1325         ot->exec = edittranslation_exec;
1326 }
1327
1328 #endif /* WITH_PYTHON */
1329
1330 static int reloadtranslation_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
1331 {
1332         BLT_lang_init();
1333         BLF_cache_clear();
1334         BLT_lang_set(NULL);
1335         UI_reinit_font();
1336         return OPERATOR_FINISHED;
1337 }
1338
1339 static void UI_OT_reloadtranslation(wmOperatorType *ot)
1340 {
1341         /* identifiers */
1342         ot->name = "Reload Translation";
1343         ot->idname = "UI_OT_reloadtranslation";
1344         ot->description = "Force a full reload of UI translation";
1345
1346         /* callbacks */
1347         ot->exec = reloadtranslation_exec;
1348 }
1349
1350 int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
1351 {
1352         /* should only return true for regions that include buttons, for now
1353          * return true always */
1354         if (drag->type == WM_DRAG_COLOR) {
1355                 SpaceImage *sima = CTX_wm_space_image(C);
1356                 ARegion *ar = CTX_wm_region(C);
1357
1358                 if (UI_but_active_drop_color(C))
1359                         return 1;
1360
1361                 if (sima && (sima->mode == SI_MODE_PAINT) &&
1362                     sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
1363                 {
1364                         return 1;
1365                 }
1366         }
1367
1368         return 0;
1369 }
1370
1371 void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
1372 {
1373         uiDragColorHandle *drag_info = drag->poin;
1374
1375         RNA_float_set_array(drop->ptr, "color", drag_info->color);
1376         RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
1377 }
1378
1379 static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1380 {
1381         ARegion *ar = CTX_wm_region(C);
1382         uiBut *but = NULL;
1383         float color[4];
1384         bool gamma;
1385
1386         RNA_float_get_array(op->ptr, "color", color);
1387         gamma = RNA_boolean_get(op->ptr, "gamma");
1388
1389         /* find button under mouse, check if it has RNA color property and
1390          * if it does copy the data */
1391         but = ui_but_find_active_in_region(ar);
1392
1393         if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
1394                 const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
1395                 BLI_assert(color_len <= 4);
1396
1397                 /* keep alpha channel as-is */
1398                 if (color_len == 4) {
1399                         color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
1400                 }
1401
1402                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
1403                         if (!gamma)
1404                                 ui_block_cm_to_display_space_v3(but->block, color);
1405                         RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
1406                         RNA_property_update(C, &but->rnapoin, but->rnaprop);
1407                 }
1408                 else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
1409                         if (gamma)
1410                                 ui_block_cm_to_scene_linear_v3(but->block, color);
1411                         RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
1412                         RNA_property_update(C, &but->rnapoin, but->rnaprop);
1413                 }
1414         }
1415         else {
1416                 if (gamma) {
1417                         srgb_to_linearrgb_v3_v3(color, color);
1418                 }
1419
1420                 ED_imapaint_bucket_fill(C, color, op);
1421         }
1422
1423         ED_region_tag_redraw(ar);
1424
1425         return OPERATOR_FINISHED;
1426 }
1427
1428
1429 static void UI_OT_drop_color(wmOperatorType *ot)
1430 {
1431         ot->name = "Drop Color";
1432         ot->idname = "UI_OT_drop_color";
1433         ot->description = "Drop colors to buttons";
1434
1435         ot->invoke = drop_color_invoke;
1436         ot->flag = OPTYPE_INTERNAL;
1437
1438         RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
1439         RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
1440 }
1441
1442
1443 /* ********************************************************* */
1444 /* Registration */
1445
1446 void ED_operatortypes_ui(void)
1447 {
1448         WM_operatortype_append(UI_OT_reset_default_theme);
1449         WM_operatortype_append(UI_OT_copy_data_path_button);
1450         WM_operatortype_append(UI_OT_copy_python_command_button);
1451         WM_operatortype_append(UI_OT_reset_default_button);
1452         WM_operatortype_append(UI_OT_unset_property_button);
1453         WM_operatortype_append(UI_OT_use_property_button);
1454         WM_operatortype_append(UI_OT_unuse_property_button);
1455         WM_operatortype_append(UI_OT_override_type_set_button);
1456         WM_operatortype_append(UI_OT_override_remove_button);
1457         WM_operatortype_append(UI_OT_copy_to_selected_button);
1458         WM_operatortype_append(UI_OT_reports_to_textblock);  /* XXX: temp? */
1459         WM_operatortype_append(UI_OT_drop_color);
1460 #ifdef WITH_PYTHON
1461         WM_operatortype_append(UI_OT_editsource);
1462         WM_operatortype_append(UI_OT_edittranslation_init);
1463 #endif
1464         WM_operatortype_append(UI_OT_reloadtranslation);
1465
1466         /* external */
1467         WM_operatortype_append(UI_OT_eyedropper_color);
1468         WM_operatortype_append(UI_OT_eyedropper_colorband);
1469         WM_operatortype_append(UI_OT_eyedropper_colorband_point);
1470         WM_operatortype_append(UI_OT_eyedropper_id);
1471         WM_operatortype_append(UI_OT_eyedropper_depth);
1472         WM_operatortype_append(UI_OT_eyedropper_driver);
1473 }
1474
1475 /**
1476  * \brief User Interface Keymap
1477  */
1478 void ED_keymap_ui(wmKeyConfig *keyconf)
1479 {
1480         wmKeyMap *keymap = WM_keymap_find(keyconf, "User Interface", 0, 0);
1481         wmKeyMapItem *kmi;
1482
1483         /* eyedroppers - notice they all have the same shortcut, but pass the event
1484          * through until a suitable eyedropper for the active button is found */
1485         WM_keymap_add_item(keymap, "UI_OT_eyedropper_color", EKEY, KM_PRESS, 0, 0);
1486         WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband", EKEY, KM_PRESS, 0, 0);
1487         WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS, KM_ALT, 0);
1488         WM_keymap_add_item(keymap, "UI_OT_eyedropper_id", EKEY, KM_PRESS, 0, 0);
1489         WM_keymap_add_item(keymap, "UI_OT_eyedropper_depth", EKEY, KM_PRESS, 0, 0);
1490
1491         /* Copy Data Path */
1492         WM_keymap_add_item(keymap, "UI_OT_copy_data_path_button", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
1493         kmi = WM_keymap_add_item(keymap, "UI_OT_copy_data_path_button", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
1494         RNA_boolean_set(kmi->ptr, "full_path", true);
1495
1496         /* keyframes */
1497         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_insert_button", IKEY, KM_PRESS, 0, 0);
1498         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_delete_button", IKEY, KM_PRESS, KM_ALT, 0);
1499         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_clear_button", IKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
1500
1501         /* drivers */
1502         WM_keymap_add_item(keymap, "ANIM_OT_driver_button_add", DKEY, KM_PRESS, KM_CTRL, 0);
1503         WM_keymap_add_item(keymap, "ANIM_OT_driver_button_remove", DKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
1504
1505         /* keyingsets */
1506         WM_keymap_add_item(keymap, "ANIM_OT_keyingset_button_add", KKEY, KM_PRESS, 0, 0);
1507         WM_keymap_add_item(keymap, "ANIM_OT_keyingset_button_remove", KKEY, KM_PRESS, KM_ALT, 0);
1508
1509         eyedropper_modal_keymap(keyconf);
1510         eyedropper_colorband_modal_keymap(keyconf);
1511 }