Blender V4.3
action_draw.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9/* System includes ----------------------------------------------------- */
10
11#include <cfloat>
12#include <cmath>
13#include <cstdlib>
14#include <cstring>
15
16#include "BLI_math_color.h"
17#include "BLI_utildefines.h"
18
19/* Types --------------------------------------------------------------- */
20
21#include "DNA_anim_types.h"
22#include "DNA_modifier_types.h"
23#include "DNA_node_types.h"
24#include "DNA_object_types.h"
25#include "DNA_scene_types.h"
26#include "DNA_screen_types.h"
27
29#include "BKE_pointcache.h"
30
31#include "ANIM_action.hh"
32
33/* Everything from source (BIF, BDR, BSE) ------------------------------ */
34
35#include "GPU_immediate.hh"
36#include "GPU_matrix.hh"
37#include "GPU_state.hh"
38
39#include "UI_interface.hh"
40#include "UI_resources.hh"
41#include "UI_view2d.hh"
42
43#include "ED_anim_api.hh"
44#include "ED_keyframes_draw.hh"
45
46#include "MOD_nodes.hh"
47
48#include "action_intern.hh"
49
50using namespace blender;
51
52/* -------------------------------------------------------------------- */
57 bAnimContext *ac,
58 ARegion *region,
59 const ListBase /*bAnimListElem*/ &anim_data)
60{
61 bAnimListElem *ale;
62 View2D *v2d = &region->v2d;
63 /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
64 UI_view2d_sync(nullptr, ac->area, v2d, V2D_LOCK_COPY);
65
66 const float channel_step = ANIM_UI_get_channel_step();
67 /* Loop through channels, and set up drawing depending on their type. */
68 { /* first pass: just the standard GL-drawing for backdrop + text */
69 size_t channel_index = 0;
70 float ymax = ANIM_UI_get_first_channel_top(v2d);
71
72 for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
73 ale = ale->next, ymax -= channel_step, channel_index++)
74 {
75 const float ymin = ymax - ANIM_UI_get_channel_height();
76
77 /* check if visible */
78 if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
79 IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax))
80 {
81 /* draw all channels using standard channel-drawing API */
82 ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
83 }
84 }
85 }
86 { /* second pass: widgets */
87 uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
88 size_t channel_index = 0;
89 float ymax = ANIM_UI_get_first_channel_top(v2d);
90
91 for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
92 ale = ale->next, ymax -= channel_step, channel_index++)
93 {
94 const float ymin = ymax - ANIM_UI_get_channel_height();
95
96 /* check if visible */
97 if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
98 IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax))
99 {
100 /* draw all channels using standard channel-drawing API */
101 rctf channel_rect;
102 BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax);
103 ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
104 }
105 }
106
107 UI_block_end(C, block);
108 UI_block_draw(C, block);
109 }
110}
111
114/* -------------------------------------------------------------------- */
118/* extra padding for lengths (to go under scrollers) */
119#define EXTRA_SCROLL_PAD 100.0f
120
121/* Draw manually set intended playback frame ranges for actions. */
122static void draw_channel_action_ranges(ListBase *anim_data, View2D *v2d)
123{
124 /* Variables for coalescing the Y region of one action. */
125 bAction *cur_action = nullptr;
126 AnimData *cur_adt = nullptr;
127 float cur_ymax;
128
129 /* Walk through channels, grouping contiguous spans referencing the same action. */
131 const float ystep = ANIM_UI_get_channel_step();
132 float ymin = ymax - ystep;
133
134 for (bAnimListElem *ale = static_cast<bAnimListElem *>(anim_data->first); ale;
135 ale = ale->next, ymax = ymin, ymin -= ystep)
136 {
137 bAction *action = nullptr;
138 AnimData *adt = nullptr;
139
140 /* check if visible */
141 if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
142 IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax))
143 {
144 /* check if anything to show for this channel */
145 if (ale->datatype != ALE_NONE) {
146 action = ANIM_channel_action_get(ale);
147
148 if (action) {
149 adt = ale->adt;
150 }
151 }
152 }
153
154 /* Extend the current region, or flush and restart. */
155 if (action != cur_action || adt != cur_adt) {
156 if (cur_action) {
157 ANIM_draw_action_framerange(cur_adt, cur_action, v2d, ymax, cur_ymax);
158 }
159
160 cur_action = action;
161 cur_adt = adt;
162 cur_ymax = ymax;
163 }
164 }
165
166 /* Flush the last region. */
167 if (cur_action) {
168 ANIM_draw_action_framerange(cur_adt, cur_action, v2d, ymax, cur_ymax);
169 }
170}
171
172static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, uint pos)
173{
174 uchar col1[4], col2[4];
175 uchar col1a[4], col2a[4];
176 uchar col1b[4], col2b[4];
177 uchar col_summary[4];
178
179 /* get theme colors */
183
186
189
190 float ymax = ANIM_UI_get_first_channel_top(v2d);
191 const float channel_step = ANIM_UI_get_channel_step();
192 bAnimListElem *ale;
193 for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
194 ale = ale->next, ymax -= channel_step)
195 {
196 const float ymin = ymax - ANIM_UI_get_channel_height();
197
198 /* check if visible */
199 if (!(IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
200 IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)))
201 {
202 continue;
203 }
205 int sel = 0;
206
207 /* determine if any need to draw channel */
208 if (ale->datatype == ALE_NONE) {
209 continue;
210 }
211 /* determine if channel is selected */
212 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
214 }
215
217 switch (ale->type) {
218 case ANIMTYPE_SUMMARY: {
219 /* reddish color from NLA */
221 break;
222 }
223 case ANIMTYPE_SCENE:
224 case ANIMTYPE_OBJECT: {
225 immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
226 break;
227 }
230 case ANIMTYPE_DSSKEY:
231 case ANIMTYPE_DSWOR: {
232 immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
233 break;
234 }
235 case ANIMTYPE_GROUP:
236 immUniformColor4ubv(sel ? col1a : col2a);
237 break;
238 default: {
239 immUniformColor4ubv(sel ? col1 : col2);
240 }
241 }
242
243 /* draw region twice: firstly backdrop, then the current range */
244 immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
245 }
246 else if (ac->datatype == ANIMCONT_GPENCIL) {
247 uchar *color;
248 switch (ale->type) {
249 case ANIMTYPE_SUMMARY:
250 color = col_summary;
251 break;
252
254 color = sel ? col1a : col2a;
255 break;
256
258 color = col2b;
259 color[3] = sel ? col1[3] : col2b[3];
260 break;
261
262 default:
263 color = sel ? col1 : col2;
264 break;
265 }
266
267 /* Color overlay on frames between the start/end frames. */
268 immUniformColor4ubv(color);
269 immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
270
271 /* Color overlay outside the start/end frame range get a more transparent overlay. */
272 immUniformColor3ubvAlpha(color, std::min(255, color[3] / 2));
273 immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
274 immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
275 }
276 else if (ac->datatype == ANIMCONT_MASK) {
277 /* TODO: this is a copy of gpencil. */
278 uchar *color;
279 if (ale->type == ANIMTYPE_SUMMARY) {
280 color = col_summary;
281 }
282 else {
283 color = sel ? col1 : col2;
284 }
285
286 /* Color overlay on frames between the start/end frames. */
287 immUniformColor4ubv(color);
288 immRectf(pos, ac->scene->r.sfra, ymin, ac->scene->r.efra, ymax);
289
290 /* Color overlay outside the start/end frame range get a more transparent overlay. */
291 immUniformColor3ubvAlpha(color, std::min(255, color[3] / 2));
292 immRectf(pos, v2d->cur.xmin, ymin, ac->scene->r.sfra, ymax);
293 immRectf(pos, ac->scene->r.efra, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
294 }
295
296 /* Alpha-over the channel color, if it's there. */
297 {
298 const bool show_group_colors = U.animation_flag & USER_ANIM_SHOW_CHANNEL_GROUP_COLORS;
299 uint8_t color[3];
300 if (show_group_colors && acf->get_channel_color && acf->get_channel_color(ale, color)) {
301 immUniformColor3ubvAlpha(color, 32);
302 immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
303 }
304 }
305 }
306}
307
309 View2D *v2d,
310 SpaceAction *saction,
311 ListBase &anim_data)
312{
313 /* Draw keyframes
314 * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
315 * This is to try to optimize this for heavier data sets
316 * 2) Keyframes which are out of view horizontally are disregarded
317 */
318 int action_flag = saction->flag;
319 bDopeSheet *ads = &saction->ads;
320
321 if (saction->mode == SACTCONT_TIMELINE) {
323 }
324
325 const float channel_step = ANIM_UI_get_channel_step();
326 float ymax = ANIM_UI_get_first_channel_top(v2d);
327
329
330 const float scale_factor = ANIM_UI_get_keyframe_scale_factor();
331
332 bAnimListElem *ale;
333 for (ale = static_cast<bAnimListElem *>(anim_data.first); ale;
334 ale = ale->next, ymax -= channel_step)
335 {
336 const float ymin = ymax - ANIM_UI_get_channel_height();
337 float ycenter = (ymin + ymax) / 2.0f;
338
339 /* check if visible */
340 if (!(IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
341 IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)))
342 {
343 continue;
344 }
345
346 /* check if anything to show for this channel */
347 if (ale->datatype == ALE_NONE) {
348 continue;
349 }
350
351 AnimData *adt = ANIM_nla_mapping_get(ac, ale);
352
353 /* Add channels to list to draw later. */
354 switch (ale->datatype) {
355 case ALE_ALL:
357 draw_list, static_cast<bAnimContext *>(ale->data), ycenter, scale_factor, action_flag);
358 break;
359 case ALE_SCE:
360 ED_add_scene_channel(draw_list,
361 ads,
362 static_cast<Scene *>(ale->key_data),
363 ycenter,
364 scale_factor,
365 action_flag);
366 break;
367 case ALE_OB:
368 ED_add_object_channel(draw_list,
369 ads,
370 static_cast<Object *>(ale->key_data),
371 ycenter,
372 scale_factor,
373 action_flag);
374 break;
377 adt,
378 static_cast<bAction *>(ale->key_data),
379 ycenter,
380 scale_factor,
381 action_flag);
382 break;
383 case ALE_ACTION_SLOT:
385 adt,
386 static_cast<bAction *>(ale->key_data)->wrap(),
387 *static_cast<animrig::Slot *>(ale->data),
388 ycenter,
389 scale_factor,
390 action_flag);
391 break;
392 case ALE_ACT:
393 ED_add_action_channel(draw_list,
394 adt,
395 static_cast<bAction *>(ale->key_data),
396 ycenter,
397 scale_factor,
398 action_flag);
399 break;
400 case ALE_GROUP:
402 adt,
403 static_cast<bActionGroup *>(ale->data),
404 ycenter,
405 scale_factor,
406 action_flag);
407 break;
408 case ALE_FCURVE:
409 ED_add_fcurve_channel(draw_list,
410 adt,
411 static_cast<FCurve *>(ale->key_data),
412 ycenter,
413 scale_factor,
414 action_flag);
415 break;
418 ads,
419 static_cast<const GreasePencilLayer *>(ale->data),
420 ycenter,
421 scale_factor,
422 action_flag);
423 break;
426 draw_list,
427 ads,
428 static_cast<const GreasePencilLayerTreeGroup *>(ale->data),
429 ycenter,
430 scale_factor,
431 action_flag);
432 break;
435 ac,
436 ale->adt,
437 static_cast<const GreasePencil *>(ale->data),
438 ycenter,
439 scale_factor,
440 action_flag);
441 break;
442 case ALE_GPFRAME:
444 ads,
445 static_cast<bGPDlayer *>(ale->data),
446 ycenter,
447 scale_factor,
448 action_flag);
449 break;
450 case ALE_MASKLAY:
452 ads,
453 static_cast<MaskLayer *>(ale->data),
454 ycenter,
455 scale_factor,
456 action_flag);
457 break;
458 case ALE_NONE:
459 case ALE_NLASTRIP:
460 break;
461 }
462 }
463
464 /* Drawing happens in here. */
465 ED_channel_list_flush(draw_list, v2d);
466 ED_channel_list_free(draw_list);
467}
468
470 SpaceAction *saction,
471 ARegion *region,
472 ListBase *anim_data)
473{
474 View2D *v2d = &region->v2d;
475
476 /* Draw the manual frame ranges for actions in the background of the dopesheet.
477 * The action editor has already drawn the range for its action so it's not needed. */
478 if (ac->datatype == ANIMCONT_DOPESHEET) {
479 draw_channel_action_ranges(anim_data, v2d);
480 }
481
482 /* Draw the background strips. */
485
487
489
490 /* first backdrop strips */
491 draw_backdrops(ac, *anim_data, v2d, pos);
492
494
495 /* black line marking 'current frame' for Time-Slide transform mode */
496 if (saction->flag & SACTION_MOVING) {
497 immUniformColor3f(0.0f, 0.0f, 0.0f);
498
501 immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
502 immEnd();
503 }
505
506 draw_keyframes(ac, v2d, saction, *anim_data);
507
508 /* free temporary channels used for drawing */
509 ANIM_animdata_freelist(anim_data);
510}
511
514/* -------------------------------------------------------------------- */
518static bool timeline_cache_is_hidden_by_setting(const SpaceAction *saction, const PTCacheID *pid)
519{
520 switch (pid->type) {
522 if ((saction->cache_display & TIME_CACHE_SOFTBODY) == 0) {
523 return true;
524 }
525 break;
527 if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) {
528 return true;
529 }
530 break;
532 if ((saction->cache_display & TIME_CACHE_CLOTH) == 0) {
533 return true;
534 }
535 break;
538 if ((saction->cache_display & TIME_CACHE_SMOKE) == 0) {
539 return true;
540 }
541 break;
543 if ((saction->cache_display & TIME_CACHE_DYNAMICPAINT) == 0) {
544 return true;
545 }
546 break;
548 if ((saction->cache_display & TIME_CACHE_RIGIDBODY) == 0) {
549 return true;
550 }
551 break;
552 }
553 return false;
554}
555
556static void timeline_cache_color_get(PTCacheID *pid, float color[4])
557{
558 switch (pid->type) {
560 color[0] = 1.0;
561 color[1] = 0.4;
562 color[2] = 0.02;
563 color[3] = 0.1;
564 break;
566 color[0] = 1.0;
567 color[1] = 0.1;
568 color[2] = 0.02;
569 color[3] = 0.1;
570 break;
572 color[0] = 0.1;
573 color[1] = 0.1;
574 color[2] = 0.75;
575 color[3] = 0.1;
576 break;
579 color[0] = 0.2;
580 color[1] = 0.2;
581 color[2] = 0.2;
582 color[3] = 0.1;
583 break;
585 color[0] = 1.0;
586 color[1] = 0.1;
587 color[2] = 0.75;
588 color[3] = 0.1;
589 break;
591 color[0] = 1.0;
592 color[1] = 0.6;
593 color[2] = 0.0;
594 color[3] = 0.1;
595 break;
596 default:
597 color[0] = 1.0;
598 color[1] = 0.0;
599 color[2] = 1.0;
600 color[3] = 0.1;
601 BLI_assert(0);
602 break;
603 }
604}
605
607 float color[4],
608 float color_state[4])
609{
610 if (cache->flag & PTCACHE_BAKED) {
611 color[3] = color_state[3] = 1.0f;
612 }
613 else if (cache->flag & PTCACHE_OUTDATED) {
614 color[3] = color_state[3] = 0.7f;
615 mul_v3_fl(color_state, 0.5f);
616 }
617 else {
618 color[3] = color_state[3] = 0.7f;
619 }
620}
621
623 int search_start_frame,
624 int *r_segment_start,
625 int *r_segment_end)
626{
627 int offset = cache->startframe;
628 int current = search_start_frame;
629
630 /* Find segment start frame. */
631 while (true) {
632 if (current > cache->endframe) {
633 return false;
634 }
635 if (cache->cached_frames[current - offset]) {
636 *r_segment_start = current;
637 break;
638 }
639 current++;
640 }
641
642 /* Find segment end frame. */
643 while (true) {
644 if (current > cache->endframe) {
645 *r_segment_end = current - 1;
646 return true;
647 }
648 if (!cache->cached_frames[current - offset]) {
649 *r_segment_end = current - 1;
650 return true;
651 }
652 current++;
653 }
654}
655
657{
658 uint count = 0;
659
660 int current = cache->startframe;
661 int segment_start;
662 int segment_end;
663 while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
664 count++;
665 current = segment_end + 1;
666 }
667
668 return count;
669}
670
672{
673 uint segments_count = timeline_cache_segments_count(cache);
674 if (segments_count == 0) {
675 return;
676 }
677
678 immBeginAtMost(GPU_PRIM_TRIS, segments_count * 6);
679
680 int current = cache->startframe;
681 int segment_start;
682 int segment_end;
683 while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
684 immRectf_fast(pos_id, segment_start, 0, segment_end + 1.0f, 1.0f);
685 current = segment_end + 1;
686 }
687
688 immEnd();
689}
690
691static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id)
692{
695 GPU_matrix_scale_2f(1.0, height);
696
698 timeline_cache_color_get(pid, color);
699
700 /* Mix in the background color to tone it down a bit. */
701 blender::ColorTheme4f background;
702 UI_GetThemeColor4fv(TH_BACK, background);
703
704 interp_v3_v3v3(color, color, background, 0.6f);
705
706 /* Highlight the frame range of the simulation. */
707 immUniform4fv("color1", color);
708 immUniform4fv("color2", color);
709 immRectf(pos_id, float(pid->cache->startframe), 0.0, float(pid->cache->endframe), 1.0);
710
711 /* Now show the cached frames on top. */
712 blender::ColorTheme4f color_state;
713 copy_v4_v4(color_state, color);
714
715 timeline_cache_modify_color_based_on_state(pid->cache, color, color_state);
716
717 immUniform4fv("color1", color);
718 immUniform4fv("color2", color_state);
719
721
723}
724
729
731 const bool all_simulations_baked,
732 float *y_offset,
733 const float line_height,
734 const uint pos_id)
735{
736 if (cache_ranges.is_empty()) {
737 return;
738 }
739
740 bool has_bake = false;
741
742 for (const CacheRange &sim_range : cache_ranges) {
743 switch (sim_range.status) {
746 break;
748 has_bake = true;
749 break;
750 }
751 }
752
753 blender::Set<int> status_change_frames_set;
754 for (const CacheRange &sim_range : cache_ranges) {
755 status_change_frames_set.add(sim_range.frames.first());
756 status_change_frames_set.add(sim_range.frames.one_after_last());
757 }
758 blender::Vector<int> status_change_frames;
759 status_change_frames.extend(status_change_frames_set.begin(), status_change_frames_set.end());
760 std::sort(status_change_frames.begin(), status_change_frames.end());
761 const blender::OffsetIndices<int> frame_ranges = status_change_frames.as_span();
762
764 GPU_matrix_translate_2f(0.0, float(V2D_SCROLL_HANDLE_HEIGHT) + *y_offset);
765 GPU_matrix_scale_2f(1.0, line_height);
766
767 blender::ColorTheme4f base_color;
769 blender::ColorTheme4f invalid_color = base_color;
770 mul_v3_fl(invalid_color, 0.5f);
771 invalid_color.a *= 0.7f;
772 blender::ColorTheme4f valid_color = base_color;
773 valid_color.a *= 0.7f;
774 blender::ColorTheme4f baked_color = base_color;
775
776 float max_used_height = 1.0f;
777 for (const int range_i : frame_ranges.index_range()) {
778 const blender::IndexRange frame_range = frame_ranges[range_i];
779 const int start_frame = frame_range.first();
780 const int end_frame = frame_range.last();
781
782 bool has_bake_at_frame = false;
783 bool has_valid_at_frame = false;
784 bool has_invalid_at_frame = false;
785 for (const CacheRange &sim_range : cache_ranges) {
786 if (sim_range.frames.contains(start_frame)) {
787 switch (sim_range.status) {
789 has_invalid_at_frame = true;
790 break;
792 has_valid_at_frame = true;
793 break;
795 has_bake_at_frame = true;
796 break;
797 }
798 }
799 }
800 if (!(has_bake_at_frame || has_valid_at_frame || has_invalid_at_frame)) {
801 continue;
802 }
803
804 if (all_simulations_baked) {
805 immUniform4fv("color1", baked_color);
806 immUniform4fv("color2", baked_color);
808 immRectf_fast(pos_id, start_frame, 0, end_frame + 1.0f, 1.0f);
809 immEnd();
810 }
811 else {
812 if (has_valid_at_frame || has_invalid_at_frame) {
813 immUniform4fv("color1", valid_color);
814 immUniform4fv("color2", has_invalid_at_frame ? invalid_color : valid_color);
816 const float top = has_bake ? 2.0f : 1.0f;
817 immRectf_fast(pos_id, start_frame, 0.0f, end_frame + 1.0f, top);
818 immEnd();
819 max_used_height = top;
820 }
821 if (has_bake_at_frame) {
822 immUniform4fv("color1", baked_color);
823 immUniform4fv("color2", baked_color);
825 immRectf_fast(pos_id, start_frame, 0, end_frame + 1.0f, 1.0f);
826 immEnd();
827 }
828 }
829 }
831
832 *y_offset += max_used_height * 2;
833}
834
835void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Scene *scene)
836{
837 if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == nullptr) {
838 return;
839 }
840
841 ListBase pidlist;
842 BKE_ptcache_ids_from_object(&pidlist, const_cast<Object *>(ob), const_cast<Scene *>(scene), 0);
843
847
849
850 /* Iterate over point-caches on the active object, and draw each one's range. */
851 float y_offset = 0.0f;
852 const float cache_draw_height = 4.0f * UI_SCALE_FAC * U.pixelsize;
853
854 immUniform1i("size1", cache_draw_height * 2.0f);
855 immUniform1i("size2", cache_draw_height);
856
857 LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
858 if (timeline_cache_is_hidden_by_setting(saction, pid)) {
859 continue;
860 }
861
862 if (pid->cache->cached_frames == nullptr) {
863 continue;
864 }
865
866 timeline_cache_draw_single(pid, y_offset, cache_draw_height, pos_id);
867
868 y_offset += cache_draw_height;
869 }
871 blender::Vector<CacheRange> cache_ranges;
872 bool all_simulations_baked = true;
874 if (md->type != eModifierType_Nodes) {
875 continue;
876 }
877 const NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md);
878 if (nmd->node_group == nullptr) {
879 continue;
880 }
881 if (!nmd->runtime->cache) {
882 continue;
883 }
884 if (nmd->node_group->nested_node_refs_num == 0) {
885 /* Skip when there are no bake nodes or simulations. */
886 continue;
887 }
888 const blender::bke::bake::ModifierCache &modifier_cache = *nmd->runtime->cache;
889 {
890 std::lock_guard lock{modifier_cache.mutex};
891 for (const auto item : modifier_cache.simulation_cache_by_id.items()) {
892 const blender::bke::bake::SimulationNodeCache &node_cache = *item.value;
893 if (node_cache.bake.frames.is_empty()) {
894 all_simulations_baked = false;
895 continue;
896 }
898 all_simulations_baked = false;
899 }
900 cache_ranges.append({node_cache.bake.frame_range(), node_cache.cache_status});
901 }
902 for (const auto item : modifier_cache.bake_cache_by_id.items()) {
903 const NodesModifierBake *bake = nmd->find_bake(item.key);
904 if (!bake) {
905 continue;
906 }
907 if (bake->bake_mode == NODES_MODIFIER_BAKE_MODE_STILL) {
908 continue;
909 }
910 const blender::bke::bake::BakeNodeCache &node_cache = *item.value;
911 if (node_cache.bake.frames.is_empty()) {
912 continue;
913 }
914 cache_ranges.append(
916 }
917 }
918 }
920 cache_ranges, all_simulations_baked, &y_offset, cache_draw_height, pos_id);
921 }
922
925
926 BLI_freelistN(&pidlist);
927}
928
Functions and classes to work with Actions.
#define PTCACHE_TYPE_SMOKE_HIGHRES
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis)
#define PTCACHE_TYPE_CLOTH
#define PTCACHE_TYPE_DYNAMICPAINT
#define PTCACHE_TYPE_PARTICLES
#define PTCACHE_TYPE_SOFTBODY
#define PTCACHE_TYPE_SMOKE_DOMAIN
#define PTCACHE_TYPE_RIGIDBODY
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.c:408
unsigned char uchar
unsigned int uint
#define IN_RANGE(a, b, c)
#define ELEM(...)
@ 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_TIMELINE
@ SACTION_SHOW_INTERPOLATION
@ SACTION_SHOW_EXTREMES
@ SACTION_MOVING
@ eModifierType_Nodes
@ NODES_MODIFIER_BAKE_MODE_STILL
Object is a sort of wrapper for general info.
@ PTCACHE_BAKED
@ PTCACHE_OUTDATED
@ USER_ANIM_SHOW_CHANNEL_GROUP_COLORS
#define UI_SCALE_FAC
@ ANIMTYPE_SUMMARY
@ ANIMTYPE_GROUP
@ ANIMTYPE_GREASE_PENCIL_DATABLOCK
@ ANIMTYPE_SCENE
@ ANIMTYPE_FILLACT_LAYERED
@ ANIMTYPE_FILLACTD
@ ANIMTYPE_OBJECT
@ ANIMTYPE_GREASE_PENCIL_LAYER_GROUP
@ ANIMTYPE_DSWOR
@ ANIMTYPE_DSSKEY
@ ALE_GREASE_PENCIL_GROUP
@ ALE_SCE
@ ALE_GREASE_PENCIL_CEL
@ ALE_GREASE_PENCIL_DATA
@ ALE_NONE
@ ALE_GPFRAME
@ ALE_FCURVE
@ ALE_NLASTRIP
@ ALE_ALL
@ ALE_ACT
@ ALE_ACTION_LAYERED
@ ALE_OB
@ ALE_GROUP
@ ALE_ACTION_SLOT
@ ALE_MASKLAY
@ ANIMCONT_MASK
@ ANIMCONT_SHAPEKEY
@ ANIMCONT_DOPESHEET
@ ANIMCONT_ACTION
@ ANIMCONT_GPENCIL
@ ACHANNEL_SETTING_SELECT
void immUniformColor4ubv(const unsigned char rgba[4])
void immEnd()
void immUnbindProgram()
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColor(int color_id)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immUniform1i(const char *name, int x)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char a)
GPUVertFormat * immVertexFormat()
void immUniformColor3f(float r, float g, float b)
void immUniform4fv(const char *name, const float data[4])
void immBegin(GPUPrimType, uint vertex_len)
void immRectf_fast(uint pos, float x1, float y1, float x2, float y2)
void immRectf(uint pos, float x1, float y1, float x2, float y2)
void GPU_matrix_scale_2f(float x, float y)
void GPU_matrix_push()
void GPU_matrix_pop()
void GPU_matrix_translate_2f(float x, float y)
@ GPU_PRIM_LINES
@ GPU_PRIM_TRIS
@ GPU_SHADER_2D_DIAG_STRIPES
@ 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
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ UI_EMBOSS
uiBlock * UI_block_begin(const bContext *C, ARegion *region, std::string name, eUIEmbossType emboss)
void UI_block_draw(const bContext *C, uiBlock *block)
void UI_block_end(const bContext *C, uiBlock *block)
@ TH_SIMULATED_FRAMES
@ TH_BACK
@ TH_GROUP
@ TH_DOPESHEET_CHANNELSUBOB
@ TH_ANIM_ACTIVE
@ TH_SHADE2
@ TH_HILITE
@ TH_GROUP_ACTIVE
@ TH_DOPESHEET_CHANNELOB
void UI_GetThemeColor4fv(int colorid, float col[4])
void UI_GetThemeColor4ubv(int colorid, unsigned char col[4])
void UI_view2d_sync(bScreen *screen, ScrArea *area, View2D *v2dcur, int flag)
Definition view2d.cc:861
#define V2D_LOCK_COPY
Definition UI_view2d.hh:85
#define V2D_SCROLL_HANDLE_HEIGHT
Definition UI_view2d.hh:67
static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, uint pos)
void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region, const ListBase &anim_data)
static uint timeline_cache_segments_count(PointCache *cache)
static void timeline_cache_draw_cached_segments(PointCache *cache, uint pos_id)
void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Scene *scene)
static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id)
static void draw_channel_action_ranges(ListBase *anim_data, View2D *v2d)
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region, ListBase *anim_data)
static void timeline_cache_draw_geometry_nodes(const blender::Span< CacheRange > cache_ranges, const bool all_simulations_baked, float *y_offset, const float line_height, const uint pos_id)
static void timeline_cache_modify_color_based_on_state(PointCache *cache, float color[4], float color_state[4])
static bool timeline_cache_is_hidden_by_setting(const SpaceAction *saction, const PTCacheID *pid)
static void draw_keyframes(bAnimContext *ac, View2D *v2d, SpaceAction *saction, ListBase &anim_data)
static void timeline_cache_color_get(PTCacheID *pid, float color[4])
static bool timeline_cache_find_next_cached_segment(PointCache *cache, int search_start_frame, int *r_segment_start, int *r_segment_end)
#define EXTRA_SCROLL_PAD
float ANIM_UI_get_channel_skip()
void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, const rctf *rect, size_t channel_index)
float ANIM_UI_get_keyframe_scale_factor()
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
const bAnimChannelType * ANIM_channel_get_typeinfo(bAnimListElem *ale)
float ANIM_UI_get_channel_step()
float ANIM_UI_get_first_channel_top(View2D *v2d)
float ANIM_UI_get_channel_height()
bAction * ANIM_channel_action_get(const bAnimListElem *ale)
short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition anim_deps.cc:457
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition anim_draw.cc:210
void ANIM_draw_action_framerange(AnimData *adt, bAction *action, View2D *v2d, float ymin, float ymax)
Definition anim_draw.cc:143
volatile int lock
unsigned int U
Definition btGjkEpa3.h:78
ChannelStorageType a
Definition BLI_color.hh:88
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
Iterator begin() const
Definition BLI_set.hh:461
Iterator end() const
Definition BLI_set.hh:471
bool add(const Key &key)
Definition BLI_set.hh:248
constexpr bool is_empty() const
Definition BLI_span.hh:261
void append(const T &value)
void extend(Span< T > array)
Span< T > as_span() const
uint top
int count
void ED_add_action_slot_channel(ChannelDrawList *channel_list, AnimData *adt, animrig::Action &action, animrig::Slot &slot, const float ypos, const float yscale_fac, int saction_flag)
void ED_add_grease_pencil_layer_legacy_channel(ChannelDrawList *channel_list, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag)
ChannelDrawList * ED_channel_draw_list_create()
void ED_add_grease_pencil_cels_channel(ChannelDrawList *channel_list, bDopeSheet *ads, const GreasePencilLayer *layer, const float ypos, const float yscale_fac, int saction_flag)
void ED_add_scene_channel(ChannelDrawList *channel_list, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac, int saction_flag)
void ED_channel_list_flush(ChannelDrawList *channel_list, View2D *v2d)
void ED_add_grease_pencil_layer_group_channel(ChannelDrawList *channel_list, bDopeSheet *ads, const GreasePencilLayerTreeGroup *layer_group, const float ypos, const float yscale_fac, int saction_flag)
void ED_add_action_channel(ChannelDrawList *channel_list, AnimData *adt, bAction *act, float ypos, float yscale_fac, int saction_flag)
void ED_add_action_layered_channel(ChannelDrawList *channel_list, AnimData *adt, bAction *action, const float ypos, const float yscale_fac, int saction_flag)
void ED_channel_list_free(ChannelDrawList *channel_list)
void ED_add_fcurve_channel(ChannelDrawList *channel_list, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac, int saction_flag)
void ED_add_action_group_channel(ChannelDrawList *channel_list, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag)
void ED_add_mask_layer_channel(ChannelDrawList *channel_list, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac, int saction_flag)
void ED_add_summary_channel(ChannelDrawList *channel_list, bAnimContext *ac, float ypos, float yscale_fac, int saction_flag)
void ED_add_object_channel(ChannelDrawList *channel_list, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac, int saction_flag)
void ED_add_grease_pencil_datablock_channel(ChannelDrawList *channel_list, bAnimContext *ac, AnimData *adt, const GreasePencil *grease_pencil, const float ypos, const float yscale_fac, int saction_flag)
format
unsigned char uint8_t
Definition stdint.h:78
blender::bke::bake::CacheStatus status
blender::IndexRange frames
void * first
struct bNodeTree * node_group
NodesModifierRuntimeHandle * runtime
ListBase modifiers
unsigned int type
struct PointCache * cache
struct RenderData r
bool(* has_setting)(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
bool(* get_channel_color)(const bAnimListElem *ale, uint8_t r_color[3])
eAnimCont_Types datatype
ScrArea * area
AnimData * adt
bAnimListElem * next
eAnim_ChannelType type
eAnim_KeyType datatype
int nested_node_refs_num
Map< int, std::unique_ptr< SimulationNodeCache > > simulation_cache_by_id
Map< int, std::unique_ptr< BakeNodeCache > > bake_cache_by_id
Vector< std::unique_ptr< FrameCache > > frames
float xmax
float xmin
float ymax
float ymin