Blender V4.3
space_action.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
9#include <cstdio>
10#include <cstring>
11
12#include "DNA_action_types.h"
14#include "DNA_scene_types.h"
15
16#include "DNA_screen_types.h"
17#include "MEM_guardedalloc.h"
18
19#include "BLI_blenlib.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_context.hh"
23#include "BKE_lib_query.hh"
24#include "BKE_lib_remap.hh"
25#include "BKE_screen.hh"
26
27#include "RNA_access.hh"
28#include "RNA_define.hh"
29#include "RNA_enum_types.hh"
30
31#include "WM_api.hh"
32#include "WM_message.hh"
33#include "WM_types.hh"
34
35#include "UI_interface.hh"
36#include "UI_resources.hh"
37#include "UI_view2d.hh"
38
39#include "ED_anim_api.hh"
40#include "ED_markers.hh"
41#include "ED_screen.hh"
42#include "ED_space_api.hh"
43#include "ED_time_scrub_ui.hh"
44
45#include "BLO_read_write.hh"
46
47#include "GPU_matrix.hh"
48
49#include "action_intern.hh" /* own include */
50
51/* -------------------------------------------------------------------- */
55static SpaceLink *action_create(const ScrArea *area, const Scene *scene)
56{
57 SpaceAction *saction;
58 ARegion *region;
59
60 saction = MEM_cnew<SpaceAction>("initaction");
61 saction->spacetype = SPACE_ACTION;
62
63 saction->mode = SACTCONT_DOPESHEET;
66
68
72
73 /* header */
74 region = MEM_cnew<ARegion>("header for action");
75
76 BLI_addtail(&saction->regionbase, region);
77 region->regiontype = RGN_TYPE_HEADER;
78 region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP;
79
80 /* channel list region */
81 region = MEM_cnew<ARegion>("channel region for action");
82 BLI_addtail(&saction->regionbase, region);
83 region->regiontype = RGN_TYPE_CHANNELS;
84 region->alignment = RGN_ALIGN_LEFT;
85
86 /* only need to set scroll settings, as this will use 'listview' v2d configuration */
87 region->v2d.scroll = V2D_SCROLL_BOTTOM;
88 region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
89
90 /* ui buttons */
91 region = MEM_cnew<ARegion>("buttons region for action");
92
93 BLI_addtail(&saction->regionbase, region);
94 region->regiontype = RGN_TYPE_UI;
95 region->alignment = RGN_ALIGN_RIGHT;
96
97 /* main region */
98 region = MEM_cnew<ARegion>("main region for action");
99
100 BLI_addtail(&saction->regionbase, region);
101 region->regiontype = RGN_TYPE_WINDOW;
102
103 region->v2d.tot.xmin = float(scene->r.sfra - 10);
104 region->v2d.tot.ymin = float(-area->winy) / 3.0f;
105 region->v2d.tot.xmax = float(scene->r.efra + 10);
106 region->v2d.tot.ymax = 0.0f;
107
108 region->v2d.cur = region->v2d.tot;
109
110 region->v2d.min[0] = 0.0f;
111 region->v2d.min[1] = 0.0f;
112
113 region->v2d.max[0] = MAXFRAMEF;
114 region->v2d.max[1] = FLT_MAX;
115
116 region->v2d.minzoom = 0.01f;
117 region->v2d.maxzoom = 50;
118 region->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
119 region->v2d.scroll |= V2D_SCROLL_RIGHT;
120 region->v2d.keepzoom = V2D_LOCKZOOM_Y;
121 region->v2d.keepofs = V2D_KEEPOFS_Y;
122 region->v2d.align = V2D_ALIGN_NO_POS_Y;
123 region->v2d.flag = V2D_VIEWSYNC_AREA_VERTICAL;
124
125 return (SpaceLink *)saction;
126}
127
128/* Doesn't free the space-link itself. */
129static void action_free(SpaceLink * /*sl*/)
130{
131 // SpaceAction *saction = (SpaceAction *) sl;
132}
133
134/* spacetype; init callback */
135static void action_init(wmWindowManager * /*wm*/, ScrArea *area)
136{
137 SpaceAction *saction = static_cast<SpaceAction *>(area->spacedata.first);
139}
140
142{
143 SpaceAction *sactionn = static_cast<SpaceAction *>(MEM_dupallocN(sl));
144
145 memset(&sactionn->runtime, 0x0, sizeof(sactionn->runtime));
146
147 /* clear or remove stuff from old */
148
149 return (SpaceLink *)sactionn;
150}
151
152/* add handlers, stuff you only do once or on area/region changes */
154{
155 wmKeyMap *keymap;
156
157 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
158
159 /* own keymap */
160 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet", SPACE_ACTION, RGN_TYPE_WINDOW);
161 WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
162 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
163 WM_event_add_keymap_handler(&region->handlers, keymap);
164}
165
166static void set_v2d_height(View2D *v2d, const size_t item_count, const bool add_marker_padding)
167{
168 const int height = ANIM_UI_get_channels_total_height(v2d, item_count);
169 float pad_bottom = add_marker_padding ? UI_MARKER_MARGIN_Y : 0;
170 /* Add padding for the collapsed redo panel. */
171 pad_bottom += HEADERY;
172 v2d->tot.ymin = -(height + pad_bottom);
174}
175
176static void action_main_region_draw(const bContext *C, ARegion *region)
177{
178 /* draw entirely, view changes should be handled here */
179 SpaceAction *saction = CTX_wm_space_action(C);
180 Scene *scene = CTX_data_scene(C);
181 bAnimContext ac;
182 View2D *v2d = &region->v2d;
183 short marker_flag = 0;
184
185 ListBase anim_data = {nullptr, nullptr};
186 const bool has_anim_context = ANIM_animdata_get_context(C, &ac);
187 if (has_anim_context) {
188 /* Build list of channels to draw. */
191 const size_t items = ANIM_animdata_filter(
192 &ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
193 /* The View2D's height needs to be set before calling UI_view2d_view_ortho because the latter
194 * uses the View2D's `cur` rect which might be modified when setting the height. */
196 }
197
199
200 /* clear and setup matrix */
202
204
205 /* time grid */
207 v2d, scene, saction->flag & SACTION_DRAWTIME, true);
208
210
211 /* start and end frame */
212 ANIM_draw_framerange(scene, v2d);
213
214 /* Draw the manually set intended playback frame range highlight in the Action editor. */
215 if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && saction->action) {
217
218 ANIM_draw_action_framerange(adt, saction->action, v2d, -FLT_MAX, FLT_MAX);
219 }
220
221 /* data */
222 if (has_anim_context) {
223 draw_channel_strips(&ac, saction, region, &anim_data);
224 }
225
226 /* markers */
227 UI_view2d_view_orthoSpecial(region, v2d, true);
228
229 marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) |
231
232 if (saction->flag & SACTION_SHOW_MARKERS) {
233 ED_markers_draw(C, marker_flag);
234 }
235
236 /* preview range */
238 ANIM_draw_previewrange(C, v2d, 0);
239
240 /* callback */
243
244 /* reset view matrix */
246
247 /* gizmos */
248 WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
249
250 /* scrubbing region */
251 ED_time_scrub_draw(region, scene, saction->flag & SACTION_DRAWTIME, true);
252}
253
255{
256 /* draw entirely, view changes should be handled here */
257 const SpaceAction *saction = CTX_wm_space_action(C);
258 const Scene *scene = CTX_data_scene(C);
259 const Object *obact = CTX_data_active_object(C);
260 View2D *v2d = &region->v2d;
261
262 /* caches */
263 if (saction->mode == SACTCONT_TIMELINE) {
265 UI_view2d_view_orthoSpecial(region, v2d, true);
266 timeline_draw_cache(saction, obact, scene);
268 }
269
270 /* scrubbing region */
271 ED_time_scrub_draw_current_frame(region, scene, saction->flag & SACTION_DRAWTIME);
272
273 /* scrollers */
274 if (region->winy > HEADERY * UI_SCALE_FAC) {
275 UI_view2d_scrollers_draw(v2d, nullptr);
276 }
277}
278
279/* add handlers, stuff you only do once or on area/region changes */
281{
282 wmKeyMap *keymap;
283
284 /* ensure the 2d view sync works - main region has bottom scroller */
285 region->v2d.scroll = V2D_SCROLL_BOTTOM;
286
287 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
288
289 /* own keymap */
290 keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", SPACE_EMPTY, RGN_TYPE_WINDOW);
291 WM_event_add_keymap_handler_v2d_mask(&region->handlers, keymap);
292
293 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
294 WM_event_add_keymap_handler(&region->handlers, keymap);
295}
296
297static void action_channel_region_draw(const bContext *C, ARegion *region)
298{
299 /* draw entirely, view changes should be handled here */
300 bAnimContext ac;
301 const bool has_valid_animcontext = ANIM_animdata_get_context(C, &ac);
302
303 /* clear and setup matrix */
305
306 if (!has_valid_animcontext) {
307 return;
308 }
309
310 View2D *v2d = &region->v2d;
311
312 ListBase anim_data = {nullptr, nullptr};
313 /* Build list of channels to draw. */
316 const size_t item_count = ANIM_animdata_filter(
317 &ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
318 /* The View2D's height needs to be set before calling UI_view2d_view_ortho because the latter
319 * uses the View2D's `cur` rect which might be modified when setting the height. */
320 set_v2d_height(v2d, item_count, !BLI_listbase_is_empty(ac.markers));
321
323 draw_channel_names((bContext *)C, &ac, region, anim_data);
324
325 /* channel filter next to scrubbing area */
327
328 /* reset view matrix */
330
331 /* no scrollers here */
332 ANIM_animdata_freelist(&anim_data);
333}
334
335/* add handlers, stuff you only do once or on area/region changes */
337{
338 ED_region_header_init(region);
339}
340
341static void action_header_region_draw(const bContext *C, ARegion *region)
342{
343 /* The anim context is not actually used, but this makes sure the action being displayed is up to
344 * date. */
345 bAnimContext ac;
347
348 ED_region_header(C, region);
349}
350
352{
353 ARegion *region = params->region;
354 const wmNotifier *wmn = params->notifier;
355
356 /* context changes */
357 switch (wmn->category) {
358 case NC_ANIMATION:
359 ED_region_tag_redraw(region);
360 break;
361 case NC_SCENE:
362 switch (wmn->data) {
363 case ND_OB_ACTIVE:
364 case ND_FRAME:
365 ED_region_tag_redraw(region);
366 break;
367 }
368 break;
369 case NC_OBJECT:
370 switch (wmn->data) {
371 case ND_BONE_ACTIVE:
372 case ND_BONE_SELECT:
373 case ND_KEYS:
374 ED_region_tag_redraw(region);
375 break;
376 case ND_MODIFIER:
377 if (wmn->action == NA_RENAME) {
378 ED_region_tag_redraw(region);
379 }
380 break;
381 }
382 break;
383 case NC_GPENCIL:
384 if (ELEM(wmn->action, NA_RENAME, NA_SELECTED)) {
385 ED_region_tag_redraw(region);
386 }
387 break;
388 case NC_ID:
389 if (wmn->action == NA_RENAME) {
390 ED_region_tag_redraw(region);
391 }
392 break;
393 default:
394 if (wmn->data == ND_KEYS) {
395 ED_region_tag_redraw(region);
396 }
397 break;
398 }
399}
400
402{
403 wmMsgBus *mbus = params->message_bus;
404 ARegion *region = params->region;
405
406 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
407 msg_sub_value_region_tag_redraw.owner = region;
408 msg_sub_value_region_tag_redraw.user_data = region;
409 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
410
411 /* All dopesheet filter settings, etc. affect the drawing of this editor,
412 * also same applies for all animation-related data-types that may appear here,
413 * so just whitelist the entire structs for updates
414 */
415 {
416 wmMsgParams_RNA msg_key_params = {{nullptr}};
417 StructRNA *type_array[] = {
418 &RNA_DopeSheet, /* dopesheet filters */
419
420 &RNA_ActionGroup, /* channel groups */
421
422 &RNA_FCurve, /* F-Curve */
423 &RNA_Keyframe,
424 &RNA_FCurveSample,
425
426 &RNA_GreasePencil, /* Grease Pencil */
427 &RNA_GPencilLayer,
428 &RNA_GPencilFrame,
429 };
430
431 for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
432 msg_key_params.ptr.type = type_array[i];
434 mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
435 }
436 }
437}
438
440{
441 ARegion *region = params->region;
442 const wmNotifier *wmn = params->notifier;
443
444 /* context changes */
445 switch (wmn->category) {
446 case NC_ANIMATION:
447 ED_region_tag_redraw(region);
448 break;
449 case NC_SCENE:
450 switch (wmn->data) {
452 case ND_OB_ACTIVE:
453 case ND_FRAME:
454 case ND_FRAME_RANGE:
455 case ND_MARKERS:
456 ED_region_tag_redraw(region);
457 break;
458 }
459 break;
460 case NC_OBJECT:
461 switch (wmn->data) {
462 case ND_TRANSFORM:
463 /* moving object shouldn't need to redraw action */
464 break;
465 case ND_BONE_ACTIVE:
466 case ND_BONE_SELECT:
468 case ND_KEYS:
469 ED_region_tag_redraw(region);
470 break;
471 }
472 break;
473 case NC_NODE:
474 switch (wmn->action) {
475 case NA_EDITED:
476 ED_region_tag_redraw(region);
477 break;
478 }
479 break;
480 case NC_ID:
481 if (wmn->action == NA_RENAME) {
482 ED_region_tag_redraw(region);
483 }
484 break;
485 case NC_SCREEN:
486 if (ELEM(wmn->data, ND_LAYER)) {
487 ED_region_tag_redraw(region);
488 }
489 break;
490 default:
491 if (wmn->data == ND_KEYS) {
492 ED_region_tag_redraw(region);
493 }
494 break;
495 }
496}
497
499{
500 wmMsgBus *mbus = params->message_bus;
501 Scene *scene = params->scene;
502 ARegion *region = params->region;
503
504 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
505 msg_sub_value_region_tag_redraw.owner = region;
506 msg_sub_value_region_tag_redraw.user_data = region;
507 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
508
509 /* Timeline depends on scene properties. */
510 {
511 bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
512 const PropertyRNA *props[] = {
513 use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
514 use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
515 &rna_Scene_use_preview_range,
516 &rna_Scene_frame_current,
517 };
518
519 PointerRNA idptr = RNA_id_pointer_create(&scene->id);
520
521 for (int i = 0; i < ARRAY_SIZE(props); i++) {
522 WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
523 }
524 }
525
526 /* Now run the general "channels region" one - since channels and main should be in sync */
528}
529
530/* editor level listener */
532{
533 ScrArea *area = params->area;
534 const wmNotifier *wmn = params->notifier;
535 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
536
537 /* context changes */
538 switch (wmn->category) {
539 case NC_GPENCIL:
540 /* only handle these events for containers in which GPencil frames are displayed */
542 if (wmn->action == NA_EDITED) {
543 ED_area_tag_redraw(area);
544 }
545 else if (wmn->action == NA_SELECTED) {
548 }
549 }
550 break;
551 case NC_ANIMATION:
552 /* For NLA tweak-mode enter/exit, need complete refresh. */
553 if (wmn->data == ND_NLA_ACTCHANGE) {
556 }
557 /* Auto-color only really needs to change when channels are added/removed,
558 * or previously hidden stuff appears
559 * (assume for now that if just adding these works, that will be fine).
560 */
561 else if (((wmn->data == ND_KEYFRAME) && ELEM(wmn->action, NA_ADDED, NA_REMOVED)) ||
562 ((wmn->data == ND_ANIMCHAN) && (wmn->action != NA_SELECTED)))
563 {
565 }
566 /* for simple edits to the curve data though (or just plain selections),
567 * a simple redraw should work
568 * (see #39851 for an example of how this can go wrong)
569 */
570 else {
571 ED_area_tag_redraw(area);
572 }
573 break;
574 case NC_SCENE:
575 switch (wmn->data) {
576 case ND_SEQUENCER:
577 if (wmn->action == NA_SELECTED) {
580 }
581 break;
582 case ND_OB_ACTIVE:
583 case ND_OB_SELECT:
584 /* Selection changed, so force refresh to flush
585 * (needs flag set to do syncing). */
588 break;
589 case ND_RENDER_RESULT:
590 ED_area_tag_redraw(area);
591 break;
592 case ND_FRAME_RANGE:
593 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
594 if (region->regiontype == RGN_TYPE_WINDOW) {
595 Scene *scene = static_cast<Scene *>(wmn->reference);
596 region->v2d.tot.xmin = float(scene->r.sfra - 4);
597 region->v2d.tot.xmax = float(scene->r.efra + 4);
598 break;
599 }
600 }
601 break;
602 default:
603 if (saction->mode != SACTCONT_TIMELINE) {
604 /* Just redrawing the view will do. */
605 ED_area_tag_redraw(area);
606 }
607 break;
608 }
609 break;
610 case NC_OBJECT:
611 switch (wmn->data) {
612 case ND_BONE_SELECT: /* Selection changed, so force refresh to flush
613 * (needs flag set to do syncing). */
614 case ND_BONE_ACTIVE:
617 break;
618 case ND_TRANSFORM:
619 /* moving object shouldn't need to redraw action */
620 break;
621 case ND_POINTCACHE:
622 case ND_MODIFIER:
623 case ND_PARTICLE:
624 /* only needed in timeline mode */
625 if (saction->mode == SACTCONT_TIMELINE) {
627 ED_area_tag_redraw(area);
628 }
629 break;
630 default: /* just redrawing the view will do */
631 ED_area_tag_redraw(area);
632 break;
633 }
634 break;
635 case NC_MASK:
636 if (saction->mode == SACTCONT_MASK) {
637 switch (wmn->data) {
638 case ND_DATA:
640 ED_area_tag_redraw(area);
641 break;
642 default: /* just redrawing the view will do */
643 ED_area_tag_redraw(area);
644 break;
645 }
646 }
647 break;
648 case NC_NODE:
649 if (wmn->action == NA_SELECTED) {
650 /* selection changed, so force refresh to flush (needs flag set to do syncing) */
653 }
654 break;
655 case NC_SPACE:
656 switch (wmn->data) {
658 ED_area_tag_redraw(area);
659 break;
660 case ND_SPACE_TIME:
661 ED_area_tag_redraw(area);
662 break;
663 case ND_SPACE_CHANGED:
666 break;
667 }
668 break;
669 case NC_WINDOW:
671 /* force redraw/refresh after undo/redo, see: #28962. */
673 }
674 break;
675 case NC_WM:
676 switch (wmn->data) {
677 case ND_FILEREAD:
679 break;
680 }
681 break;
682 }
683}
684
686{
687 ScrArea *area = params->area;
688 ARegion *region = params->region;
689 const wmNotifier *wmn = params->notifier;
690 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
691
692 /* context changes */
693 switch (wmn->category) {
694 case NC_SCREEN:
695 if (saction->mode == SACTCONT_TIMELINE) {
696 if (wmn->data == ND_ANIMPLAY) {
697 ED_region_tag_redraw(region);
698 }
699 }
700 break;
701 case NC_SCENE:
702 if (saction->mode == SACTCONT_TIMELINE) {
703 switch (wmn->data) {
704 case ND_RENDER_RESULT:
705 case ND_OB_SELECT:
706 case ND_FRAME:
707 case ND_FRAME_RANGE:
708 case ND_KEYINGSET:
710 ED_region_tag_redraw(region);
711 break;
712 }
713 }
714 else {
715 switch (wmn->data) {
716 case ND_OB_ACTIVE:
717 ED_region_tag_redraw(region);
718 break;
719 }
720 }
721 break;
722 case NC_ID:
723 if (wmn->action == NA_RENAME) {
724 ED_region_tag_redraw(region);
725 }
726 break;
727 case NC_ANIMATION:
728 switch (wmn->data) {
729 case ND_ANIMCHAN: /* set of visible animchannels changed */
730 /* NOTE: for now, this should usually just mean that the filters changed
731 * It may be better if we had a dedicated flag for that though
732 */
733 ED_region_tag_redraw(region);
734 break;
735
736 case ND_KEYFRAME: /* new keyframed added -> active action may have changed */
737 // saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
738 ED_region_tag_redraw(region);
739 break;
740 }
741 break;
742 }
743}
744
745/* add handlers, stuff you only do once or on area/region changes */
747{
748 wmKeyMap *keymap;
749
750 ED_region_panels_init(wm, region);
751
752 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
753 WM_event_add_keymap_handler(&region->handlers, keymap);
754}
755
756static void action_buttons_area_draw(const bContext *C, ARegion *region)
757{
758 ED_region_panels(C, region);
759}
760
762{
763 ARegion *region = params->region;
764 const wmNotifier *wmn = params->notifier;
765
766 /* context changes */
767 switch (wmn->category) {
768 case NC_ANIMATION:
769 ED_region_tag_redraw(region);
770 break;
771 case NC_SCENE:
772 switch (wmn->data) {
773 case ND_OB_ACTIVE:
774 case ND_FRAME:
775 case ND_MARKERS:
776 ED_region_tag_redraw(region);
777 break;
778 }
779 break;
780 case NC_OBJECT:
781 switch (wmn->data) {
782 case ND_BONE_ACTIVE:
783 case ND_BONE_SELECT:
784 case ND_KEYS:
785 ED_region_tag_redraw(region);
786 break;
787 }
788 break;
789 default:
790 if (wmn->data == ND_KEYS) {
791 ED_region_tag_redraw(region);
792 }
793 break;
794 }
795}
796
797static void action_refresh(const bContext *C, ScrArea *area)
798{
799 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
800
801 /* Update the state of the animchannels in response to changes from the data they represent
802 * NOTE: the temp flag is used to indicate when this needs to be done,
803 * and will be cleared once handled. */
805 /* Perform syncing of channel state incl. selection
806 * Active action setting also occurs here
807 * (as part of anim channel filtering in `anim_filter.cc`). */
809 saction->runtime.flag &= ~SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC;
810
811 /* Tag everything for redraw
812 * - Regions (such as header) need to be manually tagged for redraw too
813 * or else they don't update #28962.
814 */
815 ED_area_tag_redraw(area);
816 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
817 ED_region_tag_redraw(region);
818 }
819 }
820
821 /* region updates? */
822 /* XXX re-sizing y-extents of tot should go here? */
823}
824
825static void action_id_remap(ScrArea * /*area*/,
826 SpaceLink *slink,
827 const blender::bke::id::IDRemapper &mappings)
828{
829 SpaceAction *sact = (SpaceAction *)slink;
830
831 mappings.apply(reinterpret_cast<ID **>(&sact->action), ID_REMAP_APPLY_DEFAULT);
832 mappings.apply(reinterpret_cast<ID **>(&sact->ads.filter_grp), ID_REMAP_APPLY_DEFAULT);
833 mappings.apply(&sact->ads.source, ID_REMAP_APPLY_DEFAULT);
834}
835
836static void action_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
837{
838 SpaceAction *sact = reinterpret_cast<SpaceAction *>(space_link);
839 const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
840 const bool is_readonly = (data_flags & IDWALK_READONLY) != 0;
841
843
844 /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceNla and #SpaceGraph. */
847
848 if (!is_readonly) {
849 /* Force recalc of list of channels, potentially updating the active action while we're
850 * at it (as it can only be updated that way) #28962. */
852 }
853}
854
861{
862 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
864}
865
866static void action_space_subtype_set(ScrArea *area, int value)
867{
868 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
869 if (value == SACTCONT_TIMELINE) {
870 if (sact->mode != SACTCONT_TIMELINE) {
871 sact->mode_prev = sact->mode;
872 }
873 sact->mode = value;
874 }
875 else {
876 sact->mode = sact->mode_prev;
877 }
878}
879
881 EnumPropertyItem **item,
882 int *totitem)
883{
885}
886
888{
889 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
892 return item.name;
893}
894
895static int action_space_icon_get(const ScrArea *area)
896{
897 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
900 return item.icon;
901}
902
904{
905 SpaceAction *saction = (SpaceAction *)sl;
906 memset(&saction->runtime, 0x0, sizeof(saction->runtime));
907}
908
910{
911 BLO_write_struct(writer, SpaceAction, sl);
912}
913
915{
916 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
917 ARegionType *art;
918
919 st->spaceid = SPACE_ACTION;
920 STRNCPY(st->name, "Action");
921
922 st->create = action_create;
923 st->free = action_free;
924 st->init = action_init;
925 st->duplicate = action_duplicate;
926 st->operatortypes = action_operatortypes;
927 st->keymap = action_keymap;
928 st->listener = action_listener;
929 st->refresh = action_refresh;
930 st->id_remap = action_id_remap;
931 st->foreach_id = action_foreach_id;
932 st->space_subtype_item_extend = action_space_subtype_item_extend;
933 st->space_subtype_get = action_space_subtype_get;
934 st->space_subtype_set = action_space_subtype_set;
935 st->space_name_get = action_space_name_get;
936 st->space_icon_get = action_space_icon_get;
937 st->blend_read_data = action_space_blend_read_data;
938 st->blend_read_after_liblink = nullptr;
939 st->blend_write = action_space_blend_write;
940
941 /* regions: main window */
942 art = MEM_cnew<ARegionType>("spacetype action region");
950
951 BLI_addhead(&st->regiontypes, art);
952
953 /* regions: header */
954 art = MEM_cnew<ARegionType>("spacetype action region");
956 art->prefsizey = HEADERY;
958
962
963 BLI_addhead(&st->regiontypes, art);
964
965 /* regions: channels */
966 art = MEM_cnew<ARegionType>("spacetype action region");
968 art->prefsizex = 200;
970
975
976 BLI_addhead(&st->regiontypes, art);
977
978 /* regions: UI buttons */
979 art = MEM_cnew<ARegionType>("spacetype action region");
980 art->regionid = RGN_TYPE_UI;
986
987 BLI_addhead(&st->regiontypes, art);
988
990
991 art = ED_area_type_hud(st->spaceid);
992 BLI_addhead(&st->regiontypes, art);
993
994 BKE_spacetype_register(std::move(st));
995}
996
SpaceAction * CTX_wm_space_action(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
@ IDWALK_CB_DIRECT_WEAK_LINK
int BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:120
@ IDWALK_READONLY
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
@ ID_REMAP_APPLY_DEFAULT
void BKE_spacetype_register(std::unique_ptr< SpaceType > st)
Definition screen.cc:268
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
MINLINE int max_ii(int a, int b)
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ARRAY_SIZE(arr)
#define ELEM(...)
#define BLO_write_struct(writer, struct_name, data_ptr)
@ ADS_FILTER_SUMMARY
@ TIME_CACHE_PARTICLES
@ TIME_CACHE_RIGIDBODY
@ TIME_CACHE_DYNAMICPAINT
@ TIME_CACHE_SOFTBODY
@ TIME_CACHE_DISPLAY
@ TIME_CACHE_SIMULATION_NODES
@ TIME_CACHE_CLOTH
@ TIME_CACHE_SMOKE
@ SACTCONT_GPENCIL
@ SACTCONT_ACTION
@ SACTCONT_TIMELINE
@ SACTCONT_DOPESHEET
@ SACTCONT_SHAPEKEY
@ SACTCONT_MASK
@ SACTION_RUNTIME_FLAG_NEED_CHAN_SYNC
@ SACTION_SHOW_INTERPOLATION
@ SACTION_SHOW_MARKERS
@ SACTION_DRAWTIME
Object groups, one object can be in many groups at once.
@ SCER_PRV_RANGE
#define MAXFRAMEF
#define HEADERY
@ RGN_ALIGN_BOTTOM
@ RGN_ALIGN_LEFT
@ RGN_ALIGN_TOP
@ RGN_ALIGN_RIGHT
@ RGN_TYPE_CHANNELS
@ RGN_TYPE_UI
@ RGN_TYPE_WINDOW
@ RGN_TYPE_HEADER
@ SPACE_ACTION
@ SPACE_EMPTY
@ USER_HEADER_BOTTOM
#define UI_SCALE_FAC
@ V2D_ALIGN_NO_POS_Y
@ V2D_VIEWSYNC_AREA_VERTICAL
@ V2D_KEEPOFS_Y
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HANDLES
@ V2D_LOCKZOOM_Y
AnimData * ED_actedit_animdata_from_context(const bContext *C, ID **r_adt_id_owner)
eAnimCont_Types
eAnimFilter_Flags
@ ANIMFILTER_DATA_VISIBLE
@ ANIMFILTER_LIST_VISIBLE
@ ANIMFILTER_LIST_CHANNELS
@ DRAW_MARKERS_MARGIN
Definition ED_markers.hh:25
@ DRAW_MARKERS_LOCAL
Definition ED_markers.hh:24
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:708
ARegionType * ED_area_type_hud(int space_type)
void ED_region_panels(const bContext *C, ARegion *region)
Definition area.cc:3336
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3646
void ED_region_header_init(ARegion *region)
Definition area.cc:3661
void ED_area_tag_refresh(ScrArea *area)
Definition area.cc:737
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3343
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
@ ED_KEYMAP_UI
Definition ED_screen.hh:725
@ ED_KEYMAP_ANIMATION
Definition ED_screen.hh:729
@ ED_KEYMAP_HEADER
Definition ED_screen.hh:731
@ ED_KEYMAP_GIZMO
Definition ED_screen.hh:726
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:728
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:730
void ED_region_do_msg_notify_tag_redraw(bContext *C, wmMsgSubscribeKey *msg_key, wmMsgSubscribeValue *msg_val)
Definition area.cc:381
void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type)
#define REGION_DRAW_POST_VIEW
#define REGION_DRAW_PRE_VIEW
void GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
Read Guarded memory(de)allocation.
#define UI_SIDEBAR_PANEL_WIDTH
@ TH_BACK
void UI_ThemeClearColor(int colorid)
#define UI_MARKER_MARGIN_Y
Definition UI_view2d.hh:471
void UI_view2d_view_orthoSpecial(ARegion *region, View2D *v2d, bool xaxis)
Definition view2d.cc:1132
void UI_view2d_curRect_clamp_y(View2D *v2d)
Definition view2d.cc:840
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition view2d.cc:1605
void UI_view2d_view_restore(const bContext *C)
Definition view2d.cc:1158
void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy)
Definition view2d.cc:212
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1091
void UI_view2d_draw_lines_x__discrete_frames_or_seconds(const View2D *v2d, const Scene *scene, bool display_seconds, bool display_minor_lines)
@ V2D_COMMONVIEW_LIST
Definition UI_view2d.hh:35
@ V2D_COMMONVIEW_CUSTOM
Definition UI_view2d.hh:31
@ WM_GIZMOMAP_DRAWSTEP_2D
#define ND_SEQUENCER
Definition WM_types.hh:404
#define NC_WINDOW
Definition WM_types.hh:342
#define NC_ID
Definition WM_types.hh:362
#define NC_NODE
Definition WM_types.hh:361
#define ND_FILEREAD
Definition WM_types.hh:379
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:465
#define ND_SPACE_CHANGED
Definition WM_types.hh:504
#define ND_OB_ACTIVE
Definition WM_types.hh:407
#define ND_RENDER_RESULT
Definition WM_types.hh:413
#define NC_WM
Definition WM_types.hh:341
#define ND_DATA
Definition WM_types.hh:475
#define ND_RENDER_OPTIONS
Definition WM_types.hh:402
#define ND_SPACE_DOPESHEET
Definition WM_types.hh:499
#define NC_ANIMATION
Definition WM_types.hh:355
#define NC_SCREEN
Definition WM_types.hh:344
#define ND_OB_SELECT
Definition WM_types.hh:409
#define ND_ANIMPLAY
Definition WM_types.hh:391
#define ND_KEYINGSET
Definition WM_types.hh:415
#define NC_SCENE
Definition WM_types.hh:345
#define NA_ADDED
Definition WM_types.hh:552
#define ND_MODIFIER
Definition WM_types.hh:429
#define NA_EDITED
Definition WM_types.hh:550
#define ND_PARTICLE
Definition WM_types.hh:432
#define ND_FRAME_RANGE
Definition WM_types.hh:418
#define ND_MARKERS
Definition WM_types.hh:400
#define ND_FRAME
Definition WM_types.hh:401
#define ND_SPACE_TIME
Definition WM_types.hh:497
#define NA_REMOVED
Definition WM_types.hh:553
#define NC_GPENCIL
Definition WM_types.hh:366
#define ND_BONE_ACTIVE
Definition WM_types.hh:426
#define ND_TRANSFORM
Definition WM_types.hh:423
#define ND_LAYER
Definition WM_types.hh:417
#define ND_BONE_COLLECTION
Definition WM_types.hh:441
#define NC_MASK
Definition WM_types.hh:365
#define ND_KEYS
Definition WM_types.hh:430
#define NA_RENAME
Definition WM_types.hh:554
#define ND_POINTCACHE
Definition WM_types.hh:433
#define ND_BONE_SELECT
Definition WM_types.hh:427
#define ND_KEYFRAME
Definition WM_types.hh:461
#define NC_OBJECT
Definition WM_types.hh:346
#define ND_ANIMCHAN
Definition WM_types.hh:463
#define NC_SPACE
Definition WM_types.hh:359
#define NA_SELECTED
Definition WM_types.hh:555
void action_buttons_register(ARegionType *)
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region, const ListBase &anim_data)
void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Scene *scene)
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region, ListBase *anim_data)
void action_operatortypes()
Definition action_ops.cc:26
void action_keymap(wmKeyConfig *keyconf)
Definition action_ops.cc:96
float ANIM_UI_get_channels_total_height(View2D *v2d, const int item_count)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition anim_deps.cc:457
void ANIM_sync_animchannels_to_data(const bContext *C)
Definition anim_deps.cc:255
void ANIM_draw_action_framerange(AnimData *adt, bAction *action, View2D *v2d, float ymin, float ymax)
Definition anim_draw.cc:143
void ANIM_draw_previewrange(const bContext *C, View2D *v2d, int end_frame_width)
Definition anim_draw.cc:73
void ANIM_draw_framerange(Scene *scene, View2D *v2d)
Definition anim_draw.cc:107
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 ED_markers_draw(const bContext *C, int flag)
unsigned int U
Definition btGjkEpa3.h:78
IDRemapperApplyResult apply(ID **r_id_ptr, IDRemapperApplyOptions options, ID *id_self=nullptr) const
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
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_action_mode_items[]
Definition rna_space.cc:279
static int action_space_subtype_get(ScrArea *area)
static void action_foreach_id(SpaceLink *space_link, LibraryForeachIDData *data)
static void action_channel_region_init(wmWindowManager *wm, ARegion *region)
static SpaceLink * action_duplicate(SpaceLink *sl)
static void action_id_remap(ScrArea *, SpaceLink *slink, const blender::bke::id::IDRemapper &mappings)
static void action_header_region_init(wmWindowManager *, ARegion *region)
static void action_channel_region_draw(const bContext *C, ARegion *region)
static void action_space_subtype_set(ScrArea *area, int value)
static blender::StringRefNull action_space_name_get(const ScrArea *area)
static SpaceLink * action_create(const ScrArea *area, const Scene *scene)
static void action_space_subtype_item_extend(bContext *, EnumPropertyItem **item, int *totitem)
static void action_refresh(const bContext *C, ScrArea *area)
static void action_main_region_draw(const bContext *C, ARegion *region)
static void action_channel_region_listener(const wmRegionListenerParams *params)
static void action_listener(const wmSpaceTypeListenerParams *params)
static void action_header_region_listener(const wmRegionListenerParams *params)
static void action_header_region_draw(const bContext *C, ARegion *region)
static void action_init(wmWindowManager *, ScrArea *area)
static void saction_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
static void action_space_blend_read_data(BlendDataReader *, SpaceLink *sl)
static void action_main_region_draw_overlay(const bContext *C, ARegion *region)
static void action_free(SpaceLink *)
static void action_main_region_init(wmWindowManager *wm, ARegion *region)
void ED_spacetype_action()
static void action_buttons_area_init(wmWindowManager *wm, ARegion *region)
static void set_v2d_height(View2D *v2d, const size_t item_count, const bool add_marker_padding)
static void action_space_blend_write(BlendWriter *writer, SpaceLink *sl)
static void action_main_region_listener(const wmRegionListenerParams *params)
static void action_region_listener(const wmRegionListenerParams *params)
static int action_space_icon_get(const ScrArea *area)
static void saction_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
static void action_buttons_area_draw(const bContext *C, ARegion *region)
#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)
const char * name
Definition RNA_types.hh:510
Definition DNA_ID.h:413
StructRNA * type
Definition RNA_types.hh:41
ListBase markers
SpaceAction_Runtime runtime
ListBase regionbase
ListBase * markers
eAnimCont_Types datatype
bDopeSheet * ads
struct Collection * filter_grp
float ymin
unsigned int data
Definition WM_types.hh:325
unsigned int action
Definition WM_types.hh:325
unsigned int category
Definition WM_types.hh:325
void * reference
Definition WM_types.hh:327
struct wmKeyConfig * defaultconf
void ED_time_scrub_draw_current_frame(const ARegion *region, const Scene *scene, bool display_seconds)
void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDopeSheet *dopesheet)
void ED_time_scrub_draw(const ARegion *region, const Scene *scene, bool display_seconds, bool discrete_frames)
wmEventHandler_Keymap * WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap)
wmEventHandler_Keymap * WM_event_add_keymap_handler_v2d_mask(ListBase *handlers, wmKeyMap *keymap)
void WM_gizmomap_draw(wmGizmoMap *gzmap, const bContext *C, const eWM_GizmoFlagMapDrawStep drawstep)
wmKeyMap * WM_keymap_ensure(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid)
Definition wm_keymap.cc:897
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)