Blender V4.5
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
8
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_listbase.h"
20#include "BLI_string.h"
21#include "BLI_utildefines.h"
22
23#include "BKE_context.hh"
24#include "BKE_lib_query.hh"
25#include "BKE_lib_remap.hh"
26#include "BKE_screen.hh"
27
28#include "RNA_access.hh"
29#include "RNA_define.hh"
30#include "RNA_enum_types.hh"
31
32#include "WM_api.hh"
33#include "WM_message.hh"
34#include "WM_types.hh"
35
36#include "UI_interface.hh"
37#include "UI_resources.hh"
38#include "UI_view2d.hh"
39
40#include "ED_anim_api.hh"
41#include "ED_markers.hh"
42#include "ED_screen.hh"
43#include "ED_space_api.hh"
44#include "ED_time_scrub_ui.hh"
45
46#include "BLO_read_write.hh"
47
48#include "GPU_matrix.hh"
49
50#include "action_intern.hh" /* own include */
51
52/* -------------------------------------------------------------------- */
55
56static SpaceLink *action_create(const ScrArea *area, const Scene *scene)
57{
58 SpaceAction *saction;
59 ARegion *region;
60
61 saction = MEM_callocN<SpaceAction>("initaction");
62 saction->spacetype = SPACE_ACTION;
63
64 saction->mode = SACTCONT_DOPESHEET;
67
69
73
74 /* header */
75 region = BKE_area_region_new();
76
77 BLI_addtail(&saction->regionbase, region);
80
81 /* channel list region */
82 region = BKE_area_region_new();
83 BLI_addtail(&saction->regionbase, region);
85 region->alignment = RGN_ALIGN_LEFT;
86
87 /* Only need to set scroll settings, as this will use `listview` v2d configuration. */
90
91 /* ui buttons */
92 region = BKE_area_region_new();
93
94 BLI_addtail(&saction->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(&saction->regionbase, region);
102 region->regiontype = RGN_TYPE_WINDOW;
103
104 region->v2d.tot.xmin = float(scene->r.sfra - 10);
105 region->v2d.tot.ymin = float(-area->winy) / 3.0f;
106 region->v2d.tot.xmax = float(scene->r.efra + 10);
107 region->v2d.tot.ymax = 0.0f;
108
109 region->v2d.cur = region->v2d.tot;
110
111 region->v2d.min[0] = 0.0f;
112 region->v2d.min[1] = 0.0f;
113
114 region->v2d.max[0] = MAXFRAMEF;
115 region->v2d.max[1] = FLT_MAX;
116
117 region->v2d.minzoom = 0.01f;
118 region->v2d.maxzoom = 50;
121 region->v2d.keepzoom = V2D_LOCKZOOM_Y;
122 region->v2d.keepofs = V2D_KEEPOFS_Y;
123 region->v2d.align = V2D_ALIGN_NO_POS_Y;
125
126 return (SpaceLink *)saction;
127}
128
129/* Doesn't free the space-link itself. */
130static void action_free(SpaceLink * /*sl*/)
131{
132 // SpaceAction *saction = (SpaceAction *) sl;
133}
134
135/* spacetype; init callback */
136static void action_init(wmWindowManager * /*wm*/, ScrArea *area)
137{
138 SpaceAction *saction = static_cast<SpaceAction *>(area->spacedata.first);
140}
141
143{
144 SpaceAction *sactionn = static_cast<SpaceAction *>(MEM_dupallocN(sl));
145
146 sactionn->runtime = SpaceAction_Runtime{};
147
148 /* clear or remove stuff from old */
149
150 return (SpaceLink *)sactionn;
151}
152
153/* add handlers, stuff you only do once or on area/region changes */
155{
156 wmKeyMap *keymap;
157
158 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_CUSTOM, region->winx, region->winy);
159
160 /* own keymap */
161 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet", SPACE_ACTION, RGN_TYPE_WINDOW);
163 &region->runtime->handlers, keymap, WM_event_handler_region_v2d_mask_no_marker_poll);
164
165 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
166 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
167}
168
169static void set_v2d_height(View2D *v2d, const size_t item_count, const bool add_marker_padding)
170{
171 const int height = ANIM_UI_get_channels_total_height(v2d, item_count);
172 float pad_bottom = add_marker_padding ? UI_MARKER_MARGIN_Y : 0;
173 /* Add padding for the collapsed redo panel. */
174 pad_bottom += HEADERY;
175 v2d->tot.ymin = -(height + pad_bottom);
177}
178
179static void action_main_region_draw(const bContext *C, ARegion *region)
180{
181 /* draw entirely, view changes should be handled here */
183 Scene *scene = CTX_data_scene(C);
184 bAnimContext ac;
185 View2D *v2d = &region->v2d;
186 short marker_flag = 0;
187
188 const int min_height = UI_ANIM_MINY;
189
190 /* scrollers */
191 if (region->winy >= UI_ANIM_MINY) {
192 region->v2d.scroll |= V2D_SCROLL_BOTTOM;
193 }
194 else {
195 region->v2d.scroll &= ~V2D_SCROLL_BOTTOM;
196 }
197
198 ListBase anim_data = {nullptr, nullptr};
199 const bool has_anim_context = ANIM_animdata_get_context(C, &ac);
200 if (has_anim_context) {
201 /* Build list of channels to draw. */
204 const size_t items = ANIM_animdata_filter(
205 &ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
206 /* The View2D's height needs to be set before calling UI_view2d_view_ortho because the latter
207 * uses the View2D's `cur` rect which might be modified when setting the height. */
209 }
210
212
213 /* clear and setup matrix */
215
217
218 /* time grid */
219 if (region->winy > min_height) {
221 v2d, scene, saction->flag & SACTION_DRAWTIME, true);
222 }
223
225
226 /* start and end frame */
227 if (region->winy > min_height) {
228 ANIM_draw_framerange(scene, v2d);
229 }
230
231 /* Draw the manually set intended playback frame range highlight in the Action editor. */
232 if (ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY) && saction->action) {
234
235 ANIM_draw_action_framerange(adt, saction->action, v2d, -FLT_MAX, FLT_MAX);
236 }
237
238 /* data */
239 if (has_anim_context) {
240 draw_channel_strips(&ac, saction, region, &anim_data);
241 }
242
243 /* markers */
244 UI_view2d_view_orthoSpecial(region, v2d, true);
245
246 marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) |
248
249 if (saction->flag & SACTION_SHOW_MARKERS && region->winy > (UI_ANIM_MINY + UI_MARKER_MARGIN_Y)) {
250 ED_markers_draw(C, marker_flag);
251 }
252
253 /* preview range */
255 ANIM_draw_previewrange(scene, v2d, 0);
256
257 /* callback */
260
261 /* reset view matrix */
263
264 /* gizmos */
266
267 /* scrubbing region */
268 ED_time_scrub_draw(region, scene, saction->flag & SACTION_DRAWTIME, true);
269}
270
272{
273 /* draw entirely, view changes should be handled here */
274 const SpaceAction *saction = CTX_wm_space_action(C);
275 const Scene *scene = CTX_data_scene(C);
276 const Object *obact = CTX_data_active_object(C);
277 View2D *v2d = &region->v2d;
278
279 /* caches */
280 if (saction->mode == SACTCONT_TIMELINE) {
282 UI_view2d_view_orthoSpecial(region, v2d, true);
283 timeline_draw_cache(saction, obact, scene);
285 }
286
287 /* scrubbing region */
289 region, scene, saction->flag & SACTION_DRAWTIME, region->winy >= UI_ANIM_MINY);
290
291 /* scrollers */
292 const rcti scroller_mask = ED_time_scrub_clamp_scroller_mask(v2d->mask);
293 UI_view2d_scrollers_draw(v2d, &scroller_mask);
294}
295
296/* add handlers, stuff you only do once or on area/region changes */
298{
299 wmKeyMap *keymap;
300
301 /* ensure the 2d view sync works - main region has bottom scroller */
302 region->v2d.scroll = V2D_SCROLL_BOTTOM;
303
304 UI_view2d_region_reinit(&region->v2d, V2D_COMMONVIEW_LIST, region->winx, region->winy);
305
306 /* own keymap */
307 keymap = WM_keymap_ensure(wm->defaultconf, "Animation Channels", SPACE_EMPTY, RGN_TYPE_WINDOW);
308 WM_event_add_keymap_handler_v2d_mask(&region->runtime->handlers, keymap);
309
310 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
311 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
312}
313
314static void action_channel_region_draw(const bContext *C, ARegion *region)
315{
316 /* draw entirely, view changes should be handled here */
317 bAnimContext ac;
318 const bool has_valid_animcontext = ANIM_animdata_get_context(C, &ac);
319
320 /* clear and setup matrix */
322
323 if (!has_valid_animcontext) {
324 return;
325 }
326
327 View2D *v2d = &region->v2d;
328
329 ListBase anim_data = {nullptr, nullptr};
330 /* Build list of channels to draw. */
333 const size_t item_count = ANIM_animdata_filter(
334 &ac, &anim_data, filter, ac.data, eAnimCont_Types(ac.datatype));
335 /* The View2D's height needs to be set before calling UI_view2d_view_ortho because the latter
336 * uses the View2D's `cur` rect which might be modified when setting the height. */
337 set_v2d_height(v2d, item_count, !BLI_listbase_is_empty(ac.markers));
338
340 draw_channel_names((bContext *)C, &ac, region, anim_data);
341
342 /* channel filter next to scrubbing area */
344
345 /* reset view matrix */
347
348 /* no scrollers here */
349 ANIM_animdata_freelist(&anim_data);
350}
351
352/* add handlers, stuff you only do once or on area/region changes */
354{
355 ED_region_header_init(region);
356}
357
358static void action_header_region_draw(const bContext *C, ARegion *region)
359{
360 /* The anim context is not actually used, but this makes sure the action being displayed is up to
361 * date. */
362 bAnimContext ac;
364
365 ED_region_header(C, region);
366}
367
369{
370 ARegion *region = params->region;
371 const wmNotifier *wmn = params->notifier;
372
373 /* context changes */
374 switch (wmn->category) {
375 case NC_ANIMATION:
376 ED_region_tag_redraw(region);
377 break;
378 case NC_SCENE:
379 switch (wmn->data) {
380 case ND_OB_ACTIVE:
381 case ND_FRAME:
382 ED_region_tag_redraw(region);
383 break;
384 }
385 break;
386 case NC_OBJECT:
387 switch (wmn->data) {
388 case ND_BONE_ACTIVE:
389 case ND_BONE_SELECT:
390 case ND_KEYS:
391 ED_region_tag_redraw(region);
392 break;
393 case ND_MODIFIER:
394 if (wmn->action == NA_RENAME) {
395 ED_region_tag_redraw(region);
396 }
397 break;
398 }
399 break;
400 case NC_GPENCIL:
401 if (ELEM(wmn->action, NA_RENAME, NA_SELECTED)) {
402 ED_region_tag_redraw(region);
403 }
404 break;
405 case NC_ID:
406 if (wmn->action == NA_RENAME) {
407 ED_region_tag_redraw(region);
408 }
409 break;
410 default:
411 if (wmn->data == ND_KEYS) {
412 ED_region_tag_redraw(region);
413 }
414 break;
415 }
416}
417
419{
420 wmMsgBus *mbus = params->message_bus;
421 ARegion *region = params->region;
422
423 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
424 msg_sub_value_region_tag_redraw.owner = region;
425 msg_sub_value_region_tag_redraw.user_data = region;
426 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
427
428 /* All dope-sheet filter settings, etc. affect the drawing of this editor,
429 * also same applies for all animation-related data-types that may appear here,
430 * so just whitelist the entire structs for updates. */
431 {
432 wmMsgParams_RNA msg_key_params = {{}};
433 StructRNA *type_array[] = {
434 &RNA_DopeSheet, /* Dope-sheet filters. */
435
436 &RNA_ActionGroup, /* channel groups */
437
438 &RNA_FCurve, /* F-Curve */
439 &RNA_Keyframe,
440 &RNA_FCurveSample,
441
442 &RNA_GreasePencil, /* Grease Pencil */
443 &RNA_GPencilLayer,
444 &RNA_GPencilFrame,
445 };
446
447 for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
448 msg_key_params.ptr.type = type_array[i];
450 mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
451 }
452 }
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 }
475 break;
476 case NC_OBJECT:
477 switch (wmn->data) {
478 case ND_TRANSFORM:
479 /* moving object shouldn't need to redraw action */
480 break;
481 case ND_BONE_ACTIVE:
482 case ND_BONE_SELECT:
484 case ND_KEYS:
485 ED_region_tag_redraw(region);
486 break;
487 }
488 break;
489 case NC_NODE:
490 switch (wmn->action) {
491 case NA_EDITED:
492 ED_region_tag_redraw(region);
493 break;
494 }
495 break;
496 case NC_ID:
497 if (wmn->action == NA_RENAME) {
498 ED_region_tag_redraw(region);
499 }
500 break;
501 case NC_SCREEN:
502 if (ELEM(wmn->data, ND_LAYER)) {
503 ED_region_tag_redraw(region);
504 }
505 break;
506 default:
507 if (wmn->data == ND_KEYS) {
508 ED_region_tag_redraw(region);
509 }
510 break;
511 }
512}
513
515{
516 wmMsgBus *mbus = params->message_bus;
517 Scene *scene = params->scene;
518 ARegion *region = params->region;
519
520 wmMsgSubscribeValue msg_sub_value_region_tag_redraw{};
521 msg_sub_value_region_tag_redraw.owner = region;
522 msg_sub_value_region_tag_redraw.user_data = region;
523 msg_sub_value_region_tag_redraw.notify = ED_region_do_msg_notify_tag_redraw;
524
525 /* Timeline depends on scene properties. */
526 {
527 bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
528 const PropertyRNA *props[] = {
529 use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
530 use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
531 &rna_Scene_use_preview_range,
532 &rna_Scene_frame_current,
533 };
534
535 PointerRNA idptr = RNA_id_pointer_create(&scene->id);
536
537 for (int i = 0; i < ARRAY_SIZE(props); i++) {
538 WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
539 }
540 }
541
542 /* Now run the general "channels region" one - since channels and main should be in sync */
544}
545
546/* editor level listener */
548{
549 ScrArea *area = params->area;
550 const wmNotifier *wmn = params->notifier;
551 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
552
553 /* context changes */
554 switch (wmn->category) {
555 case NC_GPENCIL:
556 /* only handle these events for containers in which GPencil frames are displayed */
558 if (wmn->action == NA_EDITED) {
559 ED_area_tag_redraw(area);
560 }
561 else if (wmn->action == NA_SELECTED) {
564 }
565 }
566 break;
567 case NC_ANIMATION:
568 /* For NLA tweak-mode enter/exit, need complete refresh. */
569 if (wmn->data == ND_NLA_ACTCHANGE) {
572 }
573 /* Auto-color only really needs to change when channels are added/removed,
574 * or previously hidden stuff appears
575 * (assume for now that if just adding these works, that will be fine).
576 */
577 else if (((wmn->data == ND_KEYFRAME) && ELEM(wmn->action, NA_ADDED, NA_REMOVED)) ||
578 ((wmn->data == ND_ANIMCHAN) && (wmn->action != NA_SELECTED)))
579 {
581 }
582 /* for simple edits to the curve data though (or just plain selections),
583 * a simple redraw should work
584 * (see #39851 for an example of how this can go wrong)
585 */
586 else {
587 ED_area_tag_redraw(area);
588 }
589 break;
590 case NC_SCENE:
591 switch (wmn->data) {
592 case ND_SEQUENCER:
593 if (wmn->action == NA_SELECTED) {
596 }
597 break;
598 case ND_OB_ACTIVE:
599 case ND_OB_SELECT:
600 /* Selection changed, so force refresh to flush
601 * (needs flag set to do syncing). */
604 break;
605 case ND_RENDER_RESULT:
606 ED_area_tag_redraw(area);
607 break;
608 case ND_FRAME_RANGE:
609 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
610 if (region->regiontype == RGN_TYPE_WINDOW) {
611 Scene *scene = static_cast<Scene *>(wmn->reference);
612 region->v2d.tot.xmin = float(scene->r.sfra - 4);
613 region->v2d.tot.xmax = float(scene->r.efra + 4);
614 break;
615 }
616 }
617 break;
618 default:
619 if (saction->mode != SACTCONT_TIMELINE) {
620 /* Just redrawing the view will do. */
621 ED_area_tag_redraw(area);
622 }
623 break;
624 }
625 break;
626 case NC_OBJECT:
627 switch (wmn->data) {
628 case ND_BONE_SELECT: /* Selection changed, so force refresh to flush
629 * (needs flag set to do syncing). */
630 case ND_BONE_ACTIVE:
633 break;
634 case ND_TRANSFORM:
635 /* moving object shouldn't need to redraw action */
636 break;
637 case ND_POINTCACHE:
638 case ND_MODIFIER:
639 case ND_PARTICLE:
640 /* only needed in timeline mode */
641 if (saction->mode == SACTCONT_TIMELINE) {
643 ED_area_tag_redraw(area);
644 }
645 break;
646 default: /* just redrawing the view will do */
647 ED_area_tag_redraw(area);
648 break;
649 }
650 break;
651 case NC_MASK:
652 if (saction->mode == SACTCONT_MASK) {
653 switch (wmn->data) {
654 case ND_DATA:
656 ED_area_tag_redraw(area);
657 break;
658 default: /* just redrawing the view will do */
659 ED_area_tag_redraw(area);
660 break;
661 }
662 }
663 break;
664 case NC_NODE:
665 if (wmn->action == NA_SELECTED) {
666 /* selection changed, so force refresh to flush (needs flag set to do syncing) */
669 }
670 break;
671 case NC_SPACE:
672 switch (wmn->data) {
674 ED_area_tag_redraw(area);
675 break;
676 case ND_SPACE_TIME:
677 ED_area_tag_redraw(area);
678 break;
679 case ND_SPACE_CHANGED:
682 break;
683 }
684 break;
685 case NC_WINDOW:
687 /* force redraw/refresh after undo/redo, see: #28962. */
689 }
690 break;
691 case NC_WM:
692 switch (wmn->data) {
693 case ND_FILEREAD:
695 break;
696 }
697 break;
698 }
699}
700
702{
703 ScrArea *area = params->area;
704 ARegion *region = params->region;
705 const wmNotifier *wmn = params->notifier;
706 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
707
708 /* context changes */
709 switch (wmn->category) {
710 case NC_SCREEN:
711 if (saction->mode == SACTCONT_TIMELINE) {
712 if (wmn->data == ND_ANIMPLAY) {
713 ED_region_tag_redraw(region);
714 }
715 }
716 break;
717 case NC_SCENE:
718 if (saction->mode == SACTCONT_TIMELINE) {
719 switch (wmn->data) {
720 case ND_RENDER_RESULT:
721 case ND_OB_SELECT:
722 case ND_FRAME:
723 case ND_FRAME_RANGE:
724 case ND_KEYINGSET:
726 ED_region_tag_redraw(region);
727 break;
728 }
729 }
730 else {
731 switch (wmn->data) {
732 case ND_OB_ACTIVE:
733 ED_region_tag_redraw(region);
734 break;
735 }
736 }
737 break;
738 case NC_ID:
739 if (wmn->action == NA_RENAME) {
740 ED_region_tag_redraw(region);
741 }
742 break;
743 case NC_ANIMATION:
744 switch (wmn->data) {
745 case ND_ANIMCHAN: /* set of visible animchannels changed */
746 /* NOTE: for now, this should usually just mean that the filters changed
747 * It may be better if we had a dedicated flag for that though
748 */
749 ED_region_tag_redraw(region);
750 break;
751
752 case ND_KEYFRAME: /* new keyframed added -> active action may have changed */
753 // saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
754 ED_region_tag_redraw(region);
755 break;
756 }
757 break;
758 }
759}
760
761/* add handlers, stuff you only do once or on area/region changes */
763{
764 wmKeyMap *keymap;
765
766 ED_region_panels_init(wm, region);
767
768 keymap = WM_keymap_ensure(wm->defaultconf, "Dopesheet Generic", SPACE_ACTION, RGN_TYPE_WINDOW);
769 WM_event_add_keymap_handler(&region->runtime->handlers, keymap);
770}
771
772static void action_buttons_area_draw(const bContext *C, ARegion *region)
773{
774 ED_region_panels(C, region);
775}
776
778{
779 ARegion *region = params->region;
780 const wmNotifier *wmn = params->notifier;
781
782 /* context changes */
783 switch (wmn->category) {
784 case NC_ANIMATION:
785 ED_region_tag_redraw(region);
786 break;
787 case NC_SCENE:
788 switch (wmn->data) {
789 case ND_OB_ACTIVE:
790 case ND_FRAME:
791 case ND_MARKERS:
792 ED_region_tag_redraw(region);
793 break;
794 }
795 break;
796 case NC_OBJECT:
797 switch (wmn->data) {
798 case ND_BONE_ACTIVE:
799 case ND_BONE_SELECT:
800 case ND_KEYS:
801 ED_region_tag_redraw(region);
802 break;
803 }
804 break;
805 default:
806 if (wmn->data == ND_KEYS) {
807 ED_region_tag_redraw(region);
808 }
809 break;
810 }
811}
812
813static void action_refresh(const bContext *C, ScrArea *area)
814{
815 SpaceAction *saction = (SpaceAction *)area->spacedata.first;
816
817 /* Update the state of the animchannels in response to changes from the data they represent
818 * NOTE: the temp flag is used to indicate when this needs to be done,
819 * and will be cleared once handled. */
821 /* Perform syncing of channel state incl. selection
822 * Active action setting also occurs here
823 * (as part of anim channel filtering in `anim_filter.cc`). */
826
827 /* Tag everything for redraw
828 * - Regions (such as header) need to be manually tagged for redraw too
829 * or else they don't update #28962.
830 */
831 ED_area_tag_redraw(area);
832 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
833 ED_region_tag_redraw(region);
834 }
835 }
836
837 /* region updates? */
838 /* XXX re-sizing y-extents of tot should go here? */
839}
840
841static void action_id_remap(ScrArea * /*area*/,
842 SpaceLink *slink,
843 const blender::bke::id::IDRemapper &mappings)
844{
845 SpaceAction *sact = (SpaceAction *)slink;
846
847 mappings.apply(reinterpret_cast<ID **>(&sact->action), ID_REMAP_APPLY_DEFAULT);
848 mappings.apply(reinterpret_cast<ID **>(&sact->ads.filter_grp), ID_REMAP_APPLY_DEFAULT);
849 mappings.apply(&sact->ads.source, ID_REMAP_APPLY_DEFAULT);
850}
851
853{
854 SpaceAction *sact = reinterpret_cast<SpaceAction *>(space_link);
855 const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
856 const bool is_readonly = (data_flags & IDWALK_READONLY) != 0;
857
859
860 /* NOTE: Could be deduplicated with the #bDopeSheet handling of #SpaceNla and #SpaceGraph. */
863
864 if (!is_readonly) {
865 /* Force recalc of list of channels, potentially updating the active action while we're
866 * at it (as it can only be updated that way) #28962. */
868 }
869}
870
877{
878 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
880}
881
882static void action_space_subtype_set(ScrArea *area, int value)
883{
884 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
885 if (value == SACTCONT_TIMELINE) {
886 if (sact->mode != SACTCONT_TIMELINE) {
887 sact->mode_prev = sact->mode;
888 }
889 sact->mode = value;
890 }
891 else {
892 sact->mode = sact->mode_prev;
893 }
894}
895
897 EnumPropertyItem **item,
898 int *totitem)
899{
901}
902
904{
905 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
908 return item.name;
909}
910
911static int action_space_icon_get(const ScrArea *area)
912{
913 SpaceAction *sact = static_cast<SpaceAction *>(area->spacedata.first);
916 return item.icon;
917}
918
920{
921 SpaceAction *saction = (SpaceAction *)sl;
922 saction->runtime = SpaceAction_Runtime{};
923}
924
926{
927 BLO_write_struct(writer, SpaceAction, sl);
928}
929
931{
932 std::unique_ptr<SpaceType> st = std::make_unique<SpaceType>();
933 ARegionType *art;
934
935 st->spaceid = SPACE_ACTION;
936 STRNCPY(st->name, "Action");
937
938 st->create = action_create;
939 st->free = action_free;
940 st->init = action_init;
941 st->duplicate = action_duplicate;
942 st->operatortypes = action_operatortypes;
943 st->keymap = action_keymap;
944 st->listener = action_listener;
945 st->refresh = action_refresh;
946 st->id_remap = action_id_remap;
947 st->foreach_id = action_foreach_id;
948 st->space_subtype_item_extend = action_space_subtype_item_extend;
949 st->space_subtype_get = action_space_subtype_get;
950 st->space_subtype_set = action_space_subtype_set;
951 st->space_name_get = action_space_name_get;
952 st->space_icon_get = action_space_icon_get;
953 st->blend_read_data = action_space_blend_read_data;
954 st->blend_read_after_liblink = nullptr;
955 st->blend_write = action_space_blend_write;
956
957 /* regions: main window */
958 art = MEM_callocN<ARegionType>("spacetype action region");
966
967 BLI_addhead(&st->regiontypes, art);
968
969 /* regions: header */
970 art = MEM_callocN<ARegionType>("spacetype action region");
972 art->prefsizey = HEADERY;
974
978
979 BLI_addhead(&st->regiontypes, art);
980
981 /* regions: channels */
982 art = MEM_callocN<ARegionType>("spacetype action region");
984 art->prefsizex = 200;
986
991
992 BLI_addhead(&st->regiontypes, art);
993
994 /* regions: UI buttons */
995 art = MEM_callocN<ARegionType>("spacetype action region");
996 art->regionid = RGN_TYPE_UI;
1002
1003 BLI_addhead(&st->regiontypes, art);
1004
1006
1007 art = ED_area_type_hud(st->spaceid);
1008 BLI_addhead(&st->regiontypes, art);
1009
1010 BKE_spacetype_register(std::move(st));
1011}
1012
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
#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 LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
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
MINLINE int max_ii(int a, int b)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#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.
#define MAXFRAMEF
@ SCER_PRV_RANGE
#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_ACTION
@ SPACE_EMPTY
@ USER_HEADER_BOTTOM
@ V2D_SCROLL_VERTICAL_HIDE
@ V2D_SCROLL_RIGHT
@ V2D_SCROLL_BOTTOM
@ V2D_SCROLL_HORIZONTAL_HANDLES
@ V2D_ALIGN_NO_POS_Y
@ V2D_KEEPOFS_Y
@ V2D_LOCKZOOM_Y
@ V2D_VIEWSYNC_AREA_VERTICAL
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:27
@ DRAW_MARKERS_LOCAL
Definition ED_markers.hh:26
void ED_area_tag_redraw(ScrArea *area)
Definition area.cc:714
ARegionType * ED_area_type_hud(int space_type)
void ED_region_panels(const bContext *C, ARegion *region)
Definition area.cc:3462
void ED_region_header(const bContext *C, ARegion *region)
Definition area.cc:3750
void ED_region_header_init(ARegion *region)
Definition area.cc:3765
void ED_area_tag_refresh(ScrArea *area)
Definition area.cc:743
@ 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_GIZMO
Definition ED_screen.hh:741
@ ED_KEYMAP_VIEW2D
Definition ED_screen.hh:743
@ ED_KEYMAP_FRAMES
Definition ED_screen.hh:745
void ED_region_panels_init(wmWindowManager *wm, ARegion *region)
Definition area.cc:3469
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 GPU_matrix_push_projection()
void GPU_matrix_pop_projection()
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define UI_SIDEBAR_PANEL_WIDTH
@ TH_BACK
void UI_ThemeClearColor(int colorid)
#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_curRect_clamp_y(View2D *v2d)
Definition view2d.cc:844
void UI_view2d_scrollers_draw(View2D *v2d, const rcti *mask_custom)
Definition view2d.cc:1503
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
void UI_view2d_view_ortho(const View2D *v2d)
Definition view2d.cc:1095
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: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_FILEREAD
Definition WM_types.hh:409
#define ND_NLA_ACTCHANGE
Definition WM_types.hh:495
#define ND_SPACE_CHANGED
Definition WM_types.hh:535
#define ND_OB_ACTIVE
Definition WM_types.hh:437
#define ND_RENDER_RESULT
Definition WM_types.hh:443
#define NC_WM
Definition WM_types.hh:371
#define ND_DATA
Definition WM_types.hh:506
#define ND_RENDER_OPTIONS
Definition WM_types.hh:432
#define ND_SPACE_DOPESHEET
Definition WM_types.hh:530
#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 ND_ANIMPLAY
Definition WM_types.hh:421
#define ND_KEYINGSET
Definition WM_types.hh:445
#define NC_SCENE
Definition WM_types.hh:375
#define NA_ADDED
Definition WM_types.hh:583
#define ND_MODIFIER
Definition WM_types.hh:459
#define NA_EDITED
Definition WM_types.hh:581
#define ND_PARTICLE
Definition WM_types.hh:462
#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_SPACE_TIME
Definition WM_types.hh:528
#define NA_REMOVED
Definition WM_types.hh:584
#define NC_GPENCIL
Definition WM_types.hh:396
#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_BONE_COLLECTION
Definition WM_types.hh:471
#define NC_MASK
Definition WM_types.hh:395
#define ND_KEYS
Definition WM_types.hh:460
#define NA_RENAME
Definition WM_types.hh:585
#define ND_POINTCACHE
Definition WM_types.hh:463
#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
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:25
void action_keymap(wmKeyConfig *keyconf)
Definition action_ops.cc:95
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_action_framerange(AnimData *adt, bAction *action, View2D *v2d, float ymin, float ymax)
Definition anim_draw.cc:145
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 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
#define filter
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
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:254
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)
ARegionRuntimeHandle * runtime
const char * name
Definition RNA_types.hh:627
Definition DNA_ID.h:404
void * first
StructRNA * type
Definition RNA_types.hh:52
struct RenderData r
ListBase markers
ListBase spacedata
ListBase regionbase
SpaceAction_Runtime runtime
ListBase regionbase
float minzoom
float max[2]
short keepzoom
short keepofs
float min[2]
float maxzoom
ListBase * markers
eAnimCont_Types datatype
bDopeSheet * ads
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
void * reference
Definition WM_types.hh:357
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)
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: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)