Blender V4.5
space_graph.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdio>
10#include <cstring>
11
12#include "DNA_anim_types.h"
14#include "DNA_scene_types.h"
15#include "DNA_space_types.h"
16
17#include "MEM_guardedalloc.h"
18
19#include "BLI_listbase.h"
20#include "BLI_math_color.h"
21#include "BLI_math_vector.h"
22#include "BLI_string.h"
23#include "BLI_utildefines.h"
24
25#include "BKE_context.hh"
26#include "BKE_fcurve.hh"
27#include "BKE_lib_query.hh"
28#include "BKE_lib_remap.hh"
29#include "BKE_screen.hh"
30
31#include "ED_anim_api.hh"
32#include "ED_markers.hh"
33#include "ED_screen.hh"
34#include "ED_space_api.hh"
35#include "ED_time_scrub_ui.hh"
36
37#include "GPU_immediate.hh"
38#include "GPU_state.hh"
39
40#include "WM_api.hh"
41#include "WM_message.hh"
42#include "WM_types.hh"
43
44#include "RNA_access.hh"
45#include "RNA_define.hh"
46#include "RNA_enum_types.hh"
47
48#include "UI_interface.hh"
49#include "UI_resources.hh"
50#include "UI_view2d.hh"
51
52#include "BLO_read_write.hh"
53
54#include "graph_intern.hh" /* own include */
55
56/* ******************** default callbacks for ipo space ***************** */
57
58static SpaceLink *graph_create(const ScrArea * /*area*/, const Scene *scene)
59{
60 ARegion *region;
61 SpaceGraph *sipo;
62
63 /* Graph Editor - general stuff */
64 sipo = MEM_callocN<SpaceGraph>("init graphedit");
65 sipo->spacetype = SPACE_GRAPH;
66
67 /* allocate DopeSheet data for Graph Editor */
68 sipo->ads = MEM_callocN<bDopeSheet>("GraphEdit DopeSheet");
69 sipo->ads->source = (ID *)scene;
70
71 /* settings for making it easier by default to just see what you're interested in tweaking */
73 sipo->flag |= SIPO_SHOW_MARKERS;
74
75 /* header */
76 region = BKE_area_region_new();
77
78 BLI_addtail(&sipo->regionbase, region);
81
82 /* channels */
83 region = BKE_area_region_new();
84
85 BLI_addtail(&sipo->regionbase, region);
87 region->alignment = RGN_ALIGN_LEFT;
88
90
91 /* ui buttons */
92 region = BKE_area_region_new();
93
94 BLI_addtail(&sipo->regionbase, region);
95 region->regiontype = RGN_TYPE_UI;
96 region->alignment = RGN_ALIGN_RIGHT;
97
98 /* main region */
99 region = BKE_area_region_new();
100
101 BLI_addtail(&sipo->regionbase, region);
102 region->regiontype = RGN_TYPE_WINDOW;
103
104 region->v2d.tot.xmin = 0.0f;
105 region->v2d.tot.ymin = float(scene->r.sfra) - 10.0f;
106 region->v2d.tot.xmax = float(scene->r.efra);
107 region->v2d.tot.ymax = 10.0f;
108
109 region->v2d.cur = region->v2d.tot;
110
111 region->v2d.min[0] = FLT_MIN;
112 region->v2d.min[1] = FLT_MIN;
113
114 region->v2d.max[0] = MAXFRAMEF;
115 region->v2d.max[1] = FLT_MAX;
116
119
120 region->v2d.keeptot = 0;
121
122 return (SpaceLink *)sipo;
123}
124
125/* Doesn't free the space-link itself. */
126static void graph_free(SpaceLink *sl)
127{
128 SpaceGraph *si = (SpaceGraph *)sl;
129
130 if (si->ads) {
132 MEM_freeN(si->ads);
133 }
134
135 if (si->runtime.ghost_curves.first) {
137 }
138}
139
140/* spacetype; init callback */
141static void graph_init(wmWindowManager *wm, ScrArea *area)
142{
143 SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
144
145 /* Init dope-sheet if non-existent (i.e. for old files). */
146 if (sipo->ads == nullptr) {
147 wmWindow *win = WM_window_find_by_area(wm, area);
148 sipo->ads = MEM_callocN<bDopeSheet>("GraphEdit DopeSheet");
149 sipo->ads->source = win ? (ID *)WM_window_get_active_scene(win) : nullptr;
150 }
151
152 /* force immediate init of any invalid F-Curve colors */
153 /* XXX: but, don't do SIPO_TEMP_NEEDCHANSYNC (i.e. channel select state sync)
154 * as this is run on each region resize; setting this here will cause selection
155 * state to be lost on area/region resizing. #35744.
156 */
158}
159
161{
162 SpaceGraph *sipon = static_cast<SpaceGraph *>(MEM_dupallocN(sl));
163
164 sipon->runtime = SpaceGraph_Runtime{};
165
166 /* clear or remove stuff from old */
167 BLI_duplicatelist(&sipon->runtime.ghost_curves, &((SpaceGraph *)sl)->runtime.ghost_curves);
168 sipon->ads = static_cast<bDopeSheet *>(MEM_dupallocN(sipon->ads));
169
170 return (SpaceLink *)sipon;
171}
172
173/* add handlers, stuff you only do once or on area/region changes */
175{
176 wmKeyMap *keymap;
177
178 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
179
180 /* own keymap */
181 keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor", SPACE_GRAPH, RGN_TYPE_WINDOW);
183 &region->runtime->handlers, keymap, WM_event_handler_region_v2d_mask_no_marker_poll);
184 keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, RGN_TYPE_WINDOW);
185 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
186}
187
188/* Draw a darker area above 1 and below -1. */
189static void draw_normalization_borders(Scene *scene, View2D *v2d)
190{
192
195
198
199 if (v2d->cur.ymax >= 1) {
200 immRectf(pos, scene->r.sfra, 1, scene->r.efra, v2d->cur.ymax);
201 }
202 if (v2d->cur.ymin <= -1) {
203 immRectf(pos, scene->r.sfra, v2d->cur.ymin, scene->r.efra, -1);
204 }
205
208}
209
210static void graph_main_region_draw(const bContext *C, ARegion *region)
211{
212 /* draw entirely, view changes should be handled here */
214 Scene *scene = CTX_data_scene(C);
215 bAnimContext ac;
216 View2D *v2d = &region->v2d;
217
218 const int min_height = UI_ANIM_MINY;
219
220 /* clear and setup matrix */
222
224
225 /* grid */
226 bool display_seconds = (sipo->mode == SIPO_MODE_ANIMATION) && (sipo->flag & SIPO_DRAWTIME);
227 if (region->winy > min_height) {
228 UI_view2d_draw_lines_x__frames_or_seconds(v2d, scene, display_seconds);
230 }
231
233
234 /* start and end frame (in F-Curve mode only) */
235 if (sipo->mode != SIPO_MODE_DRIVERS && region->winy > min_height) {
236 ANIM_draw_framerange(scene, v2d);
237 }
238
239 if (sipo->mode == SIPO_MODE_ANIMATION && (sipo->flag & SIPO_NORMALIZE)) {
240 draw_normalization_borders(scene, v2d);
241 }
242
243 /* draw data */
244 if (ANIM_animdata_get_context(C, &ac)) {
245 /* draw ghost curves */
246 graph_draw_ghost_curves(&ac, sipo, region);
247
248 /* draw curves twice - unselected, then selected, so that the are fewer occlusion problems */
249 graph_draw_curves(&ac, sipo, region, 0);
250 graph_draw_curves(&ac, sipo, region, 1);
251
252 /* XXX(ton): the slow way to set tot rect... but for nice sliders needed. */
253 /* Excluding handles from the calculation to save performance. This cuts the time it takes for
254 * this function to run in half which is a major performance bottleneck on heavy scenes. */
256 &ac, &v2d->tot.xmin, &v2d->tot.xmax, &v2d->tot.ymin, &v2d->tot.ymax, false, false);
257 /* extra offset so that these items are visible */
258 v2d->tot.xmin -= 10.0f;
259 v2d->tot.xmax += 10.0f;
260 }
261
262 if ((sipo->flag & SIPO_NODRAWCURSOR) == 0) {
264
266
267 /* horizontal component of value-cursor (value line before the current frame line) */
268 float y = sipo->cursorVal;
269
270 /* Draw a line to indicate the cursor value. */
273 GPU_line_width(2.0);
274
276 immVertex2f(pos, v2d->cur.xmin, y);
277 immVertex2f(pos, v2d->cur.xmax, y);
278 immEnd();
279
281
282 /* Vertical component of the cursor. */
283 if (sipo->mode == SIPO_MODE_DRIVERS) {
284 /* cursor x-value */
285 float x = sipo->cursorTime;
286
287 /* to help differentiate this from the current frame,
288 * draw slightly darker like the horizontal one */
291 GPU_line_width(2.0);
292
294 immVertex2f(pos, x, v2d->cur.ymin);
295 immVertex2f(pos, x, v2d->cur.ymax);
296 immEnd();
297
299 }
300
302 }
303
304 /* markers */
305 if (sipo->mode != SIPO_MODE_DRIVERS) {
306 UI_view2d_view_orthoSpecial(region, v2d, true);
307 int marker_draw_flag = DRAW_MARKERS_MARGIN;
308 if (sipo->flag & SIPO_SHOW_MARKERS && region->winy > (UI_ANIM_MINY + UI_MARKER_MARGIN_Y)) {
309 ED_markers_draw(C, marker_draw_flag);
310 }
311 }
312
313 /* preview range */
314 if (sipo->mode != SIPO_MODE_DRIVERS) {
316 ANIM_draw_previewrange(scene, v2d, 0);
317 }
318
319 /* callback */
322
323 /* reset view matrix */
325
326 /* time-scrubbing */
327 ED_time_scrub_draw(region, scene, display_seconds, false);
328}
329
331{
332 /* draw entirely, view changes should be handled here */
333 const SpaceGraph *sipo = CTX_wm_space_graph(C);
334 const bool minimized = (region->winy < UI_ANIM_MINY);
335
336 const Scene *scene = CTX_data_scene(C);
337 View2D *v2d = &region->v2d;
338
339 /* Driver Editor's X axis is not time. */
340 if (sipo->mode != SIPO_MODE_DRIVERS) {
341 /* scrubbing region */
342 ED_time_scrub_draw_current_frame(region, scene, sipo->flag & SIPO_DRAWTIME, !minimized);
343 }
344
345 if (!minimized) {
346 /* scrollers */
347 const rcti scroller_mask = ED_time_scrub_clamp_scroller_mask(v2d->mask);
348 /* FIXME: args for scrollers depend on the type of data being shown. */
349 region->v2d.scroll |= V2D_SCROLL_BOTTOM;
350 UI_view2d_scrollers_draw(v2d, &scroller_mask);
351
352 /* scale numbers */
353 {
354 rcti rect;
356 &rect, 0, 15 * UI_SCALE_FAC, 15 * UI_SCALE_FAC, region->winy - UI_TIME_SCRUB_MARGIN_Y);
358 }
359 }
360 else {
361 region->v2d.scroll &= ~V2D_SCROLL_BOTTOM;
362 }
363}
364
366{
367 wmKeyMap *keymap;
368
369 /* make sure we keep the hide flags */
370 region->v2d.scroll |= V2D_SCROLL_RIGHT;
371
372 /* prevent any noise of past */
374
377
378 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
379
380 /* own keymap */
381 keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", SPACE_EMPTY, RGN_TYPE_WINDOW);
382 WM_event_add_keymap_handler_v2d_mask(&region->runtime->handlers, keymap);
383 keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, RGN_TYPE_WINDOW);
384 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
385}
386
387static void set_v2d_height(View2D *v2d, const size_t item_count)
388{
389 const int height = ANIM_UI_get_channels_total_height(v2d, item_count);
390 v2d->tot.ymin = -height;
392}
393
394static void graph_channel_region_draw(const bContext *C, ARegion *region)
395{
396 bAnimContext ac;
397 if (!ANIM_animdata_get_context(C, &ac)) {
398 return;
399 }
400 View2D *v2d = &region->v2d;
401
402 /* clear and setup matrix */
404
405 ListBase anim_data = {nullptr, nullptr};
408 const size_t item_count = ANIM_animdata_filter(
409 &ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
410 set_v2d_height(v2d, item_count);
412
413 /* draw channels */
414 graph_draw_channel_names((bContext *)C, &ac, region, anim_data);
415
416 /* channel filter next to scrubbing area */
418
419 /* reset view matrix */
421
422 /* scrollers */
423 UI_view2d_scrollers_draw(v2d, nullptr);
424
425 ANIM_animdata_freelist(&anim_data);
426}
427
428/* add handlers, stuff you only do once or on area/region changes */
430{
431 ED_region_header_init(region);
432}
433
434static void graph_header_region_draw(const bContext *C, ARegion *region)
435{
436 ED_region_header(C, region);
437}
438
439/* add handlers, stuff you only do once or on area/region changes */
441{
442 wmKeyMap *keymap;
443
444 ED_region_panels_init(wm, region);
445
446 keymap = WM_keymap_ensure(wm->defaultconf, "Graph Editor Generic", SPACE_GRAPH, RGN_TYPE_WINDOW);
447 WM_event_add_keymap_handler_v2d_mask(&region->runtime->handlers, keymap);
448}
449
450static void graph_buttons_region_draw(const bContext *C, ARegion *region)
451{
452 ED_region_panels(C, region);
453}
454
456{
457 ARegion *region = params->region;
458 const wmNotifier *wmn = params->notifier;
459
460 /* context changes */
461 switch (wmn->category) {
462 case NC_ANIMATION:
463 ED_region_tag_redraw(region);
464 break;
465 case NC_SCENE:
466 switch (wmn->data) {
468 case ND_OB_ACTIVE:
469 case ND_FRAME:
470 case ND_FRAME_RANGE:
471 case ND_MARKERS:
472 ED_region_tag_redraw(region);
473 break;
474 case ND_SEQUENCER:
475 if (wmn->action == NA_SELECTED) {
476 ED_region_tag_redraw(region);
477 }
478 break;
479 }
480 break;
481 case NC_OBJECT:
482 switch (wmn->data) {
483 case ND_BONE_ACTIVE:
484 case ND_BONE_SELECT:
485 case ND_KEYS:
486 ED_region_tag_redraw(region);
487 break;
488 case ND_MODIFIER:
489 if (wmn->action == NA_RENAME) {
490 ED_region_tag_redraw(region);
491 }
492 break;
493 }
494 break;
495 case NC_NODE:
496 switch (wmn->action) {
497 case NA_EDITED:
498 case NA_SELECTED:
499 ED_region_tag_redraw(region);
500 break;
501 }
502 break;
503 case NC_ID:
504 if (wmn->action == NA_RENAME) {
505 ED_region_tag_redraw(region);
506 }
507 break;
508 case NC_SCREEN:
509 if (ELEM(wmn->data, ND_LAYER)) {
510 ED_region_tag_redraw(region);
511 }
512 break;
513 default:
514 if (wmn->data == ND_KEYS) {
515 ED_region_tag_redraw(region);
516 }
517 break;
518 }
519}
520
522{
523 wmMsgBus *mbus = params->message_bus;
524 Scene *scene = params->scene;
525 ARegion *region = params->region;
526
527 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
528 msg_sub_value_region_tag_redraw.owner = region;
529 msg_sub_value_region_tag_redraw.user_data = region;
530 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
531
532 /* Timeline depends on scene properties. */
533 {
534 bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
535 const PropertyRNA *props[] = {
536 use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
537 use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
538 &rna_Scene_use_preview_range,
539 &rna_Scene_frame_current,
540 };
541
542 PointerRNA idptr = RNA_id_pointer_create(&scene->id);
543
544 for (int i = 0; i < ARRAY_SIZE(props); i++) {
545 WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
546 }
547 }
548
549 /* All dope-sheet filter settings, etc. affect the drawing of this editor,
550 * also same applies for all animation-related data-types that may appear here,
551 * so just whitelist the entire structs for updates
552 */
553 {
554 wmMsgParams_RNA msg_key_params = {{}};
555 StructRNA *type_array[] = {
556 &RNA_DopeSheet, /* dope-sheet filters */
557
558 &RNA_ActionGroup, /* channel groups */
559 &RNA_FCurve, /* F-Curve */
560 &RNA_Keyframe,
561 &RNA_FCurveSample,
562
563 &RNA_FModifier, /* F-Modifiers (XXX: Why can't we just do all subclasses too?) */
564 &RNA_FModifierCycles,
565 &RNA_FModifierEnvelope,
566 &RNA_FModifierEnvelopeControlPoint,
567 &RNA_FModifierFunctionGenerator,
568 &RNA_FModifierGenerator,
569 &RNA_FModifierLimits,
570 &RNA_FModifierNoise,
571 &RNA_FModifierStepped,
572 };
573
574 for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
575 msg_key_params.ptr.type = type_array[i];
577 mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
578 }
579 }
580}
581
582/* editor level listener */
584{
585 ScrArea *area = params->area;
586 const wmNotifier *wmn = params->notifier;
587 SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
588
589 /* context changes */
590 switch (wmn->category) {
591 case NC_ANIMATION:
592 /* For selection changes of animation data, we can just redraw...
593 * otherwise auto-color might need to be done again. */
594 if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED)) {
595 ED_area_tag_redraw(area);
596 }
597 else {
599 }
600 break;
601 case NC_SCENE:
602 switch (wmn->data) {
603 case ND_OB_ACTIVE: /* Selection changed, so force refresh to flush
604 * (needs flag set to do syncing). */
605 case ND_OB_SELECT:
608 break;
609
610 default: /* just redrawing the view will do */
611 ED_area_tag_redraw(area);
612 break;
613 }
614 break;
615 case NC_OBJECT:
616 switch (wmn->data) {
617 case ND_BONE_SELECT: /* Selection changed, so force refresh to flush
618 * (needs flag set to do syncing). */
619 case ND_BONE_ACTIVE:
622 break;
623 case ND_TRANSFORM:
624 break; /* Do nothing. */
625
626 default: /* just redrawing the view will do */
627 ED_area_tag_redraw(area);
628 break;
629 }
630 break;
631 case NC_NODE:
632 if (wmn->action == NA_SELECTED) {
633 /* selection changed, so force refresh to flush (needs flag set to do syncing) */
636 }
637 break;
638 case NC_SPACE:
639 if (wmn->data == ND_SPACE_GRAPH) {
640 ED_area_tag_redraw(area);
641 }
642 break;
643 case NC_WINDOW:
644 if (sipo->runtime.flag &
646 {
647 /* force redraw/refresh after undo/redo - prevents "black curve" problem */
649 }
650 break;
651
652#if 0 /* XXX: restore the case below if not enough updates occur... */
653 default: {
654 if (wmn->data == ND_KEYS) {
655 ED_area_tag_redraw(area);
656 }
657 }
658#endif
659 }
660}
661
662/* Update F-Curve colors */
664{
665 bAnimContext ac;
666
667 ListBase anim_data = {nullptr, nullptr};
668 bAnimListElem *ale;
669 size_t items;
670 int filter;
671 int i;
672
673 if (ANIM_animdata_get_context(C, &ac) == false) {
674 return;
675 }
676
678
679 /* build list of F-Curves which will be visible as channels in channel-region
680 * - we don't include ANIMFILTER_CURVEVISIBLE filter, as that will result in a
681 * mismatch between channel-colors and the drawn curves
682 */
684 items = ANIM_animdata_filter(
685 &ac, &anim_data, eAnimFilter_Flags(filter), ac.data, eAnimCont_Types(ac.datatype));
686
687 /* loop over F-Curves, assigning colors */
688 for (ale = static_cast<bAnimListElem *>(anim_data.first), i = 0; ale; ale = ale->next, i++) {
690 "Expecting only FCurves when using the ANIMFILTER_FCURVESONLY filter");
691 FCurve *fcu = (FCurve *)ale->data;
692
693 /* set color of curve here */
694 switch (fcu->color_mode) {
695 case FCURVE_COLOR_CUSTOM: {
696 /* User has defined a custom color for this curve already
697 * (we assume it's not going to cause clashes with text colors),
698 * which should be left alone... Nothing needs to be done here.
699 */
700 break;
701 }
703 /* F-Curve's array index is automatically mapped to RGB values.
704 * This works best of 3-value vectors.
705 * TODO: find a way to module the hue so that not all curves have same color...
706 */
707 float *col = fcu->color;
708
709 switch (fcu->array_index) {
710 case 0:
712 break;
713 case 1:
715 break;
716 case 2:
718 break;
719 default:
720 /* 'unknown' color - bluish so as to not conflict with handles */
721 col[0] = 0.3f;
722 col[1] = 0.8f;
723 col[2] = 1.0f;
724 break;
725 }
726 break;
727 }
729 /* Like FCURVE_COLOR_AUTO_RGB, except this is for quaternions... */
730 float *col = fcu->color;
731
732 switch (fcu->array_index) {
733 case 1:
735 break;
736 case 2:
738 break;
739 case 3:
741 break;
742
743 case 0: {
744 /* Special Case: "W" channel should be yellowish, so blend X and Y channel colors... */
745 float c1[3], c2[3];
746 float h1[3], h2[3];
747 float hresult[3];
748
749 /* - get colors (rgb) */
752
753 /* - perform blending in HSV space (to keep brightness similar) */
754 rgb_to_hsv_v(c1, h1);
755 rgb_to_hsv_v(c2, h2);
756
757 interp_v3_v3v3(hresult, h1, h2, 0.5f);
758
759 /* - convert back to RGB for display */
760 hsv_to_rgb_v(hresult, col);
761 break;
762 }
763
764 default:
765 /* 'unknown' color - bluish so as to not conflict with handles */
766 col[0] = 0.3f;
767 col[1] = 0.8f;
768 col[2] = 1.0f;
769 break;
770 }
771 break;
772 }
774 default: {
775 /* determine color 'automatically' using 'magic function' which uses the given args
776 * of current item index + total items to determine some RGB color
777 */
778 getcolor_fcurve_rainbow(i, items, fcu->color);
779 break;
780 }
781 }
782 }
783
784 /* free temp list */
785 ANIM_animdata_freelist(&anim_data);
786}
787
788static void graph_refresh(const bContext *C, ScrArea *area)
789{
790 SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first;
791
792 /* updates to data needed depends on Graph Editor mode... */
793 switch (sipo->mode) {
794 case SIPO_MODE_ANIMATION: /* all animation */
795 {
796 break;
797 }
798
799 case SIPO_MODE_DRIVERS: /* Drivers only. */
800 {
801 break;
802 }
803 }
804
805 /* region updates? */
806 /* XXX re-sizing y-extents of tot should go here? */
807
808 /* Update the state of the animchannels in response to changes from the data they represent
809 * NOTE: the temp flag is used to indicate when this needs to be done,
810 * and will be cleared once handled. */
814 ED_area_tag_redraw(area);
815 }
816
817 /* We could check 'SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR', but color is recalculated anyway. */
820#if 0 /* Done below. */
822#endif
823 ED_area_tag_redraw(area);
824 }
825
828
829 /* init/adjust F-Curve colors */
831}
832
833static void graph_id_remap(ScrArea * /*area*/,
834 SpaceLink *slink,
835 const blender::bke::id::IDRemapper &mappings)
836{
837 SpaceGraph *sgraph = (SpaceGraph *)slink;
838 if (!sgraph->ads) {
839 return;
840 }
841
842 mappings.apply(reinterpret_cast<ID **>(&sgraph->ads->filter_grp), ID_REMAP_APPLY_DEFAULT);
843 mappings.apply((&sgraph->ads->source), ID_REMAP_APPLY_DEFAULT);
844}
845
847{
848 SpaceGraph *sgraph = reinterpret_cast<SpaceGraph *>(space_link);
849 const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
850 const bool is_readonly = (data_flags & IDWALK_READONLY) != 0;
851
852 /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceAction and #SpaceNla. */
853 if (sgraph->ads == nullptr) {
854 return;
855 }
856
859
860 if (!is_readonly) {
861 /* Force recalc of list of channels (i.e. including calculating F-Curve colors) to
862 * prevent the "black curves" problem post-undo. */
864 }
865}
866
868{
869 SpaceGraph *sgraph = static_cast<SpaceGraph *>(area->spacedata.first);
870 return sgraph->mode;
871}
872
873static void graph_space_subtype_set(ScrArea *area, int value)
874{
875 SpaceGraph *sgraph = static_cast<SpaceGraph *>(area->spacedata.first);
876 sgraph->mode = value;
877}
878
880 EnumPropertyItem **item,
881 int *totitem)
882{
884}
885
887{
888 SpaceGraph *sgraph = static_cast<SpaceGraph *>(area->spacedata.first);
889 const int index = RNA_enum_from_value(rna_enum_space_graph_mode_items, sgraph->mode);
891 return item.name;
892}
893
894static int graph_space_icon_get(const ScrArea *area)
895{
896 SpaceGraph *sgraph = static_cast<SpaceGraph *>(area->spacedata.first);
897 const int index = RNA_enum_from_value(rna_enum_space_graph_mode_items, sgraph->mode);
899 return item.icon;
900}
901
903{
904 SpaceGraph *sipo = (SpaceGraph *)sl;
905
906 BLO_read_struct(reader, bDopeSheet, &sipo->ads);
907 sipo->runtime = SpaceGraph_Runtime{};
908}
909
911{
912 SpaceGraph *sipo = (SpaceGraph *)sl;
913 ListBase tmpGhosts = sipo->runtime.ghost_curves;
914
915 /* temporarily disable ghost curves when saving */
917
918 BLO_write_struct(writer, SpaceGraph, sl);
919 if (sipo->ads) {
920 BLO_write_struct(writer, bDopeSheet, sipo->ads);
921 }
922
923 /* Re-enable ghost curves. */
924 sipo->runtime.ghost_curves = tmpGhosts;
925}
926
928{
929 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
930 ARegionType *art;
931
932 st->spaceid = SPACE_GRAPH;
933 STRNCPY(st->name, "Graph");
934
935 st->create = graph_create;
936 st->free = graph_free;
937 st->init = graph_init;
938 st->duplicate = graph_duplicate;
939 st->operatortypes = graphedit_operatortypes;
940 st->keymap = graphedit_keymap;
941 st->listener = graph_listener;
942 st->refresh = graph_refresh;
943 st->id_remap = graph_id_remap;
944 st->foreach_id = graph_foreach_id;
945 st->space_subtype_item_extend = graph_space_subtype_item_extend;
946 st->space_subtype_get = graph_space_subtype_get;
947 st->space_subtype_set = graph_space_subtype_set;
948 st->space_name_get = graph_space_name_get;
949 st->space_icon_get = graph_space_icon_get;
950 st->blend_read_data = graph_space_blend_read_data;
951 st->blend_read_after_liblink = nullptr;
952 st->blend_write = graph_space_blend_write;
953
954 /* regions: main window */
955 art = MEM_callocN<ARegionType>("spacetype graphedit region");
963
964 BLI_addhead(&st->regiontypes, art);
965
966 /* regions: header */
967 art = MEM_callocN<ARegionType>("spacetype graphedit region");
969 art->prefsizey = HEADERY;
974
975 BLI_addhead(&st->regiontypes, art);
976
977 /* regions: channels */
978 art = MEM_callocN<ARegionType>("spacetype graphedit region");
980 /* 200 is the 'standard', but due to scrollers, we want a bit more to fit the lock icons in */
981 art->prefsizex = 200 + V2D_SCROLL_WIDTH;
987
988 BLI_addhead(&st->regiontypes, art);
989
990 /* regions: UI buttons */
991 art = MEM_callocN<ARegionType>("spacetype graphedit region");
992 art->regionid = RGN_TYPE_UI;
998
999 BLI_addhead(&st->regiontypes, art);
1000
1002
1003 art = ED_area_type_hud(st->spaceid);
1004 BLI_addhead(&st->regiontypes, art);
1005
1006 BKE_spacetype_register(std::move(st));
1007}
SpaceGraph * CTX_wm_space_graph(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
void BKE_fcurves_free(ListBase *list)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_DIRECT_WEAK_LINK
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_READONLY
@ ID_REMAP_APPLY_DEFAULT
void BKE_spacetype_register(std::unique_ptr< SpaceType > st)
Definition screen.cc:276
ARegion * BKE_area_region_new()
Definition screen.cc:381
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct(reader, struct_name, ptr_p)
@ ADS_FILTER_ONLYSEL
@ FCURVE_COLOR_AUTO_RGB
@ FCURVE_COLOR_AUTO_RAINBOW
@ FCURVE_COLOR_CUSTOM
@ FCURVE_COLOR_AUTO_YRGB
Object groups, one object can be in many groups at once.
@ SCER_PRV_RANGE
#define MAXFRAMEF
#define HEADERY
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ RGN_TYPE_HEADER
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ SPACE_EMPTY
@ SPACE_GRAPH
@ SIPO_MODE_DRIVERS
@ SIPO_MODE_ANIMATION
@ SIPO_DRAWTIME
@ SIPO_NODRAWCURSOR
@ SIPO_SHOW_MARKERS
@ SIPO_NORMALIZE
@ SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC
@ SIPO_RUNTIME_FLAG_NEED_CHAN_SYNC_COLOR
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT
#define UI_SCALE_FAC
@ USER_HEADER_BOTTOM
@ V2D_SCROLL_LEFT
@ V2D_SCROLL_HORIZONTAL_HIDE
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_TOP
@ V2D_SCROLL_VERTICAL_HANDLES
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HANDLES
@ ANIMTYPE_NLACURVE
@ ANIMTYPE_FCURVE
eAnimCont_Types
eAnimFilter_Flags
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_LIST_VISIBLE
@ ANIMFILTER_LIST_CHANNELS
@ ANIMFILTER_NODUPLIS
@ ANIMFILTER_FCURVESONLY
@ DRAW_MARKERS_MARGIN
Definition ED_markers.hh:27
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
ARegionType * ED_area_type_hud(int space_type)
@ ED_KEYMAP_UI
Definition ED_screen.hh:740
@ ED_KEYMAP_ANIMATION
Definition ED_screen.hh:744
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:746
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:743
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:745
void ED_region_panels(const bContext *C, ARegion *region)
Definition area.cc:3466
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3754
void ED_region_header_init(ARegion *region)
Definition area.cc:3769
void ED_area_tag_refresh(ScrArea *area)
Definition area.cc:743
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3473
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:639
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:384
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_POST_VIEW
#define REGION_DRAW_PRE_VIEW
void immEnd()
void immUnbindProgram()
void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset)
void immVertex2f(uint attr_id, float x, float y)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
GPUVertFormat * immVertexFormat()
void immBegin(GPUPrimType, uint vertex_len)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
@ GPU_PRIM_LINES
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
void GPU_blend(eGPUBlend blend)
Definition gpu_state.cc:42
void GPU_line_width(float width)
Definition gpu_state.cc:166
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define UI_SIDEBAR_PANEL_WIDTH
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_BACK
@ TH_CFRAME
@ TH_SCROLL_TEXT
@ TH_AXIS_Y
@ TH_AXIS_X
@ TH_AXIS_Z
void UI_ThemeClearColor(int colorid)
void UI_SetTheme(int spacetype, int regionid)
#define UI_ANIM_MINY
Definition UI_view2d.hh:473
#define UI_MARKER_MARGIN_Y
Definition UI_view2d.hh:470
void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, bool xaxis)
Definition view2d.cc:1136
void UI_view2d_draw_lines_x__frames_or_seconds(const View2D *v2d, const Scene *scene, bool display_seconds)
void UI_view2d_curRect_clamp_y(View2D *v2d)
Definition view2d.cc:844
#define V2D_SCROLL_WIDTH
Definition UI_view2d.hh:54
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition view2d.cc:1503
void UI_view2d_draw_lines_y__values(const View2D *v2d)
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1162
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:221
#define UI_TIME_SCRUB_MARGIN_Y
Definition UI_view2d.hh:471
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
void UI_view2d_draw_scale_y__values(const ARegion *region, const View2D *v2d, const rcti *rect, int colorid)
@ V2D_COMMONVIEW_LIST
Definition UI_view2d.hh:35
@ V2D_COMMONVIEW_CUSTOM
Definition UI_view2d.hh:31
#define ND_SEQUENCER
Definition WM_types.hh:434
#define NC_WINDOW
Definition WM_types.hh:372
#define NC_ID
Definition WM_types.hh:392
#define NC_NODE
Definition WM_types.hh:391
#define ND_OB_ACTIVE
Definition WM_types.hh:437
#define ND_RENDER_OPTIONS
Definition WM_types.hh:432
#define NC_ANIMATION
Definition WM_types.hh:385
#define NC_SCREEN
Definition WM_types.hh:374
#define ND_OB_SELECT
Definition WM_types.hh:439
#define NC_SCENE
Definition WM_types.hh:375
#define ND_MODIFIER
Definition WM_types.hh:459
#define NA_EDITED
Definition WM_types.hh:581
#define ND_SPACE_GRAPH
Definition WM_types.hh:529
#define ND_FRAME_RANGE
Definition WM_types.hh:448
#define ND_MARKERS
Definition WM_types.hh:430
#define ND_FRAME
Definition WM_types.hh:431
#define ND_BONE_ACTIVE
Definition WM_types.hh:456
#define ND_TRANSFORM
Definition WM_types.hh:453
#define ND_LAYER
Definition WM_types.hh:447
#define ND_KEYS
Definition WM_types.hh:460
#define NA_RENAME
Definition WM_types.hh:585
#define ND_BONE_SELECT
Definition WM_types.hh:457
#define ND_KEYFRAME
Definition WM_types.hh:491
#define NC_OBJECT
Definition WM_types.hh:376
#define ND_ANIMCHAN
Definition WM_types.hh:493
#define NC_SPACE
Definition WM_types.hh:389
#define NA_SELECTED
Definition WM_types.hh:586
float ANIM_UI_get_channels_total_height(View2D *v2d, const int item_count)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition anim_deps.cc:463
void ANIM_sync_animchannels_to_data(const bContext *C)
Definition anim_deps.cc:261
void ANIM_draw_previewrange(const Scene *scene, View2D *v2d, int end_frame_width)
Definition anim_draw.cc:75
void ANIM_draw_framerange(Scene *scene, View2D *v2d)
Definition anim_draw.cc:109
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, const eAnimFilter_Flags filter_mode, void *data, const eAnimCont_Types datatype)
void getcolor_fcurve_rainbow(int cur, int tot, float out[3])
void ED_markers_draw(const bContext *C, int flag)
#define U
BMesh const char void * data
IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options, ID *id_self=nullptr) const
uint pos
uint col
#define filter
void graph_buttons_register(ARegionType *art)
void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region)
void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region, const ListBase &anim_data)
void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, short sel)
void graphedit_operatortypes()
Definition graph_ops.cc:423
void graphedit_keymap(wmKeyConfig *keyconf)
Definition graph_ops.cc:527
void get_graph_keyframe_extents(bAnimContext *ac, float *xmin, float *xmax, float *ymin, float *ymax, bool do_sel_only, bool include_handles)
Definition graph_view.cc:42
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
format
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_enum_items_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
const EnumPropertyItem rna_enum_space_graph_mode_items[]
Definition rna_space.cc:167
static void graph_channel_region_draw(const bContext *C, ARegion *region)
static void graph_refresh(const bContext *C, ScrArea *area)
static void graph_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
static void draw_normalization_borders(Scene *scene, View2D *v2d)
static void graph_space_subtype_item_extend(bContext *, EnumPropertyItem **item, int *totitem)
static void graph_main_region_draw_overlay(const bContext *C, ARegion *region)
static void graph_region_listener(const wmRegionListenerParams *params)
static void graph_channel_region_init(wmWindowManager *wm, ARegion *region)
void ED_spacetype_ipo()
static int graph_space_subtype_get(ScrArea *area)
static void graph_main_region_init(wmWindowManager *wm, ARegion *region)
static void graph_header_region_draw(const bContext *C, ARegion *region)
static void graph_listener(const wmSpaceTypeListenerParams *params)
static SpaceLink * graph_duplicate(SpaceLink *sl)
static void graph_space_blend_write(BlendWriter *writer, SpaceLink *sl)
static void graph_free(SpaceLink *sl)
static void set_v2d_height(View2D *v2d, const size_t item_count)
static void graph_space_subtype_set(ScrArea *area, int value)
static blender::StringRefNull graph_space_name_get(const ScrArea *area)
static void graph_header_region_init(wmWindowManager *, ARegion *region)
static void graph_main_region_draw(const bContext *C, ARegion *region)
static void graph_refresh_fcurve_colors(const bContext *C)
static void graph_buttons_region_init(wmWindowManager *wm, ARegion *region)
static void graph_buttons_region_draw(const bContext *C, ARegion *region)
static void graph_id_remap(ScrArea *, SpaceLink *slink, const blender::bke::id::IDRemapper &mappings)
static void graph_init(wmWindowManager *wm, ScrArea *area)
static void graph_space_blend_read_data(BlendDataReader *reader, SpaceLink *sl)
static int graph_space_icon_get(const ScrArea *area)
static SpaceLink * graph_create(const ScrArea *, const Scene *scene)
static void graph_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
#define FLT_MAX
Definition stdcycles.h:14
void(* message_subscribe)(const wmRegionMessageSubscribeParams *params)
void(* listener)(const wmRegionListenerParams *params)
void(* draw)(const bContext *C, ARegion *region)
void(* draw_overlay)(const bContext *C, ARegion *region)
void(* init)(wmWindowManager *wm, ARegion *region)
ARegionRuntimeHandle * runtime
const char * name
Definition RNA_types.hh:627
float color[3]
int array_index
Definition DNA_ID.h:404
void * first
StructRNA * type
Definition RNA_types.hh:52
struct RenderData r
ListBase spacedata
struct bDopeSheet * ads
SpaceGraph_Runtime runtime
ListBase regionbase
short keeptot
float max[2]
float min[2]
eAnimCont_Types datatype
bDopeSheet * ads
bAnimListElem * next
eAnim_ChannelType type
ListBase chanbase
struct Collection * filter_grp
float xmax
float xmin
float ymax
float ymin
unsigned int data
Definition WM_types.hh:355
unsigned int action
Definition WM_types.hh:355
unsigned int category
Definition WM_types.hh:355
struct wmKeyConfig * defaultconf
i
Definition text_draw.cc:230
rcti ED_time_scrub_clamp_scroller_mask(const rcti &scroller_mask)
void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDopeSheet *dopesheet)
void ED_time_scrub_draw_current_frame(const ARegion *region, const Scene *scene, bool display_seconds, bool display_stalk)
void ED_time_scrub_draw(const ARegion *region, const Scene *scene, bool display_seconds, bool discrete_frames)
wmEventHandler_Keymap * WM_event_add_keymap_handler_poll(ListBase *handlers, wmKeyMap *keymap, EventHandlerPoll poll)
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmEventHandler_Keymap * WM_event_add_keymap_handler_v2d_mask(ListBase *handlers, wmKeyMap *keymap)
bool WM_event_handler_region_v2d_mask_no_marker_poll(const wmWindow *win, const ScrArea *area, const ARegion *region, const wmEvent *event)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:893
void WM_msg_subscribe_rna_params(wmMsgBus *mbus, const wmMsgParams_RNA *msg_key_params, const wmMsgSubscribeValue *msg_val_params, const char *id_repr)
void WM_msg_subscribe_rna(wmMsgBus *mbus, PointerRNA *ptr, const PropertyRNA *prop, const wmMsgSubscribeValue *msg_val_params, const char *id_repr)
wmWindow * WM_window_find_by_area(wmWindowManager *wm, const ScrArea *area)
Scene * WM_window_get_active_scene(const wmWindow *win)