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         bool is_overridable;
486
487         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
488
489         RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL);
490
491         return (ptr.data && prop && is_overridable);
492 }
493
494 static int override_type_set_button_exec(bContext *C, wmOperator *op)
495 {
496         PointerRNA ptr;
497         PropertyRNA *prop;
498         int index;
499         bool created;
500         const bool all = RNA_boolean_get(op->ptr, "all");
501         const int op_type = RNA_enum_get(op->ptr, "type");
502
503         short operation;
504
505         switch (op_type) {
506                 case UIOverride_Type_NOOP:
507                         operation = IDOVERRIDESTATIC_OP_NOOP;
508                         break;
509                 case UIOverride_Type_Replace:
510                         operation = IDOVERRIDESTATIC_OP_REPLACE;
511                         break;
512                 case UIOverride_Type_Difference:
513                         operation = IDOVERRIDESTATIC_OP_ADD;  /* override code will automatically switch to subtract if needed. */
514                         break;
515                 case UIOverride_Type_Factor:
516                         operation = IDOVERRIDESTATIC_OP_MULTIPLY;
517                         break;
518                 default:
519                         operation = IDOVERRIDESTATIC_OP_REPLACE;
520                         BLI_assert(0);
521                         break;
522         }
523
524         /* try to reset the nominated setting to its default value */
525         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
526
527         BLI_assert(ptr.id.data != NULL);
528
529         if (all) {
530                 index = -1;
531         }
532
533         IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
534                                                 &ptr, prop, operation, index, true, NULL, &created);
535         if (!created) {
536                 opop->operation = operation;
537         }
538
539         return operator_button_property_finish(C, &ptr, prop);
540 }
541
542 static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
543 {
544         return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
545 }
546
547 static void UI_OT_override_type_set_button(wmOperatorType *ot)
548 {
549         /* identifiers */
550         ot->name = "Define Override Type";
551         ot->idname = "UI_OT_override_type_set_button";
552         ot->description = "Create an override operation, or set the type of an existing one";
553
554         /* callbacks */
555         ot->poll = override_type_set_button_poll;
556         ot->exec = override_type_set_button_exec;
557         ot->invoke = override_type_set_button_invoke;
558
559         /* flags */
560         ot->flag = OPTYPE_UNDO;
561
562         /* properties */
563         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
564         ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
565                                 "Type", "Type of override operation");
566         /* TODO: add itemf callback, not all aoptions are available for all data types... */
567 }
568
569
570 static int override_remove_button_poll(bContext *C)
571 {
572         PointerRNA ptr;
573         PropertyRNA *prop;
574         int index;
575         bool is_overridden;
576
577         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
578
579         RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL);
580
581         return (ptr.data && ptr.id.data && prop && is_overridden);
582 }
583
584 static int override_remove_button_exec(bContext *C, wmOperator *op)
585 {
586         PointerRNA ptr, id_refptr, src;
587         PropertyRNA *prop;
588         int index;
589         const bool all = RNA_boolean_get(op->ptr, "all");
590
591         /* try to reset the nominated setting to its default value */
592         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
593
594         ID *id = ptr.id.data;
595         IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
596         BLI_assert(oprop != NULL);
597         BLI_assert(id != NULL && id->override_static != NULL);
598
599         const bool is_template = (id->override_static->reference == NULL);
600
601         /* We need source (i.e. linked data) to restore values of deleted overrides...
602          * If this is an override template, we obviously do not need to restore anything. */
603         if (!is_template) {
604                 RNA_id_pointer_create(id->override_static->reference, &id_refptr);
605                 if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
606                         BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
607                 }
608         }
609
610         if (!all && index != -1) {
611                 bool is_strict_find;
612                 /* Remove override operation for given item, add singular operations for the other items as needed. */
613                 IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
614                                                         oprop, NULL, NULL, index, index, false, &is_strict_find);
615                 BLI_assert(opop != NULL);
616                 if (!is_strict_find) {
617                         /* No specific override operation, we have to get generic one,
618                          * and create item-specific override operations for all but given index, before removing generic one. */
619                         for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
620                                 if (idx != index) {
621                                         BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
622                                 }
623                         }
624                 }
625                 BKE_override_static_property_operation_delete(oprop, opop);
626                 if (!is_template) {
627                         RNA_property_copy(&ptr, &src, prop, index);
628                 }
629                 if (BLI_listbase_is_empty(&oprop->operations)) {
630                         BKE_override_static_property_delete(id->override_static, oprop);
631                 }
632         }
633         else {
634                 /* Just remove whole generic override operation of this property. */
635                 BKE_override_static_property_delete(id->override_static, oprop);
636                 if (!is_template) {
637                         RNA_property_copy(&ptr, &src, prop, -1);
638                 }
639         }
640
641         return operator_button_property_finish(C, &ptr, prop);
642 }
643
644 static void UI_OT_override_remove_button(wmOperatorType *ot)
645 {
646         /* identifiers */
647         ot->name = "Remove Override";
648         ot->idname = "UI_OT_override_remove_button";
649         ot->description = "Remove an override operation";
650
651         /* callbacks */
652         ot->poll = override_remove_button_poll;
653         ot->exec = override_remove_button_exec;
654
655         /* flags */
656         ot->flag = OPTYPE_UNDO;
657
658         /* properties */
659         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
660 }
661
662
663
664
665 /* Copy To Selected Operator ------------------------ */
666
667 bool UI_context_copy_to_selected_list(
668         bContext *C, PointerRNA *ptr, PropertyRNA *prop,
669         ListBase *r_lb, bool *r_use_path_from_id, char **r_path)
670 {
671         *r_use_path_from_id = false;
672         *r_path = NULL;
673
674         if (RNA_struct_is_a(ptr->type, &RNA_EditBone)) {
675                 *r_lb = CTX_data_collection_get(C, "selected_editable_bones");
676         }
677         else if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) {
678                 *r_lb = CTX_data_collection_get(C, "selected_pose_bones");
679         }
680         else if (RNA_struct_is_a(ptr->type, &RNA_Bone)) {
681                 ListBase lb;
682                 lb = CTX_data_collection_get(C, "selected_pose_bones");
683
684                 if (!BLI_listbase_is_empty(&lb)) {
685                         CollectionPointerLink *link;
686                         for (link = lb.first; link; link = link->next) {
687                                 bPoseChannel *pchan = link->ptr.data;
688                                 RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
689                         }
690                 }
691
692                 *r_lb = lb;
693         }
694         else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
695                 *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
696         }
697         else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) {
698                 *r_lb = CTX_data_collection_get(C, "selected_editable_fcurves");
699         }
700         else if (RNA_struct_is_a(ptr->type, &RNA_Node) ||
701                  RNA_struct_is_a(ptr->type, &RNA_NodeSocket))
702         {
703                 ListBase lb = {NULL, NULL};
704                 char *path = NULL;
705                 bNode *node = NULL;
706
707                 /* Get the node we're editing */
708                 if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
709                         bNodeTree *ntree = ptr->id.data;
710                         bNodeSocket *sock = ptr->data;
711                         if (nodeFindNode(ntree, sock, &node, NULL)) {
712                                 if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
713                                         /* we're good! */
714                                 }
715                                 else {
716                                         node = NULL;
717                                 }
718                         }
719                 }
720                 else {
721                         node = ptr->data;
722                 }
723
724                 /* Now filter by type */
725                 if (node) {
726                         CollectionPointerLink *link, *link_next;
727                         lb = CTX_data_collection_get(C, "selected_nodes");
728
729                         for (link = lb.first; link; link = link_next) {
730                                 bNode *node_data = link->ptr.data;
731                                 link_next = link->next;
732
733                                 if (node_data->type != node->type) {
734                                         BLI_remlink(&lb, link);
735                                         MEM_freeN(link);
736                                 }
737                         }
738                 }
739
740                 *r_lb = lb;
741                 *r_path = path;
742         }
743         else if (ptr->id.data) {
744                 ID *id = ptr->id.data;
745
746                 if (GS(id->name) == ID_OB) {
747                         *r_lb = CTX_data_collection_get(C, "selected_editable_objects");
748                         *r_use_path_from_id = true;
749                         *r_path = RNA_path_from_ID_to_property(ptr, prop);
750                 }
751                 else if (OB_DATA_SUPPORT_ID(GS(id->name))) {
752                         /* check we're using the active object */
753                         const short id_code = GS(id->name);
754                         ListBase lb = CTX_data_collection_get(C, "selected_editable_objects");
755                         char *path = RNA_path_from_ID_to_property(ptr, prop);
756
757                         /* de-duplicate obdata */
758                         if (!BLI_listbase_is_empty(&lb)) {
759                                 CollectionPointerLink *link, *link_next;
760
761                                 for (link = lb.first; link; link = link->next) {
762                                         Object *ob = link->ptr.id.data;
763                                         if (ob->data) {
764                                                 ID *id_data = ob->data;
765                                                 id_data->tag |= LIB_TAG_DOIT;
766                                         }
767                                 }
768
769                                 for (link = lb.first; link; link = link_next) {
770                                         Object *ob = link->ptr.id.data;
771                                         ID *id_data = ob->data;
772                                         link_next = link->next;
773
774                                         if ((id_data == NULL) ||
775                                             (id_data->tag & LIB_TAG_DOIT) == 0 ||
776                                             ID_IS_LINKED(id_data) ||
777                                             (GS(id_data->name) != id_code))
778                                         {
779                                                 BLI_remlink(&lb, link);
780                                                 MEM_freeN(link);
781                                         }
782                                         else {
783                                                 /* avoid prepending 'data' to the path */
784                                                 RNA_id_pointer_create(id_data, &link->ptr);
785                                         }
786
787                                         if (id_data) {
788                                                 id_data->tag &= ~LIB_TAG_DOIT;
789                                         }
790                                 }
791                         }
792
793                         *r_lb = lb;
794                         *r_path = path;
795                 }
796                 else if (GS(id->name) == ID_SCE) {
797                         /* Sequencer's ID is scene :/ */
798                         /* Try to recursively find an RNA_Sequence ancestor, to handle situations like T41062... */
799                         if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != NULL) {
800                                 *r_lb = CTX_data_collection_get(C, "selected_editable_sequences");
801                         }
802                 }
803                 return (*r_path != NULL);
804         }
805         else {
806                 return false;
807         }
808
809         return true;
810 }
811
812 /**
813  * called from both exec & poll
814  *
815  * \note: normally we wouldn't call a loop from within a poll function,
816  * However this is a special case, and for regular poll calls, getting
817  * the context from the button will fail early.
818  */
819 static bool copy_to_selected_button(bContext *C, bool all, bool poll)
820 {
821         PointerRNA ptr, lptr, idptr;
822         PropertyRNA *prop, *lprop;
823         bool success = false;
824         int index;
825
826         /* try to reset the nominated setting to its default value */
827         UI_context_active_but_prop_get(C, &ptr, &prop, &index);
828
829         /* if there is a valid property that is editable... */
830         if (ptr.data && prop) {
831                 char *path = NULL;
832                 bool use_path_from_id;
833                 CollectionPointerLink *link;
834                 ListBase lb = {NULL};
835
836                 if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) &&
837                     !BLI_listbase_is_empty(&lb))
838                 {
839                         for (link = lb.first; link; link = link->next) {
840                                 if (link->ptr.data != ptr.data) {
841                                         if (use_path_from_id) {
842                                                 /* Path relative to ID. */
843                                                 lprop = NULL;
844                                                 RNA_id_pointer_create(link->ptr.id.data, &idptr);
845                                                 RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
846                                         }
847                                         else if (path) {
848                                                 /* Path relative to elements from list. */
849                                                 lprop = NULL;
850                                                 RNA_path_resolve_property(&link->ptr, path, &lptr, &lprop);
851                                         }
852                                         else {
853                                                 lptr = link->ptr;
854                                                 lprop = prop;
855                                         }
856
857                                         if (lptr.data == ptr.data) {
858                                                 /* lptr might not be the same as link->ptr! */
859                                                 continue;
860                                         }
861
862                                         if (lprop == prop) {
863                                                 if (RNA_property_editable(&lptr, lprop)) {
864                                                         if (poll) {
865                                                                 success = true;
866                                                                 break;
867                                                         }
868                                                         else {
869                                                                 if (RNA_property_copy(&lptr, &ptr, prop, (all) ? -1 : index)) {
870                                                                         RNA_property_update(C, &lptr, prop);
871                                                                         success = true;
872                                                                 }
873                                                         }
874                                                 }
875                                         }
876                                 }
877                         }
878                 }
879                 MEM_SAFE_FREE(path);
880                 BLI_freelistN(&lb);
881         }
882
883         return success;
884 }
885
886 static int copy_to_selected_button_poll(bContext *C)
887 {
888         return copy_to_selected_button(C, false, true);
889 }
890
891 static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
892 {
893         bool success;
894
895         const bool all = RNA_boolean_get(op->ptr, "all");
896
897         success = copy_to_selected_button(C, all, false);
898
899         return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
900 }
901
902 static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
903 {
904         /* identifiers */
905         ot->name = "Copy To Selected";
906         ot->idname = "UI_OT_copy_to_selected_button";
907         ot->description = "Copy property from this object to selected objects or bones";
908
909         /* callbacks */
910         ot->poll = copy_to_selected_button_poll;
911         ot->exec = copy_to_selected_button_exec;
912
913         /* flags */
914         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
915
916         /* properties */
917         RNA_def_boolean(ot->srna, "all", true, "All", "Copy to selected all elements of the array");
918 }
919
920 /* Reports to Textblock Operator ------------------------ */
921
922 /* FIXME: this is just a temporary operator so that we can see all the reports somewhere 
923  * when there are too many to display...
924  */
925
926 static int reports_to_text_poll(bContext *C)
927 {
928         return CTX_wm_reports(C) != NULL;
929 }
930
931 static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
932 {
933         ReportList *reports = CTX_wm_reports(C);
934         Main *bmain = CTX_data_main(C);
935         Text *txt;
936         char *str;
937         
938         /* create new text-block to write to */
939         txt = BKE_text_add(bmain, "Recent Reports");
940         
941         /* convert entire list to a display string, and add this to the text-block
942          *      - if commandline debug option enabled, show debug reports too
943          *      - otherwise, up to info (which is what users normally see)
944          */
945         str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
946
947         if (str) {
948                 BKE_text_write(txt, str);
949                 MEM_freeN(str);
950
951                 return OPERATOR_FINISHED;
952         }
953         else {
954                 return OPERATOR_CANCELLED;
955         }
956 }
957
958 static void UI_OT_reports_to_textblock(wmOperatorType *ot)
959 {
960         /* identifiers */
961         ot->name = "Reports to Text Block";
962         ot->idname = "UI_OT_reports_to_textblock";
963         ot->description = "Write the reports ";
964         
965         /* callbacks */
966         ot->poll = reports_to_text_poll;
967         ot->exec = reports_to_text_exec;
968 }
969
970 #ifdef WITH_PYTHON
971
972 /* ------------------------------------------------------------------------- */
973 /* EditSource Utility funcs and operator,
974  * note, this includes utility functions and button matching checks */
975
976 typedef struct uiEditSourceStore {
977         uiBut but_orig;
978         GHash *hash;
979 } uiEditSourceStore;
980
981 typedef struct uiEditSourceButStore {
982         char py_dbg_fn[FILE_MAX];
983         int py_dbg_ln;
984 } uiEditSourceButStore;
985
986 /* should only ever be set while the edit source operator is running */
987 static struct uiEditSourceStore *ui_editsource_info = NULL;
988
989 bool UI_editsource_enable_check(void)
990 {
991         return (ui_editsource_info != NULL);
992 }
993
994 static void ui_editsource_active_but_set(uiBut *but)
995 {
996         BLI_assert(ui_editsource_info == NULL);
997
998         ui_editsource_info = MEM_callocN(sizeof(uiEditSourceStore), __func__);
999         memcpy(&ui_editsource_info->but_orig, but, sizeof(uiBut));
1000
1001         ui_editsource_info->hash = BLI_ghash_ptr_new(__func__);
1002 }
1003
1004 static void ui_editsource_active_but_clear(void)
1005 {
1006         BLI_ghash_free(ui_editsource_info->hash, NULL, MEM_freeN);
1007         MEM_freeN(ui_editsource_info);
1008         ui_editsource_info = NULL;
1009 }
1010
1011 static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b)
1012 {
1013 #if 0
1014         printf("matching buttons: '%s' == '%s'\n",
1015                but_a->drawstr, but_b->drawstr);
1016 #endif
1017
1018         /* this just needs to be a 'good-enough' comparison so we can know beyond
1019          * reasonable doubt that these buttons are the same between redraws.
1020          * if this fails it only means edit-source fails - campbell */
1021         if (BLI_rctf_compare(&but_a->rect, &but_b->rect, FLT_EPSILON) &&
1022             (but_a->type == but_b->type) &&
1023             (but_a->rnaprop == but_b->rnaprop) &&
1024             (but_a->optype == but_b->optype) &&
1025             (but_a->unit_type == but_b->unit_type) &&
1026             STREQLEN(but_a->drawstr, but_b->drawstr, UI_MAX_DRAW_STR))
1027         {
1028                 return true;
1029         }
1030         else {
1031                 return false;
1032         }
1033 }
1034
1035 void UI_editsource_active_but_test(uiBut *but)
1036 {
1037         extern void PyC_FileAndNum_Safe(const char **filename, int *lineno);
1038
1039         struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__);
1040
1041         const char *fn;
1042         int lineno = -1;
1043
1044 #if 0
1045         printf("comparing buttons: '%s' == '%s'\n",
1046                but->drawstr, ui_editsource_info->but_orig.drawstr);
1047 #endif
1048
1049         PyC_FileAndNum_Safe(&fn, &lineno);
1050
1051         if (lineno != -1) {
1052                 BLI_strncpy(but_store->py_dbg_fn, fn,
1053                             sizeof(but_store->py_dbg_fn));
1054                 but_store->py_dbg_ln = lineno;
1055         }
1056         else {
1057                 but_store->py_dbg_fn[0] = '\0';
1058                 but_store->py_dbg_ln = -1;
1059         }
1060
1061         BLI_ghash_insert(ui_editsource_info->hash, but, but_store);
1062 }
1063
1064 static int editsource_text_edit(
1065         bContext *C, wmOperator *op,
1066         char filepath[FILE_MAX], int line)
1067 {
1068         struct Main *bmain = CTX_data_main(C);
1069         Text *text;
1070
1071         for (text = bmain->text.first; text; text = text->id.next) {
1072                 if (text->name && BLI_path_cmp(text->name, filepath) == 0) {
1073                         break;
1074                 }
1075         }
1076
1077         if (text == NULL) {
1078                 text = BKE_text_load(bmain, filepath, bmain->name);
1079                 id_us_ensure_real(&text->id);
1080         }
1081
1082         if (text == NULL) {
1083                 BKE_reportf(op->reports, RPT_WARNING, "File '%s' cannot be opened", filepath);
1084                 return OPERATOR_CANCELLED;
1085         }
1086         else {
1087                 /* naughty!, find text area to set, not good behavior
1088                  * but since this is a dev tool lets allow it - campbell */
1089                 ScrArea *sa = BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_TEXT, 0);
1090                 if (sa) {
1091                         SpaceText *st = sa->spacedata.first;
1092                         st->text = text;
1093                 }
1094                 else {
1095                         BKE_reportf(op->reports, RPT_INFO, "See '%s' in the text editor", text->id.name + 2);
1096                 }
1097
1098                 txt_move_toline(text, line - 1, false);
1099                 WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
1100         }
1101
1102         return OPERATOR_FINISHED;
1103 }
1104
1105 static int editsource_exec(bContext *C, wmOperator *op)
1106 {
1107         uiBut *but = UI_context_active_but_get(C);
1108
1109         if (but) {
1110                 GHashIterator ghi;
1111                 struct uiEditSourceButStore *but_store = NULL;
1112
1113                 ARegion *ar = CTX_wm_region(C);
1114                 int ret;
1115
1116                 /* needed else the active button does not get tested */
1117                 UI_screen_free_active_but(C, CTX_wm_screen(C));
1118
1119                 // printf("%s: begin\n", __func__);
1120
1121                 /* take care not to return before calling ui_editsource_active_but_clear */
1122                 ui_editsource_active_but_set(but);
1123
1124                 /* redraw and get active button python info */
1125                 ED_region_do_draw(C, ar);
1126                 ar->do_draw = false;
1127
1128                 for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash);
1129                      BLI_ghashIterator_done(&ghi) == false;
1130                      BLI_ghashIterator_step(&ghi))
1131                 {
1132                         uiBut *but_key = BLI_ghashIterator_getKey(&ghi);
1133                         if (but_key && ui_editsource_uibut_match(&ui_editsource_info->but_orig, but_key)) {
1134                                 but_store = BLI_ghashIterator_getValue(&ghi);
1135                                 break;
1136                         }
1137
1138                 }
1139
1140                 if (but_store) {
1141                         if (but_store->py_dbg_ln != -1) {
1142                                 ret = editsource_text_edit(C, op,
1143                                                            but_store->py_dbg_fn,
1144                                                            but_store->py_dbg_ln);
1145                         }
1146                         else {
1147                                 BKE_report(op->reports, RPT_ERROR, "Active button is not from a script, cannot edit source");
1148                                 ret = OPERATOR_CANCELLED;
1149                         }
1150                 }
1151                 else {
1152                         BKE_report(op->reports, RPT_ERROR, "Active button match cannot be found");
1153                         ret = OPERATOR_CANCELLED;
1154                 }
1155
1156
1157                 ui_editsource_active_but_clear();
1158
1159                 // printf("%s: end\n", __func__);
1160
1161                 return ret;
1162         }
1163         else {
1164                 BKE_report(op->reports, RPT_ERROR, "Active button not found");
1165                 return OPERATOR_CANCELLED;
1166         }
1167 }
1168
1169 static void UI_OT_editsource(wmOperatorType *ot)
1170 {
1171         /* identifiers */
1172         ot->name = "Edit Source";
1173         ot->idname = "UI_OT_editsource";
1174         ot->description = "Edit UI source code of the active button";
1175
1176         /* callbacks */
1177         ot->exec = editsource_exec;
1178 }
1179
1180 /* ------------------------------------------------------------------------- */
1181
1182 /**
1183  * EditTranslation utility funcs and operator,
1184  * \note: this includes utility functions and button matching checks.
1185  * this only works in conjunction with a py operator!
1186  */
1187 static void edittranslation_find_po_file(const char *root, const char *uilng, char *path, const size_t maxlen)
1188 {
1189         char tstr[32]; /* Should be more than enough! */
1190
1191         /* First, full lang code. */
1192         BLI_snprintf(tstr, sizeof(tstr), "%s.po", uilng);
1193         BLI_join_dirfile(path, maxlen, root, uilng);
1194         BLI_path_append(path, maxlen, tstr);
1195         if (BLI_is_file(path))
1196                 return;
1197
1198         /* Now try without the second iso code part (_ES in es_ES). */
1199         {
1200                 const char *tc = NULL;
1201                 size_t szt = 0;
1202                 tstr[0] = '\0';
1203
1204                 tc = strchr(uilng, '_');
1205                 if (tc) {
1206                         szt = tc - uilng;
1207                         if (szt < sizeof(tstr)) /* Paranoid, should always be true! */
1208                                 BLI_strncpy(tstr, uilng, szt + 1); /* +1 for '\0' char! */
1209                 }
1210                 if (tstr[0]) {
1211                         /* Because of some codes like sr_SR@latin... */
1212                         tc = strchr(uilng, '@');
1213                         if (tc)
1214                                 BLI_strncpy(tstr + szt, tc, sizeof(tstr) - szt);
1215
1216                         BLI_join_dirfile(path, maxlen, root, tstr);
1217                         strcat(tstr, ".po");
1218                         BLI_path_append(path, maxlen, tstr);
1219                         if (BLI_is_file(path))
1220                                 return;
1221                 }
1222         }
1223
1224         /* Else no po file! */
1225         path[0] = '\0';
1226 }
1227
1228 static int edittranslation_exec(bContext *C, wmOperator *op)
1229 {
1230         uiBut *but = UI_context_active_but_get(C);
1231         int ret = OPERATOR_CANCELLED;
1232
1233         if (but) {
1234                 wmOperatorType *ot;
1235                 PointerRNA ptr;
1236                 char popath[FILE_MAX];
1237                 const char *root = U.i18ndir;
1238                 const char *uilng = BLT_lang_get();
1239
1240                 uiStringInfo but_label = {BUT_GET_LABEL, NULL};
1241                 uiStringInfo rna_label = {BUT_GET_RNA_LABEL, NULL};
1242                 uiStringInfo enum_label = {BUT_GET_RNAENUM_LABEL, NULL};
1243                 uiStringInfo but_tip = {BUT_GET_TIP, NULL};
1244                 uiStringInfo rna_tip = {BUT_GET_RNA_TIP, NULL};
1245                 uiStringInfo enum_tip = {BUT_GET_RNAENUM_TIP, NULL};
1246                 uiStringInfo rna_struct = {BUT_GET_RNASTRUCT_IDENTIFIER, NULL};
1247                 uiStringInfo rna_prop = {BUT_GET_RNAPROP_IDENTIFIER, NULL};
1248                 uiStringInfo rna_enum = {BUT_GET_RNAENUM_IDENTIFIER, NULL};
1249                 uiStringInfo rna_ctxt = {BUT_GET_RNA_LABEL_CONTEXT, NULL};
1250
1251                 if (!BLI_is_dir(root)) {
1252                         BKE_report(op->reports, RPT_ERROR, "Please set your User Preferences' 'Translation Branches "
1253                                                            "Directory' path to a valid directory");
1254                         return OPERATOR_CANCELLED;
1255                 }
1256                 ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
1257                 if (ot == NULL) {
1258                         BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate add-on "
1259                                                             "in the User Preferences", EDTSRC_I18N_OP_NAME);
1260                         return OPERATOR_CANCELLED;
1261                 }
1262                 /* Try to find a valid po file for current language... */
1263                 edittranslation_find_po_file(root, uilng, popath, FILE_MAX);
1264 /*              printf("po path: %s\n", popath);*/
1265                 if (popath[0] == '\0') {
1266                         BKE_reportf(op->reports, RPT_ERROR, "No valid po found for language '%s' under %s", uilng, root);
1267                         return OPERATOR_CANCELLED;
1268                 }
1269
1270                 UI_but_string_info_get(C, but, &but_label, &rna_label, &enum_label, &but_tip, &rna_tip, &enum_tip,
1271                                 &rna_struct, &rna_prop, &rna_enum, &rna_ctxt, NULL);
1272
1273                 WM_operator_properties_create_ptr(&ptr, ot);
1274                 RNA_string_set(&ptr, "lang", uilng);
1275                 RNA_string_set(&ptr, "po_file", popath);
1276                 RNA_string_set(&ptr, "but_label", but_label.strinfo);
1277                 RNA_string_set(&ptr, "rna_label", rna_label.strinfo);
1278                 RNA_string_set(&ptr, "enum_label", enum_label.strinfo);
1279                 RNA_string_set(&ptr, "but_tip", but_tip.strinfo);
1280                 RNA_string_set(&ptr, "rna_tip", rna_tip.strinfo);
1281                 RNA_string_set(&ptr, "enum_tip", enum_tip.strinfo);
1282                 RNA_string_set(&ptr, "rna_struct", rna_struct.strinfo);
1283                 RNA_string_set(&ptr, "rna_prop", rna_prop.strinfo);
1284                 RNA_string_set(&ptr, "rna_enum", rna_enum.strinfo);
1285                 RNA_string_set(&ptr, "rna_ctxt", rna_ctxt.strinfo);
1286                 ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
1287
1288                 /* Clean up */
1289                 if (but_label.strinfo)
1290                         MEM_freeN(but_label.strinfo);
1291                 if (rna_label.strinfo)
1292                         MEM_freeN(rna_label.strinfo);
1293                 if (enum_label.strinfo)
1294                         MEM_freeN(enum_label.strinfo);
1295                 if (but_tip.strinfo)
1296                         MEM_freeN(but_tip.strinfo);
1297                 if (rna_tip.strinfo)
1298                         MEM_freeN(rna_tip.strinfo);
1299                 if (enum_tip.strinfo)
1300                         MEM_freeN(enum_tip.strinfo);
1301                 if (rna_struct.strinfo)
1302                         MEM_freeN(rna_struct.strinfo);
1303                 if (rna_prop.strinfo)
1304                         MEM_freeN(rna_prop.strinfo);
1305                 if (rna_enum.strinfo)
1306                         MEM_freeN(rna_enum.strinfo);
1307                 if (rna_ctxt.strinfo)
1308                         MEM_freeN(rna_ctxt.strinfo);
1309
1310                 return ret;
1311         }
1312         else {
1313                 BKE_report(op->reports, RPT_ERROR, "Active button not found");
1314                 return OPERATOR_CANCELLED;
1315         }
1316 }
1317
1318 static void UI_OT_edittranslation_init(wmOperatorType *ot)
1319 {
1320         /* identifiers */
1321         ot->name = "Edit Translation";
1322         ot->idname = "UI_OT_edittranslation_init";
1323         ot->description = "Edit i18n in current language for the active button";
1324
1325         /* callbacks */
1326         ot->exec = edittranslation_exec;
1327 }
1328
1329 #endif /* WITH_PYTHON */
1330
1331 static int reloadtranslation_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
1332 {
1333         BLT_lang_init();
1334         BLF_cache_clear();
1335         BLT_lang_set(NULL);
1336         UI_reinit_font();
1337         return OPERATOR_FINISHED;
1338 }
1339
1340 static void UI_OT_reloadtranslation(wmOperatorType *ot)
1341 {
1342         /* identifiers */
1343         ot->name = "Reload Translation";
1344         ot->idname = "UI_OT_reloadtranslation";
1345         ot->description = "Force a full reload of UI translation";
1346
1347         /* callbacks */
1348         ot->exec = reloadtranslation_exec;
1349 }
1350
1351 int UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event))
1352 {
1353         /* should only return true for regions that include buttons, for now
1354          * return true always */
1355         if (drag->type == WM_DRAG_COLOR) {
1356                 SpaceImage *sima = CTX_wm_space_image(C);
1357                 ARegion *ar = CTX_wm_region(C);
1358
1359                 if (UI_but_active_drop_color(C))
1360                         return 1;
1361
1362                 if (sima && (sima->mode == SI_MODE_PAINT) &&
1363                     sima->image && (ar && ar->regiontype == RGN_TYPE_WINDOW))
1364                 {
1365                         return 1;
1366                 }
1367         }
1368
1369         return 0;
1370 }
1371
1372 void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
1373 {
1374         uiDragColorHandle *drag_info = drag->poin;
1375
1376         RNA_float_set_array(drop->ptr, "color", drag_info->color);
1377         RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
1378 }
1379
1380 static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1381 {
1382         ARegion *ar = CTX_wm_region(C);
1383         uiBut *but = NULL;
1384         float color[4];
1385         bool gamma;
1386
1387         RNA_float_get_array(op->ptr, "color", color);
1388         gamma = RNA_boolean_get(op->ptr, "gamma");
1389
1390         /* find button under mouse, check if it has RNA color property and
1391          * if it does copy the data */
1392         but = ui_but_find_active_in_region(ar);
1393
1394         if (but && but->type == UI_BTYPE_COLOR && but->rnaprop) {
1395                 const int color_len = RNA_property_array_length(&but->rnapoin, but->rnaprop);
1396                 BLI_assert(color_len <= 4);
1397
1398                 /* keep alpha channel as-is */
1399                 if (color_len == 4) {
1400                         color[3] = RNA_property_float_get_index(&but->rnapoin, but->rnaprop, 3);
1401                 }
1402
1403                 if (RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
1404                         if (!gamma)
1405                                 ui_block_cm_to_display_space_v3(but->block, color);
1406                         RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
1407                         RNA_property_update(C, &but->rnapoin, but->rnaprop);
1408                 }
1409                 else if (RNA_property_subtype(but->rnaprop) == PROP_COLOR) {
1410                         if (gamma)
1411                                 ui_block_cm_to_scene_linear_v3(but->block, color);
1412                         RNA_property_float_set_array(&but->rnapoin, but->rnaprop, color);
1413                         RNA_property_update(C, &but->rnapoin, but->rnaprop);
1414                 }
1415         }
1416         else {
1417                 if (gamma) {
1418                         srgb_to_linearrgb_v3_v3(color, color);
1419                 }
1420
1421                 ED_imapaint_bucket_fill(C, color, op);
1422         }
1423
1424         ED_region_tag_redraw(ar);
1425
1426         return OPERATOR_FINISHED;
1427 }
1428
1429
1430 static void UI_OT_drop_color(wmOperatorType *ot)
1431 {
1432         ot->name = "Drop Color";
1433         ot->idname = "UI_OT_drop_color";
1434         ot->description = "Drop colors to buttons";
1435
1436         ot->invoke = drop_color_invoke;
1437         ot->flag = OPTYPE_INTERNAL;
1438
1439         RNA_def_float_color(ot->srna, "color", 3, NULL, 0.0, FLT_MAX, "Color", "Source color", 0.0, 1.0);
1440         RNA_def_boolean(ot->srna, "gamma", 0, "Gamma Corrected", "The source color is gamma corrected ");
1441 }
1442
1443
1444 /* ********************************************************* */
1445 /* Registration */
1446
1447 void ED_operatortypes_ui(void)
1448 {
1449         WM_operatortype_append(UI_OT_reset_default_theme);
1450         WM_operatortype_append(UI_OT_copy_data_path_button);
1451         WM_operatortype_append(UI_OT_copy_python_command_button);
1452         WM_operatortype_append(UI_OT_reset_default_button);
1453         WM_operatortype_append(UI_OT_unset_property_button);
1454         WM_operatortype_append(UI_OT_use_property_button);
1455         WM_operatortype_append(UI_OT_unuse_property_button);
1456         WM_operatortype_append(UI_OT_override_type_set_button);
1457         WM_operatortype_append(UI_OT_override_remove_button);
1458         WM_operatortype_append(UI_OT_copy_to_selected_button);
1459         WM_operatortype_append(UI_OT_reports_to_textblock);  /* XXX: temp? */
1460         WM_operatortype_append(UI_OT_drop_color);
1461 #ifdef WITH_PYTHON
1462         WM_operatortype_append(UI_OT_editsource);
1463         WM_operatortype_append(UI_OT_edittranslation_init);
1464 #endif
1465         WM_operatortype_append(UI_OT_reloadtranslation);
1466
1467         /* external */
1468         WM_operatortype_append(UI_OT_eyedropper_color);
1469         WM_operatortype_append(UI_OT_eyedropper_colorband);
1470         WM_operatortype_append(UI_OT_eyedropper_colorband_point);
1471         WM_operatortype_append(UI_OT_eyedropper_id);
1472         WM_operatortype_append(UI_OT_eyedropper_depth);
1473         WM_operatortype_append(UI_OT_eyedropper_driver);
1474 }
1475
1476 /**
1477  * \brief User Interface Keymap
1478  */
1479 void ED_keymap_ui(wmKeyConfig *keyconf)
1480 {
1481         wmKeyMap *keymap = WM_keymap_find(keyconf, "User Interface", 0, 0);
1482         wmKeyMapItem *kmi;
1483
1484         /* eyedroppers - notice they all have the same shortcut, but pass the event
1485          * through until a suitable eyedropper for the active button is found */
1486         WM_keymap_add_item(keymap, "UI_OT_eyedropper_color", EKEY, KM_PRESS, 0, 0);
1487         WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband", EKEY, KM_PRESS, 0, 0);
1488         WM_keymap_add_item(keymap, "UI_OT_eyedropper_colorband_point", EKEY, KM_PRESS, KM_ALT, 0);
1489         WM_keymap_add_item(keymap, "UI_OT_eyedropper_id", EKEY, KM_PRESS, 0, 0);
1490         WM_keymap_add_item(keymap, "UI_OT_eyedropper_depth", EKEY, KM_PRESS, 0, 0);
1491
1492         /* Copy Data Path */
1493         WM_keymap_add_item(keymap, "UI_OT_copy_data_path_button", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
1494         kmi = WM_keymap_add_item(keymap, "UI_OT_copy_data_path_button", CKEY, KM_PRESS, KM_CTRL | KM_SHIFT | KM_ALT, 0);
1495         RNA_boolean_set(kmi->ptr, "full_path", true);
1496
1497         /* keyframes */
1498         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_insert_button", IKEY, KM_PRESS, 0, 0);
1499         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_delete_button", IKEY, KM_PRESS, KM_ALT, 0);
1500         WM_keymap_add_item(keymap, "ANIM_OT_keyframe_clear_button", IKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0);
1501
1502         /* drivers */
1503         WM_keymap_add_item(keymap, "ANIM_OT_driver_button_add", DKEY, KM_PRESS, KM_CTRL, 0);
1504         WM_keymap_add_item(keymap, "ANIM_OT_driver_button_remove", DKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
1505
1506         /* keyingsets */
1507         WM_keymap_add_item(keymap, "ANIM_OT_keyingset_button_add", KKEY, KM_PRESS, 0, 0);
1508         WM_keymap_add_item(keymap, "ANIM_OT_keyingset_button_remove", KKEY, KM_PRESS, KM_ALT, 0);
1509
1510         eyedropper_modal_keymap(keyconf);
1511         eyedropper_colorband_modal_keymap(keyconf);
1512 }